aboutsummaryrefslogtreecommitdiff
path: root/jindroush/lib/cfs_dos2.cpp
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-05-16 01:43:09 -0400
committerB. Watson <urchlay@slackware.uk>2024-05-16 01:43:09 -0400
commita4cc3ad3504d634e379369862c9f9fd8eed379f3 (patch)
tree7b6f55c352a4ca62dddaa1b4a6854799111d2d2f /jindroush/lib/cfs_dos2.cpp
parentb33c25d1363110e6e4a714530f460b0ff951f56b (diff)
downloadbw-atari8-tools-a4cc3ad3504d634e379369862c9f9fd8eed379f3.tar.gz
Add Jindrich Kubec's tools.
Diffstat (limited to 'jindroush/lib/cfs_dos2.cpp')
-rw-r--r--jindroush/lib/cfs_dos2.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/jindroush/lib/cfs_dos2.cpp b/jindroush/lib/cfs_dos2.cpp
new file mode 100644
index 0000000..81a8037
--- /dev/null
+++ b/jindroush/lib/cfs_dos2.cpp
@@ -0,0 +1,224 @@
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "cfs_dos2.h"
+#include "autil.h"
+
+#define ROOT_DIR 361
+
+CDos2::CDos2() : CFs()
+{
+ #ifdef _MEMORY_DUMP_
+ printf( "CDos2 constructed: %08X\n", this );
+ #endif
+}
+
+CDos2::~CDos2()
+{
+ Dismount();
+ #ifdef _MEMORY_DUMP_
+ printf( "CDos2 destructed: %08X\n", this );
+ #endif
+}
+
+BOOL CDos2::Mount( ADisk* pDisk )
+{
+ m_iFilesValid = 0;
+ m_iFilesInvalid = 0;
+
+ m_pDisk = pDisk;
+ m_pRoot = NULL;
+
+ DOS2_DIRENT dire;
+
+ WORD wEntry = 0;
+
+ CDos2DirEntry* pPrev = NULL;
+
+ do
+ {
+ BYTE abtSec[ 0x100 ];
+
+ if ( !m_pDisk->ReadSector( abtSec, ROOT_DIR + ( wEntry / 8 ) ) )
+ {
+ sprintf( m_szLastError, "DOS2: Can't read directory entry %04X because\n%s", wEntry, m_pDisk->GetLastError() );
+ return FALSE;
+ }
+
+ //this is not endian-safe
+ //memcpy( &dire, abtSec + ( wEntry % 8) * sizeof( DOS2_DIRENT ), sizeof( DOS2_DIRENT ) );
+ BYTE* pTmp = abtSec + ( wEntry % 8) * sizeof( DOS2_DIRENT );
+ dire.btFlags = MGET_B( pTmp );
+ dire.wSecCount = MGET_LEW( pTmp );
+ dire.wSecStart = MGET_LEW( pTmp );
+ memcpy( dire.acAtariName, pTmp, 11 );
+
+ if ( !dire.btFlags )
+ break;
+
+ CDos2DirEntry* pE = CreateEntry( &dire, wEntry );
+
+ if ( pE && ! ( pE->m_dwFlags & DIRE_DELETED ) )
+ {
+ if ( m_pRoot )
+ {
+ pPrev->m_pNext = pE;
+ pE->m_pPrev = pPrev;
+ pPrev = pE;
+ }
+ else
+ {
+ m_pRoot = pE;
+ pPrev = pE;
+ }
+
+ }
+
+ wEntry++;
+
+ } while( dire.btFlags && ( wEntry < 64 ) );
+
+ return TRUE;
+}
+
+void CDos2::Dismount()
+{
+ DeleteList( m_pRoot );
+}
+
+CDos2DirEntry* CDos2::CreateEntry( DOS2_DIRENT* pDire, WORD wEntry )
+{
+ CDos2DirEntry* pE = new CDos2DirEntry();
+
+ if ( !pE )
+ {
+ sprintf( m_szLastError, "DOS2: Can't allocate memory for directory!" );
+ return NULL;
+ }
+
+ if ( pDire->btFlags == 0x80 )
+ {
+ pE->m_dwFlags |= DIRE_DELETED;
+ }
+
+ ADos2MsDos( pE->m_szFname, pDire->acAtariName );
+
+ sprintf( pE->m_szAscData, "%02X %04X %04X", pDire->btFlags, pDire->wSecStart, pDire->wSecCount );
+
+ pE->m_wFileNumber = wEntry;
+ pE->m_btFlags = pDire->btFlags;
+ pE->m_wSecStart = pDire->wSecStart;
+ pE->m_wSecCount = pDire->wSecCount;
+
+ if ( pE->m_dwFlags & DIRE_DELETED )
+ {
+ }
+ else if ( ExportFile( NULL, pE ) )
+ m_iFilesValid++;
+ else
+ m_iFilesInvalid++;
+
+ return pE;
+}
+
+BOOL CDos2::ExportFile( char* szOutFile, CDirEntry* pDirE )
+{
+ int hOutfile = -1;
+
+ if ( szOutFile )
+ {
+ hOutfile = open( szOutFile, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, 0666 );
+
+ if ( -1 == hOutfile )
+ {
+ sprintf( m_szLastError, "DOS2: Unable to create file '%s'!", szOutFile );
+ return FALSE;
+ }
+ }
+
+ BYTE abtBuff[ 0x0100 ];
+
+ WORD wSector = ((CDos2DirEntry*)pDirE ) -> m_wSecStart;
+ WORD wCount = ((CDos2DirEntry*)pDirE ) -> m_wSecCount;
+ WORD wSectorSize = m_pDisk->GetSectorSize();
+ WORD wFileNumber = ((CDos2DirEntry*)pDirE ) -> m_wFileNumber;
+
+ abtBuff[ wSectorSize - 1 ] = 0;
+
+ while( wCount )
+ {
+ if ( wSector < 1 )
+ {
+ sprintf( m_szLastError, "DOS2: Corrupted file '%s' (invalid sector %04X)", szOutFile, wSector );
+ return FALSE;
+ }
+
+ if ( ( abtBuff[ wSectorSize - 1 ] & 0x80 ) && ( wSectorSize == 0x80 ) )
+ {
+ sprintf( m_szLastError, "DOS2: Corrupted file '%s' (unexpected EOF)", szOutFile );
+ return FALSE;
+ }
+
+ if ( !m_pDisk->ReadSector( abtBuff, wSector ) )
+ {
+ sprintf( m_szLastError, "DOS2: Corrupted file '%s'\n%s\n", szOutFile, m_pDisk->GetLastError() );
+ return FALSE;
+ }
+
+ /*
+ if ( -1 != hOutfile )
+ {
+ printf( "%04X/%04X %02X | %02X %02X %02X\n",
+ wSector,
+ wCount,
+ wFileNumber,
+ abtBuff[ wSectorSize - 3 ],
+ abtBuff[ wSectorSize - 2 ],
+ abtBuff[ wSectorSize - 1 ] );
+ }
+ */
+
+ wSector = abtBuff[ wSectorSize - 2 ] + ( 0x03 & abtBuff[ wSectorSize - 3 ] ) * 0x100;
+
+ if ( ( abtBuff[ wSectorSize-3 ] >> 2 ) != wFileNumber )
+ {
+ WORD wFN = abtBuff[ wSectorSize - 3 ] >> 2;
+
+ sprintf( m_szLastError, "DOS2: Corrupted file '%s' (167: file number mismatch [%04X != %04X])", szOutFile, wFileNumber, wFN );
+ return FALSE;
+ }
+
+
+ if ( -1 != hOutfile )
+ write( hOutfile, abtBuff, abtBuff[ wSectorSize - 1 ] );
+
+ wCount--;
+ }
+
+ if ( ((CDos2DirEntry*)pDirE ) -> m_wSecCount )
+ {
+ if ( ! ( abtBuff[ wSectorSize - 1 ] & 128 ) && ( wSectorSize == 128 ) && wSector)
+ {
+ sprintf( m_szLastError, "DOS2: Corrupted file '%s' (expected EOF, code %02X, next sector %04X)", szOutFile, abtBuff[ wSectorSize - 1 ], wSector );
+ return FALSE;
+ }
+ }
+
+ if ( -1 != hOutfile )
+ close( hOutfile );
+
+ return TRUE;
+}
+