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/****************************************************************************
38 * CODE SECTION
39 ****************************************************************************/
40
41extern char OUTPUT_FILE_TYPE_AS_STRING[][16];
42
43void generate_prg( Environment * _environment ) {
44
45 char commandLine[8*MAX_TEMPORARY_STORAGE];
46 char executableName[MAX_TEMPORARY_STORAGE];
47 char listingFileName[MAX_TEMPORARY_STORAGE];
48
49 BUILD_SAFE_REMOVE( _environment, _environment->exeFileName );
50
51 BUILD_TOOLCHAIN_CC65_GET_EXECUTABLE( _environment, executableName );
52
53 BUILD_TOOLCHAIN_CC65_GET_LISTING_FILE( _environment, listingFileName );
54
55 BUILD_TOOLCHAIN_CC65_EXEC( _environment, "c64", executableName, listingFileName, "" );
56
57 char objectFileName[MAX_TEMPORARY_STORAGE];
58 strcopy( objectFileName, _environment->asmFileName );
59 char * p = strstr(objectFileName, ".asm");
60 if ( p ) {
61 strcopy( p, ".o" );
62 remove( objectFileName );
63 }
64
65 if ( _environment->listingFileName ) {
66
67 if ( _environment->profileFileName && _environment->profileCycles ) {
68 if ( _environment->executerFileName ) {
69 sprintf(executableName, "%s", _environment->executerFileName );
70 } else if( access( "run6502.exe", F_OK ) == 0 ) {
71 sprintf(executableName, "%s", "run6502.exe" );
72 } else {
73 sprintf(executableName, "%s", "run6502" );
74 }
75
76 sprintf( commandLine, "\"%s\" -X 0000 -R 080d -l 07ff \"%s\" -u \"%s\" -p \"%s\" %d",
77 executableName,
78 _environment->exeFileName,
79 _environment->listingFileName,
80 _environment->profileFileName,
81 _environment->profileCycles ? _environment->profileCycles : 1000000
82 );
83
84 if ( system_call( _environment, commandLine ) ) {
85 printf("The profiling of assembly program failed.\n\n");
86 return;
87 };
88
89 }
90
91 }
92
93}
94
95void generate_d64( Environment * _environment ) {
96
97 char * exeFileName = strdup( _environment->exeFileName );
98 char * extension = strstr( exeFileName, ".d64" );
99 if ( extension ) {
100 * extension = 0;
101 }
102
103 FILE * prgHandle = fopen(_environment->exeFileName, "rb");
104 if ( ! prgHandle ) {
106 }
107 fseek( prgHandle, 0, SEEK_END );
108 int prgSize = ftell( prgHandle );
109 fseek( prgHandle, 0, SEEK_SET );
110 unsigned char * prgContent = malloc( prgSize );
111 (void)!fread( prgContent, prgSize, 1, prgHandle );
112 fclose( prgHandle );
113
114 remove(_environment->exeFileName);
115
116 int diskNumber = 1;
117
118 D64Handle * handle = NULL;
119
120 Storage * storage = _environment->storage;
121
122 if ( !storage ) {
123 char * storageFileName = generate_storage_filename( _environment, exeFileName, "d64", diskNumber );
124
125 handle = d64_create( CBMDOS );
126 d64_write_file( handle, "MAIN", FT_PRG, prgContent, prgSize );
127 Bank * bank = _environment->expansionBanks;
128 while( bank ) {
129 int bankSize = bank->space - bank->remains;
130 if ( bank->remains < bank->space ) {
131 int endOfDisk = ( d64_get_free_sectors( handle ) * 256 ) < bankSize;
132 if ( ! endOfDisk ) {
133 char bankFileName[MAX_TEMPORARY_STORAGE];
134 sprintf( bankFileName, "BANK%d", bank->id );
135 endOfDisk = !d64_write_file( handle, bankFileName, FT_SEQ, bank->data, bankSize );
136 }
137 if ( endOfDisk ) {
138 d64_output( handle, storageFileName );
139 d64_free( handle );
140 if ( _environment->outputGeneratedFiles ) {
141 printf( "%s\n", storageFileName );
142 }
143 ++diskNumber;
144 storageFileName = generate_storage_filename( _environment, exeFileName, "d64", diskNumber );
145 handle = d64_create( CBMDOS );
146 } else {
147 bank = bank->next;
148 }
149 } else {
150 bank = bank->next;
151 }
152 }
153 d64_output( handle, storageFileName );
154 d64_free( handle );
155 if ( _environment->outputGeneratedFiles ) {
156 printf( "%s\n", storageFileName );
157 }
158
159 } else {
160
161 char buffer[MAX_TEMPORARY_STORAGE];
162 char filemask[MAX_TEMPORARY_STORAGE];
163 strcopy( filemask, exeFileName );
164 char * basePath = find_last_path_separator( filemask );
165 if ( basePath ) {
166 ++basePath;
167 *basePath = 0;
168 if ( storage->fileName ) {
169 strcat( basePath, storage->fileName );
170 } else {
171 strcat( basePath, "disk" );
172 }
173 } else {
174 if ( storage->fileName ) {
175 strcopy( filemask, storage->fileName );
176 } else {
177 strcopy( filemask, "disk" );
178 }
179 }
180
181 char * storageFileName = generate_storage_filename( _environment, filemask, "d64", diskNumber );
182
183 int i=0;
184 while( storage ) {
185 handle = d64_create( CBMDOS );
186 if ( i == 0 ) {
187 d64_write_file( handle, "MAIN", FT_PRG, prgContent, prgSize );
188 }
189 FileStorage * fileStorage = storage->files;
190 while( fileStorage ) {
191 int size;
192 char * buffer;
193 if ( fileStorage->content && fileStorage->size ) {
194 size = fileStorage->size + 2;
195 buffer = malloc( size );
196 memset( buffer, 0, size );
197 memcpy( &buffer[2], fileStorage->content, fileStorage->size );
198 } else {
199 FILE * file = fopen( fileStorage->sourceName, "rb" );
200 if ( !file ) {
202 }
203 fseek( file, 0, SEEK_END );
204 size = ftell( file );
205 fseek( file, 0, SEEK_SET );
206 buffer = malloc( size + 2 );
207 memset( buffer, 0, size + 2 );
208 (void)!fread( &buffer[2], size, 1, file );
209 fclose( file );
210 size += 2;
211 }
212 d64_write_file( handle, fileStorage->targetName, FT_PRG, buffer, size );
213 fileStorage = fileStorage->next;
214 }
215 d64_output( handle, storageFileName );
216 d64_free( handle );
217 handle = NULL;
218 if ( _environment->outputGeneratedFiles ) {
219 printf( "%s\n", storageFileName );
220 }
221
222 ++diskNumber;
223
224 strcopy( filemask, exeFileName );
225 char * basePath = find_last_path_separator( filemask );
226 if ( basePath ) {
227 ++basePath;
228 *basePath = 0;
229 if ( storage->fileName ) {
230 strcat( basePath, storage->fileName );
231 } else {
232 strcat( basePath, "disk" );
233 }
234 } else {
235 if ( storage->fileName ) {
236 strcopy( filemask, storage->fileName );
237 } else {
238 strcopy( filemask, "disk" );
239 }
240 }
241 storageFileName = generate_storage_filename( _environment, filemask, "d64", diskNumber );
242 storage = storage->next;
243 ++i;
244 }
245
246 Bank * bank = _environment->expansionBanks;
247 if ( bank && ! handle ) {
248 handle = d64_create( CBMDOS );
249 }
250 while( bank ) {
251 int bankSize = bank->space - bank->remains;
252 if ( ( d64_get_free_sectors( handle ) * 256 ) < bankSize ) {
253 d64_output( handle, storageFileName );
254 d64_free( handle );
255 if ( _environment->outputGeneratedFiles ) {
256 printf( "%s\n", storageFileName );
257 }
258 ++diskNumber;
259 storageFileName = generate_storage_filename( _environment, filemask, "d64", diskNumber );
260 handle = d64_create( CBMDOS );
261 }
262 if ( bank->remains < bank->space ) {
263 char bankFileName[MAX_TEMPORARY_STORAGE];
264 sprintf( bankFileName, "BANK%d", bank->id );
265 d64_write_file( handle, bankFileName, FT_SEQ, bank->data, bank->space - bank->remains );
266 }
267 bank = bank->next;
268 }
269 d64_output( handle, storageFileName );
270 d64_free( handle );
271 if ( _environment->outputGeneratedFiles ) {
272 printf( "%s\n", storageFileName );
273 }
274
275 }
276
277}
278
279void generate_reu( Environment * _environment ) {
280
281 FILE * prgHandle = fopen(_environment->exeFileName, "rb");
282 fseek( prgHandle, 0, SEEK_END );
283 int prgSize = ftell( prgHandle );
284 fseek( prgHandle, 0, SEEK_SET );
285 unsigned char * prgContent = malloc( prgSize );
286 (void)!fread( prgContent, prgSize, 1, prgHandle );
287 fclose( prgHandle );
288
289 remove(_environment->exeFileName);
290
291 char * exeFileName = strdup( _environment->exeFileName );
292 char * extension = strstr( exeFileName, ".reu" );
293 if ( extension ) {
294 * extension = 0;
295 }
296 int diskNumber = 1;
297
298 D64Handle * handle = NULL;
299
300 Storage * storage = _environment->storage;
301
302 if ( !storage ) {
303 char * storageFileName = generate_storage_filename( _environment, exeFileName, "d64", diskNumber );
304 FILE * reuHandle = fopen( _environment->exeFileName, "wb" );
305 for( int i=0; i<_environment->ramSize * 1024; ++i ) {
306 fputc( 0, reuHandle );
307 }
308 fseek( reuHandle, 0, SEEK_SET );
309 handle = d64_create( CBMDOS );
310 d64_write_file( handle, "MAIN", FT_PRG, prgContent, prgSize );
311 Bank * bank = _environment->expansionBanks;
312 while( bank ) {
313 if ( bank->remains < bank->space ) {
314 int bankSize = bank->space - bank->remains;
315 fseek( reuHandle, bank->id * bank->space, SEEK_SET );
316 fwrite( bank->data, 1, bankSize, reuHandle );
317 }
318 bank = bank->next;
319 }
320 d64_output( handle, storageFileName );
321 d64_free( handle );
322 if ( _environment->outputGeneratedFiles ) {
323 printf( "%s\n", storageFileName );
324 }
325 fclose( reuHandle );
326 if ( _environment->outputGeneratedFiles ) {
327 printf( "%s\n", _environment->exeFileName );
328 }
329 } else {
330 char buffer[MAX_TEMPORARY_STORAGE];
331 char filemask[MAX_TEMPORARY_STORAGE];
332 strcopy( filemask, exeFileName );
333 char * basePath = find_last_path_separator( filemask );
334 if ( basePath ) {
335 ++basePath;
336 *basePath = 0;
337 if ( storage->fileName ) {
338 strcat( basePath, storage->fileName );
339 } else {
340 strcat( basePath, "disk" );
341 }
342 } else {
343 if ( storage->fileName ) {
344 strcopy( filemask, storage->fileName );
345 } else {
346 strcopy( filemask, "disk" );
347 }
348 }
349
350 char * storageFileName = generate_storage_filename( _environment, filemask, "d64", diskNumber );
351
352 int i=0;
353 while( storage ) {
354 handle = d64_create( CBMDOS );
355 if ( i == 0 ) {
356 d64_write_file( handle, "MAIN", FT_PRG, prgContent, prgSize );
357 }
358 FileStorage * fileStorage = storage->files;
359 while( fileStorage ) {
360 int size;
361 char * buffer;
362 if ( fileStorage->content && fileStorage->size ) {
363 size = fileStorage->size + 2;
364 buffer = malloc( size );
365 memset( buffer, 0, size );
366 memcpy( &buffer[2], fileStorage->content, fileStorage->size );
367 } else {
368 FILE * file = fopen( fileStorage->sourceName, "rb" );
369 if ( !file ) {
371 }
372 fseek( file, 0, SEEK_END );
373 size = ftell( file );
374 fseek( file, 0, SEEK_SET );
375 buffer = malloc( size + 2 );
376 memset( buffer, 0, size + 2 );
377 (void)!fread( &buffer[2], size, 1, file );
378 fclose( file );
379 size += 2;
380 }
381 d64_write_file( handle, fileStorage->targetName, FT_PRG, buffer, size );
382 fileStorage = fileStorage->next;
383 }
384 d64_output( handle, storageFileName );
385 d64_free( handle );
386 if ( _environment->outputGeneratedFiles ) {
387 printf( "%s\n", storageFileName );
388 }
389
390 ++diskNumber;
391
392 strcopy( filemask, exeFileName );
393 char * basePath = find_last_path_separator( filemask );
394 if ( basePath ) {
395 ++basePath;
396 *basePath = 0;
397 if ( storage->fileName ) {
398 strcat( basePath, storage->fileName );
399 } else {
400 strcat( basePath, "disk" );
401 }
402 } else {
403 if ( storage->fileName ) {
404 strcopy( filemask, storage->fileName );
405 } else {
406 strcopy( filemask, "disk" );
407 }
408 }
409 storageFileName = generate_storage_filename( _environment, filemask, "d64", diskNumber );
410 storage = storage->next;
411 ++i;
412 }
413
414 FILE * reuHandle = fopen( _environment->exeFileName, "wb" );
415 for( int i=0; i<_environment->ramSize * 1024; ++i ) {
416 fputc( 0, reuHandle );
417 }
418 fseek( reuHandle, 0, SEEK_SET );
419 Bank * bank = _environment->expansionBanks;
420 while( bank ) {
421 if ( bank->remains < bank->space ) {
422 int bankSize = bank->space - bank->remains;
423 fseek( reuHandle, bank->id * bank->space, SEEK_SET );
424 fwrite( bank->data, 1, bankSize, reuHandle );
425 }
426 bank = bank->next;
427 }
428 fclose( reuHandle );
429 if ( _environment->outputGeneratedFiles ) {
430 printf( "%s\n", _environment->exeFileName );
431 }
432
433 }
434
435}
436
442void target_linkage( Environment * _environment ) {
443
444 switch( _environment->outputFileType ) {
446 generate_prg( _environment );
447 generate_d64( _environment );
448 break;
450 generate_prg( _environment );
451 generate_reu( _environment );
452 break;
453 default:
455 }
456
457}
458
459void target_cleanup( Environment * _environment ) {
460
461 remove( _environment->configurationFileName );
462 remove( _environment->asmFileName );
463
464 if ( _environment->analysis && _environment->listingFileName ) {
465 target_analysis( _environment );
466 }
467
468}
int system_call(Environment *_environment, char *_commandline)
Call an external executable.
char * find_last_path_separator(char *_path)
char * generate_storage_filename(Environment *_environment, char *_prefix, char *_suffix, int _number)
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_prg(Environment *_environment)
Definition _build.c:43
void generate_d64(Environment *_environment)
Definition _build.c:95
void generate_reu(Environment *_environment)
Definition _build.c:279
D64Handle * d64_create(D64Format _format)
Create a new D64 disk image.
Definition d64.c:779
void d64_output(D64Handle *_handle, unsigned char *_filename)
Definition d64.c:932
void d64_free(D64Handle *_handle)
Free the disk image resources.
Definition d64.c:924
int d64_write_file(D64Handle *_handle, unsigned char *_filename, D64FileType _type, unsigned char *_buffer, int _size)
Write a block of memory on a file on the D64 disk image.
Definition d64.c:802
int d64_get_free_sectors(D64Handle *_handle)
Definition d64.c:290
@ CBMDOS
Definition d64.h:436
@ FT_PRG
Definition d64.h:126
@ FT_SEQ
Definition d64.h:123
struct _D64Handle D64Handle
int remains
Definition ugbc.h:171
int id
Definition ugbc.h:153
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
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
int ramSize
Definition ugbc.h:3171
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_REU
Definition ugbc.h:269
@ OUTPUT_FILE_TYPE_D64
Definition ugbc.h:266
#define BUILD_SAFE_REMOVE(_environment, filename)
Definition ugbc.h:4748
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define CRITICAL_DLOAD_MISSING_FILE(f)
Definition ugbc.h:3578
#define BUILD_TOOLCHAIN_CC65_GET_EXECUTABLE(_environment, executableName)
Definition ugbc.h:4754
#define BUILD_TOOLCHAIN_CC65_GET_LISTING_FILE(_environment, listingFileName)
Definition ugbc.h:4773
#define CRITICAL_BUILD_CANNOT_READ_EXECUTABLE_FOR_DSK(d, f)
Definition ugbc.h:3868
struct _Environment Environment
Structure of compilation environment.
struct _Storage Storage
Structure of a single storage.
#define BUILD_TOOLCHAIN_CC65_EXEC(_environment, target, executableName, listingFileName, additionalParameters)
Definition ugbc.h:4781
struct _FileStorage FileStorage
Structure of a single file inside a storage.
struct _Bank Bank
Structure of a single bank.
#define CRITICAL_UNSUPPORTED_OUTPUT_FILE_TYPE(t)
Definition ugbc.h:3537
char OUTPUT_FILE_TYPE_AS_STRING[][16]
char * strcopy(char *_dest, char *_source)