ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
_build.c
Go to the documentation of this file.
1/*****************************************************************************
2 * ugBASIC - an isomorphic BASIC language compiler for retrocomputers *
3 *****************************************************************************
4 * Copyright 2021-2026 Marco Spedaletti (asimov@mclink.it)
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *----------------------------------------------------------------------------
18 * Concesso in licenza secondo i termini della Licenza Apache, versione 2.0
19 * (la "Licenza"); è proibito usare questo file se non in conformità alla
20 * Licenza. Una copia della Licenza è disponibile all'indirizzo:
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Se non richiesto dalla legislazione vigente o concordato per iscritto,
25 * il software distribuito nei termini della Licenza è distribuito
26 * "COSÌ COM'È", SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO, esplicite o
27 * implicite. Consultare la Licenza per il testo specifico che regola le
28 * autorizzazioni e le limitazioni previste dalla medesima.
29 ****************************************************************************/
30
31/****************************************************************************
32 * INCLUDE SECTION
33 ****************************************************************************/
34
35#include "../../ugbc.h"
36
37#include <errno.h>
38#include <sys/stat.h>
39#include <sys/types.h>
40
41/****************************************************************************
42 * CODE SECTION
43 ****************************************************************************/
44
45extern char OUTPUT_FILE_TYPE_AS_STRING[][16];
46
47void generate_bin( Environment * _environment ) {
48
49 char commandLine[8*MAX_TEMPORARY_STORAGE];
50 char executableName[MAX_TEMPORARY_STORAGE];
51 char binaryName[MAX_TEMPORARY_STORAGE];
52 char listingFileName[MAX_TEMPORARY_STORAGE];
53
54 BUILD_SAFE_REMOVE( _environment, _environment->exeFileName );
55
56 BUILD_TOOLCHAIN_Z88DK_GET_EXECUTABLE_Z80ASM( _environment, executableName );
57
58 BUILD_TOOLCHAIN_Z88DK_GET_LISTING_FILE( _environment, listingFileName );
59
60 BUILD_TOOLCHAIN_Z88DK_EXEC( _environment, "msx1", executableName, listingFileName, "z80" );
61
62 char * p;
63
64 if ( _environment->listingFileName ) {
65 strcopy( binaryName, _environment->asmFileName );
66 p = strstr( binaryName, ".asm" );
67 if ( p ) {
68 *(p+1) = 'l';
69 *(p+2) = 'i';
70 *(p+3) = 's';
71 *(p+4) = 0;
72 }
73 TRACE2( " renaming %s to %s", binaryName, _environment->listingFileName );
74 BUILD_SAFE_MOVE( _environment, binaryName, _environment->listingFileName );
75 }
76
77 strcopy( binaryName, _environment->asmFileName );
78 p = strstr( binaryName, ".asm" );
79 if ( p ) {
80 *(p+1) = 'o';
81 *(p+2) = 0;
82 }
83 system_remove_safe( _environment, binaryName );
84
85 strcopy( binaryName, _environment->asmFileName );
86 p = strstr( binaryName, ".asm" );
87 if ( p ) {
88 *p = 0;
89 --p;
90 strcat( p, "_code_user.bin");
91 }
92
93 FILE * binaryFile = fopen( binaryName, "rb" );
94 fseek( binaryFile, 0, SEEK_END );
95 long size = ftell( binaryFile );
96 fseek( binaryFile, 0, SEEK_SET );
97 char * part = malloc( size );
98 (void)!fread( part, size, 1, binaryFile );
99 fclose( binaryFile );
100
101 strcopy( binaryName, _environment->asmFileName );
102 p = strstr( binaryName, ".asm" );
103 if ( p ) {
104 *p = 0;
105 --p;
106 strcat( p, ".bin");
107 }
108
109 binaryFile = fopen( binaryName, "wb" );
110 fwrite( part, size, 1, binaryFile );
111 fclose( binaryFile );
112
113 strcopy( binaryName, _environment->asmFileName );
114 p = strstr( binaryName, ".asm" );
115 if ( p ) {
116 *p = 0;
117 --p;
118 strcat( p, "_data_user.bin");
119 }
120
121 binaryFile = fopen( binaryName, "rb" );
122 fseek( binaryFile, 0, SEEK_END );
123 size = ftell( binaryFile );
124 fseek( binaryFile, 0, SEEK_SET );
125 part = malloc( size );
126 (void)!fread( part, size, 1, binaryFile );
127 fclose( binaryFile );
128
129 strcopy( binaryName, _environment->asmFileName );
130 p = strstr( binaryName, ".asm" );
131 if ( p ) {
132 *p = 0;
133 --p;
134 strcat( p, ".bin");
135 }
136
137 binaryFile = fopen( binaryName, "a+b" );
138 fwrite( part, size, 1, binaryFile );
139 fclose( binaryFile );
140
141 BUILD_TOOLCHAIN_Z88DK_GET_EXECUTABLE_APPMAKE( _environment, executableName );
142
143 char pipes[256];
144
145 #ifdef _WIN32
146 strcopy( pipes, ">nul 2>nul");
147 #else
148 strcopy( pipes, ">/dev/null 2>/dev/null");
149 #endif
150
151 strcopy( binaryName, _environment->asmFileName );
152 p = strstr( binaryName, ".asm" );
153 if ( p ) {
154 strcat( p, "_data_user.bin");
155 }
156 remove(binaryName);
157
158 strcopy( binaryName, _environment->asmFileName );
159 p = strstr( binaryName, ".asm" );
160 if ( p ) {
161 strcat( p, "_code_user.bin");
162 }
163 remove(binaryName);
164
165}
166
167void generate_rom( Environment * _environment ) {
168
169 char commandLine[8*MAX_TEMPORARY_STORAGE];
170 char executableName[MAX_TEMPORARY_STORAGE];
171 char binaryName[MAX_TEMPORARY_STORAGE];
172 char bankName[MAX_TEMPORARY_STORAGE];
173 char listingFileName[MAX_TEMPORARY_STORAGE];
174
175 char * p;
176
177 strcopy( binaryName, _environment->asmFileName );
178 p = strstr( binaryName, ".asm" );
179 if ( p ) {
180 *p = 0;
181 --p;
182 strcat( p, ".bin");
183 }
184
185 int binaryFileSize = file_get_size( _environment, binaryName );
186 if ( binaryFileSize > 32768 ) {
187 CRITICAL_BINARY_FILE_TOO_BIG_FOR_ROM( binaryFileSize - 32768 );
188 }
189 if ( binaryFileSize < 16384 ) {
190 FILE * fh = fopen( binaryName, "ab" );
191 while( binaryFileSize < 0x8000 ) {
192 fputc( 0xFF, fh );
193 ++binaryFileSize;
194 }
195 fclose(fh);
196 }
197
198 Bank * bank = _environment->expansionBanks;
199 int bankId = 2;
200 while( bank ) {
201 Bank * bank2 = bank->next;
202 strcopy( bankName, _environment->asmFileName );
203 p = strstr( bankName, ".asm" );
204 if ( p ) {
205 *p = 0;
206 }
207 char temp[MAX_TEMPORARY_STORAGE];
208 sprintf(temp, "%s_BANK_%02X.bin", bankName, bankId );
209 strcpy( bankName, temp );
210 int bankSize = bank->space;
211 FILE * fh = fopen( bankName, "wb" );
212 fwrite( bank->data, 1, bankSize, fh );
213 fwrite( bank2->data, 1, bankSize, fh );
214 fclose( fh );
215 bank = bank2->next;
216 ++bankId;
217 }
218 if ( _environment->outputGeneratedFiles ) {
219 printf( "%s\n", _environment->exeFileName );
220 }
221
222 BUILD_TOOLCHAIN_Z88DK_GET_EXECUTABLE_APPMAKE( _environment, executableName );
223
224 char pipes[256];
225
226 #ifdef _WIN32
227 strcopy( pipes, ">nul 2>nul");
228 #else
229 strcopy( pipes, ">/dev/null 2>/dev/null");
230 #endif
231
232 sprintf( commandLine, "\"%s\" +msxrom -b \"%s\" %s",
233 executableName,
234 binaryName,
235 pipes );
236
237 p = strstr( binaryName, ".bin" );
238 if ( p ) {
239 *(p+1) = 'r';
240 *(p+2) = 'o';
241 *(p+3) = 'm';
242 }
243
244 if ( system_call( _environment, commandLine ) ) {
245 printf("The compilation of assembly program failed.\n\n");
246 printf("Please use option '-I' to install chain tool.\n\n");
247 return;
248 };
249
250 remove( _environment->exeFileName );
251
252 BUILD_SAFE_MOVE( _environment, binaryName, _environment->exeFileName );
253
254 char symbolName[MAX_TEMPORARY_STORAGE];
255 strcopy( symbolName, _environment->exeFileName );
256 p = strstr( symbolName, ".rom" );
257 if ( p ) {
258 *p = 0;
259 --p;
260 strcat( p, ".sym");
261
262 strcopy( binaryName, _environment->asmFileName );
263 p = strstr( binaryName, ".asm" );
264 if ( p ) {
265 *p = 0;
266 --p;
267 strcat( p, ".sym");
268 BUILD_SAFE_MOVE( _environment, binaryName, symbolName );
269 }
270 }
271
272 if ( _environment->listingFileName ) {
273 strcopy( binaryName, _environment->asmFileName );
274 p = strstr( binaryName, ".asm" );
275 if ( p ) {
276 *p = 0;
277 --p;
278 strcat( p, ".lis");
279 BUILD_SAFE_MOVE( _environment, binaryName, _environment->listingFileName );
280 }
281
282 if ( _environment->profileFileName && _environment->profileCycles ) {
283 strcopy( binaryName, _environment->profileFileName );
284 if ( _environment->executerFileName ) {
285 sprintf(executableName, "%s", _environment->executerFileName );
286 } else if( access( "runz80.exe", F_OK ) == 0 ) {
287 sprintf(executableName, "%s", "runz80.exe" );
288 } else {
289 sprintf(executableName, "%s", "runz80" );
290 }
291
292 sprintf( commandLine, "\"%s\" -m -p \"%s\" %d -l 4000 \"%s\" -R 4010 -u \"%s\" \"%s\"",
293 executableName,
294 binaryName,
295 _environment->profileCycles ? _environment->profileCycles : 1000000,
296 _environment->exeFileName,
297 _environment->listingFileName,
298 pipes );
299
300 if ( system_call( _environment, commandLine ) ) {
301 printf("The profiling of assembly program failed.\n\n");
302 return;
303 };
304
305 }
306
307 }
308
309 strcopy( binaryName, _environment->asmFileName );
310 p = strstr( binaryName, ".asm" );
311 if ( p ) {
312 strcat( p, "_data_user.bin");
313 }
314 remove(binaryName);
315
316 strcopy( binaryName, _environment->asmFileName );
317 p = strstr( binaryName, ".asm" );
318 if ( p ) {
319 strcat( p, "_code_user.bin");
320 }
321 remove(binaryName);
322
323}
324
325void generate_dsk( Environment * _environment ) {
326
327 Storage * storage = _environment->storage;
328
329 char pipes[256];
330
331 #ifdef _WIN32
332 strcopy( pipes, ">nul 2>nul");
333 #else
334 strcopy( pipes, ">/dev/null 2>/dev/null");
335 #endif
336
337 char temporaryPath[MAX_TEMPORARY_STORAGE];
338 strcopy( temporaryPath, _environment->temporaryPath );
339 strcat( temporaryPath, " " );
340 temporaryPath[strlen(temporaryPath)-1] = PATH_SEPARATOR;
341 strcat( temporaryPath, "dsk" );
342#ifdef _WIN32
343 mkdir( temporaryPath );
344#else
345 mkdir( temporaryPath, 0777 );
346#endif
347 strcat( temporaryPath, " " );
348 temporaryPath[strlen(temporaryPath)-1] = PATH_SEPARATOR;
349
350 char commandLine[8*MAX_TEMPORARY_STORAGE];
351 char executableName[MAX_TEMPORARY_STORAGE];
352 char binaryName[MAX_TEMPORARY_STORAGE];
353 char binaryName2[MAX_TEMPORARY_STORAGE];
354 char listingFileName[MAX_TEMPORARY_STORAGE];
355 char diskToolsExecutableName[MAX_TEMPORARY_STORAGE];
356
357 #ifdef _WIN32
358 sprintf( commandLine, "del /f /q %s*.* %s", temporaryPath, pipes );
359 #else
360 sprintf( commandLine, "rm %s* %s", temporaryPath, pipes );
361 #endif
362 system_call( _environment, commandLine );
363
364 char * p;
365
366 strcopy( binaryName, _environment->asmFileName );
367 p = strstr( binaryName, ".asm" );
368 if ( p ) {
369 *p = 0;
370 --p;
371 strcat( p, ".bin");
372 }
373
374 strcopy( binaryName2, _environment->asmFileName );
375 p = strstr( binaryName2, ".asm" );
376 if ( p ) {
377 *p = 0;
378 --p;
379 strcat( p, ".bi2");
380 }
381
382 BUILD_TOOLCHAIN_Z88DK_GET_EXECUTABLE_APPMAKE( _environment, executableName );
383
384 sprintf( commandLine, "\"%s\" +msx -b \"%s\" -o \"%s\" --org 33024 %s",
385 executableName,
386 binaryName,
387 binaryName2,
388 pipes );
389 if ( system_call( _environment, commandLine ) ) {
390 printf("The compilation of assembly program failed.\n\n");
391 printf("Please use option '-I' to install chain tool.\n\n");
392 return;
393 };
394
395 remove( binaryName );
396
397 strcopy( binaryName, _environment->exeFileName );
398 p = strstr( binaryName, ".dsk" );
399 if ( p ) {
400 *p = 0;
401 --p;
402 strcat( p, ".bin");
403 }
404
405 BUILD_SAFE_MOVE( _environment, binaryName2, binaryName );
406
407 BUILD_TOOLCHAIN_DSKTOOLS_GET_EXECUTABLE( _environment, diskToolsExecutableName );
408
409 if ( !storage ) {
410
411 sprintf( commandLine, "\"%s\" \"%s\" \"%s\" %s",
412 diskToolsExecutableName,
413 _environment->exeFileName,
414 binaryName,
415 pipes );
416 if ( system_call( _environment, commandLine ) ) {
417 printf("The compilation of assembly program failed.\n\n");
418 printf("Please use option '-I' to install chain tool.\n\n");
419 return;
420 };
421
422 if ( _environment->outputGeneratedFiles ) {
423 printf( "%s\n", _environment->exeFileName );
424 }
425
426 } else {
427
428 char diskName[MAX_TEMPORARY_STORAGE];
429 char buffer[MAX_TEMPORARY_STORAGE];
430 char filemask[MAX_TEMPORARY_STORAGE];
431 strcopy( filemask, _environment->exeFileName );
432 char * basePath = find_last_path_separator( filemask );
433 if ( basePath ) {
434 ++basePath;
435 *basePath = 0;
436 if ( storage->fileName ) {
437 strcat( basePath, storage->fileName );
438 } else {
439 strcat( basePath, "disk%d.dsk" );
440 }
441 } else {
442 if ( storage->fileName ) {
443 strcopy( filemask, storage->fileName );
444 } else {
445 strcopy( filemask, "disk%d.dsk" );
446 }
447 }
448 sprintf( diskName, filemask, 0 );
449 if ( !strstr( diskName, ".dsk" ) ) {
450 strcat( diskName, ".dsk" );
451 }
452
453 int i=0;
454 char * additionalFiles = NULL;
455 while( storage ) {
456 additionalFiles = NULL;
457 FileStorage * fileStorage = storage->files;
458 while( fileStorage ) {
459 int size;
460 char * buffer;
461
462 if ( fileStorage->content && fileStorage->size ) {
463 size = fileStorage->size;
464 buffer = malloc( size );
465 memset( buffer, 0, size );
466 memcpy( buffer, fileStorage->content, fileStorage->size );
467 } else {
468 FILE * file = fopen( fileStorage->sourceName, "rb" );
469 if ( !file ) {
471 }
472 fseek( file, 0, SEEK_END );
473 size = ftell( file );
474 fseek( file, 0, SEEK_SET );
475 buffer = malloc( size );
476 memset( buffer, 0, size );
477 (void)!fread( buffer, size, 1, file );
478 fclose( file );
479 }
480 char dataFilename[MAX_TEMPORARY_STORAGE];
481 sprintf( dataFilename, "%s%s", temporaryPath, fileStorage->targetName );
482 FILE * fileOut = fopen( dataFilename, "wb" );
483 if ( fileOut ) {
484 fwrite( buffer, 1, size, fileOut );
485 fclose(fileOut );
486 }
487 if ( additionalFiles ) {
488 additionalFiles = realloc( additionalFiles, strlen(additionalFiles) + strlen( dataFilename ) + 3 );
489 strcat( additionalFiles, " " );
490 strcat( additionalFiles, dataFilename );
491 } else {
492 additionalFiles = strdup( dataFilename );
493 }
494 fileStorage = fileStorage->next;
495 }
496
497 sprintf( commandLine, "\"%s\" \"%s\" \"%s\" %s %s",
498 diskToolsExecutableName,
499 diskName,
500 binaryName,
501 additionalFiles,
502 pipes );
503 if ( system_call( _environment, commandLine ) ) {
504 printf("The compilation of assembly program failed.\n\n");
505 printf("Please use option '-I' to install chain tool.\n\n");
506 return;
507 };
508
509 if ( _environment->outputGeneratedFiles ) {
510 printf( "%s\n", diskName );
511 }
512
513 storage = storage->next;
514 ++i;
515
516 if ( storage ) {
517 strcopy( filemask, _environment->exeFileName );
518 char * basePath = find_last_path_separator( filemask );
519 if ( basePath ) {
520 ++basePath;
521 *basePath = 0;
522 if ( storage->fileName ) {
523 strcat( basePath, storage->fileName );
524 } else {
525 strcat( basePath, "disk%d.dsk" );
526 }
527 } else {
528 if ( storage->fileName ) {
529 strcopy( filemask, storage->fileName );
530 } else {
531 strcopy( filemask, "disk%d.dsk" );
532 }
533 }
534 sprintf( diskName, filemask, i );
535 if ( !strstr( diskName, ".dsk" ) ) {
536 strcat( diskName, ".dsk" );
537 }
538
539 #ifdef _WIN32
540 sprintf( commandLine, "del /f /q %s*.* %s", temporaryPath, pipes );
541 #else
542 sprintf( commandLine, "rm %s* %s", temporaryPath, pipes );
543 #endif
544 system_call( _environment, commandLine );
545
546 }
547
548 }
549
550 }
551
552 remove( binaryName );
553
554}
555
556void target_linkage( Environment * _environment ) {
557
558 switch( _environment->outputFileType ) {
560 generate_bin( _environment );
561 generate_rom( _environment );
562 break;
564 generate_bin( _environment );
565 generate_dsk( _environment );
566 break;
567 default:
569 }
570
571}
572
573void target_cleanup( Environment * _environment ) {
574
575 if ( _environment->exeFileName ) {
576
577 char binFileName[MAX_TEMPORARY_STORAGE];
578
579 // strcopy( binFileName, _environment->exeFileName );
580 // char * p = strrchr( binFileName, '.' );
581 // memcpy( p, ".bin", 4 );
582
583 remove( _environment->configurationFileName );
584 // remove( binFileName );
585 remove( _environment->asmFileName );
586
587 if ( _environment->analysis && _environment->listingFileName ) {
588 target_analysis( _environment );
589 }
590
591 }
592
593}
int system_call(Environment *_environment, char *_commandline)
Call an external executable.
char * find_last_path_separator(char *_path)
int system_remove_safe(Environment *_environment, char *_filename)
int file_get_size(Environment *_environment, char *_filename)
void target_linkage(Environment *_environment)
Convert C64's assembly to executable.
Definition _build.c:327
void target_cleanup(Environment *_environment)
Definition _build.c:343
void target_analysis(Environment *_environment)
Definition _cleanup.c:68
int size
Definition _optimizer.c:678
void generate_dsk(Environment *_environment)
Definition _build.c:100
void generate_bin(Environment *_environment)
Definition _build.c:43
void generate_rom(Environment *_environment)
Definition _build.c:167
struct _Bank * next
Definition ugbc.h:185
char * data
Definition ugbc.h:177
int space
Definition ugbc.h:168
Storage * storage
Definition ugbc.h:2526
char * listingFileName
Definition ugbc.h:2305
char * temporaryPath
Definition ugbc.h:2360
int analysis
Definition ugbc.h:2365
char * configurationFileName
Definition ugbc.h:2295
char * executerFileName
Definition ugbc.h:2315
OutputFileType outputFileType
Definition ugbc.h:2452
Bank * expansionBanks
Definition ugbc.h:3005
int outputGeneratedFiles
Definition ugbc.h:3173
char * profileFileName
Definition ugbc.h:2310
char * asmFileName
Definition ugbc.h:2285
int profileCycles
Definition ugbc.h:2375
char * exeFileName
Definition ugbc.h:2290
char * targetName
Definition ugbc.h:201
int size
Definition ugbc.h:204
char * sourceName
Definition ugbc.h:198
char * content
Definition ugbc.h:210
struct _FileStorage * next
Definition ugbc.h:213
FileStorage * files
Definition ugbc.h:232
char * fileName
Definition ugbc.h:229
struct _Storage * next
Definition ugbc.h:235
void * malloc(YYSIZE_T)
@ OUTPUT_FILE_TYPE_ROM
Definition ugbc.h:265
@ OUTPUT_FILE_TYPE_DSK
Definition ugbc.h:267
#define BUILD_SAFE_REMOVE(_environment, filename)
Definition ugbc.h:4748
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define PATH_SEPARATOR
Definition ugbc.h:69
#define CRITICAL_DLOAD_MISSING_FILE(f)
Definition ugbc.h:3578
#define BUILD_TOOLCHAIN_Z88DK_GET_LISTING_FILE(_environment, listingFileName)
Definition ugbc.h:4810
#define BUILD_TOOLCHAIN_DSKTOOLS_GET_EXECUTABLE(_environment, executableName)
Definition ugbc.h:4945
struct _Environment Environment
Structure of compilation environment.
#define BUILD_TOOLCHAIN_Z88DK_GET_EXECUTABLE_Z80ASM(_environment, executableName)
Definition ugbc.h:4795
struct _Storage Storage
Structure of a single storage.
#define CRITICAL_BINARY_FILE_TOO_BIG_FOR_ROM(s)
Definition ugbc.h:3870
struct _FileStorage FileStorage
Structure of a single file inside a storage.
#define BUILD_SAFE_MOVE(_environment, source, destination)
Definition ugbc.h:4751
struct _Bank Bank
Structure of a single bank.
#define TRACE2(s, p1, p2)
Definition ugbc.h:88
#define BUILD_TOOLCHAIN_Z88DK_EXEC(_environment, target, executableName, listingFileName, cpu)
Definition ugbc.h:4818
#define CRITICAL_UNSUPPORTED_OUTPUT_FILE_TYPE(t)
Definition ugbc.h:3537
#define BUILD_TOOLCHAIN_Z88DK_GET_EXECUTABLE_APPMAKE(_environment, executableName)
Definition ugbc.h:4840
char OUTPUT_FILE_TYPE_AS_STRING[][16]
char * strcopy(char *_dest, char *_source)