// 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_dos3.h" #include "autil.h" #define ROOT_DIR 0x10 #define FAT 0x18 CDos3::CDos3() : CFs() { #ifdef _MEMORY_DUMP_ printf( "CDos3 constructed: %08X\n", this ); #endif } CDos3::~CDos3() { Dismount(); #ifdef _MEMORY_DUMP_ printf( "CDos3 destructed: %08X\n", this ); #endif } BOOL CDos3::Mount( ADisk* pDisk ) { m_iFilesValid = 0; m_iFilesInvalid = 0; m_pDisk = pDisk; m_pRoot = NULL; if ( m_pDisk->GetSectorSize() != 0x80 ) { sprintf( m_szLastError, "DOS3: Can't process DD disk!" ); return FALSE; } CDos3DirEntry* pPrev = NULL; DOS3_DIRENT dire; WORD wEntry = 1; if ( !pDisk->ReadSector( m_abtFat, FAT ) ) { sprintf( m_szLastError, "DOS3: Can't read FAT sector because\n%s", m_pDisk->GetLastError() ); return FALSE; } do { BYTE abtSec[ 0x100 ]; if ( !pDisk->ReadSector( abtSec, ROOT_DIR + ( wEntry / 8 ) ) ) { sprintf( m_szLastError, "DOS3: Can't read directory entry %04X because\n%s", wEntry, m_pDisk->GetLastError() ); return FALSE; } memcpy( &dire, abtSec + ( wEntry % 8) * sizeof( DOS3_DIRENT ), sizeof( DOS3_DIRENT ) ); if ( !dire.btFlags ) break; CDos3DirEntry* pE = CreateEntry( &dire ); 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 ); return TRUE; } void CDos3::Dismount() { DeleteList( m_pRoot ); } CDos3DirEntry* CDos3::CreateEntry( DOS3_DIRENT* pDire ) { CDos3DirEntry* pE = new CDos3DirEntry(); if ( !pE ) return NULL; if ( pDire->btFlags == 0x80 ) { pE->m_dwFlags |= DIRE_DELETED; } ADos2MsDos( pE->m_szFname, pDire->acAtariName ); //sprintf( pE->m_szAscData, "%02X %02X %02X %04X", pDire->btSecStart, pDire->btSecCount, pDire->btFlags, pDire->wFileLen ); sprintf( pE->m_szAscData, "%02X %04X", pDire->btFlags, pDire->wFileLen ); pE->m_btSecStart = pDire->btSecStart; pE->m_btSecCount = pDire->btSecCount; pE->m_btFlags = pDire->btFlags; pE->m_wFileLen = pDire->wFileLen; if ( pE->m_dwFlags & DIRE_DELETED ) { } else if ( ExportFile( NULL, pE ) ) m_iFilesValid++; else m_iFilesInvalid++; return pE; } BOOL CDos3::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, "DOS3: Unable to create file '%s'!", szOutFile ); return FALSE; } } BYTE abtBuff[ 0x80 * 8 ]; BYTE btSecCount = ((CDos3DirEntry*)pDirE) ->m_btSecCount; BYTE btSector = ((CDos3DirEntry*)pDirE) ->m_btSecStart; WORD wFileLen = ((CDos3DirEntry*)pDirE) ->m_wFileLen; while( btSecCount ) { WORD wToCopy = ( wFileLen < 0x400 ) ? wFileLen : 0x400; if ( !m_pDisk->ReadSectors( abtBuff, ( btSector * 8 ) + FAT + 1, 8 ) ) { { sprintf( m_szLastError, "DOS3: Corrupted file '%s'\n%s\n", szOutFile, m_pDisk->GetLastError() ); return FALSE; } } if ( -1 != hOutfile ) write( hOutfile, abtBuff, wToCopy ); btSecCount--; wFileLen -= wToCopy; btSector = m_abtFat[ btSector ]; if ( wToCopy == 0x400 ) { if ( btSector >= 0xFD ) { sprintf( m_szLastError, "DOS3: Corrupted file '%s' (unexpected EOF)", szOutFile ); return FALSE; } } else { if ( btSector != 0xFD ) { sprintf( m_szLastError, "DOS3: Corrupted file '%s' (missed EOF) %02X", szOutFile, btSector ); return FALSE; } } } if ( -1 != hOutfile ) close( hOutfile ); return TRUE; }