ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/1541d64.cpp
(Generate patch)

Comparing Frodo4/Src/1541d64.cpp (file contents):
Revision 1.5 by cebix, 2004-01-11T14:03:29Z vs.
Revision 1.11 by cebix, 2010-04-21T19:52:53Z

# Line 1 | Line 1
1   /*
2   *  1541d64.cpp - 1541 emulation in disk image files (.d64/.x64/zipcode)
3   *
4 < *  Frodo (C) 1994-1997,2002-2003 Christian Bauer
4 > *  Frodo Copyright (C) Christian Bauer
5   *  zipcode decoding routines (C) 1993-1997 Marko Mäkelä, Paul David Doherty
6   *
7   *  This program is free software; you can redistribute it and/or modify
# Line 34 | Line 34
34   #include "C64.h"
35   #include "main.h"
36  
37 + #define DEBUG 0
38 + #include "debug.h"
39 +
40  
41   // Channel modes (IRC users listen up :-)
42   enum {
# Line 106 | Line 109 | const int accum_num_sectors[41] = {
109  
110   // Prototypes
111   static bool match(const uint8 *p, int p_len, const uint8 *n);
112 + static FILE *open_image_file(const char *path, bool write_mode);
113 + static bool parse_image_file(FILE *f, image_file_desc &desc);
114  
115  
116   /*
117   *  Constructor: Prepare emulation, open image file
118   */
119  
120 < D64Drive::D64Drive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false)
120 > ImageDrive::ImageDrive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false)
121   {
122 +        desc.type = TYPE_D64;
123 +        desc.header_size = 0;
124 +        desc.num_tracks = 35;
125 +        desc.id1 = desc.id2 = 0;
126 +        desc.has_error_info = false;
127 +
128          for (int i=0; i<18; i++) {
129                  ch[i].mode = CHMOD_FREE;
130                  ch[i].buf = NULL;
# Line 132 | Line 143 | D64Drive::D64Drive(IEC *iec, const char
143   *  Destructor
144   */
145  
146 < D64Drive::~D64Drive()
146 > ImageDrive::~ImageDrive()
147   {
148          close_image();
149   }
# Line 142 | Line 153 | D64Drive::~D64Drive()
153   *  Close the image file
154   */
155  
156 < void D64Drive::close_image(void)
156 > void ImageDrive::close_image(void)
157   {
158          if (the_file) {
159                  close_all_channels();
# Line 160 | Line 171 | void D64Drive::close_image(void)
171   *  Open the image file
172   */
173  
174 < bool D64Drive::change_image(const char *path)
174 > bool ImageDrive::change_image(const char *path)
175   {
176          // Close old image file
177          close_image();
# Line 194 | Line 205 | bool D64Drive::change_image(const char *
205   *  Open channel
206   */
207  
208 < uint8 D64Drive::Open(int channel, const uint8 *name, int name_len)
208 > uint8 ImageDrive::Open(int channel, const uint8 *name, int name_len)
209   {
210 +        D(bug("ImageDrive::Open channel %d, file %s\n", channel, name));
211 +
212          set_error(ERR_OK);
213  
214          // Channel 15: execute file name as command
# Line 226 | Line 239 | uint8 D64Drive::Open(int channel, const
239   *  Open file
240   */
241  
242 < uint8 D64Drive::open_file(int channel, const uint8 *name, int name_len)
242 > uint8 ImageDrive::open_file(int channel, const uint8 *name, int name_len)
243   {
244          uint8 plain_name[NAMEBUF_LENGTH];
245          int plain_name_len;
# Line 237 | Line 250 | uint8 D64Drive::open_file(int channel, c
250          if (plain_name_len > 16)
251                  plain_name_len = 16;
252  
253 +        D(bug(" plain name %s, type %d, mode %d\n", plain_name, type, mode));
254 +
255          // Channel 0 is READ, channel 1 is WRITE
256          if (channel == 0 || channel == 1) {
257                  mode = channel ? FMODE_WRITE : FMODE_READ;
# Line 269 | Line 284 | uint8 D64Drive::open_file(int channel, c
284          if (find_first_file(plain_name, plain_name_len, dir_track, dir_sector, entry)) {
285  
286                  // File exists
287 +                D(bug(" file exists, dir track %d, sector %d, entry %d\n", dir_track, dir_sector, entry));
288                  ch[channel].dir_track = dir_track;
289                  ch[channel].dir_sector = dir_sector;
290                  ch[channel].entry = entry;
# Line 334 | Line 350 | uint8 D64Drive::open_file(int channel, c
350          } else {
351  
352                  // File doesn't exist
353 +                D(bug(" file not found\n"));
354 +
355                  // Set file type to SEQ if not specified in file name
356                  if (type == FTYPE_DEL)
357                          type = FTYPE_SEQ;
# Line 354 | Line 372 | uint8 D64Drive::open_file(int channel, c
372   *  Open channel for reading from file given track/sector of first block
373   */
374  
375 < uint8 D64Drive::open_file_ts(int channel, int track, int sector)
375 > uint8 ImageDrive::open_file_ts(int channel, int track, int sector)
376   {
377 +        D(bug("open_file_ts track %d, sector %d\n", track, sector));
378 +
379          // Allocate buffer and set channel mode
380          int buf = alloc_buffer(-1);
381          if (buf == -1) {
# Line 379 | Line 399 | uint8 D64Drive::open_file_ts(int channel
399   *  Create file and open channel for writing to file
400   */
401  
402 < uint8 D64Drive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite)
402 > uint8 ImageDrive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite)
403   {
404 +        D(bug("create_file %s, type %d\n", name, type));
405 +
406          // Allocate buffer
407          int buf = alloc_buffer(-1);
408          if (buf == -1) {
# Line 407 | Line 429 | uint8 D64Drive::create_file(int channel,
429                  return ST_OK;
430          }
431          ch[channel].num_blocks = 1;
432 +        D(bug(" first data block on track %d, sector %d\n", ch[channel].track, ch[channel].sector));
433  
434          // Write directory entry
435          memset(de, 0, SIZEOF_DE);
# Line 439 | Line 462 | const char type_char_1[] = "DSPUREER";
462   const char type_char_2[] = "EERSELQG";
463   const char type_char_3[] = "LQGRL???";
464  
465 < uint8 D64Drive::open_directory(const uint8 *pattern, int pattern_len)
465 > uint8 ImageDrive::open_directory(const uint8 *pattern, int pattern_len)
466   {
467          // Special treatment for "$0"
468          if (pattern[0] == '0' && pattern_len == 1) {
# Line 594 | Line 617 | uint8 D64Drive::open_directory(const uin
617   *  Open channel for direct buffer access
618   */
619  
620 < uint8 D64Drive::open_direct(int channel, const uint8 *name)
620 > uint8 ImageDrive::open_direct(int channel, const uint8 *name)
621   {
622          int buf = -1;
623  
# Line 627 | Line 650 | uint8 D64Drive::open_direct(int channel,
650   *  Close channel
651   */
652  
653 < uint8 D64Drive::Close(int channel)
653 > uint8 ImageDrive::Close(int channel)
654   {
655 +        D(bug("ImageDrive::Close channel %d\n", channel));
656 +
657          switch (ch[channel].mode) {
658                  case CHMOD_FREE:
659                          break;
# Line 655 | Line 680 | uint8 D64Drive::Close(int channel)
680                                  // Write last data block
681                                  ch[channel].buf[0] = 0;
682                                  ch[channel].buf[1] = ch[channel].buf_len - 1;
683 +                                D(bug(" writing last data block\n"));
684                                  if (!write_sector(ch[channel].track, ch[channel].sector, ch[channel].buf))
685                                          goto free;
686  
# Line 672 | Line 698 | uint8 D64Drive::Close(int channel)
698                                          de[DE_OVR_TRACK] = de[DE_OVR_SECTOR] = 0;
699                                  }
700                                  write_sector(ch[channel].dir_track, ch[channel].dir_sector, dir);
701 +                                D(bug(" directory entry updated\n"));
702                          }
703   free:           free_buffer(ch[channel].buf_num);
704                          ch[channel].buf = NULL;
# Line 693 | Line 720 | free:          free_buffer(ch[channel].buf_num);
720   *  Close all channels
721   */
722  
723 < void D64Drive::close_all_channels()
723 > void ImageDrive::close_all_channels()
724   {
725          for (int i=0; i<15; i++)
726                  Close(i);
# Line 708 | Line 735 | void D64Drive::close_all_channels()
735   *  Read from channel
736   */
737  
738 < uint8 D64Drive::Read(int channel, uint8 &byte)
738 > uint8 ImageDrive::Read(int channel, uint8 &byte)
739   {
740 + //      D(bug("ImageDrive::Read channel %d\n", channel));
741 +
742          switch (ch[channel].mode) {
743                  case CHMOD_FREE:
744                          if (current_error == ERR_OK)
# Line 735 | Line 764 | uint8 D64Drive::Read(int channel, uint8
764  
765                          // Read next block if necessary
766                          if (ch[channel].buf_len == 0 && ch[channel].buf[0]) {
767 +                                D(bug(" reading next data block track %d, sector %d\n", ch[channel].buf[0], ch[channel].buf[1]));
768                                  if (!read_sector(ch[channel].buf[0], ch[channel].buf[1], ch[channel].buf))
769                                          return ST_READ_TIMEOUT;
770                                  ch[channel].buf_ptr = ch[channel].buf + 2;
# Line 773 | Line 803 | uint8 D64Drive::Read(int channel, uint8
803   *  Write byte to channel
804   */
805  
806 < uint8 D64Drive::Write(int channel, uint8 byte, bool eoi)
806 > uint8 ImageDrive::Write(int channel, uint8 byte, bool eoi)
807   {
808 + //      D(bug("ImageDrive::Write channel %d, byte %02x, eoi %d\n", channel, byte, eoi));
809 +
810          switch (ch[channel].mode) {
811                  case CHMOD_FREE:
812                          if (current_error == ERR_OK)
# Line 814 | Line 846 | uint8 D64Drive::Write(int channel, uint8
846                                  if (!alloc_next_block(track, sector, DATA_INTERLEAVE))
847                                          return ST_TIMEOUT;
848                                  ch[channel].num_blocks++;
849 +                                D(bug("next data block on track %d, sector %d\n", track, sector));
850  
851                                  // Write buffer with link to new block
852                                  ch[channel].buf[0] = track;
# Line 847 | Line 880 | uint8 D64Drive::Write(int channel, uint8
880   *  Reset drive
881   */
882  
883 < void D64Drive::Reset(void)
883 > void ImageDrive::Reset(void)
884   {
885          close_all_channels();
886  
# Line 874 | Line 907 | void D64Drive::Reset(void)
907   *   <- Allocated buffer number or -1
908   */
909  
910 < int D64Drive::alloc_buffer(int want)
910 > int ImageDrive::alloc_buffer(int want)
911   {
912          if (want == -1) {
913                  for (want=3; want>=0; want--)
# Line 900 | Line 933 | int D64Drive::alloc_buffer(int want)
933   *  Free floppy buffer
934   */
935  
936 < void D64Drive::free_buffer(int buf)
936 > void ImageDrive::free_buffer(int buf)
937   {
938          buf_free[buf] = true;
939   }
# Line 929 | Line 962 | static bool match(const uint8 *p, int p_
962          return *n == 0xa0 || c == 16;
963   }
964  
965 < bool D64Drive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont)
965 > bool ImageDrive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont)
966   {
967          // Counter to prevent cyclic directories from resulting in an infinite loop
968          int num_dir_blocks = 0;
# Line 967 | Line 1000 | bool D64Drive::find_file(const uint8 *pa
1000          return false;
1001   }
1002  
1003 < bool D64Drive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1003 > bool ImageDrive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1004   {
1005          return find_file(pattern, pattern_len, dir_track, dir_sector, entry, false);
1006   }
1007  
1008 < bool D64Drive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1008 > bool ImageDrive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1009   {
1010          return find_file(pattern, pattern_len, dir_track, dir_sector, entry, true);
1011   }
# Line 984 | Line 1017 | bool D64Drive::find_next_file(const uint
1017   *  The track/sector and entry numbers are returned
1018   */
1019  
1020 < bool D64Drive::alloc_dir_entry(int &track, int &sector, int &entry)
1020 > bool ImageDrive::alloc_dir_entry(int &track, int &sector, int &entry)
1021   {
1022          // First look for free entry in existing directory blocks
1023          dir[DIR_NEXT_TRACK] = DIR_TRACK;
# Line 995 | Line 1028 | bool D64Drive::alloc_dir_entry(int &trac
1028  
1029                  uint8 *de = dir + DIR_ENTRIES;
1030                  for (entry=0; entry<8; entry++, de+=SIZEOF_DE) {
1031 <                        if (de[DE_TYPE] == 0)
1031 >                        if (de[DE_TYPE] == 0) {
1032 >                                D(bug(" allocated entry %d in dir track %d, sector %d\n", entry, track, sector));
1033                                  return true;
1034 +                        }
1035                  }
1036          }
1037  
# Line 1004 | Line 1039 | bool D64Drive::alloc_dir_entry(int &trac
1039          int last_track = track, last_sector = sector;
1040          if (!alloc_next_block(track, sector, DIR_INTERLEAVE))
1041                  return false;
1042 +        D(bug(" new directory block track %d, sector %d\n", track, sector));
1043  
1044          // Write link to new block to last block
1045          dir[DIR_NEXT_TRACK] = track;
# Line 1022 | Line 1058 | bool D64Drive::alloc_dir_entry(int &trac
1058   *  Test if block is free in BAM (track/sector are not checked for validity)
1059   */
1060  
1061 < bool D64Drive::is_block_free(int track, int sector)
1061 > bool ImageDrive::is_block_free(int track, int sector)
1062   {
1063          uint8 *p = bam + BAM_BITMAP + (track - 1) * 4;
1064          int byte = sector / 8 + 1;
# Line 1035 | Line 1071 | bool D64Drive::is_block_free(int track,
1071   *  Get number of free blocks on a track
1072   */
1073  
1074 < int D64Drive::num_free_blocks(int track)
1074 > int ImageDrive::num_free_blocks(int track)
1075   {
1076          return bam[BAM_BITMAP + (track - 1) * 4];
1077   }
# Line 1061 | Line 1097 | static void clear_bam(uint8 *bam)
1097   *  Allocate block in BAM, returns error code
1098   */
1099  
1100 < int D64Drive::alloc_block(int track, int sector)
1100 > int ImageDrive::alloc_block(int track, int sector)
1101   {
1102          if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track])
1103                  return ERR_ILLEGALTS;
# Line 1074 | Line 1110 | int D64Drive::alloc_block(int track, int
1110          if (p[byte] & (1 << bit)) {
1111  
1112                  // Yes, allocate and decrement free block count
1113 +                D(bug("allocating block at track %d, sector %d\n", track, sector));
1114                  p[byte] &= ~(1 << bit);
1115                  p[0]--;
1116                  bam_dirty = true;
# Line 1088 | Line 1125 | int D64Drive::alloc_block(int track, int
1125   *  Free block in BAM, returns error code
1126   */
1127  
1128 < int D64Drive::free_block(int track, int sector)
1128 > int ImageDrive::free_block(int track, int sector)
1129   {
1130          if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track])
1131                  return ERR_ILLEGALTS;
# Line 1101 | Line 1138 | int D64Drive::free_block(int track, int
1138          if (!(p[byte] & (1 << bit))) {
1139  
1140                  // Yes, free and increment free block count
1141 +                D(bug("freeing block at track %d, sector %d\n", track, sector));
1142                  p[byte] |= (1 << bit);
1143                  p[0]++;
1144                  bam_dirty = true;
# Line 1113 | Line 1151 | int D64Drive::free_block(int track, int
1151   *  Allocate chain of data blocks in BAM
1152   */
1153  
1154 < bool D64Drive::alloc_block_chain(int track, int sector)
1154 > bool ImageDrive::alloc_block_chain(int track, int sector)
1155   {
1156          uint8 buf[256];
1157          while (alloc_block(track, sector) == ERR_OK) {
# Line 1130 | Line 1168 | bool D64Drive::alloc_block_chain(int tra
1168   *  Free chain of data blocks in BAM
1169   */
1170  
1171 < bool D64Drive::free_block_chain(int track, int sector)
1171 > bool ImageDrive::free_block_chain(int track, int sector)
1172   {
1173          uint8 buf[256];
1174          while (free_block(track, sector) == ERR_OK) {
# Line 1150 | Line 1188 | bool D64Drive::free_block_chain(int trac
1188   *  begin
1189   */
1190  
1191 < bool D64Drive::alloc_next_block(int &track, int &sector, int interleave)
1191 > bool ImageDrive::alloc_next_block(int &track, int &sector, int interleave)
1192   {
1193          // Find track with free blocks
1194          bool side_changed = false;
# Line 1262 | Line 1300 | const int conv_job_error[16] = {
1300   };
1301  
1302   // Read sector, return error code
1303 < int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1303 > static int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1304   {
1305          // Convert track/sector to byte offset in file
1306          long offset = offset_from_ts(desc, track, sector);
# Line 1282 | Line 1320 | int read_sector(FILE *f, const image_fil
1320   }
1321  
1322   // Write sector, return error code
1323 < int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1323 > static int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1324   {
1325          // Convert track/sector to byte offset in file
1326          long offset = offset_from_ts(desc, track, sector);
# Line 1300 | Line 1338 | int write_sector(FILE *f, const image_fi
1338   }
1339  
1340   // Read sector and set error message, returns false on error
1341 < bool D64Drive::read_sector(int track, int sector, uint8 *buffer)
1341 > bool ImageDrive::read_sector(int track, int sector, uint8 *buffer)
1342   {
1343          int error = ::read_sector(the_file, desc, track, sector, buffer);
1344          if (error)
# Line 1309 | Line 1347 | bool D64Drive::read_sector(int track, in
1347   }
1348  
1349   // Write sector and set error message, returns false on error
1350 < bool D64Drive::write_sector(int track, int sector, uint8 *buffer)
1350 > bool ImageDrive::write_sector(int track, int sector, uint8 *buffer)
1351   {
1352          int error = ::write_sector(the_file, desc, track, sector, buffer);
1353          if (error)
# Line 1318 | Line 1356 | bool D64Drive::write_sector(int track, i
1356   }
1357  
1358   // Write error info back to image file
1359 < void write_back_error_info(FILE *f, const image_file_desc &desc)
1359 > static void write_back_error_info(FILE *f, const image_file_desc &desc)
1360   {
1361          if (desc.type == TYPE_D64 && desc.has_error_info) {
1362                  int num_sectors = desc.num_tracks == 40 ? NUM_SECTORS_40 : NUM_SECTORS_35;
# Line 1328 | Line 1366 | void write_back_error_info(FILE *f, cons
1366   }
1367  
1368   // Format disk image
1369 < bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len)
1369 > static bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len)
1370   {
1371          uint8 p[256];
1372  
# Line 1392 | Line 1430 | bool format_image(FILE *f, image_file_de
1430   */
1431  
1432   // BLOCK-READ:channel,0,track,sector
1433 < void D64Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
1433 > void ImageDrive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
1434   {
1435          if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) {
1436                  set_error(ERR_NOCHANNEL);
# Line 1410 | Line 1448 | void D64Drive::block_read_cmd(int channe
1448   }
1449  
1450   // BLOCK-WRITE:channel,0,track,sector
1451 < void D64Drive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
1451 > void ImageDrive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
1452   {
1453          if (write_protected) {
1454                  set_error(ERR_WRITEPROTECT);
# Line 1431 | Line 1469 | void D64Drive::block_write_cmd(int chann
1469   }
1470  
1471   // BLOCK-ALLOCATE:0,track,sector
1472 < void D64Drive::block_allocate_cmd(int track, int sector)
1472 > void ImageDrive::block_allocate_cmd(int track, int sector)
1473   {
1474          int err = alloc_block(track, sector);
1475          if (err) {
# Line 1459 | Line 1497 | void D64Drive::block_allocate_cmd(int tr
1497   }
1498  
1499   // BLOCK-FREE:0,track,sector
1500 < void D64Drive::block_free_cmd(int track, int sector)
1500 > void ImageDrive::block_free_cmd(int track, int sector)
1501   {
1502          int err = free_block(track, sector);
1503          if (err)
# Line 1467 | Line 1505 | void D64Drive::block_free_cmd(int track,
1505   }
1506  
1507   // BUFFER-POINTER:channel,pos
1508 < void D64Drive::buffer_pointer_cmd(int channel, int pos)
1508 > void ImageDrive::buffer_pointer_cmd(int channel, int pos)
1509   {
1510          if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) {
1511                  set_error(ERR_NOCHANNEL);
# Line 1478 | Line 1516 | void D64Drive::buffer_pointer_cmd(int ch
1516   }
1517  
1518   // M-R<adr low><adr high>[<number>]
1519 < void D64Drive::mem_read_cmd(uint16 adr, uint8 len)
1519 > void ImageDrive::mem_read_cmd(uint16 adr, uint8 len)
1520   {
1521          error_len = len;
1522          if (adr >= 0x300 && adr < 0x1000) {
# Line 1495 | Line 1533 | void D64Drive::mem_read_cmd(uint16 adr,
1533   }
1534  
1535   // M-W<adr low><adr high><number><data...>
1536 < void D64Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
1536 > void ImageDrive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
1537   {
1538          while (len) {
1539                  if (adr >= 0x300 && adr < 0x1000) {
# Line 1512 | Line 1550 | void D64Drive::mem_write_cmd(uint16 adr,
1550   //   COPY:new=file1,file2,...
1551   //        ^   ^
1552   // new_file   old_files
1553 < void D64Drive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
1553 > void ImageDrive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
1554   {
1555          // Check if destination file is already present
1556          int dir_track, dir_sector, entry;
# Line 1575 | Line 1613 | void D64Drive::copy_cmd(const uint8 *new
1613   // RENAME:new=old
1614   //        ^   ^
1615   // new_file   old_file
1616 < void D64Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
1616 > void ImageDrive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
1617   {
1618          // Check if destination file is already present
1619          int dir_track, dir_sector, entry;
# Line 1606 | Line 1644 | void D64Drive::rename_cmd(const uint8 *n
1644   // SCRATCH:file1,file2,...
1645   //         ^
1646   //         files
1647 < void D64Drive::scratch_cmd(const uint8 *files, int files_len)
1647 > void ImageDrive::scratch_cmd(const uint8 *files, int files_len)
1648   {
1649          // Check for write-protection
1650          if (write_protected) {
# Line 1654 | Line 1692 | void D64Drive::scratch_cmd(const uint8 *
1692   }
1693  
1694   // INITIALIZE
1695 < void D64Drive::initialize_cmd(void)
1695 > void ImageDrive::initialize_cmd(void)
1696   {
1697          // Close all channels and re-read BAM
1698          close_all_channels();
# Line 1668 | Line 1706 | void D64Drive::initialize_cmd(void)
1706   // NEW:name,id
1707   //     ^   ^
1708   //  name   comma (or NULL)
1709 < void D64Drive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
1709 > void ImageDrive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
1710   {
1711          // Check for write-protection
1712          if (write_protected) {
# Line 1705 | Line 1743 | void D64Drive::new_cmd(const uint8 *name
1743   }
1744  
1745   // VALIDATE
1746 < void D64Drive::validate_cmd(void)
1746 > void ImageDrive::validate_cmd(void)
1747   {
1748          // Backup of old BAM in case something goes amiss
1749          uint8 old_bam[256];
# Line 1925 | Line 1963 | error:
1963   *  Open disk image file, return file handle
1964   */
1965  
1966 < FILE *open_image_file(const char *path, bool write_mode)
1966 > static FILE *open_image_file(const char *path, bool write_mode)
1967   {
1968   #if 0
1969          if (is_zipcode_file(path)) {
# Line 2009 | Line 2047 | static bool parse_x64_file(FILE *f, imag
2047          return true;
2048   }
2049  
2050 < bool parse_image_file(FILE *f, image_file_desc &desc)
2050 > static bool parse_image_file(FILE *f, image_file_desc &desc)
2051   {
2052          // Read header
2053          uint8 header[64];
# Line 2031 | Line 2069 | bool parse_image_file(FILE *f, image_fil
2069   }
2070  
2071  
2072 + /*
2073 + *  Read directory of disk image file into (empty) c64_dir_entry vector,
2074 + *  returns false on error
2075 + */
2076 +
2077 + bool ReadImageDirectory(const char *path, vector<c64_dir_entry> &vec)
2078 + {
2079 +        bool result = false;
2080 +
2081 +        // Open file
2082 +        FILE *f = open_image_file(path, false);
2083 +        if (f) {
2084 +                int num_dir_blocks = 0;
2085 +
2086 +                // Determine file type and fill in image_file_desc structure
2087 +                image_file_desc desc;
2088 +                if (!parse_image_file(f, desc))
2089 +                        goto done;
2090 +
2091 +                // Scan all directory blocks
2092 +                uint8 dir[256];
2093 +                dir[DIR_NEXT_TRACK] = DIR_TRACK;
2094 +                dir[DIR_NEXT_SECTOR] = 1;
2095 +
2096 +                while (dir[DIR_NEXT_TRACK] && num_dir_blocks < num_sectors[DIR_TRACK]) {
2097 +                        if (read_sector(f, desc, dir[DIR_NEXT_TRACK], dir[DIR_NEXT_SECTOR], dir) != ERR_OK)
2098 +                                break;
2099 +                        num_dir_blocks++;
2100 +
2101 +                        // Scan all 8 entries of a block
2102 +                        uint8 *de = dir + DIR_ENTRIES;
2103 +                        for (int j=0; j<8; j++, de+=SIZEOF_DE) {
2104 +
2105 +                                // Skip empty entries
2106 +                                if (de[DE_TYPE] == 0)
2107 +                                        continue;
2108 +
2109 +                                // Convert file name (strip everything after and including the first trailing space)
2110 +                                uint8 name_buf[17];
2111 +                                memcpy(name_buf, de + DE_NAME, 16);
2112 +                                name_buf[16] = 0;
2113 +                                uint8 *p = (uint8 *)memchr(name_buf, 0xa0, 16);
2114 +                                if (p)
2115 +                                        *p = 0;
2116 +
2117 +                                // Convert file type
2118 +                                int type = de[DE_TYPE] & 7;
2119 +                                if (type > 4)
2120 +                                        type = FTYPE_UNKNOWN;
2121 +
2122 +                                // Read start address
2123 +                                uint8 sa_lo = 0, sa_hi = 0;
2124 +                                uint8 buf[256];
2125 +                                if (read_sector(f, desc, de[DE_TRACK], de[DE_SECTOR], buf) == ERR_OK) {
2126 +                                        sa_lo = buf[2];
2127 +                                        sa_hi = buf[3];
2128 +                                }
2129 +
2130 +                                // Add entry
2131 +                                vec.push_back(c64_dir_entry(name_buf, type, !(de[DE_TYPE] & 0x80), de[DE_TYPE] & 0x40, ((de[DE_NUM_BLOCKS_H] << 8) + de[DE_NUM_BLOCKS_L]) * 254, 0, sa_lo, sa_hi));
2132 +                        }
2133 +                }
2134 +
2135 +                result = true;
2136 + done:   fclose(f);
2137 +        }
2138 +        return result;
2139 + }
2140 +
2141 +
2142   /*
2143   *  Create new blank disk image file, returns false on error
2144   */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines