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.9 by cebix, 2004-01-14T16:46:17Z

# 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 (C) 1994-1997,2002-2004 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          for (int i=0; i<18; i++) {
123                  ch[i].mode = CHMOD_FREE;
# Line 132 | Line 137 | D64Drive::D64Drive(IEC *iec, const char
137   *  Destructor
138   */
139  
140 < D64Drive::~D64Drive()
140 > ImageDrive::~ImageDrive()
141   {
142          close_image();
143   }
# Line 142 | Line 147 | D64Drive::~D64Drive()
147   *  Close the image file
148   */
149  
150 < void D64Drive::close_image(void)
150 > void ImageDrive::close_image(void)
151   {
152          if (the_file) {
153                  close_all_channels();
# Line 160 | Line 165 | void D64Drive::close_image(void)
165   *  Open the image file
166   */
167  
168 < bool D64Drive::change_image(const char *path)
168 > bool ImageDrive::change_image(const char *path)
169   {
170          // Close old image file
171          close_image();
# Line 194 | Line 199 | bool D64Drive::change_image(const char *
199   *  Open channel
200   */
201  
202 < uint8 D64Drive::Open(int channel, const uint8 *name, int name_len)
202 > uint8 ImageDrive::Open(int channel, const uint8 *name, int name_len)
203   {
204 +        D(bug("ImageDrive::Open channel %d, file %s\n", channel, name));
205 +
206          set_error(ERR_OK);
207  
208          // Channel 15: execute file name as command
# Line 226 | Line 233 | uint8 D64Drive::Open(int channel, const
233   *  Open file
234   */
235  
236 < uint8 D64Drive::open_file(int channel, const uint8 *name, int name_len)
236 > uint8 ImageDrive::open_file(int channel, const uint8 *name, int name_len)
237   {
238          uint8 plain_name[NAMEBUF_LENGTH];
239          int plain_name_len;
# Line 237 | Line 244 | uint8 D64Drive::open_file(int channel, c
244          if (plain_name_len > 16)
245                  plain_name_len = 16;
246  
247 +        D(bug(" plain name %s, type %d, mode %d\n", plain_name, type, mode));
248 +
249          // Channel 0 is READ, channel 1 is WRITE
250          if (channel == 0 || channel == 1) {
251                  mode = channel ? FMODE_WRITE : FMODE_READ;
# Line 269 | Line 278 | uint8 D64Drive::open_file(int channel, c
278          if (find_first_file(plain_name, plain_name_len, dir_track, dir_sector, entry)) {
279  
280                  // File exists
281 +                D(bug(" file exists, dir track %d, sector %d, entry %d\n", dir_track, dir_sector, entry));
282                  ch[channel].dir_track = dir_track;
283                  ch[channel].dir_sector = dir_sector;
284                  ch[channel].entry = entry;
# Line 334 | Line 344 | uint8 D64Drive::open_file(int channel, c
344          } else {
345  
346                  // File doesn't exist
347 +                D(bug(" file not found\n"));
348 +
349                  // Set file type to SEQ if not specified in file name
350                  if (type == FTYPE_DEL)
351                          type = FTYPE_SEQ;
# Line 354 | Line 366 | uint8 D64Drive::open_file(int channel, c
366   *  Open channel for reading from file given track/sector of first block
367   */
368  
369 < uint8 D64Drive::open_file_ts(int channel, int track, int sector)
369 > uint8 ImageDrive::open_file_ts(int channel, int track, int sector)
370   {
371 +        D(bug("open_file_ts track %d, sector %d\n", track, sector));
372 +
373          // Allocate buffer and set channel mode
374          int buf = alloc_buffer(-1);
375          if (buf == -1) {
# Line 379 | Line 393 | uint8 D64Drive::open_file_ts(int channel
393   *  Create file and open channel for writing to file
394   */
395  
396 < uint8 D64Drive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite)
396 > uint8 ImageDrive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite)
397   {
398 +        D(bug("create_file %s, type %d\n", name, type));
399 +
400          // Allocate buffer
401          int buf = alloc_buffer(-1);
402          if (buf == -1) {
# Line 407 | Line 423 | uint8 D64Drive::create_file(int channel,
423                  return ST_OK;
424          }
425          ch[channel].num_blocks = 1;
426 +        D(bug(" first data block on track %d, sector %d\n", ch[channel].track, ch[channel].sector));
427  
428          // Write directory entry
429          memset(de, 0, SIZEOF_DE);
# Line 439 | Line 456 | const char type_char_1[] = "DSPUREER";
456   const char type_char_2[] = "EERSELQG";
457   const char type_char_3[] = "LQGRL???";
458  
459 < uint8 D64Drive::open_directory(const uint8 *pattern, int pattern_len)
459 > uint8 ImageDrive::open_directory(const uint8 *pattern, int pattern_len)
460   {
461          // Special treatment for "$0"
462          if (pattern[0] == '0' && pattern_len == 1) {
# Line 594 | Line 611 | uint8 D64Drive::open_directory(const uin
611   *  Open channel for direct buffer access
612   */
613  
614 < uint8 D64Drive::open_direct(int channel, const uint8 *name)
614 > uint8 ImageDrive::open_direct(int channel, const uint8 *name)
615   {
616          int buf = -1;
617  
# Line 627 | Line 644 | uint8 D64Drive::open_direct(int channel,
644   *  Close channel
645   */
646  
647 < uint8 D64Drive::Close(int channel)
647 > uint8 ImageDrive::Close(int channel)
648   {
649 +        D(bug("ImageDrive::Close channel %d\n", channel));
650 +
651          switch (ch[channel].mode) {
652                  case CHMOD_FREE:
653                          break;
# Line 655 | Line 674 | uint8 D64Drive::Close(int channel)
674                                  // Write last data block
675                                  ch[channel].buf[0] = 0;
676                                  ch[channel].buf[1] = ch[channel].buf_len - 1;
677 +                                D(bug(" writing last data block\n"));
678                                  if (!write_sector(ch[channel].track, ch[channel].sector, ch[channel].buf))
679                                          goto free;
680  
# Line 672 | Line 692 | uint8 D64Drive::Close(int channel)
692                                          de[DE_OVR_TRACK] = de[DE_OVR_SECTOR] = 0;
693                                  }
694                                  write_sector(ch[channel].dir_track, ch[channel].dir_sector, dir);
695 +                                D(bug(" directory entry updated\n"));
696                          }
697   free:           free_buffer(ch[channel].buf_num);
698                          ch[channel].buf = NULL;
# Line 693 | Line 714 | free:          free_buffer(ch[channel].buf_num);
714   *  Close all channels
715   */
716  
717 < void D64Drive::close_all_channels()
717 > void ImageDrive::close_all_channels()
718   {
719          for (int i=0; i<15; i++)
720                  Close(i);
# Line 708 | Line 729 | void D64Drive::close_all_channels()
729   *  Read from channel
730   */
731  
732 < uint8 D64Drive::Read(int channel, uint8 &byte)
732 > uint8 ImageDrive::Read(int channel, uint8 &byte)
733   {
734 + //      D(bug("ImageDrive::Read channel %d\n", channel));
735 +
736          switch (ch[channel].mode) {
737                  case CHMOD_FREE:
738                          if (current_error == ERR_OK)
# Line 735 | Line 758 | uint8 D64Drive::Read(int channel, uint8
758  
759                          // Read next block if necessary
760                          if (ch[channel].buf_len == 0 && ch[channel].buf[0]) {
761 +                                D(bug(" reading next data block track %d, sector %d\n", ch[channel].buf[0], ch[channel].buf[1]));
762                                  if (!read_sector(ch[channel].buf[0], ch[channel].buf[1], ch[channel].buf))
763                                          return ST_READ_TIMEOUT;
764                                  ch[channel].buf_ptr = ch[channel].buf + 2;
# Line 773 | Line 797 | uint8 D64Drive::Read(int channel, uint8
797   *  Write byte to channel
798   */
799  
800 < uint8 D64Drive::Write(int channel, uint8 byte, bool eoi)
800 > uint8 ImageDrive::Write(int channel, uint8 byte, bool eoi)
801   {
802 + //      D(bug("ImageDrive::Write channel %d, byte %02x, eoi %d\n", channel, byte, eoi));
803 +
804          switch (ch[channel].mode) {
805                  case CHMOD_FREE:
806                          if (current_error == ERR_OK)
# Line 814 | Line 840 | uint8 D64Drive::Write(int channel, uint8
840                                  if (!alloc_next_block(track, sector, DATA_INTERLEAVE))
841                                          return ST_TIMEOUT;
842                                  ch[channel].num_blocks++;
843 +                                D(bug("next data block on track %d, sector %d\n", track, sector));
844  
845                                  // Write buffer with link to new block
846                                  ch[channel].buf[0] = track;
# Line 847 | Line 874 | uint8 D64Drive::Write(int channel, uint8
874   *  Reset drive
875   */
876  
877 < void D64Drive::Reset(void)
877 > void ImageDrive::Reset(void)
878   {
879          close_all_channels();
880  
# Line 874 | Line 901 | void D64Drive::Reset(void)
901   *   <- Allocated buffer number or -1
902   */
903  
904 < int D64Drive::alloc_buffer(int want)
904 > int ImageDrive::alloc_buffer(int want)
905   {
906          if (want == -1) {
907                  for (want=3; want>=0; want--)
# Line 900 | Line 927 | int D64Drive::alloc_buffer(int want)
927   *  Free floppy buffer
928   */
929  
930 < void D64Drive::free_buffer(int buf)
930 > void ImageDrive::free_buffer(int buf)
931   {
932          buf_free[buf] = true;
933   }
# Line 929 | Line 956 | static bool match(const uint8 *p, int p_
956          return *n == 0xa0 || c == 16;
957   }
958  
959 < bool D64Drive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont)
959 > bool ImageDrive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont)
960   {
961          // Counter to prevent cyclic directories from resulting in an infinite loop
962          int num_dir_blocks = 0;
# Line 967 | Line 994 | bool D64Drive::find_file(const uint8 *pa
994          return false;
995   }
996  
997 < bool D64Drive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
997 > bool ImageDrive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
998   {
999          return find_file(pattern, pattern_len, dir_track, dir_sector, entry, false);
1000   }
1001  
1002 < bool D64Drive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1002 > bool ImageDrive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1003   {
1004          return find_file(pattern, pattern_len, dir_track, dir_sector, entry, true);
1005   }
# Line 984 | Line 1011 | bool D64Drive::find_next_file(const uint
1011   *  The track/sector and entry numbers are returned
1012   */
1013  
1014 < bool D64Drive::alloc_dir_entry(int &track, int &sector, int &entry)
1014 > bool ImageDrive::alloc_dir_entry(int &track, int &sector, int &entry)
1015   {
1016          // First look for free entry in existing directory blocks
1017          dir[DIR_NEXT_TRACK] = DIR_TRACK;
# Line 995 | Line 1022 | bool D64Drive::alloc_dir_entry(int &trac
1022  
1023                  uint8 *de = dir + DIR_ENTRIES;
1024                  for (entry=0; entry<8; entry++, de+=SIZEOF_DE) {
1025 <                        if (de[DE_TYPE] == 0)
1025 >                        if (de[DE_TYPE] == 0) {
1026 >                                D(bug(" allocated entry %d in dir track %d, sector %d\n", entry, track, sector));
1027                                  return true;
1028 +                        }
1029                  }
1030          }
1031  
# Line 1004 | Line 1033 | bool D64Drive::alloc_dir_entry(int &trac
1033          int last_track = track, last_sector = sector;
1034          if (!alloc_next_block(track, sector, DIR_INTERLEAVE))
1035                  return false;
1036 +        D(bug(" new directory block track %d, sector %d\n", track, sector));
1037  
1038          // Write link to new block to last block
1039          dir[DIR_NEXT_TRACK] = track;
# Line 1022 | Line 1052 | bool D64Drive::alloc_dir_entry(int &trac
1052   *  Test if block is free in BAM (track/sector are not checked for validity)
1053   */
1054  
1055 < bool D64Drive::is_block_free(int track, int sector)
1055 > bool ImageDrive::is_block_free(int track, int sector)
1056   {
1057          uint8 *p = bam + BAM_BITMAP + (track - 1) * 4;
1058          int byte = sector / 8 + 1;
# Line 1035 | Line 1065 | bool D64Drive::is_block_free(int track,
1065   *  Get number of free blocks on a track
1066   */
1067  
1068 < int D64Drive::num_free_blocks(int track)
1068 > int ImageDrive::num_free_blocks(int track)
1069   {
1070          return bam[BAM_BITMAP + (track - 1) * 4];
1071   }
# Line 1061 | Line 1091 | static void clear_bam(uint8 *bam)
1091   *  Allocate block in BAM, returns error code
1092   */
1093  
1094 < int D64Drive::alloc_block(int track, int sector)
1094 > int ImageDrive::alloc_block(int track, int sector)
1095   {
1096          if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track])
1097                  return ERR_ILLEGALTS;
# Line 1074 | Line 1104 | int D64Drive::alloc_block(int track, int
1104          if (p[byte] & (1 << bit)) {
1105  
1106                  // Yes, allocate and decrement free block count
1107 +                D(bug("allocating block at track %d, sector %d\n", track, sector));
1108                  p[byte] &= ~(1 << bit);
1109                  p[0]--;
1110                  bam_dirty = true;
# Line 1088 | Line 1119 | int D64Drive::alloc_block(int track, int
1119   *  Free block in BAM, returns error code
1120   */
1121  
1122 < int D64Drive::free_block(int track, int sector)
1122 > int ImageDrive::free_block(int track, int sector)
1123   {
1124          if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track])
1125                  return ERR_ILLEGALTS;
# Line 1101 | Line 1132 | int D64Drive::free_block(int track, int
1132          if (!(p[byte] & (1 << bit))) {
1133  
1134                  // Yes, free and increment free block count
1135 +                D(bug("freeing block at track %d, sector %d\n", track, sector));
1136                  p[byte] |= (1 << bit);
1137                  p[0]++;
1138                  bam_dirty = true;
# Line 1113 | Line 1145 | int D64Drive::free_block(int track, int
1145   *  Allocate chain of data blocks in BAM
1146   */
1147  
1148 < bool D64Drive::alloc_block_chain(int track, int sector)
1148 > bool ImageDrive::alloc_block_chain(int track, int sector)
1149   {
1150          uint8 buf[256];
1151          while (alloc_block(track, sector) == ERR_OK) {
# Line 1130 | Line 1162 | bool D64Drive::alloc_block_chain(int tra
1162   *  Free chain of data blocks in BAM
1163   */
1164  
1165 < bool D64Drive::free_block_chain(int track, int sector)
1165 > bool ImageDrive::free_block_chain(int track, int sector)
1166   {
1167          uint8 buf[256];
1168          while (free_block(track, sector) == ERR_OK) {
# Line 1150 | Line 1182 | bool D64Drive::free_block_chain(int trac
1182   *  begin
1183   */
1184  
1185 < bool D64Drive::alloc_next_block(int &track, int &sector, int interleave)
1185 > bool ImageDrive::alloc_next_block(int &track, int &sector, int interleave)
1186   {
1187          // Find track with free blocks
1188          bool side_changed = false;
# Line 1262 | Line 1294 | const int conv_job_error[16] = {
1294   };
1295  
1296   // Read sector, return error code
1297 < int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1297 > static int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1298   {
1299          // Convert track/sector to byte offset in file
1300          long offset = offset_from_ts(desc, track, sector);
# Line 1282 | Line 1314 | int read_sector(FILE *f, const image_fil
1314   }
1315  
1316   // Write sector, return error code
1317 < int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1317 > static int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer)
1318   {
1319          // Convert track/sector to byte offset in file
1320          long offset = offset_from_ts(desc, track, sector);
# Line 1300 | Line 1332 | int write_sector(FILE *f, const image_fi
1332   }
1333  
1334   // Read sector and set error message, returns false on error
1335 < bool D64Drive::read_sector(int track, int sector, uint8 *buffer)
1335 > bool ImageDrive::read_sector(int track, int sector, uint8 *buffer)
1336   {
1337          int error = ::read_sector(the_file, desc, track, sector, buffer);
1338          if (error)
# Line 1309 | Line 1341 | bool D64Drive::read_sector(int track, in
1341   }
1342  
1343   // Write sector and set error message, returns false on error
1344 < bool D64Drive::write_sector(int track, int sector, uint8 *buffer)
1344 > bool ImageDrive::write_sector(int track, int sector, uint8 *buffer)
1345   {
1346          int error = ::write_sector(the_file, desc, track, sector, buffer);
1347          if (error)
# Line 1318 | Line 1350 | bool D64Drive::write_sector(int track, i
1350   }
1351  
1352   // Write error info back to image file
1353 < void write_back_error_info(FILE *f, const image_file_desc &desc)
1353 > static void write_back_error_info(FILE *f, const image_file_desc &desc)
1354   {
1355          if (desc.type == TYPE_D64 && desc.has_error_info) {
1356                  int num_sectors = desc.num_tracks == 40 ? NUM_SECTORS_40 : NUM_SECTORS_35;
# Line 1328 | Line 1360 | void write_back_error_info(FILE *f, cons
1360   }
1361  
1362   // Format disk image
1363 < bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len)
1363 > static bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len)
1364   {
1365          uint8 p[256];
1366  
# Line 1392 | Line 1424 | bool format_image(FILE *f, image_file_de
1424   */
1425  
1426   // BLOCK-READ:channel,0,track,sector
1427 < void D64Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
1427 > void ImageDrive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
1428   {
1429          if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) {
1430                  set_error(ERR_NOCHANNEL);
# Line 1410 | Line 1442 | void D64Drive::block_read_cmd(int channe
1442   }
1443  
1444   // BLOCK-WRITE:channel,0,track,sector
1445 < void D64Drive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
1445 > void ImageDrive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
1446   {
1447          if (write_protected) {
1448                  set_error(ERR_WRITEPROTECT);
# Line 1431 | Line 1463 | void D64Drive::block_write_cmd(int chann
1463   }
1464  
1465   // BLOCK-ALLOCATE:0,track,sector
1466 < void D64Drive::block_allocate_cmd(int track, int sector)
1466 > void ImageDrive::block_allocate_cmd(int track, int sector)
1467   {
1468          int err = alloc_block(track, sector);
1469          if (err) {
# Line 1459 | Line 1491 | void D64Drive::block_allocate_cmd(int tr
1491   }
1492  
1493   // BLOCK-FREE:0,track,sector
1494 < void D64Drive::block_free_cmd(int track, int sector)
1494 > void ImageDrive::block_free_cmd(int track, int sector)
1495   {
1496          int err = free_block(track, sector);
1497          if (err)
# Line 1467 | Line 1499 | void D64Drive::block_free_cmd(int track,
1499   }
1500  
1501   // BUFFER-POINTER:channel,pos
1502 < void D64Drive::buffer_pointer_cmd(int channel, int pos)
1502 > void ImageDrive::buffer_pointer_cmd(int channel, int pos)
1503   {
1504          if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) {
1505                  set_error(ERR_NOCHANNEL);
# Line 1478 | Line 1510 | void D64Drive::buffer_pointer_cmd(int ch
1510   }
1511  
1512   // M-R<adr low><adr high>[<number>]
1513 < void D64Drive::mem_read_cmd(uint16 adr, uint8 len)
1513 > void ImageDrive::mem_read_cmd(uint16 adr, uint8 len)
1514   {
1515          error_len = len;
1516          if (adr >= 0x300 && adr < 0x1000) {
# Line 1495 | Line 1527 | void D64Drive::mem_read_cmd(uint16 adr,
1527   }
1528  
1529   // M-W<adr low><adr high><number><data...>
1530 < void D64Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
1530 > void ImageDrive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
1531   {
1532          while (len) {
1533                  if (adr >= 0x300 && adr < 0x1000) {
# Line 1512 | Line 1544 | void D64Drive::mem_write_cmd(uint16 adr,
1544   //   COPY:new=file1,file2,...
1545   //        ^   ^
1546   // new_file   old_files
1547 < void D64Drive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
1547 > void ImageDrive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
1548   {
1549          // Check if destination file is already present
1550          int dir_track, dir_sector, entry;
# Line 1575 | Line 1607 | void D64Drive::copy_cmd(const uint8 *new
1607   // RENAME:new=old
1608   //        ^   ^
1609   // new_file   old_file
1610 < void D64Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
1610 > void ImageDrive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
1611   {
1612          // Check if destination file is already present
1613          int dir_track, dir_sector, entry;
# Line 1606 | Line 1638 | void D64Drive::rename_cmd(const uint8 *n
1638   // SCRATCH:file1,file2,...
1639   //         ^
1640   //         files
1641 < void D64Drive::scratch_cmd(const uint8 *files, int files_len)
1641 > void ImageDrive::scratch_cmd(const uint8 *files, int files_len)
1642   {
1643          // Check for write-protection
1644          if (write_protected) {
# Line 1654 | Line 1686 | void D64Drive::scratch_cmd(const uint8 *
1686   }
1687  
1688   // INITIALIZE
1689 < void D64Drive::initialize_cmd(void)
1689 > void ImageDrive::initialize_cmd(void)
1690   {
1691          // Close all channels and re-read BAM
1692          close_all_channels();
# Line 1668 | Line 1700 | void D64Drive::initialize_cmd(void)
1700   // NEW:name,id
1701   //     ^   ^
1702   //  name   comma (or NULL)
1703 < void D64Drive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
1703 > void ImageDrive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
1704   {
1705          // Check for write-protection
1706          if (write_protected) {
# Line 1705 | Line 1737 | void D64Drive::new_cmd(const uint8 *name
1737   }
1738  
1739   // VALIDATE
1740 < void D64Drive::validate_cmd(void)
1740 > void ImageDrive::validate_cmd(void)
1741   {
1742          // Backup of old BAM in case something goes amiss
1743          uint8 old_bam[256];
# Line 1925 | Line 1957 | error:
1957   *  Open disk image file, return file handle
1958   */
1959  
1960 < FILE *open_image_file(const char *path, bool write_mode)
1960 > static FILE *open_image_file(const char *path, bool write_mode)
1961   {
1962   #if 0
1963          if (is_zipcode_file(path)) {
# Line 2009 | Line 2041 | static bool parse_x64_file(FILE *f, imag
2041          return true;
2042   }
2043  
2044 < bool parse_image_file(FILE *f, image_file_desc &desc)
2044 > static bool parse_image_file(FILE *f, image_file_desc &desc)
2045   {
2046          // Read header
2047          uint8 header[64];
# Line 2031 | Line 2063 | bool parse_image_file(FILE *f, image_fil
2063   }
2064  
2065  
2066 + /*
2067 + *  Read directory of disk image file into (empty) c64_dir_entry vector,
2068 + *  returns false on error
2069 + */
2070 +
2071 + bool ReadImageDirectory(const char *path, vector<c64_dir_entry> &vec)
2072 + {
2073 +        bool result = false;
2074 +
2075 +        // Open file
2076 +        FILE *f = open_image_file(path, false);
2077 +        if (f) {
2078 +                int num_dir_blocks = 0;
2079 +
2080 +                // Determine file type and fill in image_file_desc structure
2081 +                image_file_desc desc;
2082 +                if (!parse_image_file(f, desc))
2083 +                        goto done;
2084 +
2085 +                // Scan all directory blocks
2086 +                uint8 dir[256];
2087 +                dir[DIR_NEXT_TRACK] = DIR_TRACK;
2088 +                dir[DIR_NEXT_SECTOR] = 1;
2089 +
2090 +                while (dir[DIR_NEXT_TRACK] && num_dir_blocks < num_sectors[DIR_TRACK]) {
2091 +                        if (read_sector(f, desc, dir[DIR_NEXT_TRACK], dir[DIR_NEXT_SECTOR], dir) != ERR_OK)
2092 +                                break;
2093 +                        num_dir_blocks++;
2094 +
2095 +                        // Scan all 8 entries of a block
2096 +                        uint8 *de = dir + DIR_ENTRIES;
2097 +                        for (int j=0; j<8; j++, de+=SIZEOF_DE) {
2098 +
2099 +                                // Skip empty entries
2100 +                                if (de[DE_TYPE] == 0)
2101 +                                        continue;
2102 +
2103 +                                // Convert file name (strip everything after and including the first trailing space)
2104 +                                uint8 name_buf[17];
2105 +                                memcpy(name_buf, de + DE_NAME, 16);
2106 +                                name_buf[16] = 0;
2107 +                                uint8 *p = (uint8 *)memchr(name_buf, 0xa0, 16);
2108 +                                if (p)
2109 +                                        *p = 0;
2110 +
2111 +                                // Convert file type
2112 +                                int type = de[DE_TYPE] & 7;
2113 +                                if (type > 4)
2114 +                                        type = FTYPE_UNKNOWN;
2115 +
2116 +                                // Read start address
2117 +                                uint8 sa_lo = 0, sa_hi = 0;
2118 +                                uint8 buf[256];
2119 +                                if (read_sector(f, desc, de[DE_TRACK], de[DE_SECTOR], buf) == ERR_OK) {
2120 +                                        sa_lo = buf[2];
2121 +                                        sa_hi = buf[3];
2122 +                                }
2123 +
2124 +                                // Add entry
2125 +                                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));
2126 +                        }
2127 +                }
2128 +
2129 +                result = true;
2130 + done:   fclose(f);
2131 +        }
2132 +        return result;
2133 + }
2134 +
2135 +
2136   /*
2137   *  Create new blank disk image file, returns false on error
2138   */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines