aboutsummaryrefslogtreecommitdiff
path: root/jindroush/bas2boot/bas2boot.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/bas2boot/bas2boot.cpp
parentb33c25d1363110e6e4a714530f460b0ff951f56b (diff)
downloadbw-atari8-tools-a4cc3ad3504d634e379369862c9f9fd8eed379f3.tar.gz
Add Jindrich Kubec's tools.
Diffstat (limited to 'jindroush/bas2boot/bas2boot.cpp')
-rw-r--r--jindroush/bas2boot/bas2boot.cpp286
1 files changed, 286 insertions, 0 deletions
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;
+}
+