38
38
* CODE SECTION
39
39
****************************************************************************/
40
40
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
+
41
46
extern char OUTPUT_FILE_TYPE_AS_STRING [][16 ];
42
47
43
48
void generate_bin ( Environment * _environment ) {
@@ -94,108 +99,188 @@ void generate_bin( Environment * _environment ) {
94
99
95
100
void generate_dsk ( Environment * _environment ) {
96
101
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.
97
105
char originalBinaryFile [MAX_TEMPORARY_STORAGE ];
98
-
99
106
strcpy ( originalBinaryFile , _environment -> exeFileName );
100
107
char * p = strstr ( originalBinaryFile , ".dsk" );
101
108
if ( p ) {
102
109
strcpy ( p , ".bin" );
103
110
}
104
111
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 ;
131
115
if ( fh ) {
132
116
fseek ( fh , 0 , SEEK_END );
133
- fileSize = ftell ( fh );
117
+ executableBinaryFileSize = ftell ( fh );
134
118
fclose ( fh );
135
119
} else {
136
120
CRITICAL ( "cannot create dsk file" );
137
121
}
138
122
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 );
148
137
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 );
154
141
142
+ int programExeSize = 0x4d00 - _environment -> program .startingAddress ;
143
+ if ( executableBinaryFileSize < programExeSize ) {
144
+ programExeSize = executableBinaryFileSize ;
155
145
}
156
-
157
- int programExeSize = 5 + standardSize + data_coco_footer_bin_len ;
158
-
159
146
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
+ }
169
170
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 ;
172
175
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 );
174
202
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 );
178
230
179
- for ( int block ; block < blocks ; ++ block ) {
231
+ }
232
+ }
180
233
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.
182
235
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 ];
192
237
193
- }
238
+ // 206 16 0
194
239
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 );
195
262
}
196
-
263
+ fprintf ( fh , "90?\"*\";:LOADM\"P.\":?\".\":EXEC10752\n" );
197
264
fclose ( fh );
198
265
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 ;
199
284
char buffer [MAX_TEMPORARY_STORAGE ];
200
285
if ( storage ) {
201
286
char filemask [MAX_TEMPORARY_STORAGE ];
@@ -230,51 +315,14 @@ void generate_dsk( Environment * _environment ) {
230
315
_environment -> exeFileName = strdup ( binaryName );
231
316
}
232
317
318
+ char commandLine [8 * MAX_TEMPORARY_STORAGE ];
233
319
remove ( _environment -> exeFileName );
234
320
sprintf ( commandLine , "\"%s\" dskini \"%s\"" , executableName , _environment -> exeFileName );
235
321
if ( system_call ( _environment , commandLine ) ) {
236
322
printf ("The compilation of assembly program failed.\n\n" );
237
323
printf ("Please use option '-I' to install chain tool.\n\n" );
238
324
};
239
325
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
-
278
326
sprintf ( commandLine , "\"%s\" copy -0 -t \"%s\" \"%s,LOADER.BAS\"" ,
279
327
executableName ,
280
328
basFileName ,
@@ -286,44 +334,33 @@ void generate_dsk( Environment * _environment ) {
286
334
287
335
remove ( basFileName );
288
336
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\"" ,
297
338
executableName ,
298
- tempFileName ,
339
+ temporaryPath ,
299
340
_environment -> exeFileName );
300
341
if ( system_call ( _environment , commandLine ) ) {
301
342
printf ("The compilation of assembly program failed.\n\n" );
302
343
printf ("Please use option '-I' to install chain tool.\n\n" );
303
344
};
304
345
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 );
326
348
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
+ }
327
364
}
328
365
329
366
if ( !storage ) {
0 commit comments