Skip to content

Commit db2c7b6

Browse files
Refactorized disk generation for coco (from beta).
1 parent 1fd62a9 commit db2c7b6

File tree

1 file changed

+178
-141
lines changed

1 file changed

+178
-141
lines changed

ugbc/src/targets/coco/_build.c

Lines changed: 178 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
* CODE SECTION
3939
****************************************************************************/
4040

41+
// This patch has been needed to port "beta" code under "main" branch
42+
#ifndef UGBASIC_VERSION
43+
#define UGBASIC_VERSION "1.16.3"
44+
#endif
45+
4146
extern char OUTPUT_FILE_TYPE_AS_STRING[][16];
4247

4348
void generate_bin( Environment * _environment ) {
@@ -94,108 +99,188 @@ void generate_bin( Environment * _environment ) {
9499

95100
void generate_dsk( Environment * _environment ) {
96101

102+
// Let's cut the executable file into multiple segments.
103+
// The name of the binary is equal to the disk file name,
104+
// but with a different extension.
97105
char originalBinaryFile[MAX_TEMPORARY_STORAGE];
98-
99106
strcpy( originalBinaryFile, _environment->exeFileName );
100107
char * p = strstr( originalBinaryFile, ".dsk" );
101108
if ( p ) {
102109
strcpy( p, ".bin" );
103110
}
104111

105-
Storage * storage = _environment->storage;
106-
107-
char temporaryPath[MAX_TEMPORARY_STORAGE];
108-
strcpy( temporaryPath, _environment->temporaryPath );
109-
strcat( temporaryPath, " " );
110-
temporaryPath[strlen(temporaryPath)-1] = PATH_SEPARATOR;
111-
112-
char commandLine[8*MAX_TEMPORARY_STORAGE];
113-
char executableName[MAX_TEMPORARY_STORAGE];
114-
char listingFileName[MAX_TEMPORARY_STORAGE];
115-
char binaryName[MAX_TEMPORARY_STORAGE];
116-
char originalFileName[MAX_TEMPORARY_STORAGE];
117-
118-
int fileSize = 0;
119-
int standardSize = 0;
120-
int ondemandSize = 0;
121-
int blockSize = 0;
122-
int blocks = 0;
123-
int block = 0;
124-
int remainSize = 0;
125-
126-
strcpy( binaryName, _environment->exeFileName );
127-
128-
BUILD_TOOLCHAIN_DECB_GET_EXECUTABLE( _environment, executableName );
129-
130-
FILE * fh = fopen( binaryName, "rb" );
112+
// Calculate the effective size.
113+
FILE * fh = fopen( originalBinaryFile, "rb" );
114+
int executableBinaryFileSize = 0;
131115
if ( fh ) {
132116
fseek( fh, 0, SEEK_END );
133-
fileSize = ftell( fh );
117+
executableBinaryFileSize = ftell( fh );
134118
fclose( fh );
135119
} else {
136120
CRITICAL( "cannot create dsk file");
137121
}
138122

139-
if ( fileSize < 22016 ) {
140-
141-
standardSize = fileSize - 10;
142-
ondemandSize = 0;
143-
blockSize = 4096;
144-
blocks = 0;
145-
remainSize = 0;
146-
147-
} else {
123+
// The LOADM command is able to read a limited size of binary file.
124+
// So we are going to split the original file as follows:
125+
// | $2a00 ............. $4d00 ... $4e00 ........ $xx00 .....
126+
// +---------------------+---------+---------+....+---------+
127+
// | PROGRAM.EXE | P01.DAT | P02.DAT |....| P0n.DAT |
128+
// +---------------------+---------+---------+....+---------+
129+
//
130+
131+
executableBinaryFileSize -= 5;
132+
char * originalBinaryFileContent = malloc( executableBinaryFileSize );
133+
fh = fopen( originalBinaryFile, "rb" );
134+
(void)!fread( originalBinaryFileContent, 1, 5, fh);
135+
(void)!fread( originalBinaryFileContent, 1, executableBinaryFileSize, fh);
136+
fclose( fh );
148137

149-
standardSize = 22016;
150-
ondemandSize = fileSize - standardSize - 10;
151-
blockSize = 4096;
152-
blocks = ( ondemandSize / blockSize ) + 1;
153-
remainSize = ondemandSize - ( ( blocks - 1 ) * blockSize ) - 5;
138+
fh = fopen( "/tmp/original.bin", "wb" );
139+
fwrite( originalBinaryFileContent, 1, executableBinaryFileSize, fh);
140+
fclose( fh );
154141

142+
int programExeSize = 0x4d00 - _environment->program.startingAddress;
143+
if ( executableBinaryFileSize < programExeSize ) {
144+
programExeSize = executableBinaryFileSize;
155145
}
156-
157-
int programExeSize = 5 + standardSize + data_coco_footer_bin_len;
158-
159146
char * programExe = malloc( programExeSize );
160-
memset( programExe, 0, programExeSize );
161-
fh = fopen( binaryName, "rb" );
162-
if ( !fh ) {
163-
CRITICAL( "cannot create dsk file");
164-
}
165-
(void)!fread( &programExe[0], 1, standardSize + 5, fh );
166-
programExe[1] = standardSize >> 8;
167-
programExe[2] = standardSize & 0xff;
168-
memcpy( &programExe[standardSize + 5], &data_coco_footer_bin[0], data_coco_footer_bin_len );
147+
memcpy( programExe, originalBinaryFileContent, programExeSize );
148+
executableBinaryFileSize -= programExeSize;
149+
150+
char * programDats[MAX_TEMPORARY_STORAGE];
151+
int programDatsSize[MAX_TEMPORARY_STORAGE];
152+
int programDataCount = 0;
153+
154+
if ( executableBinaryFileSize ) {
155+
char * originalBinaryFileContentPtr = originalBinaryFileContent + programExeSize;
156+
int blockSize = 0x2000;
157+
while( executableBinaryFileSize ) {
158+
if ( blockSize > executableBinaryFileSize ) {
159+
blockSize = executableBinaryFileSize;
160+
executableBinaryFileSize = blockSize;
161+
}
162+
programDats[programDataCount] = malloc( blockSize );
163+
programDatsSize[programDataCount] = blockSize;
164+
memcpy( programDats[programDataCount], originalBinaryFileContentPtr, blockSize );
165+
executableBinaryFileSize -= blockSize;
166+
originalBinaryFileContentPtr += blockSize;
167+
++programDataCount;
168+
}
169+
}
169170

170-
char * programBlocks = NULL;
171-
int programBlockSize = 0;
171+
char temporaryPath[MAX_TEMPORARY_STORAGE];
172+
strcpy( temporaryPath, _environment->temporaryPath );
173+
strcat( temporaryPath, " " );
174+
temporaryPath[strlen(temporaryPath)-1] = PATH_SEPARATOR;
172175

173-
if ( blocks ) {
176+
char outputFileName[MAX_TEMPORARY_STORAGE*2];
177+
178+
// Now we are going to write down the effective files, that must
179+
// have the LOADM format, as follows:
180+
//
181+
// +------------+--------------....--------------+---------------+
182+
// | PREAMBLE | DATA | POSTAMBLE |
183+
// +------------+--------------....--------------+---------------+
184+
// |00|LEN |LOAD| .............................. |FF|00|00| EXEC |
185+
// +------------+--------------....--------------+---------------+
186+
//
187+
188+
sprintf( outputFileName, "%sprogram.exe", temporaryPath);
189+
fh = fopen( outputFileName, "wb" );
190+
fputc( 0x00, fh );
191+
fputc( programExeSize >> 8, fh );
192+
fputc( programExeSize & 0xff, fh );
193+
fputc( _environment->program.startingAddress >> 8, fh );
194+
fputc( _environment->program.startingAddress & 0xff, fh );
195+
fwrite( programExe, 1, programExeSize, fh );
196+
fputc( 0xff, fh );
197+
fputc( 0x00, fh );
198+
fputc( 0x00, fh );
199+
fputc( _environment->program.startingAddress >> 8, fh );
200+
fputc( _environment->program.startingAddress & 0xff, fh );
201+
fclose( fh );
174202

175-
programBlockSize = 5 + blockSize + data_coco_footer_bin_len;
176-
programBlocks = malloc( programBlockSize * blocks );
177-
memset( &programBlocks[0], 0, programBlockSize * blocks );
203+
if ( programDataCount ) {
204+
for( int i=0; i<programDataCount; ++i ) {
205+
206+
// The dat files will be loaded to a fixed position,
207+
// because they will be copied under ROM bank
208+
// using the LOADER.BAS.
209+
//
210+
// +------------+--------------....--------------+--------------+
211+
// | PREAMBLE | DATA | POSTAMBLE |
212+
// +------------+--------------....--------------+--------------+
213+
// |00|LEN |3000| .............................. |FF|00|00|00|00|
214+
// +------------+--------------....--------------+--------------+
215+
216+
sprintf( outputFileName, "%sprogram.%03d", temporaryPath, i);
217+
fh = fopen( outputFileName, "wb" );
218+
fputc( 0x00, fh );
219+
fputc( programDatsSize[i] >> 8, fh );
220+
fputc( programDatsSize[i] & 0xff, fh );
221+
fputc( 0x2a, fh );
222+
fputc( 0x00, fh );
223+
fwrite( programDats[i], 1, programDatsSize[i], fh );
224+
fputc( 0xff, fh );
225+
fputc( 0x00, fh );
226+
fputc( 0x00, fh );
227+
fputc( 0x00, fh );
228+
fputc( 0x00, fh );
229+
fclose( fh );
178230

179-
for( int block; block < blocks; ++block ) {
231+
}
232+
}
180233

181-
memcpy( &programBlocks[block * programBlockSize], &data_coco_header_bin[0], data_coco_header_bin_len );
234+
// Now we are going to create the BASIC loader.
182235

183-
if ( block < ( blocks - 1 ) ) {
184-
(void)!fread( &programBlocks[block * programBlockSize + data_coco_header_bin_len], 1, blockSize, fh );
185-
memcpy( &programBlocks[block * programBlockSize + data_coco_header_bin_len + blockSize], &data_coco_footer_bin[0], data_coco_footer_bin_len );
186-
} else {
187-
(void)!fread( &programBlocks[block * programBlockSize + data_coco_header_bin_len], 1, remainSize + 5, fh );
188-
programBlocks[block * programBlockSize + 1] = ( remainSize + 5 ) >> 8;
189-
programBlocks[block * programBlockSize + 2] = ( remainSize + 5 ) & 0xff;
190-
memcpy( &programBlocks[block * programBlockSize + data_coco_header_bin_len + remainSize + 5], &data_coco_footer_bin[0], data_coco_footer_bin_len );
191-
}
236+
char basFileName[MAX_TEMPORARY_STORAGE];
192237

193-
}
238+
// 206 16 0
194239

240+
sprintf( basFileName, "%sloader.bas", temporaryPath);
241+
fh = fopen( basFileName, "wb" );
242+
fprintf( fh, "1REM ugBASIC %s\n", UGBASIC_VERSION );
243+
fprintf( fh, "2DATA26,80,52,16,52,6,142,14,0,159,31,31\n" );
244+
fprintf( fh, "3DATA65,16,206,15,0,16,223,33,198,255,166\n" );
245+
fprintf( fh, "4DATA133,167,229,90,38,249,53,6,53,16,28\n" );
246+
fprintf( fh, "5DATA159,57,26,80,142,42,0,16,142,42,0\n" );
247+
fprintf( fh, "6DATA183,255,223,206,16,0,166,128,167,160\n" );
248+
fprintf( fh, "7DATA51,95,17,131,0,0,38,244,183,255,222\n" );
249+
fprintf( fh, "9DATA28,159,57\n" );
250+
fprintf( fh, "10FORA=&HE00 TO&HE44:READX:POKEA,X:NEXTA\n" );
251+
fprintf( fh, "11POKE27,12:POKE28,0:POKE29,12:POKE30,172\n");
252+
fprintf( fh, "12POKE31,13:POKE32,0:POKE33,13:POKE34,64:POKE35,13:POKE36,172\n" );
253+
fprintf( fh, "13POKE37,13:POKE38,172:POKE39,13:POKE40,250:EXEC3584:? \"WAIT\";\n" );
254+
for( int i=0; i<programDataCount; ++i ) {
255+
int lineNr = 14 + i*2;
256+
fprintf( fh, "%dLOADM\"P.%02d\":?\".\";\n", lineNr, i);
257+
lineNr = 15 + i*2;
258+
int address = 0x4d + i*32;
259+
int sizeHi = ( programDatsSize[i] >> 8 ) & 0xff;
260+
int sizeLo = ( programDatsSize[i] ) & 0xff;
261+
fprintf( fh, "%dPOKE3627,%d:POKE3633,%d:POKE3634,%d:EXEC3620\n", lineNr, address, sizeHi, sizeLo );
195262
}
196-
263+
fprintf( fh, "90?\"*\";:LOADM\"P.\":?\".\":EXEC10752\n" );
197264
fclose( fh );
198265

266+
// char executableName[MAX_TEMPORARY_STORAGE];
267+
// char listingFileName[MAX_TEMPORARY_STORAGE];
268+
char binaryName[MAX_TEMPORARY_STORAGE];
269+
// char originalFileName[MAX_TEMPORARY_STORAGE];
270+
271+
// int fileSize = 0;
272+
// int standardSize = 0;
273+
// int ondemandSize = 0;
274+
// int blockSize = 0;
275+
// int blocks = 0;
276+
// int block = 0;
277+
// int remainSize = 0;
278+
279+
char executableName[MAX_TEMPORARY_STORAGE];
280+
BUILD_TOOLCHAIN_DECB_GET_EXECUTABLE( _environment, executableName );
281+
282+
strcpy( binaryName, _environment->exeFileName );
283+
Storage * storage = _environment->storage;
199284
char buffer[MAX_TEMPORARY_STORAGE];
200285
if ( storage ) {
201286
char filemask[MAX_TEMPORARY_STORAGE];
@@ -230,51 +315,14 @@ void generate_dsk( Environment * _environment ) {
230315
_environment->exeFileName = strdup( binaryName );
231316
}
232317

318+
char commandLine[8*MAX_TEMPORARY_STORAGE];
233319
remove( _environment->exeFileName );
234320
sprintf( commandLine, "\"%s\" dskini \"%s\"", executableName, _environment->exeFileName );
235321
if ( system_call( _environment, commandLine ) ) {
236322
printf("The compilation of assembly program failed.\n\n");
237323
printf("Please use option '-I' to install chain tool.\n\n");
238324
};
239325

240-
char * loaderBas = malloc( MAX_TEMPORARY_STORAGE * 100 );
241-
242-
strcpy( loaderBas, "1 REM ugBASIC loader\n" );
243-
strcat( loaderBas, "2 REM --[ PROLOGUE ]--\n" );
244-
strcat( loaderBas, "3 DATA 26,80,52,16,52,6,142,14,0,159,31,31\n" );
245-
strcat( loaderBas, "4 DATA 65,16,206,15,0,16,223,33,198,255,166\n" );
246-
strcat( loaderBas, "5 DATA 133,167,229,90,38,249,53,6,53,16,28\n" );
247-
strcat( loaderBas, "6 DATA 159,57,26,80,142,42,0,16,142,42,0\n" );
248-
strcat( loaderBas, "7 DATA 183,255,223,206,16,0,166,128,167,160\n" );
249-
strcat( loaderBas, "8 DATA 51,95,17,131,0,0,38,244,183,255,222\n" );
250-
strcat( loaderBas, "9 DATA 28,159,57\n" );
251-
strcat( loaderBas, "11FORA=&HE00 TO &HE44:READX:POKEA,X:NEXTA\n" );
252-
strcat( loaderBas, "12REM --[ MAIN ]--\n" );
253-
strcat( loaderBas, "13CLEAR 999: PRINT \"LOADING, PLEASE WAIT\";\n" );
254-
255-
for( block = 0; block < blocks; ++block ) {
256-
257-
int lineNr = 14 + block*2;
258-
char line[MAX_TEMPORARY_STORAGE];
259-
sprintf( line, "%dLOADM\"PROGRAM.%03d\":PRINT\".\";\n", lineNr, block);
260-
strcat( loaderBas, line );
261-
262-
lineNr = 15 + block*2;
263-
int address = 128 + block*16;
264-
sprintf( line, "%dPOKE 3627, %d: EXEC 3620\n", lineNr, address);
265-
strcat( loaderBas, line );
266-
267-
}
268-
269-
strcat( loaderBas, "90EXEC 3584: PRINT \"...\";: LOADM\"PROGRAM.EXE\": PRINT \"...\": EXEC\n");
270-
271-
char basFileName[MAX_TEMPORARY_STORAGE];
272-
sprintf( basFileName, "%sloader.bas", temporaryPath );
273-
274-
fh = fopen( basFileName, "wb" );
275-
fwrite( loaderBas, 1, strlen(loaderBas), fh );
276-
fclose( fh );
277-
278326
sprintf( commandLine, "\"%s\" copy -0 -t \"%s\" \"%s,LOADER.BAS\"",
279327
executableName,
280328
basFileName,
@@ -286,44 +334,33 @@ void generate_dsk( Environment * _environment ) {
286334

287335
remove( basFileName );
288336

289-
char tempFileName[MAX_TEMPORARY_STORAGE];
290-
sprintf( tempFileName, "%sprogram.exe", temporaryPath );
291-
292-
fh = fopen( tempFileName, "wb" );
293-
fwrite( programExe, 1, programExeSize, fh );
294-
fclose( fh );
295-
296-
sprintf( commandLine, "\"%s\" copy -2 \"%s\" \"%s,PROGRAM.EXE\"",
337+
sprintf( commandLine, "\"%s\" copy -2 \"%sprogram.exe\" \"%s,P\"",
297338
executableName,
298-
tempFileName,
339+
temporaryPath,
299340
_environment->exeFileName );
300341
if ( system_call( _environment, commandLine ) ) {
301342
printf("The compilation of assembly program failed.\n\n");
302343
printf("Please use option '-I' to install chain tool.\n\n");
303344
};
304345

305-
remove( tempFileName );
306-
307-
for( block = 0; block < blocks; ++block ) {
308-
309-
sprintf( tempFileName, "%sprogram.%03d", temporaryPath, block );
310-
311-
fh = fopen( tempFileName, "wb" );
312-
fwrite( &programBlocks[block * programBlockSize], 1, ( block < ( blocks - 1 ) ) ? programBlockSize : ( remainSize + 15 ), fh );
313-
fclose( fh );
314-
315-
sprintf( commandLine, "\"%s\" copy -2 \"%s\" \"%s,PROGRAM.%03d\"",
316-
executableName,
317-
tempFileName,
318-
_environment->exeFileName,
319-
block );
320-
if ( system_call( _environment, commandLine ) ) {
321-
printf("The compilation of assembly program failed.\n\n");
322-
printf("Please use option '-I' to install chain tool.\n\n");
323-
};
324-
325-
// remove( tempFileName );
346+
sprintf( commandLine, "%sprogram.exe", temporaryPath);
347+
remove( commandLine );
326348

349+
if ( programDataCount ) {
350+
for( int i=0; i<programDataCount; ++i ) {
351+
sprintf( commandLine, "\"%s\" copy -2 \"%sprogram.%03d\" \"%s,P.%02d\"",
352+
executableName,
353+
temporaryPath,
354+
i,
355+
_environment->exeFileName,
356+
i );
357+
if ( system_call( _environment, commandLine ) ) {
358+
printf("The compilation of assembly program failed.\n\n");
359+
printf("Please use option '-I' to install chain tool.\n\n");
360+
};
361+
sprintf( commandLine, "%sprogram.%03d", temporaryPath, i);
362+
remove( commandLine );
363+
}
327364
}
328365

329366
if ( !storage ) {

0 commit comments

Comments
 (0)