src/mess/machine/vc1541.c
| r3282 | r3283 | |
| 136 | 136 | } \ |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | #define XTAL_16_MHz 16000000 |
| 140 | |
| 141 | /* Are there other formats to support which could require more tracks? */ |
| 142 | #define IMAGE_MAX_TRACKS 154 |
| 143 | |
| 139 | 144 | #define D64_MAX_TRACKS 35 |
| 145 | #define D64_40T_MAX_TRACKS 40 |
| 140 | 146 | |
| 141 | 147 | static const int d64_sectors_per_track[] = |
| 142 | 148 | { |
| 143 | 149 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, |
| 144 | 150 | 19, 19, 19, 19, 19, 19, 19, |
| 145 | 151 | 18, 18, 18, 18, 18, 18, |
| 152 | 17, 17, 17, 17, 17, |
| 153 | 17, 17, 17, 17, 17 /* only for 40 tracks d64 */ |
| 154 | }; |
| 155 | |
| 156 | #define D71_MAX_TRACKS 70 |
| 157 | |
| 158 | static const int d71_sectors_per_track[] = |
| 159 | { |
| 160 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, |
| 161 | 19, 19, 19, 19, 19, 19, 19, |
| 162 | 18, 18, 18, 18, 18, 18, |
| 163 | 17, 17, 17, 17, 17, |
| 164 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, |
| 165 | 19, 19, 19, 19, 19, 19, 19, |
| 166 | 18, 18, 18, 18, 18, 18, |
| 146 | 167 | 17, 17, 17, 17, 17 |
| 147 | 168 | }; |
| 148 | 169 | |
| 149 | | static int d64_offset[D64_MAX_TRACKS]; /* offset of begin of track in d64 file */ |
| 170 | #define D81_MAX_TRACKS 80 |
| 150 | 171 | |
| 151 | | /* calculates offset to beginning of d64 file for sector beginning */ |
| 152 | | static int d64_tracksector2offset (int track, int sector) |
| 172 | /* Each track in a d81 file has 40 sectors, so no need of a sectors_per_track table */ |
| 173 | |
| 174 | #define D80_MAX_TRACKS 77 |
| 175 | |
| 176 | static const int d80_sectors_per_track[] = |
| 153 | 177 | { |
| 154 | | return d64_offset[track - 1] + sector * 256; |
| 178 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 179 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 180 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 181 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 182 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23 |
| 183 | }; |
| 184 | |
| 185 | |
| 186 | #define D82_MAX_TRACKS 154 |
| 187 | |
| 188 | static const int d82_sectors_per_track[] = |
| 189 | { |
| 190 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 191 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 192 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 193 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 194 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, |
| 195 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 196 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 197 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 198 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, |
| 199 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23 |
| 200 | }; |
| 201 | |
| 202 | |
| 203 | static int image_offset[IMAGE_MAX_TRACKS] = { 0 }; |
| 204 | |
| 205 | |
| 206 | static void offset_init (int format) |
| 207 | { |
| 208 | int i; |
| 209 | |
| 210 | /* Track # starts from 1 */ |
| 211 | image_offset[0] = 0; |
| 212 | |
| 213 | switch (format) |
| 214 | { |
| 215 | case format_d64: |
| 216 | for (i = 1; i <= D64_MAX_TRACKS; i++) |
| 217 | image_offset[i] = image_offset[i - 1] + d64_sectors_per_track[i - 1] * 256; |
| 218 | break; |
| 219 | |
| 220 | case format_d64_40t: |
| 221 | for (i = 1; i <= D64_40T_MAX_TRACKS; i++) |
| 222 | image_offset[i] = image_offset[i - 1] + d64_sectors_per_track[i - 1] * 256; |
| 223 | break; |
| 224 | |
| 225 | case format_d71: |
| 226 | for (i = 1; i <= D71_MAX_TRACKS; i++) |
| 227 | image_offset[i] = image_offset[i - 1] + d71_sectors_per_track[i - 1] * 256; |
| 228 | break; |
| 229 | |
| 230 | case format_d81: |
| 231 | for (i = 1; i <= D81_MAX_TRACKS; i++) |
| 232 | image_offset[i] = image_offset[i - 1] + 40 * 256; |
| 233 | break; |
| 234 | |
| 235 | case format_d80: |
| 236 | for (i = 1; i <= D80_MAX_TRACKS; i++) |
| 237 | image_offset[i] = image_offset[i - 1] + d80_sectors_per_track[i - 1] * 256; |
| 238 | break; |
| 239 | |
| 240 | case format_d82: |
| 241 | for (i = 1; i <= D82_MAX_TRACKS; i++) |
| 242 | image_offset[i] = image_offset[i - 1] + d82_sectors_per_track[i - 1] * 256; |
| 243 | break; |
| 244 | |
| 245 | default: |
| 246 | logerror("Unsupported format"); |
| 247 | break; |
| 248 | } |
| 155 | 249 | } |
| 156 | 250 | |
| 157 | 251 | |
| 158 | | #define D64_TRACK_ID1 (d64_tracksector2offset(18,0)+162) |
| 159 | | #define D64_TRACK_ID2 (d64_tracksector2offset(18,0)+163) |
| 252 | /* calculates offset to beginning of the image file for sector beginning */ |
| 253 | /* since sectors are always 256 bytes large, this works for each file format! */ |
| 254 | static int image_tracksector2offset (int track, int sector) |
| 255 | { |
| 256 | return image_offset[track - 1] + sector * 256; |
| 257 | } |
| 160 | 258 | |
| 259 | |
| 260 | #define D64_TRACK_ID1 (image_tracksector2offset(18,0)+162) |
| 261 | #define D64_TRACK_ID2 (image_tracksector2offset(18,0)+163) |
| 262 | |
| 161 | 263 | /* |
| 162 | 264 | * only for testing at the moment |
| 163 | 265 | */ |
| r3282 | r3283 | |
| 214 | 316 | int pos; /* position in sector */ |
| 215 | 317 | int sector; |
| 216 | 318 | UINT8 *data; |
| 217 | | } d64; |
| 319 | } image; |
| 218 | 320 | } CBM_Drive_Emu; |
| 219 | 321 | |
| 220 | 322 | static CBM_Drive_Emu drive_static= { 0 }, *drive = &drive_static; |
| r3282 | r3283 | |
| 325 | 427 | { |
| 326 | 428 | int i=0, j, offset, chksum=0; |
| 327 | 429 | |
| 328 | | if (drive->d64.data==NULL) return; |
| 430 | if (drive->image.data==NULL) return; |
| 329 | 431 | drive->head.data[i++]=0xff; |
| 330 | 432 | drive->head.data[i++]=0xff; |
| 331 | 433 | drive->head.data[i++]=0xff; |
| r3282 | r3283 | |
| 335 | 437 | |
| 336 | 438 | drive_sector_data(8, &i); |
| 337 | 439 | chksum= sector^track |
| 338 | | ^drive->d64.data[D64_TRACK_ID1]^drive->d64.data[D64_TRACK_ID2]; |
| 440 | ^drive->image.data[D64_TRACK_ID1]^drive->image.data[D64_TRACK_ID2]; |
| 339 | 441 | drive_sector_data(chksum, &i); |
| 340 | 442 | drive_sector_data(sector, &i); |
| 341 | 443 | drive_sector_data(track, &i); |
| 342 | | drive_sector_data(drive->d64.data[D64_TRACK_ID1], &i); |
| 343 | | drive_sector_data(drive->d64.data[D64_TRACK_ID2], &i); |
| 444 | drive_sector_data(drive->image.data[D64_TRACK_ID1], &i); |
| 445 | drive_sector_data(drive->image.data[D64_TRACK_ID2], &i); |
| 344 | 446 | drive_sector_data(0xf, &i); |
| 345 | 447 | drive_sector_data(0xf, &i); |
| 346 | 448 | drive_sector_end(&i); |
| r3282 | r3283 | |
| 356 | 458 | drive_sector_data(0x7, &i); |
| 357 | 459 | |
| 358 | 460 | chksum=0; |
| 359 | | for (offset=d64_tracksector2offset(track,sector), j=0; j<256; j++) { |
| 360 | | chksum^=drive->d64.data[offset]; |
| 361 | | drive_sector_data(drive->d64.data[offset++], &i); |
| 461 | for (offset=image_tracksector2offset(track,sector), j=0; j<256; j++) { |
| 462 | chksum^=drive->image.data[offset]; |
| 463 | drive_sector_data(drive->image.data[offset++], &i); |
| 362 | 464 | } |
| 363 | 465 | drive_sector_data(chksum, &i); |
| 364 | 466 | drive_sector_data(0, &i); /* padding up */ |
| r3282 | r3283 | |
| 371 | 473 | |
| 372 | 474 | /************************************** |
| 373 | 475 | |
| 374 | | VC1541 |
| 476 | 1541 / 1541II |
| 375 | 477 | |
| 376 | 478 | **************************************/ |
| 377 | 479 | |
| 378 | 480 | |
| 379 | | static ADDRESS_MAP_START( vc1541_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 481 | static ADDRESS_MAP_START( _1541_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 380 | 482 | AM_RANGE(0x0000, 0x07ff) AM_RAM |
| 381 | 483 | AM_RANGE(0x1800, 0x180f) AM_READWRITE(via_2_r, via_2_w) /* 0 and 1 used in vc20 */ |
| 382 | 484 | AM_RANGE(0x1810, 0x189f) AM_READ(SMH_NOP) /* for debugger */ |
| r3282 | r3283 | |
| 418 | 520 | } |
| 419 | 521 | return; |
| 420 | 522 | } |
| 421 | | if (++(drive->d64.pos)>=sizeof(drive->head.data)) { |
| 422 | | if (++(drive->d64.sector)>= |
| 523 | if (++(drive->image.pos)>=sizeof(drive->head.data)) { |
| 524 | if (++(drive->image.sector)>= |
| 423 | 525 | d64_sectors_per_track[(int)drive->track-1]) { |
| 424 | | drive->d64.sector=0; |
| 526 | drive->image.sector=0; |
| 425 | 527 | } |
| 426 | | drive_sector_to_gcr((int)drive->track,drive->d64.sector); |
| 427 | | drive->d64.pos=0; |
| 528 | drive_sector_to_gcr((int)drive->track,drive->image.sector); |
| 529 | drive->image.pos=0; |
| 428 | 530 | } |
| 429 | 531 | drive->head.ready=1; |
| 430 | | if (drive->head.data[drive->d64.pos]==0xff) { |
| 532 | if (drive->head.data[drive->image.pos]==0xff) { |
| 431 | 533 | drive->head.ffcount++; |
| 432 | 534 | if (drive->head.ffcount==5) { |
| 433 | 535 | drive->head.sync=1; |
| r3282 | r3283 | |
| 567 | 669 | |
| 568 | 670 | static READ8_HANDLER( vc1541_via1_read_porta ) |
| 569 | 671 | { |
| 570 | | int data=drive->head.data[drive->d64.pos]; |
| 672 | int data=drive->head.data[drive->image.pos]; |
| 571 | 673 | DBG_LOG(2, "vc1541 drive",("port a read %.2x\n", data)); |
| 572 | 674 | return data; |
| 573 | 675 | } |
| r3282 | r3283 | |
| 795 | 897 | |
| 796 | 898 | /************************************** |
| 797 | 899 | |
| 798 | | C1551 |
| 900 | 1570 / 1571 / 1571CR |
| 799 | 901 | |
| 800 | 902 | **************************************/ |
| 801 | 903 | |
| 904 | static ADDRESS_MAP_START( _1571_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 905 | AM_RANGE(0x0000, 0x07ff) AM_RAM |
| 906 | AM_RANGE(0x1800, 0x180f) AM_READWRITE(via_2_r, via_2_w) /* 0 and 1 used in vc20 */ |
| 907 | AM_RANGE(0x1810, 0x189f) AM_READ(SMH_NOP) /* for debugger */ |
| 908 | AM_RANGE(0x1c00, 0x1c0f) AM_READWRITE(via_3_r, via_3_w) |
| 909 | AM_RANGE(0x1c10, 0x1c9f) AM_READ(SMH_NOP) /* for debugger */ |
| 910 | // AM_RANGE(0x2000, 0x2003) // WD17xx |
| 911 | // AM_RANGE(0x4000, 0x400f) // CIA |
| 912 | AM_RANGE(0xc000, 0xffff) AM_ROM |
| 913 | ADDRESS_MAP_END |
| 914 | |
| 915 | |
| 916 | /************************************** |
| 917 | |
| 918 | 1581 |
| 919 | |
| 920 | **************************************/ |
| 921 | |
| 922 | static ADDRESS_MAP_START( _1581_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 923 | // AM_RANGE(0x4000, 0x400f) // CIA |
| 924 | // AM_RANGE(0x6000, 0x6003) // WD17xx |
| 925 | ADDRESS_MAP_END |
| 926 | |
| 927 | |
| 928 | /************************************** |
| 929 | |
| 930 | 2031 / 2040 / 3040 / 4040 / |
| 931 | 1001 / 8050 / 8250 |
| 932 | |
| 933 | **************************************/ |
| 934 | |
| 935 | static ADDRESS_MAP_START( _2031_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 936 | // AM_RANGE(0x0200, 0x021f) // RIOT1 |
| 937 | // AM_RANGE(0x0280, 0x029f) // RIOT2 |
| 938 | ADDRESS_MAP_END |
| 939 | |
| 940 | |
| 941 | /************************************** |
| 942 | |
| 943 | 1551 |
| 944 | |
| 945 | **************************************/ |
| 946 | |
| 802 | 947 | /* |
| 803 | 948 | c1551 irq line |
| 804 | 949 | only timing related??? (60 hz?), delivered from c16? |
| r3282 | r3283 | |
| 924 | 1069 | |
| 925 | 1070 | static int c1551_port_b_r (void) |
| 926 | 1071 | { |
| 927 | | int data=drive->head.data[drive->d64.pos]; |
| 1072 | int data=drive->head.data[drive->image.pos]; |
| 928 | 1073 | DBG_LOG(2, "c1551 drive",("port a read %.2x\n", data)); |
| 929 | 1074 | return data; |
| 930 | 1075 | } |
| 931 | 1076 | |
| 932 | 1077 | |
| 933 | | static ADDRESS_MAP_START( c1551_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 1078 | static ADDRESS_MAP_START( _1551_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 934 | 1079 | AM_RANGE(0x0000, 0x0001) AM_READWRITE(c1551_port_r, c1551_port_w) |
| 935 | 1080 | AM_RANGE(0x0002, 0x07ff) AM_RAM |
| 936 | 1081 | AM_RANGE(0x4000, 0x4007) AM_READWRITE(tpi6525_0_port_r, tpi6525_0_port_w) |
| r3282 | r3283 | |
| 1085 | 1230 | **************************************/ |
| 1086 | 1231 | |
| 1087 | 1232 | MACHINE_DRIVER_START( cpu_vc1540 ) |
| 1088 | | MDRV_CPU_ADD("cpu_vc1540", M6502, 1000000) |
| 1089 | | MDRV_CPU_PROGRAM_MAP(vc1541_map, 0) |
| 1233 | MDRV_CPU_ADD("cpu_vc1540", M6502, XTAL_16_MHz / 16) |
| 1234 | MDRV_CPU_PROGRAM_MAP(_1541_map, 0) |
| 1090 | 1235 | MACHINE_DRIVER_END |
| 1091 | 1236 | |
| 1092 | 1237 | MACHINE_DRIVER_START( cpu_vc1541 ) |
| r3282 | r3283 | |
| 1098 | 1243 | MACHINE_DRIVER_END |
| 1099 | 1244 | |
| 1100 | 1245 | MACHINE_DRIVER_START( cpu_dolphin ) |
| 1101 | | MDRV_CPU_ADD("cpu_dolphin", M6502, 1000000) |
| 1246 | MDRV_CPU_ADD("cpu_dolphin", M6502, XTAL_16_MHz / 16) |
| 1102 | 1247 | MDRV_CPU_PROGRAM_MAP(dolphin_map, 0) |
| 1103 | 1248 | MACHINE_DRIVER_END |
| 1104 | 1249 | |
| 1105 | 1250 | MACHINE_DRIVER_START( cpu_c1551 ) |
| 1106 | 1251 | MDRV_CPU_ADD("cpu_c1551", M6510T, 2000000) |
| 1107 | | MDRV_CPU_PROGRAM_MAP(c1551_map, 0) |
| 1252 | MDRV_CPU_PROGRAM_MAP(_1551_map, 0) |
| 1108 | 1253 | MACHINE_DRIVER_END |
| 1109 | 1254 | |
| 1110 | 1255 | MACHINE_DRIVER_START( cpu_c1571 ) |
| 1111 | | MDRV_IMPORT_FROM(cpu_vc1541) |
| 1256 | MDRV_CPU_ADD("cpu_vc1540", M6502, XTAL_16_MHz / 16) |
| 1257 | MDRV_CPU_PROGRAM_MAP(_1571_map, 0) |
| 1112 | 1258 | MACHINE_DRIVER_END |
| 1113 | 1259 | |
| 1114 | 1260 | /************************************** |
| r3282 | r3283 | |
| 1119 | 1265 | |
| 1120 | 1266 | DEVICE_IMAGE_LOAD(vc1541) |
| 1121 | 1267 | { |
| 1122 | | drive->d64.data = image_ptr(image); |
| 1123 | | if (!drive->d64.data) |
| 1268 | offset_init (format_d64); |
| 1269 | |
| 1270 | /* Fix me: we should load directly the GCR data */ |
| 1271 | drive->image.data = image_ptr(image); |
| 1272 | if (!drive->image.data) |
| 1124 | 1273 | return INIT_FAIL; |
| 1125 | 1274 | |
| 1126 | 1275 | logerror("floppy image %s loaded\n", image_filename(image)); |
| r3282 | r3283 | |
| 1131 | 1280 | DEVICE_IMAGE_UNLOAD(vc1541) |
| 1132 | 1281 | { |
| 1133 | 1282 | /* writeback of image data */ |
| 1134 | | drive->d64.data = NULL; |
| 1283 | drive->image.data = NULL; |
| 1135 | 1284 | } |
| 1136 | 1285 | |
| 1137 | 1286 | void vc1541_device_getinfo(const mess_device_class *devclass, UINT32 state, union devinfo *info) |