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/bas2boot/bas2boot.cpp | 286 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 jindroush/bas2boot/bas2boot.cpp (limited to 'jindroush/bas2boot/bas2boot.cpp') diff --git a/jindroush/bas2boot/bas2boot.cpp b/jindroush/bas2boot/bas2boot.cpp new file mode 100644 index 0000000..bb8f2f8 --- /dev/null +++ b/jindroush/bas2boot/bas2boot.cpp @@ -0,0 +1,286 @@ +// 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 "pub.def" +#include "jintypes.h" +#include "autil.h" +#include "adsk.h" + +DISK_TYPE g_dtypeOut = DISK_ATR; +BOOL g_bClassic = FALSE; +#define MAX_STRING 256 +char g_szMessage[ MAX_STRING ] = ""; + +typedef struct +{ + WORD w1; + WORD w2; + WORD w3; + WORD w4; + WORD w5; + WORD w6; + WORD w7; +} BASHEAD; + +#define BAS_HEAD_SIZE 0x0E + +#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n" + +#define HEADER SHEADER \ + PRG_DESC "\n" \ + " Latest version can be found at " PRG_URL "\n" \ + " Published under GPL. See GPL.TXT.\n\n" + +#define USAGE HEADER "Usage: " PRG_NAME " " PRG_USAGE + +#include "switches.cpp" + +int main( int argc, char* argv[] ) +{ + setbuf( stdout, NULL ); + setbuf( stderr, NULL ); + + if ( !SWITCHES_Init( &argc, argv ) ) + return 1; + + if ( argc < 2 ) + { + SWFN_HELP( USAGE ); + return 1; + } + + fprintf( stderr, SHEADER ); + + char* szInFile = argv[ 1 ]; + char szOutFile[ MAX_STRING ]; + + //setting the message + char szMessage[ MAX_STRING ]; + strcpy( szMessage, g_szMessage ); + + //if not present, set to 'Loading prgname' + if ( ! *szMessage ) + { + strcpy( szMessage, "Loading " ); + strcat( szMessage, szInFile ); + } + + //and pad it with spaces + memset( szMessage + strlen( szMessage), 0x20, MAX_STRING - strlen( szMessage ) ); + szMessage[ MAX_STRING - 1 ] = '\0'; + + //get output filename + if ( argc >= 3 ) + { + strcpy( szOutFile, argv[ 2 ] ); + } + else + { + GuessBestFnameFromPC( szOutFile, szInFile, GetDiskTypeExt( g_dtypeOut ) ); + } + + ADisk* pDisk = NULL; + switch( g_dtypeOut ) + { + case DISK_ATR: + pDisk = new CAtr(); + break; + + case DISK_XFD: + pDisk = new CXfd(); + break; + + case DISK_SCP: + pDisk = new CScp(); + break; + + case DISK_DCM: + pDisk = new CDcm(); + break; + + case DISK_DI: + pDisk = new CDi(); + break; + + default: + break; + } + + if ( !pDisk ) + { + printf( "Can't create such image!\n" ); + return FALSE; + } + + //reads boot stub + char szBootName[ MAX_STRING ]; + strcpy( szBootName, argv[ 0 ] ); + char* szWhere = strrchr( szBootName, '/' ); + + if ( szWhere ) + szWhere++; + else + szWhere = szBootName; + + strcpy( szWhere, "bas2boot.boo" ); + + CFile cf; + + if ( !cf.Open( szBootName ) ) + { + printf( "Can't open boot image: %s\n", szBootName ); + return 1; + } + + long lBootLen = cf.GetLength(); + + if ( lBootLen % 0x80 ) + { + printf( "Invalid boot image: %s\n", szBootName ); + cf.Close(); + return 1; + } + + BYTE* pbtBoot = new BYTE [ lBootLen ]; + + cf.Read( pbtBoot, lBootLen ); + + cf.Close(); + + int iBootSectors = lBootLen / 0x80; + + if ( pbtBoot[ 1 ] != iBootSectors ) + { + printf( "Invalid boot image: %s\nSize mismatch.\n", szBootName ); + cf.Close(); + delete [] pbtBoot; + return 1; + } + + //open basic file + if ( !cf.Open( szInFile ) ) + { + printf( "Can't open source file '%s'!\n", szInFile ); + return 1; + } + + long lBasicLen = cf.GetLength(); + + //set real length in header + pbtBoot[ 8 ] = lBasicLen & 0xFF; + pbtBoot[ 9 ] = lBasicLen >> 8; + + lBasicLen -= BAS_HEAD_SIZE; + + int iBasicSectors = ( lBasicLen + 0x7F ) / 0x80; + + //load and relocate basic header + BASHEAD head; + head.w1 = cf.readLEw(); + head.w2 = cf.readLEw() - head.w1; + head.w3 = cf.readLEw() - head.w1; + head.w4 = cf.readLEw() - head.w1; + head.w5 = cf.readLEw() - head.w1; + head.w6 = cf.readLEw() - head.w1; + head.w7 = cf.readLEw() - head.w1; + + BYTE* pbtHd = pbtBoot + lBootLen - BAS_HEAD_SIZE - 2; + + *( pbtHd++ ) = ( iBasicSectors - 1 ) & 0xFF; + *( pbtHd++ ) = ( iBasicSectors - 1 ) >>8; + + *( pbtHd++ ) = head.w1 & 0xFF; + *( pbtHd++ ) = head.w1 >> 8; + + *( pbtHd++ ) = head.w2 & 0xFF; + *( pbtHd++ ) = head.w2 >> 8; + + *( pbtHd++ ) = head.w3 & 0xFF; + *( pbtHd++ ) = head.w3 >> 8; + + *( pbtHd++ ) = head.w4 & 0xFF; + *( pbtHd++ ) = head.w4 >> 8; + + *( pbtHd++ ) = head.w5 & 0xFF; + *( pbtHd++ ) = head.w5 >> 8; + + *( pbtHd++ ) = head.w6 & 0xFF; + *( pbtHd++ ) = head.w6 >> 8; + + *( pbtHd++ ) = head.w7 & 0xFF; + *( pbtHd++ ) = head.w7 >> 8; + + //find empty space at the end of boot + BYTE* pbtString = pbtBoot + lBootLen - BAS_HEAD_SIZE - 2 - 2; + BYTE* pbtStringEnd = pbtString; + + while( *pbtString == 0x20 ) + pbtString--; + + pbtString++; + + int iStringLen = pbtStringEnd - pbtString; + + //put the message there + memcpy( pbtString, szMessage, iStringLen + 1 ); + + //read basic program + BYTE* pbtBas = new BYTE [ iBasicSectors * 0x80 ]; + memset( pbtBas, 0, iBasicSectors * 0x80 ); + + cf.Read( pbtBas, lBasicLen ); + + cf.Close(); + + //format disk + DISK_GEOMETRY dg; + + if ( g_bClassic ) + ForceClassicSize( iBasicSectors + iBootSectors, 0x80, &dg ); + else + GuessClassicSizes( iBasicSectors + iBootSectors, 0x80, &dg ); + + if ( !pDisk->Format( &dg ) ) + { + delete pDisk; + delete[] pbtBoot; + delete [] pbtBas; + return 1; + } + + //write boot & body + pDisk->WriteSectors( 1, pbtBoot, iBootSectors ); + pDisk->WriteSectors( 1 + iBootSectors, pbtBas, iBasicSectors ); + + //save it to disk + if ( !pDisk->Save( szOutFile, FALSE ) ) + { + printf( "Error! %s\n", pDisk->GetLastError() ); + delete pDisk; + delete [] pbtBoot; + delete [] pbtBas; + return 1; + } + + delete pDisk; + + delete [] pbtBoot; + delete [] pbtBas; + + printf( "Written to %s (%s)\n", szOutFile, GetDiskTypeName( g_dtypeOut ) ); + + return 0; +} + -- cgit v1.2.3