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_robc.cpp | 231 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 jindroush/lib/cfs_robc.cpp (limited to 'jindroush/lib/cfs_robc.cpp') diff --git a/jindroush/lib/cfs_robc.cpp b/jindroush/lib/cfs_robc.cpp new file mode 100644 index 0000000..089b4bc --- /dev/null +++ b/jindroush/lib/cfs_robc.cpp @@ -0,0 +1,231 @@ +// 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_robc.h" +#include "autil.h" +#include "adsk_atr.h" + +#define ROBC_MAX_NAME 20 + +CRobc::CRobc() : CFs() +{ + #ifdef _MEMORY_DUMP_ + printf( "CRobc constructed: %08X\n", this ); + #endif +} + +CRobc::~CRobc() +{ + Dismount(); + #ifdef _MEMORY_DUMP_ + printf( "CRobc destructed: %08X\n", this ); + #endif +} + +BOOL CRobc::Mount( ADisk* pDisk ) +{ + m_iFilesValid = 0; + m_iFilesInvalid = 0; + m_pDisk = pDisk; + m_pRoot = NULL; + + if ( m_pDisk->GetSectorSize() != 0x80 ) + { + sprintf( m_szLastError, "ROBC: Can't process DD disk!" ); + return FALSE; + } + + switch( m_pDisk->GetBootSectorCount() ) + { + case 0x04: + break; + + default: + { + sprintf( m_szLastError, "ROBC: Can't identify disk as a RobC menu!" ); + return FALSE; + } + } + + CRobcDirEntry* pPrev = NULL; + + BYTE abtSec[ 0x180 ]; + + if ( !m_pDisk->ReadSectors( abtSec, 0x02, 3 ) ) + { + sprintf( m_szLastError, "ROBC: Can't read directory because\n%s", m_pDisk->GetLastError() ); + return FALSE; + } + + BYTE* abtStartSecLo = abtSec + 0x77; + BYTE* abtStartSecHi = abtSec + 0x6E; + BYTE* pbtName = abtSec + 0xB9; + + for( int i = 0; i < 10; i++ ) + { + WORD wSec = *abtStartSecLo + ( *abtStartSecHi << 8 ); + + //printf( "%d) %04X\n", i, wSec ); + + if ( ! wSec ) + continue; + + BYTE abtLocSec[ 0x80 ]; + BYTE btSecCount; + + if( !m_pDisk->ReadSector( abtLocSec, wSec ) ) + { + sprintf( m_szLastError, "ROBC: Can't read dir entry %d!", i ); + return FALSE; + } + + btSecCount = abtLocSec[ 1 ]; + + if ( ! btSecCount ) + break; + + CRobcDirEntry* pE = CreateEntry( btSecCount, wSec, pbtName + 2 ); + + if ( m_pRoot ) + { + pPrev->m_pNext = pE; + pE->m_pPrev = pPrev; + pPrev = pE; + } + else + { + m_pRoot = pE; + pPrev = pE; + } + + abtStartSecLo++; + abtStartSecHi++; + pbtName += ROBC_MAX_NAME; + } + + return TRUE; +} + +void CRobc::Dismount() +{ + DeleteList( m_pRoot ); +} + +CRobcDirEntry* CRobc::CreateEntry( BYTE btSecCount, WORD wStartSec, BYTE* btName ) +{ + CRobcDirEntry* pE = new CRobcDirEntry(); + + if ( !pE ) + return NULL; + + pE->m_iStartSec = wStartSec; + pE->m_iSecCount = btSecCount; + + sprintf( pE->m_szAscData, "%04X %02X", wStartSec, btSecCount ); + + char szTemp[ ROBC_MAX_NAME + 1 - 2 ]; + memcpy( szTemp, btName, ROBC_MAX_NAME - 2 ); + szTemp[ ROBC_MAX_NAME - 2 ] = '\0'; + + //printf( "%s\n", szTemp ); + + char* szT = szTemp; + + while( *szT ) + { + *szT &= 0x7F; + *szT -= 0x20; + szT++; + } + + GuessBestFnameFromAtari( pE->m_szFname, szTemp, "atr" ); + + //printf( "%s\n", pE->m_szFname ); + + if ( ExportFile( NULL, pE ) ) + m_iFilesValid++; + else + m_iFilesInvalid++; + + return pE; +} + +BOOL CRobc::ExportFile( char* szOutFile, CDirEntry* pDirE ) +{ + int iSecCount = ((CRobcDirEntry*)pDirE) ->m_iSecCount; + int iStartSec = ((CRobcDirEntry*)pDirE) ->m_iStartSec; + + BYTE abtBuff[ 0x80 ]; + + if ( ( iStartSec + iSecCount - 1 ) > m_pDisk->GetSectorCount() ) + { + sprintf( m_szLastError, "ROBC: File '%s' goes past last sector!", szOutFile ); + return FALSE; + } + + m_pDisk->ReadSector( abtBuff, iStartSec ); + + if ( abtBuff[ 1 ] != iSecCount ) + { + sprintf( m_szLastError, "ROBC: File '%s' Mismatched length (%d<>%d)!", szOutFile, abtBuff[ 1 ], iSecCount ); + return FALSE; + } + + if ( !szOutFile ) + return TRUE; + + CAtr newdisk; + + DISK_GEOMETRY dg; + + dg.iSides = 1; + dg.iTracks = 1; + dg.iSectorsPerTrack = iSecCount; + dg.iBytesPerSector = 0x80; + + if ( !newdisk.Format( &dg ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + int iCurrSec = 1; + + while( iSecCount ) + { + if( !m_pDisk->ReadSector( abtBuff, iStartSec++ ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, m_pDisk->GetLastError() ); + return FALSE; + } + + if ( !newdisk.WriteSector( iCurrSec++, abtBuff ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + iSecCount--; + } + + if ( !newdisk.Save( szOutFile, FALSE ) ) + { + sprintf( m_szLastError, "ROBC: File '%s' can't create because\n%s", szOutFile, newdisk.GetLastError() ); + return FALSE; + } + + return TRUE; +} + -- cgit v1.2.3