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.8 by cebix, 2004-01-12T15:13:20Z

# 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 112 | Line 115 | static bool match(const uint8 *p, int p_
115   *  Constructor: Prepare emulation, open image file
116   */
117  
118 < D64Drive::D64Drive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false)
118 > ImageDrive::ImageDrive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false)
119   {
120          for (int i=0; i<18; i++) {
121                  ch[i].mode = CHMOD_FREE;
# Line 132 | Line 135 | D64Drive::D64Drive(IEC *iec, const char
135   *  Destructor
136   */
137  
138 < D64Drive::~D64Drive()
138 > ImageDrive::~ImageDrive()
139   {
140          close_image();
141   }
# Line 142 | Line 145 | D64Drive::~D64Drive()
145   *  Close the image file
146   */
147  
148 < void D64Drive::close_image(void)
148 > void ImageDrive::close_image(void)
149   {
150          if (the_file) {
151                  close_all_channels();
# Line 160 | Line 163 | void D64Drive::close_image(void)
163   *  Open the image file
164   */
165  
166 < bool D64Drive::change_image(const char *path)
166 > bool ImageDrive::change_image(const char *path)
167   {
168          // Close old image file
169          close_image();
# Line 194 | Line 197 | bool D64Drive::change_image(const char *
197   *  Open channel
198   */
199  
200 < uint8 D64Drive::Open(int channel, const uint8 *name, int name_len)
200 > uint8 ImageDrive::Open(int channel, const uint8 *name, int name_len)
201   {
202 +        D(bug("ImageDrive::Open channel %d, file %s\n", channel, name));
203 +
204          set_error(ERR_OK);
205  
206          // Channel 15: execute file name as command
# Line 226 | Line 231 | uint8 D64Drive::Open(int channel, const
231   *  Open file
232   */
233  
234 < uint8 D64Drive::open_file(int channel, const uint8 *name, int name_len)
234 > uint8 ImageDrive::open_file(int channel, const uint8 *name, int name_len)
235   {
236          uint8 plain_name[NAMEBUF_LENGTH];
237          int plain_name_len;
# Line 237 | Line 242 | uint8 D64Drive::open_file(int channel, c
242          if (plain_name_len > 16)
243                  plain_name_len = 16;
244  
245 +        D(bug(" plain name %s, type %d, mode %d\n", plain_name, type, mode));
246 +
247          // Channel 0 is READ, channel 1 is WRITE
248          if (channel == 0 || channel == 1) {
249                  mode = channel ? FMODE_WRITE : FMODE_READ;
# Line 269 | Line 276 | uint8 D64Drive::open_file(int channel, c
276          if (find_first_file(plain_name, plain_name_len, dir_track, dir_sector, entry)) {
277  
278                  // File exists
279 +                D(bug(" file exists, dir track %d, sector %d, entry %d\n", dir_track, dir_sector, entry));
280                  ch[channel].dir_track = dir_track;
281                  ch[channel].dir_sector = dir_sector;
282                  ch[channel].entry = entry;
# Line 334 | Line 342 | uint8 D64Drive::open_file(int channel, c
342          } else {
343  
344                  // File doesn't exist
345 +                D(bug(" file not found\n"));
346 +
347                  // Set file type to SEQ if not specified in file name
348                  if (type == FTYPE_DEL)
349                          type = FTYPE_SEQ;
# Line 354 | Line 364 | uint8 D64Drive::open_file(int channel, c
364   *  Open channel for reading from file given track/sector of first block
365   */
366  
367 < uint8 D64Drive::open_file_ts(int channel, int track, int sector)
367 > uint8 ImageDrive::open_file_ts(int channel, int track, int sector)
368   {
369 +        D(bug("open_file_ts track %d, sector %d\n", track, sector));
370 +
371          // Allocate buffer and set channel mode
372          int buf = alloc_buffer(-1);
373          if (buf == -1) {
# Line 379 | Line 391 | uint8 D64Drive::open_file_ts(int channel
391   *  Create file and open channel for writing to file
392   */
393  
394 < uint8 D64Drive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite)
394 > uint8 ImageDrive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite)
395   {
396 +        D(bug("create_file %s, type %d\n", name, type));
397 +
398          // Allocate buffer
399          int buf = alloc_buffer(-1);
400          if (buf == -1) {
# Line 407 | Line 421 | uint8 D64Drive::create_file(int channel,
421                  return ST_OK;
422          }
423          ch[channel].num_blocks = 1;
424 +        D(bug(" first data block on track %d, sector %d\n", ch[channel].track, ch[channel].sector));
425  
426          // Write directory entry
427          memset(de, 0, SIZEOF_DE);
# Line 439 | Line 454 | const char type_char_1[] = "DSPUREER";
454   const char type_char_2[] = "EERSELQG";
455   const char type_char_3[] = "LQGRL???";
456  
457 < uint8 D64Drive::open_directory(const uint8 *pattern, int pattern_len)
457 > uint8 ImageDrive::open_directory(const uint8 *pattern, int pattern_len)
458   {
459          // Special treatment for "$0"
460          if (pattern[0] == '0' && pattern_len == 1) {
# Line 594 | Line 609 | uint8 D64Drive::open_directory(const uin
609   *  Open channel for direct buffer access
610   */
611  
612 < uint8 D64Drive::open_direct(int channel, const uint8 *name)
612 > uint8 ImageDrive::open_direct(int channel, const uint8 *name)
613   {
614          int buf = -1;
615  
# Line 627 | Line 642 | uint8 D64Drive::open_direct(int channel,
642   *  Close channel
643   */
644  
645 < uint8 D64Drive::Close(int channel)
645 > uint8 ImageDrive::Close(int channel)
646   {
647 +        D(bug("ImageDrive::Close channel %d\n", channel));
648 +
649          switch (ch[channel].mode) {
650                  case CHMOD_FREE:
651                          break;
# Line 655 | Line 672 | uint8 D64Drive::Close(int channel)
672                                  // Write last data block
673                                  ch[channel].buf[0] = 0;
674                                  ch[channel].buf[1] = ch[channel].buf_len - 1;
675 +                                D(bug(" writing last data block\n"));
676                                  if (!write_sector(ch[channel].track, ch[channel].sector, ch[channel].buf))
677                                          goto free;
678  
# Line 672 | Line 690 | uint8 D64Drive::Close(int channel)
690                                          de[DE_OVR_TRACK] = de[DE_OVR_SECTOR] = 0;
691                                  }
692                                  write_sector(ch[channel].dir_track, ch[channel].dir_sector, dir);
693 +                                D(bug(" directory entry updated\n"));
694                          }
695   free:           free_buffer(ch[channel].buf_num);
696                          ch[channel].buf = NULL;
# Line 693 | Line 712 | free:          free_buffer(ch[channel].buf_num);
712   *  Close all channels
713   */
714  
715 < void D64Drive::close_all_channels()
715 > void ImageDrive::close_all_channels()
716   {
717          for (int i=0; i<15; i++)
718                  Close(i);
# Line 708 | Line 727 | void D64Drive::close_all_channels()
727   *  Read from channel
728   */
729  
730 < uint8 D64Drive::Read(int channel, uint8 &byte)
730 > uint8 ImageDrive::Read(int channel, uint8 &byte)
731   {
732 + //      D(bug("ImageDrive::Read channel %d\n", channel));
733 +
734          switch (ch[channel].mode) {
735                  case CHMOD_FREE:
736                          if (current_error == ERR_OK)
# Line 735 | Line 756 | uint8 D64Drive::Read(int channel, uint8
756  
757                          // Read next block if necessary
758                          if (ch[channel].buf_len == 0 && ch[channel].buf[0]) {
759 +                                D(bug(" reading next data block track %d, sector %d\n", ch[channel].buf[0], ch[channel].buf[1]));
760                                  if (!read_sector(ch[channel].buf[0], ch[channel].buf[1], ch[channel].buf))
761                                          return ST_READ_TIMEOUT;
762                                  ch[channel].buf_ptr = ch[channel].buf + 2;
# Line 773 | Line 795 | uint8 D64Drive::Read(int channel, uint8
795   *  Write byte to channel
796   */
797  
798 < uint8 D64Drive::Write(int channel, uint8 byte, bool eoi)
798 > uint8 ImageDrive::Write(int channel, uint8 byte, bool eoi)
799   {
800 + //      D(bug("ImageDrive::Write channel %d, byte %02x, eoi %d\n", channel, byte, eoi));
801 +
802          switch (ch[channel].mode) {
803                  case CHMOD_FREE:
804                          if (current_error == ERR_OK)
# Line 814 | Line 838 | uint8 D64Drive::Write(int channel, uint8
838                                  if (!alloc_next_block(track, sector, DATA_INTERLEAVE))
839                                          return ST_TIMEOUT;
840                                  ch[channel].num_blocks++;
841 +                                D(bug("next data block on track %d, sector %d\n", track, sector));
842  
843                                  // Write buffer with link to new block
844                                  ch[channel].buf[0] = track;
# Line 847 | Line 872 | uint8 D64Drive::Write(int channel, uint8
872   *  Reset drive
873   */
874  
875 < void D64Drive::Reset(void)
875 > void ImageDrive::Reset(void)
876   {
877          close_all_channels();
878  
# Line 874 | Line 899 | void D64Drive::Reset(void)
899   *   <- Allocated buffer number or -1
900   */
901  
902 < int D64Drive::alloc_buffer(int want)
902 > int ImageDrive::alloc_buffer(int want)
903   {
904          if (want == -1) {
905                  for (want=3; want>=0; want--)
# Line 900 | Line 925 | int D64Drive::alloc_buffer(int want)
925   *  Free floppy buffer
926   */
927  
928 < void D64Drive::free_buffer(int buf)
928 > void ImageDrive::free_buffer(int buf)
929   {
930          buf_free[buf] = true;
931   }
# Line 929 | Line 954 | static bool match(const uint8 *p, int p_
954          return *n == 0xa0 || c == 16;
955   }
956  
957 < bool D64Drive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont)
957 > bool ImageDrive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont)
958   {
959          // Counter to prevent cyclic directories from resulting in an infinite loop
960          int num_dir_blocks = 0;
# Line 967 | Line 992 | bool D64Drive::find_file(const uint8 *pa
992          return false;
993   }
994  
995 < bool D64Drive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
995 > bool ImageDrive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
996   {
997          return find_file(pattern, pattern_len, dir_track, dir_sector, entry, false);
998   }
999  
1000 < bool D64Drive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1000 > bool ImageDrive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry)
1001   {
1002          return find_file(pattern, pattern_len, dir_track, dir_sector, entry, true);
1003   }
# Line 984 | Line 1009 | bool D64Drive::find_next_file(const uint
1009   *  The track/sector and entry numbers are returned
1010   */
1011  
1012 < bool D64Drive::alloc_dir_entry(int &track, int &sector, int &entry)
1012 > bool ImageDrive::alloc_dir_entry(int &track, int &sector, int &entry)
1013   {
1014          // First look for free entry in existing directory blocks
1015          dir[DIR_NEXT_TRACK] = DIR_TRACK;
# Line 995 | Line 1020 | bool D64Drive::alloc_dir_entry(int &trac
1020  
1021                  uint8 *de = dir + DIR_ENTRIES;
1022                  for (entry=0; entry<8; entry++, de+=SIZEOF_DE) {
1023 <                        if (de[DE_TYPE] == 0)
1023 >                        if (de[DE_TYPE] == 0) {
1024 >                                D(bug(" allocated entry %d in dir track %d, sector %d\n", entry, track, sector));
1025                                  return true;
1026 +                        }
1027                  }
1028          }
1029  
# Line 1004 | Line 1031 | bool D64Drive::alloc_dir_entry(int &trac
1031          int last_track = track, last_sector = sector;
1032          if (!alloc_next_block(track, sector, DIR_INTERLEAVE))
1033                  return false;
1034 +        D(bug(" new directory block track %d, sector %d\n", track, sector));
1035  
1036          // Write link to new block to last block
1037          dir[DIR_NEXT_TRACK] = track;
# Line 1022 | Line 1050 | bool D64Drive::alloc_dir_entry(int &trac
1050   *  Test if block is free in BAM (track/sector are not checked for validity)
1051   */
1052  
1053 < bool D64Drive::is_block_free(int track, int sector)
1053 > bool ImageDrive::is_block_free(int track, int sector)
1054   {
1055          uint8 *p = bam + BAM_BITMAP + (track - 1) * 4;
1056          int byte = sector / 8 + 1;
# Line 1035 | Line 1063 | bool D64Drive::is_block_free(int track,
1063   *  Get number of free blocks on a track
1064   */
1065  
1066 < int D64Drive::num_free_blocks(int track)
1066 > int ImageDrive::num_free_blocks(int track)
1067   {
1068          return bam[BAM_BITMAP + (track - 1) * 4];
1069   }
# Line 1061 | Line 1089 | static void clear_bam(uint8 *bam)
1089   *  Allocate block in BAM, returns error code
1090   */
1091  
1092 < int D64Drive::alloc_block(int track, int sector)
1092 > int ImageDrive::alloc_block(int track, int sector)
1093   {
1094          if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track])
1095                  return ERR_ILLEGALTS;
# Line 1074 | Line 1102 | int D64Drive::alloc_block(int track, int
1102          if (p[byte] & (1 << bit)) {
1103  
1104                  // Yes, allocate and decrement free block count
1105 +                D(bug("allocating block at track %d, sector %d\n", track, sector));
1106                  p[byte] &= ~(1 << bit);
1107                  p[0]--;
1108                  bam_dirty = true;
# Line 1088 | Line 1117 | int D64Drive::alloc_block(int track, int
1117   *  Free block in BAM, returns error code
1118   */
1119  
1120 < int D64Drive::free_block(int track, int sector)
1120 > int ImageDrive::free_block(int track, int sector)
1121   {
1122          if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track])
1123                  return ERR_ILLEGALTS;
# Line 1101 | Line 1130 | int D64Drive::free_block(int track, int
1130          if (!(p[byte] & (1 << bit))) {
1131  
1132                  // Yes, free and increment free block count
1133 +                D(bug("freeing block at track %d, sector %d\n", track, sector));
1134                  p[byte] |= (1 << bit);
1135                  p[0]++;
1136                  bam_dirty = true;
# Line 1113 | Line 1143 | int D64Drive::free_block(int track, int
1143   *  Allocate chain of data blocks in BAM
1144   */
1145  
1146 < bool D64Drive::alloc_block_chain(int track, int sector)
1146 > bool ImageDrive::alloc_block_chain(int track, int sector)
1147   {
1148          uint8 buf[256];
1149          while (alloc_block(track, sector) == ERR_OK) {
# Line 1130 | Line 1160 | bool D64Drive::alloc_block_chain(int tra
1160   *  Free chain of data blocks in BAM
1161   */
1162  
1163 < bool D64Drive::free_block_chain(int track, int sector)
1163 > bool ImageDrive::free_block_chain(int track, int sector)
1164   {
1165          uint8 buf[256];
1166          while (free_block(track, sector) == ERR_OK) {
# Line 1150 | Line 1180 | bool D64Drive::free_block_chain(int trac
1180   *  begin
1181   */
1182  
1183 < bool D64Drive::alloc_next_block(int &track, int &sector, int interleave)
1183 > bool ImageDrive::alloc_next_block(int &track, int &sector, int interleave)
1184   {
1185          // Find track with free blocks
1186          bool side_changed = false;
# Line 1300 | Line 1330 | int write_sector(FILE *f, const image_fi
1330   }
1331  
1332   // Read sector and set error message, returns false on error
1333 < bool D64Drive::read_sector(int track, int sector, uint8 *buffer)
1333 > bool ImageDrive::read_sector(int track, int sector, uint8 *buffer)
1334   {
1335          int error = ::read_sector(the_file, desc, track, sector, buffer);
1336          if (error)
# Line 1309 | Line 1339 | bool D64Drive::read_sector(int track, in
1339   }
1340  
1341   // Write sector and set error message, returns false on error
1342 < bool D64Drive::write_sector(int track, int sector, uint8 *buffer)
1342 > bool ImageDrive::write_sector(int track, int sector, uint8 *buffer)
1343   {
1344          int error = ::write_sector(the_file, desc, track, sector, buffer);
1345          if (error)
# Line 1392 | Line 1422 | bool format_image(FILE *f, image_file_de
1422   */
1423  
1424   // BLOCK-READ:channel,0,track,sector
1425 < void D64Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
1425 > void ImageDrive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
1426   {
1427          if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) {
1428                  set_error(ERR_NOCHANNEL);
# Line 1410 | Line 1440 | void D64Drive::block_read_cmd(int channe
1440   }
1441  
1442   // BLOCK-WRITE:channel,0,track,sector
1443 < void D64Drive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
1443 > void ImageDrive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
1444   {
1445          if (write_protected) {
1446                  set_error(ERR_WRITEPROTECT);
# Line 1431 | Line 1461 | void D64Drive::block_write_cmd(int chann
1461   }
1462  
1463   // BLOCK-ALLOCATE:0,track,sector
1464 < void D64Drive::block_allocate_cmd(int track, int sector)
1464 > void ImageDrive::block_allocate_cmd(int track, int sector)
1465   {
1466          int err = alloc_block(track, sector);
1467          if (err) {
# Line 1459 | Line 1489 | void D64Drive::block_allocate_cmd(int tr
1489   }
1490  
1491   // BLOCK-FREE:0,track,sector
1492 < void D64Drive::block_free_cmd(int track, int sector)
1492 > void ImageDrive::block_free_cmd(int track, int sector)
1493   {
1494          int err = free_block(track, sector);
1495          if (err)
# Line 1467 | Line 1497 | void D64Drive::block_free_cmd(int track,
1497   }
1498  
1499   // BUFFER-POINTER:channel,pos
1500 < void D64Drive::buffer_pointer_cmd(int channel, int pos)
1500 > void ImageDrive::buffer_pointer_cmd(int channel, int pos)
1501   {
1502          if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) {
1503                  set_error(ERR_NOCHANNEL);
# Line 1478 | Line 1508 | void D64Drive::buffer_pointer_cmd(int ch
1508   }
1509  
1510   // M-R<adr low><adr high>[<number>]
1511 < void D64Drive::mem_read_cmd(uint16 adr, uint8 len)
1511 > void ImageDrive::mem_read_cmd(uint16 adr, uint8 len)
1512   {
1513          error_len = len;
1514          if (adr >= 0x300 && adr < 0x1000) {
# Line 1495 | Line 1525 | void D64Drive::mem_read_cmd(uint16 adr,
1525   }
1526  
1527   // M-W<adr low><adr high><number><data...>
1528 < void D64Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
1528 > void ImageDrive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
1529   {
1530          while (len) {
1531                  if (adr >= 0x300 && adr < 0x1000) {
# Line 1512 | Line 1542 | void D64Drive::mem_write_cmd(uint16 adr,
1542   //   COPY:new=file1,file2,...
1543   //        ^   ^
1544   // new_file   old_files
1545 < void D64Drive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
1545 > void ImageDrive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
1546   {
1547          // Check if destination file is already present
1548          int dir_track, dir_sector, entry;
# Line 1575 | Line 1605 | void D64Drive::copy_cmd(const uint8 *new
1605   // RENAME:new=old
1606   //        ^   ^
1607   // new_file   old_file
1608 < void D64Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
1608 > void ImageDrive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
1609   {
1610          // Check if destination file is already present
1611          int dir_track, dir_sector, entry;
# Line 1606 | Line 1636 | void D64Drive::rename_cmd(const uint8 *n
1636   // SCRATCH:file1,file2,...
1637   //         ^
1638   //         files
1639 < void D64Drive::scratch_cmd(const uint8 *files, int files_len)
1639 > void ImageDrive::scratch_cmd(const uint8 *files, int files_len)
1640   {
1641          // Check for write-protection
1642          if (write_protected) {
# Line 1654 | Line 1684 | void D64Drive::scratch_cmd(const uint8 *
1684   }
1685  
1686   // INITIALIZE
1687 < void D64Drive::initialize_cmd(void)
1687 > void ImageDrive::initialize_cmd(void)
1688   {
1689          // Close all channels and re-read BAM
1690          close_all_channels();
# Line 1668 | Line 1698 | void D64Drive::initialize_cmd(void)
1698   // NEW:name,id
1699   //     ^   ^
1700   //  name   comma (or NULL)
1701 < void D64Drive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
1701 > void ImageDrive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
1702   {
1703          // Check for write-protection
1704          if (write_protected) {
# Line 1705 | Line 1735 | void D64Drive::new_cmd(const uint8 *name
1735   }
1736  
1737   // VALIDATE
1738 < void D64Drive::validate_cmd(void)
1738 > void ImageDrive::validate_cmd(void)
1739   {
1740          // Backup of old BAM in case something goes amiss
1741          uint8 old_bam[256];

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines