00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "sysdeps.h"
00017
00018 #include "1541d64.h"
00019 #include "IEC.h"
00020 #include "Prefs.h"
00021
00022
00023
00024 enum {
00025 CHMOD_FREE,
00026 CHMOD_COMMAND,
00027 CHMOD_DIRECTORY,
00028 CHMOD_FILE,
00029 CHMOD_DIRECT
00030 };
00031
00032
00033 enum {
00034 FMODE_READ, FMODE_WRITE, FMODE_APPEND
00035 };
00036
00037
00038 enum {
00039 FTYPE_PRG, FTYPE_SEQ, FTYPE_USR, FTYPE_REL
00040 };
00041
00042
00043 const int NUM_TRACKS = 35;
00044 const int NUM_SECTORS = 683;
00045
00046
00047 static bool match(uint8 *p, uint8 *n);
00048
00049
00050
00051
00052
00053
00054 D64Drive::D64Drive(IEC *iec, char *filepath) : Drive(iec)
00055 {
00056 __CHECK_NULL(iec);
00057 __CHECK_NULL(filepath);
00058
00059 CTOR(D64Drive);
00060
00061 the_file = NULL;
00062 ram = NULL;
00063
00064 Ready = false;
00065 strcpy(orig_d64_name, filepath);
00066 for (int i=0; i<=14; i++) {
00067 chan_mode[i] = CHMOD_FREE;
00068 chan_buf[i] = NULL;
00069 }
00070 chan_mode[15] = CHMOD_COMMAND;
00071
00072
00073 open_close_d64_file(filepath);
00074 if (the_file != NULL) {
00075
00076
00077 ram = new uint8[0x800];
00078 bam = (BAM *)(ram + 0x700);
00079
00080 Reset();
00081 Ready = true;
00082 }
00083
00084 }
00085
00086
00087
00088
00089
00090
00091 D64Drive::~D64Drive()
00092 {
00093
00094 open_close_d64_file("");
00095
00096 delete[] ram;
00097 Ready = false;
00098
00099 DTOR(D64Drive);
00100 }
00101
00102
00103
00104
00105
00106
00107 void D64Drive::open_close_d64_file(char *d64name)
00108 {
00109 long size;
00110 uint8 magic[4];
00111
00112
00113 if (the_file != NULL) {
00114 close_all_channels();
00115 fclose(the_file);
00116 the_file = NULL;
00117 }
00118
00119
00120 if (d64name[0]) {
00121 if ((the_file = fopen(d64name, "rb")) != NULL) {
00122
00123
00124 fseek(the_file, 0, SEEK_END);
00125 if ((size = ftell(the_file)) < NUM_SECTORS * 256) {
00126 fclose(the_file);
00127 the_file = NULL;
00128 return;
00129 }
00130
00131
00132 rewind(the_file);
00133 fread(&magic, 4, 1, the_file);
00134 if (magic[0] == 0x43 && magic[1] == 0x15 && magic[2] == 0x41 && magic[3] == 0x64)
00135 image_header = 64;
00136 else
00137 image_header = 0;
00138
00139
00140 memset(error_info, 1, NUM_SECTORS);
00141
00142
00143 if (!image_header && size == NUM_SECTORS * 257) {
00144 fseek(the_file, NUM_SECTORS * 256, SEEK_SET);
00145 fread(&error_info, NUM_SECTORS, 1, the_file);
00146 }
00147 }
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156 uint8 D64Drive::Open(int channel, char *filename)
00157 {
00158 set_error(ERR_OK);
00159
00160
00161 if (channel == 15) {
00162 execute_command(filename);
00163 return ST_OK;
00164 }
00165
00166 if (chan_mode[channel] != CHMOD_FREE) {
00167 set_error(ERR_NOCHANNEL);
00168 return ST_OK;
00169 }
00170
00171 if (filename[0] == '$')
00172 if (channel)
00173 return open_file_ts(channel, 18, 0);
00174 else
00175 return open_directory(filename+1);
00176
00177 if (filename[0] == '#')
00178 return open_direct(channel, filename);
00179
00180 return open_file(channel, filename);
00181 }
00182
00183
00184
00185
00186
00187
00188 uint8 D64Drive::open_file(int channel, char *filename)
00189 {
00190 char plainname[256];
00191 int filemode = FMODE_READ;
00192 int filetype = FTYPE_PRG;
00193 int track, sector;
00194
00195 convert_filename(filename, plainname, &filemode, &filetype);
00196
00197
00198 if (!channel) {
00199 filemode = FMODE_READ;
00200 filetype = FTYPE_PRG;
00201 }
00202 if (channel == 1) {
00203 filemode = FMODE_WRITE;
00204 filetype = FTYPE_PRG;
00205 }
00206
00207
00208 if (filemode != FMODE_READ) {
00209 set_error(ERR_WRITEPROTECT);
00210 return ST_OK;
00211 }
00212
00213
00214 if (find_file(plainname, &track, §or))
00215 return open_file_ts(channel, track, sector);
00216 else
00217 set_error(ERR_FILENOTFOUND);
00218
00219 return ST_OK;
00220 }
00221
00222
00223
00224
00225
00226
00227 void D64Drive::convert_filename(char *srcname, char *destname, int *filemode, int *filetype)
00228 {
00229 char *p;
00230
00231
00232 if ((p = strchr(srcname, ':')) != NULL)
00233 p++;
00234 else
00235 p = srcname;
00236
00237
00238 strncpy(destname, p, NAMEBUF_LENGTH);
00239
00240
00241 p = destname;
00242 while (*p && (*p != ',')) p++;
00243
00244
00245 p = destname;
00246 while ((p = strchr(p, ',')) != NULL) {
00247
00248
00249 *p++ = 0;
00250
00251 switch (*p) {
00252 case 'P':
00253 *filetype = FTYPE_PRG;
00254 break;
00255 case 'S':
00256 *filetype = FTYPE_SEQ;
00257 break;
00258 case 'U':
00259 *filetype = FTYPE_USR;
00260 break;
00261 case 'L':
00262 *filetype = FTYPE_REL;
00263 break;
00264 case 'R':
00265 *filemode = FMODE_READ;
00266 break;
00267 case 'W':
00268 *filemode = FMODE_WRITE;
00269 break;
00270 case 'A':
00271 *filemode = FMODE_APPEND;
00272 break;
00273 }
00274 }
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 bool D64Drive::find_file(char *filename, int *track, int *sector)
00284 {
00285 int i, j;
00286 uint8 *p, *q;
00287 DirEntry *de;
00288
00289
00290 dir.next_track = bam->dir_track;
00291 dir.next_sector = bam->dir_sector;
00292
00293 while (dir.next_track) {
00294 if (!read_sector(dir.next_track, dir.next_sector, (uint8 *) &dir.next_track))
00295 return false;
00296
00297
00298 for (j=0; j<8; j++) {
00299 de = &dir.entry[j];
00300 *track = de->track;
00301 *sector = de->sector;
00302
00303 if (de->type) {
00304 p = (uint8 *)filename;
00305 q = de->name;
00306 for (i=0; i<16 && *p; i++, p++, q++) {
00307 if (*p == '*')
00308 return true;
00309 if (*p != *q) {
00310 if (*p != '?') goto next_entry;
00311 if (*q == 0xa0) goto next_entry;
00312 }
00313 }
00314
00315 if (i == 16 || *q == 0xa0)
00316 return true;
00317 }
00318 next_entry: ;
00319 }
00320 }
00321
00322 return false;
00323 }
00324
00325
00326
00327
00328
00329
00330 uint8 D64Drive::open_file_ts(int channel, int track, int sector)
00331 {
00332 chan_buf[channel] = new uint8[256];
00333 chan_mode[channel] = CHMOD_FILE;
00334
00335
00336 chan_buf[channel][0] = track;
00337 chan_buf[channel][1] = sector;
00338 buf_len[channel] = 0;
00339
00340 return ST_OK;
00341 }
00342
00343
00344
00345
00346
00347
00348 const char type_char_1[] = "DSPUREERSELQGRL?";
00349 const char type_char_2[] = "EERSELQGRL??????";
00350 const char type_char_3[] = "LQGRL???????????";
00351
00352
00353 static bool match(uint8 *p, uint8 *n)
00354 {
00355 if (!*p)
00356 return true;
00357
00358 do {
00359 if (*p == '*')
00360 return true;
00361 if ((*p != *n) && (*p != '?'))
00362 return false;
00363 p++; n++;
00364 } while (*p);
00365
00366 return *n == 0xa0;
00367 }
00368
00369 uint8 D64Drive::open_directory(char *pattern)
00370 {
00371 int i, j, n, m;
00372 uint8 *p, *q;
00373 DirEntry *de;
00374 uint8 c;
00375 char *tmppat;
00376
00377
00378 if (pattern[0] == '0' && pattern[1] == 0)
00379 pattern += 1;
00380
00381
00382 if ((tmppat = strchr(pattern, ':')) != NULL)
00383 pattern = tmppat + 1;
00384
00385 p = buf_ptr[0] = chan_buf[0] = new uint8[8192];
00386 chan_mode[0] = CHMOD_DIRECTORY;
00387
00388
00389 *p++ = 0x01;
00390 *p++ = 0x04;
00391 *p++ = 0x01;
00392 *p++ = 0x01;
00393 *p++ = 0;
00394 *p++ = 0;
00395 *p++ = 0x12;
00396 *p++ = '\"';
00397
00398 q = bam->disk_name;
00399 for (i=0; i<23; i++) {
00400 if ((c = *q++) == 0xa0)
00401 *p++ = ' ';
00402 else
00403 *p++ = c;
00404 }
00405 *(p-7) = '\"';
00406 *p++ = 0;
00407
00408
00409 dir.next_track = bam->dir_track;
00410 dir.next_sector = bam->dir_sector;
00411
00412 while (dir.next_track) {
00413 if (!read_sector(dir.next_track, dir.next_sector, (uint8 *) &dir.next_track))
00414 return ST_OK;
00415
00416
00417 for (j=0; j<8; j++) {
00418 de = &dir.entry[j];
00419
00420 if (de->type && match((uint8 *)pattern, de->name)) {
00421 *p++ = 0x01;
00422 *p++ = 0x01;
00423
00424 *p++ = de->num_blocks_l;
00425 *p++ = de->num_blocks_h;
00426
00427 *p++ = ' ';
00428 n = (de->num_blocks_h << 8) + de->num_blocks_l;
00429 if (n<10) *p++ = ' ';
00430 if (n<100) *p++ = ' ';
00431
00432 *p++ = '\"';
00433 q = de->name;
00434 m = 0;
00435 for (i=0; i<16; i++) {
00436 if ((c = *q++) == 0xa0) {
00437 if (m)
00438 *p++ = ' ';
00439 else
00440 m = *p++ = '\"';
00441 } else
00442 *p++ = c;
00443 }
00444 if (m)
00445 *p++ = ' ';
00446 else
00447 *p++ = '\"';
00448
00449 if (de->type & 0x80)
00450 *p++ = ' ';
00451 else
00452 *p++ = '*';
00453
00454 *p++ = type_char_1[de->type & 0x0f];
00455 *p++ = type_char_2[de->type & 0x0f];
00456 *p++ = type_char_3[de->type & 0x0f];
00457
00458 if (de->type & 0x40)
00459 *p++ = '<';
00460 else
00461 *p++ = ' ';
00462
00463 *p++ = ' ';
00464 if (n >= 10) *p++ = ' ';
00465 if (n >= 100) *p++ = ' ';
00466 *p++ = 0;
00467 }
00468 }
00469 }
00470
00471
00472 q = p;
00473 for (i=0; i<29; i++)
00474 *q++ = ' ';
00475
00476 n = 0;
00477 for (i=0; i<35; i++)
00478 n += bam->bitmap[i*4];
00479
00480 *p++ = 0x01;
00481 *p++ = 0x01;
00482 *p++ = n & 0xff;
00483 *p++ = (n >> 8) & 0xff;
00484
00485 *p++ = 'B';
00486 *p++ = 'L';
00487 *p++ = 'O';
00488 *p++ = 'C';
00489 *p++ = 'K';
00490 *p++ = 'S';
00491 *p++ = ' ';
00492 *p++ = 'F';
00493 *p++ = 'R';
00494 *p++ = 'E';
00495 *p++ = 'E';
00496 *p++ = '.';
00497
00498 p = q;
00499 *p++ = 0;
00500 *p++ = 0;
00501 *p++ = 0;
00502
00503 buf_len[0] = p - chan_buf[0];
00504
00505 return ST_OK;
00506 }
00507
00508
00509
00510
00511
00512
00513 uint8 D64Drive::open_direct(int channel, char *filename)
00514 {
00515 int buf = -1;
00516
00517 if (filename[1] == 0)
00518 buf = alloc_buffer(-1);
00519 else
00520 if ((filename[1] >= '0') && (filename[1] <= '3') && (filename[2] == 0))
00521 buf = alloc_buffer(filename[1] - '0');
00522
00523 if (buf == -1) {
00524 set_error(ERR_NOCHANNEL);
00525 return ST_OK;
00526 }
00527
00528
00529 chan_buf[channel] = buf_ptr[channel] = ram + 0x300 + (buf << 8);
00530 chan_mode[channel] = CHMOD_DIRECT;
00531 chan_buf_num[channel] = buf;
00532
00533
00534 *chan_buf[channel] = buf + '0';
00535 buf_len[channel] = 1;
00536
00537 return ST_OK;
00538 }
00539
00540
00541
00542
00543
00544
00545 uint8 D64Drive::Close(int channel)
00546 {
00547 if (channel == 15) {
00548 close_all_channels();
00549 return ST_OK;
00550 }
00551
00552 switch (chan_mode[channel]) {
00553 case CHMOD_FREE:
00554 break;
00555
00556 case CHMOD_DIRECT:
00557 free_buffer(chan_buf_num[channel]);
00558 chan_buf[channel] = NULL;
00559 chan_mode[channel] = CHMOD_FREE;
00560 break;
00561
00562 default:
00563 delete[] chan_buf[channel];
00564 chan_buf[channel] = NULL;
00565 chan_mode[channel] = CHMOD_FREE;
00566 break;
00567 }
00568
00569 return ST_OK;
00570 }
00571
00572
00573
00574
00575
00576
00577 void D64Drive::close_all_channels()
00578 {
00579 for (int i=0; i<15; i++)
00580 Close(i);
00581
00582 cmd_len = 0;
00583 }
00584
00585
00586
00587
00588
00589
00590 uint8 D64Drive::Read(int channel, uint8 *byte)
00591 {
00592 switch (chan_mode[channel]) {
00593 case CHMOD_COMMAND:
00594 *byte = *error_ptr++;
00595 if (--error_len)
00596 return ST_OK;
00597 else {
00598 set_error(ERR_OK);
00599 return ST_EOF;
00600 }
00601 break;
00602
00603 case CHMOD_FILE:
00604
00605 if (chan_buf[channel][0] && !buf_len[channel]) {
00606 if (!read_sector(chan_buf[channel][0], chan_buf[channel][1], chan_buf[channel]))
00607 return ST_READ_TIMEOUT;
00608 buf_ptr[channel] = chan_buf[channel] + 2;
00609
00610
00611 buf_len[channel] = chan_buf[channel][0] ? 254 : (uint8)chan_buf[channel][1]-1;
00612 }
00613
00614 if (buf_len[channel] > 0) {
00615 *byte = *buf_ptr[channel]++;
00616 if (!--buf_len[channel] && !chan_buf[channel][0])
00617 return ST_EOF;
00618 else
00619 return ST_OK;
00620 } else
00621 return ST_READ_TIMEOUT;
00622 break;
00623
00624 case CHMOD_DIRECTORY:
00625 case CHMOD_DIRECT:
00626 if (buf_len[channel] > 0) {
00627 *byte = *buf_ptr[channel]++;
00628 if (--buf_len[channel])
00629 return ST_OK;
00630 else
00631 return ST_EOF;
00632 } else
00633 return ST_READ_TIMEOUT;
00634 break;
00635 }
00636 return ST_READ_TIMEOUT;
00637 }
00638
00639
00640
00641
00642
00643
00644 uint8 D64Drive::Write(int channel, uint8 byte, bool eoi)
00645 {
00646 switch (chan_mode[channel]) {
00647 case CHMOD_FREE:
00648 set_error(ERR_FILENOTOPEN);
00649 break;
00650
00651 case CHMOD_COMMAND:
00652
00653 if (cmd_len >= 40)
00654 return ST_TIMEOUT;
00655
00656 cmd_buffer[cmd_len++] = byte;
00657
00658 if (eoi) {
00659 cmd_buffer[cmd_len++] = 0;
00660 cmd_len = 0;
00661 execute_command(cmd_buffer);
00662 }
00663 return ST_OK;
00664
00665 case CHMOD_DIRECTORY:
00666 set_error(ERR_WRITEFILEOPEN);
00667 break;
00668 }
00669 return ST_TIMEOUT;
00670 }
00671
00672
00673
00674
00675
00676
00677 void D64Drive::execute_command(char *command)
00678 {
00679 uint16 adr;
00680 int len;
00681
00682 switch (command[0]) {
00683 case 'B':
00684 if (command[1] != '-')
00685 set_error(ERR_SYNTAX30);
00686 else
00687 switch (command[2]) {
00688 case 'R':
00689 block_read_cmd(&command[3]);
00690 break;
00691
00692 case 'P':
00693 buffer_ptr_cmd(&command[3]);
00694 break;
00695
00696 case 'A':
00697 case 'F':
00698 case 'W':
00699 set_error(ERR_WRITEPROTECT);
00700 break;
00701
00702 default:
00703 set_error(ERR_SYNTAX30);
00704 break;
00705 }
00706 break;
00707
00708 case 'M':
00709 if (command[1] != '-')
00710 set_error(ERR_SYNTAX30);
00711 else
00712 switch (command[2]) {
00713 case 'R':
00714 adr = ((uint8)command[4] << 8) | ((uint8)command[3]);
00715 error_ptr = (char *)(ram + (adr & 0x07ff));
00716 if (!(error_len = (uint8)command[5]))
00717 error_len = 1;
00718 break;
00719
00720 case 'W':
00721 {
00722 adr = ((uint8)command[4] << 8) | ((uint8)command[3]);
00723 len = (uint8)command[5];
00724 for (int i=0; i<len; i++)
00725 ram[adr+i] = (uint8)command[i+6];
00726 }
00727 break;
00728
00729 default:
00730 set_error(ERR_SYNTAX30);
00731 }
00732 break;
00733
00734 case 'I':
00735 close_all_channels();
00736 read_sector(18, 0, (uint8 *)bam);
00737 set_error(ERR_OK);
00738 break;
00739
00740 case 'U':
00741 switch (command[1] & 0x0f) {
00742 case 1:
00743 block_read_cmd(&command[2]);
00744 break;
00745
00746 case 2:
00747 set_error(ERR_WRITEPROTECT);
00748 break;
00749
00750 case 10:
00751 Reset();
00752 break;
00753
00754 default:
00755 set_error(ERR_SYNTAX30);
00756 break;
00757 }
00758 break;
00759
00760 case 'G':
00761 if (command[1] != ':')
00762 set_error(ERR_SYNTAX30);
00763 else
00764 chd64_cmd(&command[2]);
00765 break;
00766
00767 case 'C':
00768 case 'N':
00769 case 'R':
00770 case 'S':
00771 case 'V':
00772 set_error(ERR_WRITEPROTECT);
00773 break;
00774
00775 default:
00776 set_error(ERR_SYNTAX30);
00777 break;
00778 }
00779 }
00780
00781
00782
00783
00784
00785
00786 void D64Drive::block_read_cmd(char *command)
00787 {
00788 int channel, drvnum, track, sector;
00789
00790 if (parse_bcmd(command, &channel, &drvnum, &track, §or)) {
00791 if (chan_mode[channel] == CHMOD_DIRECT) {
00792 read_sector(track, sector, buf_ptr[channel] = chan_buf[channel]);
00793 buf_len[channel] = 256;
00794 set_error(ERR_OK);
00795 } else
00796 set_error(ERR_NOCHANNEL);
00797 } else
00798 set_error(ERR_SYNTAX30);
00799 }
00800
00801
00802
00803
00804
00805
00806 void D64Drive::buffer_ptr_cmd(char *command)
00807 {
00808 int channel, pointer, i;
00809
00810 if (parse_bcmd(command, &channel, &pointer, &i, &i)) {
00811 if (chan_mode[channel] == CHMOD_DIRECT) {
00812 buf_ptr[channel] = chan_buf[channel] + pointer;
00813 buf_len[channel] = 256 - pointer;
00814 set_error(ERR_OK);
00815 } else
00816 set_error(ERR_NOCHANNEL);
00817 } else
00818 set_error(ERR_SYNTAX30);
00819 }
00820
00821
00822
00823
00824
00825
00826
00827 bool D64Drive::parse_bcmd(char *cmd, int *arg1, int *arg2, int *arg3, int *arg4)
00828 {
00829 int i;
00830
00831 if (*cmd == ':') cmd++;
00832
00833
00834 while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
00835 if (!*cmd) return false;
00836
00837 i = 0;
00838 while (*cmd >= 0x30 && *cmd < 0x40) {
00839 i *= 10;
00840 i += *cmd++ & 0x0f;
00841 }
00842 *arg1 = i & 0xff;
00843
00844 while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
00845 if (!*cmd) return false;
00846
00847 i = 0;
00848 while (*cmd >= 0x30 && *cmd < 0x40) {
00849 i *= 10;
00850 i += *cmd++ & 0x0f;
00851 }
00852 *arg2 = i & 0xff;
00853
00854 while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
00855 if (!*cmd) return false;
00856
00857 i = 0;
00858 while (*cmd >= 0x30 && *cmd < 0x40) {
00859 i *= 10;
00860 i += *cmd++ & 0x0f;
00861 }
00862 *arg3 = i & 0xff;
00863
00864 while (*cmd == ' ' || *cmd == 0x1d || *cmd == 0x2c) cmd++;
00865 if (!*cmd) return false;
00866
00867 i = 0;
00868 while (*cmd >= 0x30 && *cmd < 0x40) {
00869 i *= 10;
00870 i += *cmd++ & 0x0f;
00871 }
00872 *arg4 = i & 0xff;
00873
00874 return true;
00875 }
00876
00877
00878
00879
00880
00881
00882 void D64Drive::chd64_cmd(char *d64name)
00883 {
00884 char str[NAMEBUF_LENGTH];
00885 char *p = str;
00886
00887
00888 for (int i=0; i<NAMEBUF_LENGTH && (*p++ = conv_from_64(*d64name++, false)); i++) ;
00889
00890 close_all_channels();
00891
00892
00893 if (str[0] == '.' && str[1] == 0)
00894 open_close_d64_file(orig_d64_name);
00895 else
00896 open_close_d64_file(str);
00897
00898
00899 read_sector(18, 0, (uint8 *)bam);
00900 }
00901
00902
00903
00904
00905
00906
00907 void D64Drive::Reset(void)
00908 {
00909 close_all_channels();
00910
00911 read_sector(18, 0, (uint8 *)bam);
00912
00913 cmd_len = 0;
00914 for (int i=0; i<4; i++)
00915 buf_free[i] = true;
00916
00917 set_error(ERR_STARTUP);
00918
00919 ELOG1(_L8("D64 drive reset\n"));
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929 int D64Drive::alloc_buffer(int want)
00930 {
00931 if (want == -1) {
00932 for (want=3; want>=0; want--)
00933 if (buf_free[want]) {
00934 buf_free[want] = false;
00935 return want;
00936 }
00937 return -1;
00938 }
00939
00940 if (want < 4)
00941 if (buf_free[want]) {
00942 buf_free[want] = false;
00943 return want;
00944 } else
00945 return -1;
00946 else
00947 return -1;
00948 }
00949
00950
00951
00952
00953
00954
00955 void D64Drive::free_buffer(int buf)
00956 {
00957 buf_free[buf] = true;
00958 }
00959
00960
00961
00962
00963
00964
00965
00966 bool D64Drive::read_sector(int track, int sector, uint8 *buffer)
00967 {
00968 int offset;
00969
00970
00971 if ((offset = offset_from_ts(track, sector)) < 0) {
00972 set_error(ERR_ILLEGALTS);
00973 return false;
00974 }
00975
00976 if (the_file == NULL) {
00977 set_error(ERR_NOTREADY);
00978 return false;
00979 }
00980
00981 #ifdef AMIGA
00982 if (offset != ftell(the_file))
00983 fseek(the_file, offset + image_header, SEEK_SET);
00984 #else
00985 fseek(the_file, offset + image_header, SEEK_SET);
00986 #endif
00987 fread(buffer, 256, 1, the_file);
00988 return true;
00989 }
00990
00991
00992
00993
00994
00995
00996 const int num_sectors[41] = {
00997 0,
00998 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
00999 19,19,19,19,19,19,19,
01000 18,18,18,18,18,18,
01001 17,17,17,17,17,
01002 17,17,17,17,17
01003 };
01004
01005 const int sector_offset[41] = {
01006 0,
01007 0,21,42,63,84,105,126,147,168,189,210,231,252,273,294,315,336,
01008 357,376,395,414,433,452,471,
01009 490,508,526,544,562,580,
01010 598,615,632,649,666,
01011 683,700,717,734,751
01012 };
01013
01014 int D64Drive::offset_from_ts(int track, int sector)
01015 {
01016 if ((track < 1) || (track > NUM_TRACKS) ||
01017 (sector < 0) || (sector >= num_sectors[track]))
01018 return -1;
01019
01020 return (sector_offset[track] + sector) << 8;
01021 }
01022
01023
01024
01025
01026
01027
01028 uint8 D64Drive::conv_from_64(uint8 c, bool map_slash)
01029 {
01030 if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
01031 return c ^ 0x20;
01032 if ((c >= 0xc1) && (c <= 0xda))
01033 return c ^ 0x80;
01034 if ((c == '/') && map_slash)
01035 return '\\';
01036 return c;
01037 }