ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
d64.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#include "d64.h"
32
33/****************************************************************************
34 * DATA TYPES AND CONSTANTS
35 ****************************************************************************/
36
37// The various DOS version for each format.
39 0x41, // Original CBM DOS v2.6
40 0x41, // SpeedDOS+
41 0x41, // Professional DOS Initial
42 0x41, // Professional DOS Version 1/Prototype
43 0x41, // ProfDOS Release
44 0x41, // Dolphin-DOS 2.0/3.0 (35)
45 0x41, // Dolphin-DOS 2.0/3.0 (40)
46 0x41, // PrologicDOS 1541 (35)
47 0x50, // PrologicDOS 1541 (40)
48 0x41, // ProSpeed 1571 2.0 (35)
49 0x50 // ProSpeed 1571 2.0 (40)
50};
51
52// The various DOS TYPE for each format.
53unsigned char dosTypeByFormat[][3] = {
54 "2A", // Original CBM DOS v2.6
55 "2A", // SpeedDOS+
56 "2A", // Professional DOS Initial
57 "2A", // Professional DOS Version 1/Prototype
58 "4A", // ProfDOS Release
59 "2A", // Dolphin-DOS 2.0/3.0 (35)
60 "2A", // Dolphin-DOS 2.0/3.0 (40)
61 "2A", // PrologicDOS 1541 (35)
62 "2P", // PrologicDOS 1541 (40)
63 "2A", // ProSpeed 1571 2.0 (35)
64 "2P" // ProSpeed 1571 2.0 (40)
65};
66
67// This is the numer of sectors for each track.
69 // 1-17
70 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
71 // 18-24
72 19, 19, 19, 19, 19, 19, 19,
73 // 25-30
74 18, 18, 18, 18, 18, 18,
75 // 31-35
76 17, 17, 17, 17, 17,
77 // 36-40
78 17, 17, 17, 17, 17,
79 // 41-42
80 17, 17
81};
82
83// This is the starting offset (in memory) of each track.
85 // 1-8
86 0x00000, 0x01500, 0x02A00, 0x03F00, 0x05400, 0x06900, 0x07E00, 0x09300,
87 // 9-16
88 0x0A800, 0x0BD00, 0x0D200, 0x0E700, 0x0FC00, 0x11100, 0x12600, 0x13B00,
89 // 17-24
90 0x15000, 0x16500, 0x17800, 0x18B00, 0x19E00, 0x1B100, 0x1C400, 0x1D700,
91 // 25-32
92 0x1EA00, 0x1FC00, 0x20E00, 0x22000, 0x23200, 0x24400, 0x25600, 0x26700,
93 // 33-40
94 0x27800, 0x28900, 0x29A00, 0x2AB00, 0x2BC00, 0x2CD00, 0x2DE00, 0x2EF00,
95 // 41-42
96 0x30000, 0x31100
97};
98
99/****************************************************************************
100 * STATIC FUNCTIONS
101 ****************************************************************************/
102
103
104static void d64_free_sectors_on_bam( D64BAMEntry * _entry, D64Sector _sectors );
105static void d64_free_sector_on_bam( D64BAMEntry * _entry, D64Sector _sector );
106
107static void d64_start_transaction( D64Handle * _handle ) {
108
109 _handle->snapshot = malloc( _handle->contentSize );
110 memset( _handle->snapshot, 0, _handle->contentSize );
111 memcpy( _handle->snapshot, _handle->content, _handle->contentSize );
112
113}
114
115static void d64_commit_transaction( D64Handle * _handle ) {
116
117 free( _handle->snapshot );
118 _handle->snapshot = NULL;
119
120}
121
122static void d64_rollback_transaction( D64Handle * _handle ) {
123
124 memcpy( _handle->content, _handle->snapshot, _handle->contentSize );
125 free( _handle->snapshot );
126 _handle->snapshot = NULL;
127
128}
129
137static int d64_calculate_offset( D64Track _track, D64Sector _sector ) {
138
139 int offset = 0;
140
141 // Let's take the starting offset in memory for the given track.
142 offset = D64OffsetPerTrack[_track-1];
143
144 // Next, move ahead of 256 bytes for each sector.
145 offset += _sector * sizeof( D64SectorData );
146
147 return offset;
148
149}
150
158static int d64_calculate_sectors( D64Track _track, D64Sector _sector ) {
159
160 int offset = 0;
161
162 // In order to calculate the starting position, expressed as sectors,
163 // we need to sum up all the sectors of each track, from the first
164 // to the one needed.
165 for(int i=0; i<(_track-1); ++i ) {
167 }
168
169 // Finally, we can sum the number
170 offset += _sector;
171
172 return offset;
173
174}
175
184static D64SectorData * d64_get_sector( D64Handle * _handle, D64Track _track, D64Sector _sector ) {
185
186 // Retrieve the offset in memory for the given track / sector,
187 // given in bytes.
188 int offset = d64_calculate_offset( _track, _sector );
189
190 // printf("offset = %d\n", offset );
191
192 // Return the address of the disk image in memory,
193 // by using the calculated offset.
194 return (D64SectorData *) &_handle->content[offset];
195
196}
197
204static void d64_free_sectors_on_bam( D64BAMEntry * _entry, D64Sector _sectors ) {
205
206 // By default, sectors that are not eligible to be present
207 // in a track are always occupied.
208 _entry->bitmappedFree[0] = 0x0;
209 _entry->bitmappedFree[1] = 0x0;
210 _entry->bitmappedFree[2] = 0x0;
211
212 // For each sector (0...(sectors-1)), we are going to put it as free.
213 for( int i=0; i<_sectors; ++i ) {
214 d64_free_sector_on_bam( _entry, i );
215 }
216
217}
218
225static void d64_free_sector_on_bam( D64BAMEntry * _entry, D64Sector _sector ) {
226
227 // Let's calculate the offset and the bitmap for the given sector.
228 int offset = _sector >> 3;
229 int bitmap = 1 << ( _sector & 0x07 );
230
231 // If the sector is already free...
232 if ( ( _entry->bitmappedFree[offset] | (bitmap) ) == _entry->bitmappedFree[offset] ) {
233
234 // ... we will do nothing.
235
236 } else {
237
238 // Put the sector as "free".
239 _entry->bitmappedFree[offset] |= bitmap;
240
241 // Increase the number of free sectors.
242 ++_entry->freeSectors;
243
244 }
245
246
247}
248
255static void d64_allocate_sector_on_bam( D64BAMEntry * _entry, D64Sector _sector ) {
256
257 // If the sector has no more free sectors,
258 // we move away.
259 if ( _entry->freeSectors == 0 ) {
260 // printf( " > no more sectors...\n");
261 return;
262 }
263
264 // Let's calculate the offset and the bitmap for the given sector.
265 int offset = _sector >> 3;
266 int bitmap = 1 << ( _sector & 0x07 );
267
268 // printf( "offset = %d\n", offset );
269 // printf( "bitmap = %2.2x\n", bitmap );
270 // printf( "_entry->bitmappedFree[offset] & ~(bitmap) = %2.2x\n", _entry->bitmappedFree[offset] & ~(bitmap) );
271 // printf( "_entry->bitmappedFree[offset] = %2.2x\n", _entry->bitmappedFree[offset] );
272
273 // If the sector is already allocated...
274 if ( ( _entry->bitmappedFree[offset] & ~(bitmap) ) == _entry->bitmappedFree[offset] ) {
275
276 // Do nothing...
277
278 } else {
279
280 // Allocate the sector.
281 _entry->bitmappedFree[offset] &= ~(bitmap);
282
283 // Decrease the number of the free sectors.
284 --_entry->freeSectors;
285
286 }
287
288}
289
291
292 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
293
294 int freeSectors = 0;
295
296 for( int i=0; i<35; ++i ) {
297 if ( i != 18 ) {
298 freeSectors += bam->entries[i].freeSectors;
299 }
300 }
301
302 return freeSectors;
303
304}
305
313static void d64_allocate_sector( D64Handle * _handle, D64Track _track, D64Sector _sector ) {
314
315 // printf( "d64_allocate_sector(..., %d, %d )\n", _track, _sector );
316
317 // Retrieve the sector with the BAM.
318 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
319
320 // If a track more than 35, we must use the correct BAM
321 // based on the Disk Image format.
322 if ( _track > 35 ) {
323
324 switch( _handle->format ) {
325 case SPEEDDOS40:
326 d64_allocate_sector_on_bam( &bam->entriesSpeedDOS[_track-36], _sector );
327 break;
328
331 d64_allocate_sector_on_bam( &bam->entriesSpeedDOS[_track-36], _sector );
332 break;
333
334 case DOLPHINDOS40:
335 d64_allocate_sector_on_bam( &bam->entriesDolphinDOS[_track-36], _sector );
336 break;
337
338 case PROLOGICDOS40:
339 d64_allocate_sector_on_bam( &bam->prologic.entriesPrologicDOS[_track-36], _sector );
340 break;
341
342 case PROSPEED40:
343 d64_allocate_sector_on_bam( &bam->entriesSpeedDOS[_track-36], _sector );
344 break;
345
346 default:
347 // We cannot allocate!
348 return;
349 }
350
351 } else {
352 // Allocate using standard BAM.
353 d64_allocate_sector_on_bam( &bam->entries[_track-1], _sector );
354 }
355
356}
357
365static void d64_find_free_sector( D64Handle * _handle, D64Track * _track, D64Sector * _sector ) {
366
367 // printf( "d64_find_free_sector\n" );
368
369 // A 0/0 result means "no free sector available".
370 *_track = 0;
371 *_sector = 0;
372
373 // Retrieve the sector with the BAM.
374 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
375
376 // This will contain the BAM entry with the free sector.
377 D64BAMEntry * entry;
378
379 _handle->lastUsedTrack = 17;
380
381 // We are going to examinate tracks from 1 to the maximum number.
382 while( _handle->lastUsedTrack != 0 ) {
383
384 // With tracks greater of 35 we have to use the extension
385 // of the BAM based on disk's format.
386 if ( _handle->lastUsedTrack > 35 ) {
387
388 switch( _handle->format ) {
389 case SPEEDDOS40:
392 case PROSPEED40:
393 entry = &bam->entriesSpeedDOS[_handle->lastUsedTrack-36];
394 break;
395
396 case DOLPHINDOS40:
397 entry = &bam->entriesDolphinDOS[_handle->lastUsedTrack-36];
398 break;
399
400 case PROLOGICDOS40:
401 entry = &bam->prologic.entriesPrologicDOS[_handle->lastUsedTrack-36];
402 break;
403
404 default:
405 // No free sectors available!
406 return;
407 }
408
409 } else {
410 entry = &bam->entries[_handle->lastUsedTrack-1];
411 }
412
413 // printf( " >> track %d, free sectors = %d\n", _handle->lastUsedTrack, entry->freeSectors );
414
415 // A fast check if free sectors are available.
416 if ( entry->freeSectors > 0 ) {
417 // A detailed check to find out the correct sector
418 // must be executed.
419 int sector = 0;
420 for( int j=0; j<D64SectorsPerTrack[_handle->lastUsedTrack-1]; ++j ) {
421 // printf( " > sector = %d\n", j );
422 // Let's calculate the offset and the bitmap for the given sector.
423 int offset = sector >> 3;
424 int bitmap = 1 << ( sector & 0x07 );
425 // printf( " > offset, bitmap = %2.2x %2.2x\n", offset, bitmap );
426 // If the bit is set, the sector is free.
427 if ( ( entry->bitmappedFree[offset] & bitmap ) == bitmap ) {
428 *_track = _handle->lastUsedTrack;
429 *_sector = sector;
430 // printf( "found %2.2x %2.2x -> track = %d sector = %d\n", offset, bitmap, *_track, *_sector );
431 return;
432 }
433 sector += 10;
434 sector = sector % D64SectorsPerTrack[_handle->lastUsedTrack-1];
435 }
436 }
437
438 --_handle->lastUsedTrack;
439
440 if ( _handle->lastUsedTrack == 0 ) {
441 _handle->lastUsedTrack = _handle->tracks;
442 }
443
444 if ( _handle->lastUsedTrack == 18 ) {
445 _handle->lastUsedTrack = 0;
446 }
447
448 }
449}
450
457static D64DirectoryEntry * d64_allocate_directory_entry( D64Handle * _handle ) {
458
459 // The directory entry address to return.
460 D64DirectoryEntry * value = NULL;
461
462 // Retrieve the sector with the BAM.
463 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
464
465 // Retrieve the (first) sector with directory.
466 D64SectorDirectory * directory = (D64SectorDirectory *) d64_get_sector( _handle, bam->firstDirectoryTrack, bam->firstDirectorySector );
467
468 // Take note of the index into the directory's entries.
469 int directoryIndex = 0;
470
471 do {
472
473 // Retrieve the address of the directory's entry.
474 value = &directory->entries[directoryIndex];
475
476 // If the file type value is not DEL (0), it means that
477 // the entry is used. So we must go ahead to the next entry.
478 if ( value->attribute.type != FT_DEL ) {
479
480 // Reset the address.
481 value = NULL;
482
483 // Move to the next index
484 ++directoryIndex;
485
486 // If we reached the end of the directory's sector...
487 if ( directoryIndex == 8 ) {
488
489 // Restart from the beginning.
490 directoryIndex = 0;
491
492 // If the current track and sector for the first entry
493 // is 0/0 it means we need to allocate another sector
494 // for the directory.
495 if ( directory->entries[0].track == 0 && directory->entries[0].sector == 0 ) {
496
497 // Find out the next free sector to use.
498 D64Track track;
499 D64Sector sector;
500 d64_find_free_sector( _handle, &track, &sector );
501
502 if ( track == 0 && sector == 0 ) {
503 return NULL;
504 }
505
506 // Allocate the sector.
507 d64_allocate_sector( _handle, track, sector );
508
509 // Set the track and sector on the directory's entry.
510 directory->entries[0].track = track;
511 directory->entries[0].sector = sector;
512 }
513
514 // Move to the next directory sector.
515 directory = (D64SectorDirectory *) d64_get_sector( _handle, directory->entries[0].track, directory->entries[0].sector );
516 }
517 }
518
519 } while( value == NULL );
520
521 return value;
522
523}
524
533static void d64_write_error( D64Handle * _handle, D64Track _track, D64Sector _sector, D64ErrorCode _error_code ) {
534
535 // If the memory for storing errors is not allocated,
536 // it will be allocated.
537 if ( !_handle->errors ) {
538 // Memory needed is of 1 byte for each sector.
539 _handle->errorsSize = sizeof( _handle->sectors ) * sizeof( D64ErrorCode );
540 _handle->errors = malloc( _handle->errorsSize );
541 memset( _handle->errors, NO_ERRORX, sizeof( _handle->sectors ) * sizeof( D64ErrorCode ) );
542 }
543
544 // Calculate the offset (in sectors) for the given track/sector.
545 int offsetAsSectors = d64_calculate_sectors( _track, _sector );
546
547 // Update the error code.
548 _handle->errors[offsetAsSectors] = _error_code;
549
550}
551
562static void d64_write_directory_entry( D64DirectoryEntry * _entry, unsigned char * _filename, D64FileType _type, D64Track _firstTrack, D64Sector _firstSector, int _size_sectors ) {
563
564 // Update the track/sector to 0/0.
565 _entry->track = 0;
566 _entry->sector = 0;
567
568 // Update the attribute.
569 _entry->attribute.type = _type;
570 _entry->attribute.unused = 0;
571 _entry->attribute.saveReplacement = 0;
572 _entry->attribute.lockedFlag = 0;
573 _entry->attribute.closedFlag = 1;
574
575 // Update the first sector track/sector.
576 _entry->trackFirstSector = _firstTrack;
577 _entry->sectorFirstSector = _firstSector;
578
579 // Update the filename.
580 memset( _entry->filename, 0xa0, 16 );
581 for( int i=0,c=strlen( _filename ) > 16 ? 16 : strlen( _filename ); i<c; ++i ) {
582 _entry->filename[i] = toupper(_filename[i]);
583 }
584
585 // Currently, REL files are not supported.
586 _entry->trackFirstSectorREL = 0;
587 _entry->sectorFirstSectorREL = 0;
588 _entry->lengthREL = 0;
589
590 // _entry->unused[6];
591
592 // Update the size in sectors
593 _entry->sizeSectors = _size_sectors;
594
595}
596
602static void d64_format( D64Handle * _handle ) {
603
604 // Free the actual disk image's content.
605 if ( _handle->content ) {
606 free( _handle->content );
607 }
608
609 // Based on the disk image format, the number of tracks
610 // will be different.
611 switch( _handle->format ) {
612
613 // Original CBM DOS v2.6 35 $0f $0f "2A" $41/'A'
614 case CBMDOS:
615 // Professional DOS Initial 35 $0f $0f "2A" $41/'A'
617 // Dolphin-DOS 2.0/3.0 35 $0f $0f "2A" $41/'A'
618 case DOLPHINDOS35:
619 // PrologicDOS 1541 35 $0f $0f "2A" $41/'A'
620 case PROLOGICDOS35:
621 // ProSpeed 1571 2.0 35 $0f $0f "2A" $41/'A'
622 case PROSPEED35:
623 _handle->tracks = 35;
624 break;
625
626 // SpeedDOS+ 40 $0f $0f "2A" $41/'A'
627 case SPEEDDOS40:
628 // Professional DOS Version 1/Prototype 40 $0f $0f "2A" $41/'A'
630 // ProfDOS Release 40 $0f $0f "4A" $41/'A'
632 // Dolphin-DOS 2.0/3.0 40 $0d $0f "2A" $41/'A'
633 case DOLPHINDOS40:
634 // PrologicDOS 1541 40 $0f $0f "2P" $50/'P'
635 case PROLOGICDOS40:
636 // ProSpeed 1571 2.0 40 $0f $0f "2P" $50/'P'
637 case PROSPEED40:
638 _handle->tracks = 40;
639 break;
640
641 }
642
643 // The real disk size is the first position of the
644 // last track + 1.
645 _handle->contentSize = D64OffsetPerTrack[_handle->tracks];
646
647 // Calculate the effective number of sectors.
648 _handle->sectors = d64_calculate_sectors( _handle->tracks + 1, 1 );
649
650 // Allocate the memory space for the disk image.
651 // printf( "ALLOCATING %d bytes\n", _handle->contentSize );
652
653 _handle->content = malloc( _handle->contentSize );
654 memset( _handle->content, 0, _handle->contentSize );
655
656 // printf( "MALLOC %p\n", _handle->content );
657
658 // Retrieve the sector with the BAM.
659 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
660
661 // Set the first track/sector for the directory sector.
664
665 // Set the DOS version accordingly with the format.
666 d64_set_dos_version( _handle, versionByFormat[_handle->format] );
667
668 // Set the free sectors on BAM for each track.
669 for( int i=0; i<_handle->tracks; ++i ) {
670 d64_free_sectors_on_bam( &bam->entries[i], D64SectorsPerTrack[i] );
671 }
672
673 // Set the default disk name
674 d64_set_disk_name( _handle, "UGBASIC" );
675
676 // Set the default disk id
677 d64_set_disk_id( _handle, 0xa0a0 );
678
679 // Set the dos type based on format
680 d64_set_dos_type( _handle, dosTypeByFormat[_handle->format] );
681
682 bam->unused5 = 0x00;
683 bam->unused3 = 0xa0;
684
685 _handle->lastUsedTrack = 17;
686
687}
688
689/****************************************************************************
690 * PUBLIC FUNCTIONS
691 ****************************************************************************/
698void d64_set_dos_version( D64Handle * _handle, D64DosVersion _version ) {
699
700 // Retrieve the sector with the BAM.
701 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
702
703 // Assign the given DOS version to the disk.
704 bam->dosVersion = _version;
705
706}
707
714void d64_set_disk_name( D64Handle * _handle, unsigned char * _disk_name ) {
715
716 // Retrieve the sector with the BAM.
717 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
718
719 // Put the name on the disk based on the format.
720 switch( _handle->format ) {
721 case PROLOGICDOS35:
722 case PROLOGICDOS40:
723 break;
724 default:
725 memset( bam->standard.diskName, 0xa0, 16 );
726 memcpy( bam->standard.diskName, _disk_name, strlen( _disk_name ) > 16 ? 16 : strlen( _disk_name ) );
727 bam->standard.unused2[0] = 0xa0;
728 bam->standard.unused2[1] = 0xa0;
729 break;
730 }
731
732}
733
740void d64_set_disk_id( D64Handle * _handle, D64DiskId _disk_id ) {
741
742 // Retrieve the sector with the BAM.
743 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
744
745 // Put the disk id on the disk based on the format.
746 switch( _handle->format ) {
747 case PROLOGICDOS35:
748 case PROLOGICDOS40:
749 break;
750 default:
751 memcpy( &bam->standard.diskId, &_disk_id, sizeof( D64DiskId ) );
752 break;
753 }
754
755}
756
763void d64_set_dos_type( D64Handle * _handle, unsigned char * _dos_type ) {
764
765 // Retrieve the sector with the BAM.
766 D64SectorBAM * bam = (D64SectorBAM *) d64_get_sector( _handle, D64_BAM_TRACK, D64_BAM_SECTOR );
767
768 // Put the DOS Type on the disk
769 memcpy( bam->dosType, _dos_type, 2 );
770
771}
772
780
781 // Allocate the handle.
782 D64Handle * handle = malloc( sizeof( D64Handle ) );
783 memset( handle, 0, sizeof( D64Handle ) );
784
785 // Update and format the disk image
786 handle->format = _format;
787 d64_format( handle );
788
789 return handle;
790
791}
792
802int d64_write_file( D64Handle * _handle, unsigned char * _filename, D64FileType _type, unsigned char * _buffer, int _size ) {
803
804 // printf( "FILE = %s\n", _filename );
805
806 d64_start_transaction( _handle );
807
808 // Track and sector number of the first sector data.
809 D64Track firstTrack = 0;
810 D64Sector firstSector = 0;
811
812 // Size of the file (in sectors)
813 D64WordLength sectors = 0;
814
815 // Current track and sector.
816 D64Track track = 0;
817 D64Sector sector = 0;
818
819 // Pointer of the buffer to write
820 unsigned char * buffer = _buffer;
821
822 // Sectors
823 D64SectorData * sectorData = NULL;
824 D64SectorData * previous = NULL;
825
826 // Repeat the process until the buffer has been written.
827 while( _size ) {
828
829 // Increment the number of total sectors.
830 ++sectors;
831
832 // If there is a previous data sector, we must
833 // update its t/s fields with the values found.
834 if ( previous ) {
835 previous->track = track;
836 previous->sector = sector;
837 // printf( "(previous updated)\n" );
838 }
839
840 // Find out a free t/s sector.
841 d64_find_free_sector( _handle, &track, &sector );
842
843 if ( track == 0 && sector == 0 ) {
844 d64_rollback_transaction( _handle );
845 return 0;
846 }
847
848 // Allocate the free t/s sector.
849 d64_allocate_sector( _handle, track, sector );
850
851 // If the first track has not been setted, the
852 // one found is the first track.
853 if ( firstTrack == 0 ) {
854 firstTrack = track;
855 firstSector = sector;
856 // printf( "(first t/s updated)\n" );
857 }
858
859 // Save the previous sector, if any.
860 previous = sectorData;
861
862 // Retrieve the sector data with the given t/s.
863 sectorData = (D64SectorData *) d64_get_sector( _handle, track, sector );
864
865 // printf( "SECTOR AT %p (%p)\n", sectorData, &sectorData->data[0] );
866
867 // If the size is less or equal 254, we can put it entirely
868 // in the (final) sector.
869 if ( _size <= 254 ) {
870
871 // printf( "FILL UP TO %d bytes\n", _size );
872
873 // Set the effective size on the "sector" field.
874 sectorData->track = 0;
875 sectorData->sector = (_size + 1);
876
877 // Copy the memory on the sector data.
878 memcpy( &sectorData->data[0], buffer, _size );
879
880 _size = 0;
881
882 } else {
883
884 // printf( "FILL UP TO [254] bytes\n" );
885
886 // Copy a 254 bytes segment.
887 memcpy( &sectorData->data[0], buffer, 254 );
888
889 buffer += 254;
890 _size -= 254;
891
892 }
893
894 }
895
896 // If there is a previous data sector, we must
897 // update its t/s fields with the values found.
898 if ( previous ) {
899 previous->track = track;
900 previous->sector = sector;
901 // printf( "(previous updated)\n" );
902 }
903
904 // Allocate a new directory's entry.
905 D64DirectoryEntry * entry = d64_allocate_directory_entry( _handle );
906
907 if ( entry ) {
908 // Update the directory's entry.
909 d64_write_directory_entry( entry, _filename, _type, firstTrack, firstSector, sectors );
910 d64_commit_transaction( _handle );
911 return 1;
912 } else {
913 d64_rollback_transaction( _handle );
914 return 0;
915 }
916
917}
918
924void d64_free( D64Handle * _handle ) {
925
926 free( _handle->errors );
927 free( _handle->content );
928 free( _handle );
929
930}
931
932void d64_output( D64Handle * _handle, unsigned char * _filename ) {
933
934 remove( _filename );
935
936 FILE * fHandle = fopen( _filename, "wb" );
937 fwrite( _handle->content, _handle->contentSize, 1, fHandle );
938 if ( _handle->errors ) {
939 fwrite( _handle->errors, _handle->errorsSize, 1, fHandle );
940 }
941 fclose( fHandle );
942
943}
int offset
Definition _optimizer.c:681
void d64_set_disk_name(D64Handle *_handle, unsigned char *_disk_name)
Set the disk name for the given disk image.
Definition d64.c:714
D64DosVersion versionByFormat[]
Definition d64.c:38
D64Handle * d64_create(D64Format _format)
Create a new D64 disk image.
Definition d64.c:779
void d64_set_disk_id(D64Handle *_handle, D64DiskId _disk_id)
Set the disk id for the given disk image.
Definition d64.c:740
void d64_output(D64Handle *_handle, unsigned char *_filename)
Definition d64.c:932
unsigned char dosTypeByFormat[][3]
Definition d64.c:53
void d64_set_dos_version(D64Handle *_handle, D64DosVersion _version)
Set the DOS version for the given disk image.
Definition d64.c:698
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
void d64_set_dos_type(D64Handle *_handle, unsigned char *_dos_type)
Set the DOS Type for the given disk image.
Definition d64.c:763
int D64OffsetPerTrack[]
Definition d64.c:84
int D64SectorsPerTrack[]
Definition d64.c:68
int d64_get_free_sectors(D64Handle *_handle)
Definition d64.c:290
@ NO_ERRORX
Definition d64.h:491
struct _D64BAMEntry D64BAMEntry
#define D64_DIRECTORY_TRACK
Definition d64.h:625
#define D64_BAM_TRACK
Definition d64.h:623
struct _D64BAM D64SectorBAM
unsigned char D64Sector
Definition d64.h:100
unsigned char D64DosVersion
Definition d64.h:103
@ DOLPHINDOS40
Definition d64.h:454
@ PROFESSIONALDOS35
Definition d64.h:442
@ SPEEDDOS40
Definition d64.h:439
@ DOLPHINDOS35
Definition d64.h:451
@ CBMDOS
Definition d64.h:436
@ PROLOGICDOS40
Definition d64.h:460
@ PROSPEED40
Definition d64.h:466
@ PROFESSIONALDOS40B
Definition d64.h:448
@ PROFESSIONALDOS40
Definition d64.h:445
@ PROSPEED35
Definition d64.h:463
@ PROLOGICDOS35
Definition d64.h:457
struct _D64SectorData D64SectorData
enum _D64FileType D64FileType
unsigned short D64DiskId
Definition d64.h:226
unsigned short D64WordLength
Definition d64.h:109
@ FT_DEL
Definition d64.h:120
#define D64_DIRECTORY_SECTOR
Definition d64.h:626
enum _D64ErrorCode D64ErrorCode
struct _D64DirectoryEntry D64DirectoryEntry
enum _D64Format D64Format
#define D64_BAM_SECTOR
Definition d64.h:624
struct _D64Handle D64Handle
struct _D64Directory D64SectorDirectory
unsigned char D64Track
Definition d64.h:96
unsigned char saveReplacement
Definition d64.h:150
unsigned char closedFlag
Definition d64.h:156
unsigned char lockedFlag
Definition d64.h:153
unsigned char type
Definition d64.h:144
unsigned char unused
Definition d64.h:147
D64ByteLength freeSectors
Definition d64.h:278
unsigned char bitmappedFree[3]
Definition d64.h:297
D64DiskId diskId
Definition d64.h:333
struct _D64BAM::@256036255133227046226271146257246372060017123336::@271123314305046123343155131234272165152237056144 prologic
struct _D64BAM::@256036255133227046226271146257246372060017123336::@324076120047031363306223216253037144316004175331 standard
D64BAMEntry entries[35]
Definition d64.h:317
D64BAMEntry entriesSpeedDOS[5]
Definition d64.h:361
unsigned char unused2[2]
Definition d64.h:330
D64BAMEntry entriesPrologicDOS[5]
Definition d64.h:339
unsigned char unused5
Definition d64.h:355
D64DosVersion dosVersion
Definition d64.h:310
unsigned char diskName[16]
Definition d64.h:327
unsigned char dosType[2]
Definition d64.h:349
unsigned char unused3
Definition d64.h:346
D64BAMEntry entriesDolphinDOS[5]
Definition d64.h:358
D64Track firstDirectoryTrack
Definition d64.h:306
D64Sector firstDirectorySector
Definition d64.h:307
D64Attribute attribute
Definition d64.h:178
D64WordLength sizeSectors
Definition d64.h:199
D64Track trackFirstSector
Definition d64.h:181
D64ByteLength lengthREL
Definition d64.h:192
unsigned char filename[16]
Definition d64.h:185
D64Sector sectorFirstSector
Definition d64.h:182
D64Sector sectorFirstSectorREL
Definition d64.h:189
D64Track trackFirstSectorREL
Definition d64.h:188
D64Track track
Definition d64.h:174
D64Sector sector
Definition d64.h:175
D64DirectoryEntry entries[8]
Definition d64.h:207
int contentSize
Definition d64.h:610
D64Track lastUsedTrack
Definition d64.h:619
D64Format format
Definition d64.h:595
D64ErrorCode * errors
Definition d64.h:613
unsigned char * content
Definition d64.h:604
D64Track tracks
Definition d64.h:598
D64Sector sectors
Definition d64.h:601
unsigned char * snapshot
Definition d64.h:607
int errorsSize
Definition d64.h:616
unsigned char data[254]
Definition d64.h:221
D64Track track
Definition d64.h:217
D64Sector sector
Definition d64.h:218
void * malloc(YYSIZE_T)
void free(void *)