112 |
|
* Constructor: Prepare emulation, open image file |
113 |
|
*/ |
114 |
|
|
115 |
< |
D64Drive::D64Drive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false) |
115 |
> |
ImageDrive::ImageDrive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false) |
116 |
|
{ |
117 |
|
for (int i=0; i<18; i++) { |
118 |
|
ch[i].mode = CHMOD_FREE; |
132 |
|
* Destructor |
133 |
|
*/ |
134 |
|
|
135 |
< |
D64Drive::~D64Drive() |
135 |
> |
ImageDrive::~ImageDrive() |
136 |
|
{ |
137 |
|
close_image(); |
138 |
|
} |
142 |
|
* Close the image file |
143 |
|
*/ |
144 |
|
|
145 |
< |
void D64Drive::close_image(void) |
145 |
> |
void ImageDrive::close_image(void) |
146 |
|
{ |
147 |
|
if (the_file) { |
148 |
|
close_all_channels(); |
160 |
|
* Open the image file |
161 |
|
*/ |
162 |
|
|
163 |
< |
bool D64Drive::change_image(const char *path) |
163 |
> |
bool ImageDrive::change_image(const char *path) |
164 |
|
{ |
165 |
|
// Close old image file |
166 |
|
close_image(); |
194 |
|
* Open channel |
195 |
|
*/ |
196 |
|
|
197 |
< |
uint8 D64Drive::Open(int channel, const uint8 *name, int name_len) |
197 |
> |
uint8 ImageDrive::Open(int channel, const uint8 *name, int name_len) |
198 |
|
{ |
199 |
|
set_error(ERR_OK); |
200 |
|
|
226 |
|
* Open file |
227 |
|
*/ |
228 |
|
|
229 |
< |
uint8 D64Drive::open_file(int channel, const uint8 *name, int name_len) |
229 |
> |
uint8 ImageDrive::open_file(int channel, const uint8 *name, int name_len) |
230 |
|
{ |
231 |
|
uint8 plain_name[NAMEBUF_LENGTH]; |
232 |
|
int plain_name_len; |
354 |
|
* Open channel for reading from file given track/sector of first block |
355 |
|
*/ |
356 |
|
|
357 |
< |
uint8 D64Drive::open_file_ts(int channel, int track, int sector) |
357 |
> |
uint8 ImageDrive::open_file_ts(int channel, int track, int sector) |
358 |
|
{ |
359 |
|
// Allocate buffer and set channel mode |
360 |
|
int buf = alloc_buffer(-1); |
379 |
|
* Create file and open channel for writing to file |
380 |
|
*/ |
381 |
|
|
382 |
< |
uint8 D64Drive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite) |
382 |
> |
uint8 ImageDrive::create_file(int channel, const uint8 *name, int name_len, int type, bool overwrite) |
383 |
|
{ |
384 |
|
// Allocate buffer |
385 |
|
int buf = alloc_buffer(-1); |
439 |
|
const char type_char_2[] = "EERSELQG"; |
440 |
|
const char type_char_3[] = "LQGRL???"; |
441 |
|
|
442 |
< |
uint8 D64Drive::open_directory(const uint8 *pattern, int pattern_len) |
442 |
> |
uint8 ImageDrive::open_directory(const uint8 *pattern, int pattern_len) |
443 |
|
{ |
444 |
|
// Special treatment for "$0" |
445 |
|
if (pattern[0] == '0' && pattern_len == 1) { |
594 |
|
* Open channel for direct buffer access |
595 |
|
*/ |
596 |
|
|
597 |
< |
uint8 D64Drive::open_direct(int channel, const uint8 *name) |
597 |
> |
uint8 ImageDrive::open_direct(int channel, const uint8 *name) |
598 |
|
{ |
599 |
|
int buf = -1; |
600 |
|
|
627 |
|
* Close channel |
628 |
|
*/ |
629 |
|
|
630 |
< |
uint8 D64Drive::Close(int channel) |
630 |
> |
uint8 ImageDrive::Close(int channel) |
631 |
|
{ |
632 |
|
switch (ch[channel].mode) { |
633 |
|
case CHMOD_FREE: |
693 |
|
* Close all channels |
694 |
|
*/ |
695 |
|
|
696 |
< |
void D64Drive::close_all_channels() |
696 |
> |
void ImageDrive::close_all_channels() |
697 |
|
{ |
698 |
|
for (int i=0; i<15; i++) |
699 |
|
Close(i); |
708 |
|
* Read from channel |
709 |
|
*/ |
710 |
|
|
711 |
< |
uint8 D64Drive::Read(int channel, uint8 &byte) |
711 |
> |
uint8 ImageDrive::Read(int channel, uint8 &byte) |
712 |
|
{ |
713 |
|
switch (ch[channel].mode) { |
714 |
|
case CHMOD_FREE: |
773 |
|
* Write byte to channel |
774 |
|
*/ |
775 |
|
|
776 |
< |
uint8 D64Drive::Write(int channel, uint8 byte, bool eoi) |
776 |
> |
uint8 ImageDrive::Write(int channel, uint8 byte, bool eoi) |
777 |
|
{ |
778 |
|
switch (ch[channel].mode) { |
779 |
|
case CHMOD_FREE: |
847 |
|
* Reset drive |
848 |
|
*/ |
849 |
|
|
850 |
< |
void D64Drive::Reset(void) |
850 |
> |
void ImageDrive::Reset(void) |
851 |
|
{ |
852 |
|
close_all_channels(); |
853 |
|
|
874 |
|
* <- Allocated buffer number or -1 |
875 |
|
*/ |
876 |
|
|
877 |
< |
int D64Drive::alloc_buffer(int want) |
877 |
> |
int ImageDrive::alloc_buffer(int want) |
878 |
|
{ |
879 |
|
if (want == -1) { |
880 |
|
for (want=3; want>=0; want--) |
900 |
|
* Free floppy buffer |
901 |
|
*/ |
902 |
|
|
903 |
< |
void D64Drive::free_buffer(int buf) |
903 |
> |
void ImageDrive::free_buffer(int buf) |
904 |
|
{ |
905 |
|
buf_free[buf] = true; |
906 |
|
} |
929 |
|
return *n == 0xa0 || c == 16; |
930 |
|
} |
931 |
|
|
932 |
< |
bool D64Drive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont) |
932 |
> |
bool ImageDrive::find_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry, bool cont) |
933 |
|
{ |
934 |
|
// Counter to prevent cyclic directories from resulting in an infinite loop |
935 |
|
int num_dir_blocks = 0; |
967 |
|
return false; |
968 |
|
} |
969 |
|
|
970 |
< |
bool D64Drive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry) |
970 |
> |
bool ImageDrive::find_first_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry) |
971 |
|
{ |
972 |
|
return find_file(pattern, pattern_len, dir_track, dir_sector, entry, false); |
973 |
|
} |
974 |
|
|
975 |
< |
bool D64Drive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry) |
975 |
> |
bool ImageDrive::find_next_file(const uint8 *pattern, int pattern_len, int &dir_track, int &dir_sector, int &entry) |
976 |
|
{ |
977 |
|
return find_file(pattern, pattern_len, dir_track, dir_sector, entry, true); |
978 |
|
} |
984 |
|
* The track/sector and entry numbers are returned |
985 |
|
*/ |
986 |
|
|
987 |
< |
bool D64Drive::alloc_dir_entry(int &track, int §or, int &entry) |
987 |
> |
bool ImageDrive::alloc_dir_entry(int &track, int §or, int &entry) |
988 |
|
{ |
989 |
|
// First look for free entry in existing directory blocks |
990 |
|
dir[DIR_NEXT_TRACK] = DIR_TRACK; |
1022 |
|
* Test if block is free in BAM (track/sector are not checked for validity) |
1023 |
|
*/ |
1024 |
|
|
1025 |
< |
bool D64Drive::is_block_free(int track, int sector) |
1025 |
> |
bool ImageDrive::is_block_free(int track, int sector) |
1026 |
|
{ |
1027 |
|
uint8 *p = bam + BAM_BITMAP + (track - 1) * 4; |
1028 |
|
int byte = sector / 8 + 1; |
1035 |
|
* Get number of free blocks on a track |
1036 |
|
*/ |
1037 |
|
|
1038 |
< |
int D64Drive::num_free_blocks(int track) |
1038 |
> |
int ImageDrive::num_free_blocks(int track) |
1039 |
|
{ |
1040 |
|
return bam[BAM_BITMAP + (track - 1) * 4]; |
1041 |
|
} |
1061 |
|
* Allocate block in BAM, returns error code |
1062 |
|
*/ |
1063 |
|
|
1064 |
< |
int D64Drive::alloc_block(int track, int sector) |
1064 |
> |
int ImageDrive::alloc_block(int track, int sector) |
1065 |
|
{ |
1066 |
|
if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track]) |
1067 |
|
return ERR_ILLEGALTS; |
1088 |
|
* Free block in BAM, returns error code |
1089 |
|
*/ |
1090 |
|
|
1091 |
< |
int D64Drive::free_block(int track, int sector) |
1091 |
> |
int ImageDrive::free_block(int track, int sector) |
1092 |
|
{ |
1093 |
|
if (track < 1 || track > 35 || sector < 0 || sector >= num_sectors[track]) |
1094 |
|
return ERR_ILLEGALTS; |
1113 |
|
* Allocate chain of data blocks in BAM |
1114 |
|
*/ |
1115 |
|
|
1116 |
< |
bool D64Drive::alloc_block_chain(int track, int sector) |
1116 |
> |
bool ImageDrive::alloc_block_chain(int track, int sector) |
1117 |
|
{ |
1118 |
|
uint8 buf[256]; |
1119 |
|
while (alloc_block(track, sector) == ERR_OK) { |
1130 |
|
* Free chain of data blocks in BAM |
1131 |
|
*/ |
1132 |
|
|
1133 |
< |
bool D64Drive::free_block_chain(int track, int sector) |
1133 |
> |
bool ImageDrive::free_block_chain(int track, int sector) |
1134 |
|
{ |
1135 |
|
uint8 buf[256]; |
1136 |
|
while (free_block(track, sector) == ERR_OK) { |
1150 |
|
* begin |
1151 |
|
*/ |
1152 |
|
|
1153 |
< |
bool D64Drive::alloc_next_block(int &track, int §or, int interleave) |
1153 |
> |
bool ImageDrive::alloc_next_block(int &track, int §or, int interleave) |
1154 |
|
{ |
1155 |
|
// Find track with free blocks |
1156 |
|
bool side_changed = false; |
1300 |
|
} |
1301 |
|
|
1302 |
|
// Read sector and set error message, returns false on error |
1303 |
< |
bool D64Drive::read_sector(int track, int sector, uint8 *buffer) |
1303 |
> |
bool ImageDrive::read_sector(int track, int sector, uint8 *buffer) |
1304 |
|
{ |
1305 |
|
int error = ::read_sector(the_file, desc, track, sector, buffer); |
1306 |
|
if (error) |
1309 |
|
} |
1310 |
|
|
1311 |
|
// Write sector and set error message, returns false on error |
1312 |
< |
bool D64Drive::write_sector(int track, int sector, uint8 *buffer) |
1312 |
> |
bool ImageDrive::write_sector(int track, int sector, uint8 *buffer) |
1313 |
|
{ |
1314 |
|
int error = ::write_sector(the_file, desc, track, sector, buffer); |
1315 |
|
if (error) |
1392 |
|
*/ |
1393 |
|
|
1394 |
|
// BLOCK-READ:channel,0,track,sector |
1395 |
< |
void D64Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd) |
1395 |
> |
void ImageDrive::block_read_cmd(int channel, int track, int sector, bool user_cmd) |
1396 |
|
{ |
1397 |
|
if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) { |
1398 |
|
set_error(ERR_NOCHANNEL); |
1410 |
|
} |
1411 |
|
|
1412 |
|
// BLOCK-WRITE:channel,0,track,sector |
1413 |
< |
void D64Drive::block_write_cmd(int channel, int track, int sector, bool user_cmd) |
1413 |
> |
void ImageDrive::block_write_cmd(int channel, int track, int sector, bool user_cmd) |
1414 |
|
{ |
1415 |
|
if (write_protected) { |
1416 |
|
set_error(ERR_WRITEPROTECT); |
1431 |
|
} |
1432 |
|
|
1433 |
|
// BLOCK-ALLOCATE:0,track,sector |
1434 |
< |
void D64Drive::block_allocate_cmd(int track, int sector) |
1434 |
> |
void ImageDrive::block_allocate_cmd(int track, int sector) |
1435 |
|
{ |
1436 |
|
int err = alloc_block(track, sector); |
1437 |
|
if (err) { |
1459 |
|
} |
1460 |
|
|
1461 |
|
// BLOCK-FREE:0,track,sector |
1462 |
< |
void D64Drive::block_free_cmd(int track, int sector) |
1462 |
> |
void ImageDrive::block_free_cmd(int track, int sector) |
1463 |
|
{ |
1464 |
|
int err = free_block(track, sector); |
1465 |
|
if (err) |
1467 |
|
} |
1468 |
|
|
1469 |
|
// BUFFER-POINTER:channel,pos |
1470 |
< |
void D64Drive::buffer_pointer_cmd(int channel, int pos) |
1470 |
> |
void ImageDrive::buffer_pointer_cmd(int channel, int pos) |
1471 |
|
{ |
1472 |
|
if (channel >= 16 || ch[channel].mode != CHMOD_DIRECT) { |
1473 |
|
set_error(ERR_NOCHANNEL); |
1478 |
|
} |
1479 |
|
|
1480 |
|
// M-R<adr low><adr high>[<number>] |
1481 |
< |
void D64Drive::mem_read_cmd(uint16 adr, uint8 len) |
1481 |
> |
void ImageDrive::mem_read_cmd(uint16 adr, uint8 len) |
1482 |
|
{ |
1483 |
|
error_len = len; |
1484 |
|
if (adr >= 0x300 && adr < 0x1000) { |
1495 |
|
} |
1496 |
|
|
1497 |
|
// M-W<adr low><adr high><number><data...> |
1498 |
< |
void D64Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p) |
1498 |
> |
void ImageDrive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p) |
1499 |
|
{ |
1500 |
|
while (len) { |
1501 |
|
if (adr >= 0x300 && adr < 0x1000) { |
1512 |
|
// COPY:new=file1,file2,... |
1513 |
|
// ^ ^ |
1514 |
|
// new_file old_files |
1515 |
< |
void D64Drive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len) |
1515 |
> |
void ImageDrive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len) |
1516 |
|
{ |
1517 |
|
// Check if destination file is already present |
1518 |
|
int dir_track, dir_sector, entry; |
1575 |
|
// RENAME:new=old |
1576 |
|
// ^ ^ |
1577 |
|
// new_file old_file |
1578 |
< |
void D64Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len) |
1578 |
> |
void ImageDrive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len) |
1579 |
|
{ |
1580 |
|
// Check if destination file is already present |
1581 |
|
int dir_track, dir_sector, entry; |
1606 |
|
// SCRATCH:file1,file2,... |
1607 |
|
// ^ |
1608 |
|
// files |
1609 |
< |
void D64Drive::scratch_cmd(const uint8 *files, int files_len) |
1609 |
> |
void ImageDrive::scratch_cmd(const uint8 *files, int files_len) |
1610 |
|
{ |
1611 |
|
// Check for write-protection |
1612 |
|
if (write_protected) { |
1654 |
|
} |
1655 |
|
|
1656 |
|
// INITIALIZE |
1657 |
< |
void D64Drive::initialize_cmd(void) |
1657 |
> |
void ImageDrive::initialize_cmd(void) |
1658 |
|
{ |
1659 |
|
// Close all channels and re-read BAM |
1660 |
|
close_all_channels(); |
1668 |
|
// NEW:name,id |
1669 |
|
// ^ ^ |
1670 |
|
// name comma (or NULL) |
1671 |
< |
void D64Drive::new_cmd(const uint8 *name, int name_len, const uint8 *comma) |
1671 |
> |
void ImageDrive::new_cmd(const uint8 *name, int name_len, const uint8 *comma) |
1672 |
|
{ |
1673 |
|
// Check for write-protection |
1674 |
|
if (write_protected) { |
1705 |
|
} |
1706 |
|
|
1707 |
|
// VALIDATE |
1708 |
< |
void D64Drive::validate_cmd(void) |
1708 |
> |
void ImageDrive::validate_cmd(void) |
1709 |
|
{ |
1710 |
|
// Backup of old BAM in case something goes amiss |
1711 |
|
uint8 old_bam[256]; |