From a4cc3ad3504d634e379369862c9f9fd8eed379f3 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Thu, 16 May 2024 01:43:09 -0400 Subject: Add Jindrich Kubec's tools. --- jindroush/lib/cfs_dosm.cpp | 240 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 jindroush/lib/cfs_dosm.cpp (limited to 'jindroush/lib/cfs_dosm.cpp') diff --git a/jindroush/lib/cfs_dosm.cpp b/jindroush/lib/cfs_dosm.cpp new file mode 100644 index 0000000..96c04fb --- /dev/null +++ b/jindroush/lib/cfs_dosm.cpp @@ -0,0 +1,240 @@ +// 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_dosm.h" +#include "autil.h" + +#define ROOT_DIR 361 + +CDosM::CDosM() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CDosM constructed: %08X\n", this ); + #endif +} + +CDosM::~CDosM() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CDosM destructed: %08X\n", this ); + #endif +} + +BOOL CDosM::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + + m_pDisk = pDisk; + m_pRoot = NULL; + + return ReadDir( ROOT_DIR, (CDosMDirEntry**)&m_pRoot ); +} + +BOOL CDosM::ReadDir( int iSector, CDosMDirEntry** ppRoot ) +{ + DOSM_DIRENT dire; + + WORD wEntry = 0; + + CDosMDirEntry* pPrev = NULL; + + do + { + BYTE abtSec[ 0x100 ]; + + //printf( "reading sec %d\n", iSector + ( wEntry / 8 ) ); + + if ( !m_pDisk->ReadSector( abtSec, iSector + ( wEntry / 8 ) ) ) + { + sprintf( m_szLastError, "DOSM: 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( DOSM_DIRENT ), sizeof( DOSM_DIRENT ) ); + BYTE* pTmp = abtSec + ( wEntry % 8) * sizeof( DOSM_DIRENT ); + dire.btFlags = MGET_B( pTmp ); + dire.wSecCount = MGET_LEW( pTmp ); + dire.wSecStart = MGET_LEW( pTmp ); + memcpy( dire.acAtariName, pTmp, 11 ); + + //printf( "%p %p %04X %02X\n", pTmp, abtSec, wEntry, dire.btFlags ); + + if ( !dire.btFlags ) + break; + + CDosMDirEntry* pE = CreateEntry( &dire ); + + if ( pE && ! ( pE->m_dwFlags & DIRE_DELETED ) ) + { + if ( *ppRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + *ppRoot = pE; + pPrev = pE; + } + + } + + wEntry++; + + } while( dire.btFlags && ( wEntry < 64 ) ); + + return TRUE; +} + +void CDosM::Dismount() +{ + DeleteList( m_pRoot ); +} + +CDosMDirEntry* CDosM::CreateEntry( DOSM_DIRENT* pDire ) +{ + CDosMDirEntry* pE = new CDosMDirEntry(); + + if ( !pE ) + { + sprintf( m_szLastError, "DOSM: 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 ); + //printf( "%02X %04X %04X %s\n", pDire->btFlags, pDire->wSecStart, pDire->wSecCount, pE->m_szFname ); + + pE->m_btFlags = pDire->btFlags; + pE->m_wSecStart = pDire->wSecStart; + pE->m_wSecCount = pDire->wSecCount; + + if ( pDire->btFlags == 0x10 ) + { + pE->m_dwFlags |= DIRE_SUBDIR; + + BOOL bRes = ReadDir( pE->m_wSecStart, (CDosMDirEntry**)&pE->m_pSubdir ); + + if ( !bRes ) + return NULL; + } + else + { + if ( pE->m_dwFlags & DIRE_DELETED ) + { + } + else if ( ExportFile( NULL, pE ) ) + { + m_iFilesValid++; + } + else + { + m_iFilesInvalid++; + } + } + + return pE; +} + +BOOL CDosM::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, "DOSM: Unable to create file '%s'!", szOutFile ); + return FALSE; + } + } + + BYTE abtBuff[ 0x0100 ]; + + WORD wSector = ((CDosMDirEntry*)pDirE ) -> m_wSecStart; + WORD wCount = ((CDosMDirEntry*)pDirE ) -> m_wSecCount; + WORD wSectorSize = m_pDisk->GetSectorSize(); + + abtBuff[ wSectorSize - 1 ] = 0; + + while( wCount ) + { + if ( wSector < 1 ) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s' (invalid sector %04X)", szOutFile, wSector ); + return FALSE; + } + + if ( ( abtBuff[ wSectorSize - 1 ] & 0x80 ) && ( wSectorSize == 0x80 ) ) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s' (unexpected EOF)", szOutFile ); + return FALSE; + } + + if ( !m_pDisk->ReadSector( abtBuff, wSector ) ) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s'\n%s\n", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + +// if ( -1 != hOutfile ) +// { +// printf( "%04X/%04X | %02X %02X %02X\n", +// wSector, +// wCount, +// abtBuff[ wSectorSize - 3 ], +// abtBuff[ wSectorSize - 2 ], +// abtBuff[ wSectorSize - 1 ] ); +// } + + //originally, there was 0x07 as a mask, but megaimages were not working with it + if ( m_pDisk->GetSectorCount() > 943 ) + wSector = abtBuff[ wSectorSize - 2 ] + ( (WORD)abtBuff[ wSectorSize - 3 ] & 0xff ) * 0x100; + else + wSector = abtBuff[ wSectorSize - 2 ] + ( 0x03 & (WORD)abtBuff[ wSectorSize - 3 ] ) * 0x100; + + if ( -1 != hOutfile ) + write( hOutfile, abtBuff, abtBuff[ wSectorSize - 1 ] ); + + wCount--; + } + + if ( ((CDosMDirEntry*)pDirE ) -> m_wSecCount ) + { + if ( ! ( abtBuff[ wSectorSize - 1 ] & 128 ) && ( wSectorSize == 128 ) && wSector) + { + sprintf( m_szLastError, "DOSM: Corrupted file '%s' (expected EOF, code %02X, next sector %04X)", szOutFile, abtBuff[ wSectorSize - 1 ], wSector ); + return FALSE; + } + } + + if ( -1 != hOutfile ) + close( hOutfile ); + + return TRUE; +} + -- cgit v1.2.3