trunk/src/emu/bus/a2bus/a2diskiing.c
| r0 | r29576 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | a2diskii.c |
| 4 | |
| 5 | Implementation of the Apple II Disk II controller card |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #include "emu.h" |
| 10 | #include "imagedev/floppy.h" |
| 11 | #include "formats/ap2_dsk.h" |
| 12 | #include "a2diskiing.h" |
| 13 | #include <assert.h> |
| 14 | |
| 15 | /*************************************************************************** |
| 16 | PARAMETERS |
| 17 | ***************************************************************************/ |
| 18 | |
| 19 | //************************************************************************** |
| 20 | // GLOBAL VARIABLES |
| 21 | //************************************************************************** |
| 22 | |
| 23 | const device_type A2BUS_DISKIING = &device_creator<a2bus_diskiing_device>; |
| 24 | |
| 25 | #define WOZFDC_TAG "wozfdc" |
| 26 | #define DISKII_ROM_REGION "diskii_rom" |
| 27 | |
| 28 | static SLOT_INTERFACE_START( a2_floppies ) |
| 29 | SLOT_INTERFACE( "525", FLOPPY_525_SD ) |
| 30 | SLOT_INTERFACE_END |
| 31 | |
| 32 | static MACHINE_CONFIG_FRAGMENT( diskiing ) |
| 33 | MCFG_DEVICE_ADD(WOZFDC_TAG, DISKII_FDC, 1021800*2) |
| 34 | MCFG_FLOPPY_DRIVE_ADD("0", a2_floppies, "525", a2bus_diskiing_device::floppy_formats) |
| 35 | MCFG_FLOPPY_DRIVE_ADD("1", a2_floppies, "525", a2bus_diskiing_device::floppy_formats) |
| 36 | MACHINE_CONFIG_END |
| 37 | |
| 38 | ROM_START( diskiing ) |
| 39 | ROM_REGION(0x100, DISKII_ROM_REGION, 0) |
| 40 | ROM_LOAD( "341-0027-a.p5", 0x0000, 0x0100, CRC(ce7144f6) SHA1(d4181c9f046aafc3fb326b381baac809d9e38d16) ) /* 341-0027-a: 16-sector disk drive (older version), PROM P5 */ |
| 41 | ROM_END |
| 42 | |
| 43 | FLOPPY_FORMATS_MEMBER( a2bus_diskiing_device::floppy_formats ) |
| 44 | FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT |
| 45 | FLOPPY_FORMATS_END |
| 46 | |
| 47 | //------------------------------------------------- |
| 48 | // machine_config_additions - device-specific |
| 49 | // machine configurations |
| 50 | //------------------------------------------------- |
| 51 | |
| 52 | machine_config_constructor a2bus_diskiing_device::device_mconfig_additions() const |
| 53 | { |
| 54 | return MACHINE_CONFIG_NAME( diskiing ); |
| 55 | } |
| 56 | |
| 57 | //------------------------------------------------- |
| 58 | // rom_region - device-specific ROM region |
| 59 | //------------------------------------------------- |
| 60 | |
| 61 | const rom_entry *a2bus_diskiing_device::device_rom_region() const |
| 62 | { |
| 63 | return ROM_NAME( diskiing ); |
| 64 | } |
| 65 | |
| 66 | //************************************************************************** |
| 67 | // LIVE DEVICE |
| 68 | //************************************************************************** |
| 69 | |
| 70 | a2bus_diskiing_device::a2bus_diskiing_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 71 | device_t(mconfig, A2BUS_DISKIING, "Apple Disk II NG controller", tag, owner, clock, "a2diskiing", __FILE__), |
| 72 | device_a2bus_card_interface(mconfig, *this), |
| 73 | m_wozfdc(*this, WOZFDC_TAG), |
| 74 | floppy0(*this, "0"), |
| 75 | floppy1(*this, "1") |
| 76 | { |
| 77 | } |
| 78 | |
| 79 | //------------------------------------------------- |
| 80 | // device_start - device-specific startup |
| 81 | //------------------------------------------------- |
| 82 | |
| 83 | void a2bus_diskiing_device::device_start() |
| 84 | { |
| 85 | // set_a2bus_device makes m_slot valid |
| 86 | set_a2bus_device(); |
| 87 | |
| 88 | astring tempstring; |
| 89 | m_rom = device().machine().root_device().memregion(this->subtag(tempstring, DISKII_ROM_REGION))->base(); |
| 90 | } |
| 91 | |
| 92 | void a2bus_diskiing_device::device_reset() |
| 93 | { |
| 94 | m_wozfdc->set_floppies(floppy0, floppy1); |
| 95 | } |
| 96 | |
| 97 | /*------------------------------------------------- |
| 98 | read_c0nx - called for reads from this card's c0nx space |
| 99 | -------------------------------------------------*/ |
| 100 | |
| 101 | UINT8 a2bus_diskiing_device::read_c0nx(address_space &space, UINT8 offset) |
| 102 | { |
| 103 | return m_wozfdc->read(space, offset); |
| 104 | } |
| 105 | |
| 106 | |
| 107 | /*------------------------------------------------- |
| 108 | write_c0nx - called for writes to this card's c0nx space |
| 109 | -------------------------------------------------*/ |
| 110 | |
| 111 | void a2bus_diskiing_device::write_c0nx(address_space &space, UINT8 offset, UINT8 data) |
| 112 | { |
| 113 | m_wozfdc->write(space, offset, data); |
| 114 | } |
| 115 | |
| 116 | /*------------------------------------------------- |
| 117 | read_cnxx - called for reads from this card's cnxx space |
| 118 | -------------------------------------------------*/ |
| 119 | |
| 120 | UINT8 a2bus_diskiing_device::read_cnxx(address_space &space, UINT8 offset) |
| 121 | { |
| 122 | return m_rom[offset]; |
| 123 | } |
| 124 | |
trunk/src/emu/machine/wozfdc.c
| r0 | r29576 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | wozfdc.c |
| 4 | |
| 5 | Implementation of the Apple Disk II floppy disk controller |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #include "emu.h" |
| 10 | #include "imagedev/floppy.h" |
| 11 | #include "formats/ap2_dsk.h" |
| 12 | #include "wozfdc.h" |
| 13 | #include <assert.h> |
| 14 | |
| 15 | /*************************************************************************** |
| 16 | PARAMETERS |
| 17 | ***************************************************************************/ |
| 18 | |
| 19 | //************************************************************************** |
| 20 | // GLOBAL VARIABLES |
| 21 | //************************************************************************** |
| 22 | |
| 23 | const device_type DISKII_FDC = &device_creator<diskii_fdc>; |
| 24 | const device_type APPLEIII_FDC = &device_creator<appleiii_fdc>; |
| 25 | |
| 26 | #define DISKII_P6_REGION "diskii_rom_p6" |
| 27 | |
| 28 | ROM_START( diskiing ) |
| 29 | ROM_REGION(0x100, DISKII_P6_REGION, 0) |
| 30 | ROM_LOAD( "341-0028-a.rom", 0x0000, 0x0100, CRC(b72a2c70) SHA1(bc39fbd5b9a8d2287ac5d0a42e639fc4d3c2f9d4)) /* 341-0028: 16-sector disk drive (older version), PROM P6 */ |
| 31 | ROM_END |
| 32 | |
| 33 | //------------------------------------------------- |
| 34 | // rom_region - device-specific ROM region |
| 35 | //------------------------------------------------- |
| 36 | |
| 37 | const rom_entry *wozfdc_device::device_rom_region() const |
| 38 | { |
| 39 | return ROM_NAME( diskiing ); |
| 40 | } |
| 41 | |
| 42 | //************************************************************************** |
| 43 | // LIVE DEVICE |
| 44 | //************************************************************************** |
| 45 | |
| 46 | wozfdc_device::wozfdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : |
| 47 | device_t(mconfig, type, name, tag, owner, clock, shortname, source) |
| 48 | { |
| 49 | } |
| 50 | |
| 51 | diskii_fdc::diskii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 52 | wozfdc_device(mconfig, DISKII_FDC, "Apple Disk II floppy controller", tag, owner, clock, "d2fdc", __FILE__) |
| 53 | { |
| 54 | } |
| 55 | |
| 56 | appleiii_fdc::appleiii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 57 | wozfdc_device(mconfig, DISKII_FDC, "Apple III floppy controller", tag, owner, clock, "a3fdc", __FILE__) |
| 58 | { |
| 59 | } |
| 60 | |
| 61 | //------------------------------------------------- |
| 62 | // device_start - device-specific startup |
| 63 | //------------------------------------------------- |
| 64 | |
| 65 | void wozfdc_device::device_start() |
| 66 | { |
| 67 | astring tempstring; |
| 68 | m_rom_p6 = machine().root_device().memregion(this->subtag(tempstring, DISKII_P6_REGION))->base(); |
| 69 | |
| 70 | timer = timer_alloc(0); |
| 71 | delay_timer = timer_alloc(1); |
| 72 | } |
| 73 | |
| 74 | void wozfdc_device::device_reset() |
| 75 | { |
| 76 | current_cyl = 0; |
| 77 | floppy = NULL; |
| 78 | active = MODE_IDLE; |
| 79 | phases = 0x00; |
| 80 | mode_write = false; |
| 81 | mode_load = false; |
| 82 | last_6502_write = 0x00; |
| 83 | cur_lss.tm = machine().time(); |
| 84 | cur_lss.cycles = time_to_cycles(cur_lss.tm); |
| 85 | cur_lss.data_reg = 0x00; |
| 86 | cur_lss.address = 0x00; |
| 87 | cur_lss.write_start_time = attotime::never; |
| 88 | cur_lss.write_position = 0; |
| 89 | predicted_lss.tm = attotime::never; |
| 90 | } |
| 91 | |
| 92 | void wozfdc_device::a3_update_drive_sel() |
| 93 | { |
| 94 | floppy_image_device *newflop; |
| 95 | |
| 96 | if (enable1) |
| 97 | { |
| 98 | newflop = floppy0->get_device(); |
| 99 | } |
| 100 | else |
| 101 | { |
| 102 | switch (drvsel & 3) |
| 103 | { |
| 104 | case 0: |
| 105 | newflop = floppy0->get_device(); |
| 106 | break; |
| 107 | |
| 108 | case 1: |
| 109 | newflop = floppy1->get_device(); |
| 110 | break; |
| 111 | |
| 112 | case 2: |
| 113 | newflop = floppy2->get_device(); |
| 114 | break; |
| 115 | |
| 116 | case 3: |
| 117 | newflop = floppy3->get_device(); |
| 118 | break; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | if (floppy != newflop) |
| 123 | { |
| 124 | if(active) { |
| 125 | lss_sync(); |
| 126 | floppy->mon_w(true); |
| 127 | } |
| 128 | floppy = newflop; |
| 129 | if(active) { |
| 130 | floppy->mon_w(false); |
| 131 | lss_predict(); |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | void diskii_fdc::device_reset() |
| 137 | { |
| 138 | wozfdc_device::device_reset(); |
| 139 | external_drive_select = false; |
| 140 | |
| 141 | if (floppy0 != NULL) |
| 142 | { |
| 143 | floppy = floppy0->get_device(); |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | void appleiii_fdc::device_reset() |
| 148 | { |
| 149 | wozfdc_device::device_reset(); |
| 150 | external_drive_select = true; |
| 151 | drvsel = 0; |
| 152 | enable1 = 1; |
| 153 | } |
| 154 | |
| 155 | void wozfdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 156 | { |
| 157 | if(active) |
| 158 | lss_sync(); |
| 159 | |
| 160 | if(id == 1 && active == MODE_DELAY) { |
| 161 | if(floppy) |
| 162 | floppy->mon_w(true); |
| 163 | active = MODE_IDLE; |
| 164 | } |
| 165 | |
| 166 | if(active) |
| 167 | lss_predict(); |
| 168 | } |
| 169 | |
| 170 | /*------------------------------------------------- |
| 171 | read - called to read the FDC's registers |
| 172 | -------------------------------------------------*/ |
| 173 | |
| 174 | READ8_MEMBER(wozfdc_device::read) |
| 175 | { |
| 176 | control(offset); |
| 177 | |
| 178 | if(!(offset & 1)) |
| 179 | return cur_lss.data_reg; |
| 180 | return 0xff; |
| 181 | } |
| 182 | |
| 183 | |
| 184 | /*------------------------------------------------- |
| 185 | write - called to write the FDC's registers |
| 186 | -------------------------------------------------*/ |
| 187 | |
| 188 | WRITE8_MEMBER(wozfdc_device::write) |
| 189 | { |
| 190 | control(offset); |
| 191 | last_6502_write = data; |
| 192 | lss_predict(); |
| 193 | } |
| 194 | |
| 195 | void wozfdc_device::phase(int ph, bool on) |
| 196 | { |
| 197 | if(on) |
| 198 | phases |= 1 << ph; |
| 199 | else |
| 200 | phases &= ~(1 << ph); |
| 201 | |
| 202 | if(floppy && active) { |
| 203 | int cph = current_cyl & 3; |
| 204 | int pcyl = current_cyl; |
| 205 | if(!(phases & (1 << cph))) { |
| 206 | if(current_cyl < 70 && (phases & (1 << ((cph+1) & 3)))) |
| 207 | current_cyl++; |
| 208 | if(current_cyl && (phases & (1 << ((cph+3) & 3)))) |
| 209 | current_cyl--; |
| 210 | if(current_cyl != pcyl && !(current_cyl & 1)) { |
| 211 | floppy->dir_w(current_cyl < pcyl); |
| 212 | floppy->stp_w(true); |
| 213 | floppy->stp_w(false); |
| 214 | floppy->stp_w(true); |
| 215 | } |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | void wozfdc_device::control(int offset) |
| 221 | { |
| 222 | if(offset < 8) { |
| 223 | if(active) |
| 224 | lss_sync(); |
| 225 | phase(offset >> 1, offset & 1); |
| 226 | if(active) |
| 227 | lss_predict(); |
| 228 | |
| 229 | } else |
| 230 | switch(offset) { |
| 231 | case 0x8: |
| 232 | if(active == MODE_ACTIVE) { |
| 233 | lss_sync(); |
| 234 | delay_timer->adjust(attotime::from_seconds(1)); |
| 235 | active = MODE_DELAY; |
| 236 | } |
| 237 | break; |
| 238 | case 0x9: |
| 239 | switch(active) { |
| 240 | case MODE_IDLE: |
| 241 | if(floppy) { |
| 242 | floppy->mon_w(false); |
| 243 | current_cyl = floppy->get_cyl() << 1; |
| 244 | } |
| 245 | active = MODE_ACTIVE; |
| 246 | if(floppy) |
| 247 | lss_start(); |
| 248 | break; |
| 249 | case MODE_DELAY: |
| 250 | active = MODE_ACTIVE; |
| 251 | delay_timer->adjust(attotime::never); |
| 252 | break; |
| 253 | } |
| 254 | break; |
| 255 | case 0xa: |
| 256 | if(floppy != floppy0->get_device()) { |
| 257 | if(active) { |
| 258 | lss_sync(); |
| 259 | floppy->mon_w(true); |
| 260 | } |
| 261 | floppy = floppy0->get_device(); |
| 262 | if(active) { |
| 263 | floppy->mon_w(false); |
| 264 | lss_predict(); |
| 265 | } |
| 266 | } |
| 267 | break; |
| 268 | case 0xb: |
| 269 | if (!external_drive_select) |
| 270 | { |
| 271 | if (floppy != floppy1->get_device()) |
| 272 | { |
| 273 | if(active) { |
| 274 | lss_sync(); |
| 275 | floppy->mon_w(true); |
| 276 | } |
| 277 | floppy = floppy1->get_device(); |
| 278 | if(active) { |
| 279 | floppy->mon_w(false); |
| 280 | lss_predict(); |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | else |
| 285 | { |
| 286 | a3_update_drive_sel(); |
| 287 | } |
| 288 | break; |
| 289 | case 0xc: |
| 290 | if(mode_load) { |
| 291 | if(active) { |
| 292 | lss_sync(); |
| 293 | cur_lss.address &= ~0x04; |
| 294 | } |
| 295 | mode_load = false; |
| 296 | if(active) |
| 297 | lss_predict(); |
| 298 | } |
| 299 | break; |
| 300 | case 0xd: |
| 301 | if(!mode_load) { |
| 302 | if(active) { |
| 303 | lss_sync(); |
| 304 | cur_lss.address |= 0x04; |
| 305 | } |
| 306 | mode_load = true; |
| 307 | if(active) |
| 308 | lss_predict(); |
| 309 | } |
| 310 | break; |
| 311 | case 0xe: |
| 312 | if(mode_write) { |
| 313 | if(active) { |
| 314 | lss_sync(); |
| 315 | cur_lss.address &= ~0x08; |
| 316 | } |
| 317 | mode_write = false; |
| 318 | if(active) |
| 319 | lss_predict(); |
| 320 | } |
| 321 | break; |
| 322 | case 0xf: |
| 323 | if(!mode_write) { |
| 324 | if(active) { |
| 325 | lss_sync(); |
| 326 | cur_lss.address |= 0x08; |
| 327 | cur_lss.write_start_time = machine().time(); |
| 328 | if(floppy) |
| 329 | floppy->set_write_splice(cur_lss.write_start_time); |
| 330 | } |
| 331 | mode_write = true; |
| 332 | if(active) |
| 333 | lss_predict(); |
| 334 | } |
| 335 | break; |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | UINT64 wozfdc_device::time_to_cycles(attotime tm) |
| 340 | { |
| 341 | // Clock is falling edges of the ~2Mhz clock |
| 342 | // The 1021800 must be the controlling 6502's speed |
| 343 | |
| 344 | UINT64 cycles = tm.as_ticks(1021800*2*2); |
| 345 | cycles = (cycles+1) >> 1; |
| 346 | return cycles; |
| 347 | } |
| 348 | |
| 349 | attotime wozfdc_device::cycles_to_time(UINT64 cycles) |
| 350 | { |
| 351 | return attotime::from_ticks(cycles*2+1, 1021800*2*2); |
| 352 | } |
| 353 | |
| 354 | void wozfdc_device::lss_start() |
| 355 | { |
| 356 | cur_lss.tm = machine().time(); |
| 357 | cur_lss.cycles = time_to_cycles(cur_lss.tm); |
| 358 | cur_lss.data_reg = 0x00; |
| 359 | cur_lss.address &= ~0x0e; |
| 360 | cur_lss.write_position = 0; |
| 361 | cur_lss.write_start_time = mode_write ? machine().time() : attotime::never; |
| 362 | cur_lss.write_line_active = false; |
| 363 | if(mode_write && floppy) |
| 364 | floppy->set_write_splice(cur_lss.write_start_time); |
| 365 | lss_predict(); |
| 366 | } |
| 367 | |
| 368 | void wozfdc_device::lss_delay(UINT64 cycles, attotime tm, UINT8 data_reg, UINT8 address, bool write_line_active) |
| 369 | { |
| 370 | if(data_reg & 0x80) |
| 371 | address |= 0x02; |
| 372 | else |
| 373 | address &= ~0x02; |
| 374 | predicted_lss.cycles = cycles; |
| 375 | predicted_lss.tm = tm; |
| 376 | predicted_lss.data_reg = data_reg; |
| 377 | predicted_lss.address = address; |
| 378 | predicted_lss.write_line_active = write_line_active; |
| 379 | attotime mtm = machine().time(); |
| 380 | if(predicted_lss.tm > mtm) |
| 381 | timer->adjust(predicted_lss.tm - mtm); |
| 382 | } |
| 383 | |
| 384 | void wozfdc_device::lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active) |
| 385 | { |
| 386 | lss_delay(cycles, cycles_to_time(cycles), data_reg, address, write_line_active); |
| 387 | } |
| 388 | |
| 389 | void wozfdc_device::commit_predicted() |
| 390 | { |
| 391 | cur_lss = predicted_lss; |
| 392 | assert(!mode_write || (cur_lss.write_line_active && (cur_lss.address & 0x80)) || ((!cur_lss.write_line_active) && !(cur_lss.address & 0x80))); |
| 393 | if(mode_write) { |
| 394 | if(floppy) |
| 395 | floppy->write_flux(cur_lss.write_start_time, cur_lss.tm, cur_lss.write_position, cur_lss.write_buffer); |
| 396 | cur_lss.write_start_time = cur_lss.tm; |
| 397 | cur_lss.write_position = 0; |
| 398 | } |
| 399 | |
| 400 | predicted_lss.tm = attotime::never; |
| 401 | } |
| 402 | |
| 403 | void wozfdc_device::lss_sync() |
| 404 | { |
| 405 | attotime tm = machine().time(); |
| 406 | if(!predicted_lss.tm.is_never() && predicted_lss.tm <= tm) |
| 407 | commit_predicted(); |
| 408 | |
| 409 | while(cur_lss.tm < tm) { |
| 410 | lss_predict(tm); |
| 411 | commit_predicted(); |
| 412 | } |
| 413 | } |
| 414 | |
| 415 | void wozfdc_device::lss_predict(attotime limit) |
| 416 | { |
| 417 | predicted_lss.write_start_time = cur_lss.write_start_time; |
| 418 | predicted_lss.write_position = cur_lss.write_position; |
| 419 | memcpy(predicted_lss.write_buffer, cur_lss.write_buffer, cur_lss.write_position * sizeof(attotime)); |
| 420 | bool write_line_active = cur_lss.write_line_active; |
| 421 | |
| 422 | attotime next_flux = floppy ? floppy->get_next_transition(cur_lss.tm - attotime::from_usec(1)) : attotime::never; |
| 423 | attotime next_flux_down = next_flux != attotime::never ? next_flux + attotime::from_usec(1) : attotime::never; |
| 424 | |
| 425 | if(limit == attotime::never) |
| 426 | limit = machine().time() + attotime::from_usec(50); |
| 427 | |
| 428 | UINT64 cycles = cur_lss.cycles; |
| 429 | UINT64 cycles_limit = time_to_cycles(limit); |
| 430 | UINT64 cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : UINT64(-1); |
| 431 | UINT64 cycles_next_flux_down = next_flux_down != attotime::never ? time_to_cycles(next_flux_down) : UINT64(-1); |
| 432 | |
| 433 | UINT8 address = cur_lss.address; |
| 434 | UINT8 data_reg = cur_lss.data_reg; |
| 435 | |
| 436 | if(cycles >= cycles_next_flux && cycles < cycles_next_flux_down) |
| 437 | address &= ~0x10; |
| 438 | else |
| 439 | address |= 0x10; |
| 440 | |
| 441 | while(cycles < cycles_limit) { |
| 442 | UINT64 cycles_next_trans = cycles_limit; |
| 443 | if(cycles_next_trans > cycles_next_flux && cycles < cycles_next_flux) |
| 444 | cycles_next_trans = cycles_next_flux; |
| 445 | if(cycles_next_trans > cycles_next_flux_down && cycles < cycles_next_flux_down) |
| 446 | cycles_next_trans = cycles_next_flux_down; |
| 447 | |
| 448 | while(cycles < cycles_next_trans) { |
| 449 | UINT8 opcode = m_rom_p6[address]; |
| 450 | |
| 451 | if(mode_write) { |
| 452 | if((write_line_active && !(address & 0x80)) || |
| 453 | (!write_line_active && (address & 0x80))) { |
| 454 | write_line_active = !write_line_active; |
| 455 | assert(predicted_lss.write_position != 32); |
| 456 | predicted_lss.write_buffer[predicted_lss.write_position++] = cycles_to_time(cycles); |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | address = (address & 0x1e) | (opcode & 0xc0) | ((opcode & 0x20) >> 5) | ((opcode & 0x10) << 1); |
| 461 | switch(opcode & 0x0f) { |
| 462 | case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: |
| 463 | if(data_reg) { |
| 464 | lss_delay(cycles+1, 0x00, address, write_line_active); |
| 465 | return; |
| 466 | } |
| 467 | break; |
| 468 | case 0x8: case 0xc: |
| 469 | break; |
| 470 | case 0x9: |
| 471 | lss_delay(cycles+1, data_reg << 1, address, write_line_active); |
| 472 | return; |
| 473 | case 0xa: case 0xe: |
| 474 | lss_delay(cycles+1, (data_reg >> 1) | (floppy && floppy->wpt_r() ? 0x80 : 0x00), address, write_line_active); |
| 475 | return; |
| 476 | case 0xb: case 0xf: |
| 477 | lss_delay(cycles+1, last_6502_write, address, write_line_active); |
| 478 | return; |
| 479 | case 0xd: |
| 480 | lss_delay(cycles+1, (data_reg << 1) | 0x01, address, write_line_active); |
| 481 | return; |
| 482 | } |
| 483 | cycles++; |
| 484 | } |
| 485 | |
| 486 | if(cycles == cycles_next_flux) |
| 487 | address &= ~0x10; |
| 488 | else if(cycles == cycles_next_flux_down) { |
| 489 | address |= 0x10; |
| 490 | next_flux = floppy ? floppy->get_next_transition(cycles_to_time(cycles)) : attotime::never; |
| 491 | next_flux_down = next_flux != attotime::never ? next_flux + attotime::from_usec(1) : attotime::never; |
| 492 | cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : UINT64(-1); |
| 493 | cycles_next_flux_down = next_flux_down != attotime::never ? time_to_cycles(next_flux_down) : UINT64(-1); |
| 494 | } |
| 495 | } |
| 496 | |
| 497 | lss_delay(cycles, limit, data_reg, address, write_line_active); |
| 498 | } |
| 499 | |
| 500 | // set the two images for the Disk II |
| 501 | void diskii_fdc::set_floppies(floppy_connector *f0, floppy_connector *f1) |
| 502 | { |
| 503 | floppy0 = f0; |
| 504 | floppy1 = f1; |
| 505 | |
| 506 | if (floppy0) |
| 507 | { |
| 508 | floppy = floppy0->get_device(); |
| 509 | } |
| 510 | } |
| 511 | |
| 512 | void appleiii_fdc::set_floppies_4(floppy_connector *f0, floppy_connector *f1, floppy_connector *f2, floppy_connector *f3) |
| 513 | { |
| 514 | floppy0 = f0; |
| 515 | floppy1 = f1; |
| 516 | floppy2 = f2; |
| 517 | floppy3 = f3; |
| 518 | |
| 519 | if (floppy0) |
| 520 | { |
| 521 | floppy = floppy0->get_device(); |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | READ8_MEMBER(appleiii_fdc::read_c0dx) |
| 526 | { |
| 527 | control_dx(offset); |
| 528 | |
| 529 | return 0xff; |
| 530 | } |
| 531 | |
| 532 | WRITE8_MEMBER(appleiii_fdc::write_c0dx) |
| 533 | { |
| 534 | control_dx(offset); |
| 535 | } |
| 536 | |
| 537 | void appleiii_fdc::control_dx(int offset) |
| 538 | { |
| 539 | switch (offset) |
| 540 | { |
| 541 | case 0: // clear drive select bit 0 |
| 542 | drvsel &= ~1; |
| 543 | break; |
| 544 | |
| 545 | case 1: // set drive select bit 0 |
| 546 | drvsel |= 1; |
| 547 | break; |
| 548 | |
| 549 | case 2: // clear drive select bit 1 |
| 550 | drvsel &= ~2; |
| 551 | break; |
| 552 | |
| 553 | case 3: // set drive select bit 1 |
| 554 | drvsel |= 2; |
| 555 | break; |
| 556 | |
| 557 | case 4: // clear enable 1 |
| 558 | enable1 = 0; |
| 559 | break; |
| 560 | |
| 561 | case 5: // set enable 1 |
| 562 | enable1 = 1; |
| 563 | break; |
| 564 | |
| 565 | case 6: // clear side 2 |
| 566 | case 7: // set side 2 |
| 567 | break; |
| 568 | |
| 569 | default: // cod8-c0df are not FDC related |
| 570 | break; |
| 571 | } |
| 572 | } |
| 573 | |
trunk/src/emu/machine/wozfdc.h
| r0 | r29576 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | wozfdc.h |
| 4 | |
| 5 | Apple Disk II floppy disk controller |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #pragma once |
| 10 | |
| 11 | #ifndef __WOZFDC_H__ |
| 12 | #define __WOZFDC_H__ |
| 13 | |
| 14 | #include "emu.h" |
| 15 | #include "imagedev/floppy.h" |
| 16 | #include "formats/flopimg.h" |
| 17 | |
| 18 | //************************************************************************** |
| 19 | // TYPE DEFINITIONS |
| 20 | //************************************************************************** |
| 21 | |
| 22 | |
| 23 | class wozfdc_device: |
| 24 | public device_t |
| 25 | { |
| 26 | friend class diskii_fdc; |
| 27 | friend class appleiii_fdc; |
| 28 | |
| 29 | public: |
| 30 | // construction/destruction |
| 31 | wozfdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); |
| 32 | |
| 33 | // optional information overrides |
| 34 | virtual const rom_entry *device_rom_region() const; |
| 35 | |
| 36 | DECLARE_READ8_MEMBER(read); |
| 37 | DECLARE_WRITE8_MEMBER(write); |
| 38 | |
| 39 | protected: |
| 40 | virtual void device_start(); |
| 41 | virtual void device_reset(); |
| 42 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 43 | |
| 44 | floppy_connector *floppy0, *floppy1, *floppy2, *floppy3; |
| 45 | floppy_image_device *floppy; |
| 46 | |
| 47 | private: |
| 48 | enum { |
| 49 | MODE_IDLE, MODE_ACTIVE, MODE_DELAY |
| 50 | }; |
| 51 | |
| 52 | struct lss { |
| 53 | attotime tm; |
| 54 | UINT64 cycles; |
| 55 | UINT8 data_reg, address; |
| 56 | attotime write_start_time; |
| 57 | attotime write_buffer[32]; |
| 58 | int write_position; |
| 59 | bool write_line_active; |
| 60 | }; |
| 61 | |
| 62 | const UINT8 *m_rom_p6; |
| 63 | UINT8 current_cyl, last_6502_write; |
| 64 | bool mode_write, mode_load; |
| 65 | int active; |
| 66 | UINT8 phases; |
| 67 | emu_timer *timer, *delay_timer; |
| 68 | bool external_drive_select; |
| 69 | |
| 70 | lss cur_lss, predicted_lss; |
| 71 | |
| 72 | int drvsel; |
| 73 | int enable1; |
| 74 | |
| 75 | void control(int offset); |
| 76 | void phase(int ph, bool on); |
| 77 | UINT64 time_to_cycles(attotime tm); |
| 78 | attotime cycles_to_time(UINT64 cycles); |
| 79 | void a3_update_drive_sel(); |
| 80 | |
| 81 | void lss_start(); |
| 82 | void lss_delay(UINT64 cycles, attotime tm, UINT8 data_reg, UINT8 address, bool write_line_active); |
| 83 | void lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active); |
| 84 | void lss_sync(); |
| 85 | void lss_predict(attotime limit = attotime::never); |
| 86 | void commit_predicted(); |
| 87 | }; |
| 88 | |
| 89 | class diskii_fdc : public wozfdc_device |
| 90 | { |
| 91 | public: |
| 92 | diskii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 93 | |
| 94 | virtual void device_reset(); |
| 95 | |
| 96 | void set_floppies(floppy_connector *f0, floppy_connector *f1); |
| 97 | }; |
| 98 | |
| 99 | class appleiii_fdc : public wozfdc_device |
| 100 | { |
| 101 | public: |
| 102 | appleiii_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 103 | |
| 104 | virtual void device_reset(); |
| 105 | |
| 106 | void set_floppies_4(floppy_connector *f0, floppy_connector *f1, floppy_connector *f2, floppy_connector *f3); |
| 107 | |
| 108 | DECLARE_READ8_MEMBER(read_c0dx); |
| 109 | DECLARE_WRITE8_MEMBER(write_c0dx); |
| 110 | |
| 111 | private: |
| 112 | void control_dx(int offset); |
| 113 | }; |
| 114 | |
| 115 | // device type definition |
| 116 | extern const device_type DISKII_FDC; |
| 117 | extern const device_type APPLEIII_FDC; |
| 118 | |
| 119 | #endif /* __WOZFDC_H__ */ |
trunk/src/lib/formats/ap2_dsk.c
| r29575 | r29576 | |
| 520 | 520 | |
| 521 | 521 | ****************************************************************************/ |
| 522 | 522 | |
| 523 | static const UINT8 dos_skewing[] = |
| 524 | { |
| 525 | 0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04, |
| 526 | 0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F |
| 527 | }; |
| 523 | 528 | |
| 529 | static const UINT8 prodos_skewing[] = |
| 530 | { |
| 531 | 0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B, |
| 532 | 0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F |
| 533 | }; |
| 534 | |
| 535 | |
| 524 | 536 | a2_16sect_format::a2_16sect_format() : floppy_image_format_t() |
| 525 | 537 | { |
| 526 | 538 | } |
| r29575 | r29576 | |
| 537 | 549 | |
| 538 | 550 | const char *a2_16sect_format::extensions() const |
| 539 | 551 | { |
| 540 | | return "dsk"; |
| 552 | return "dsk,do,po"; |
| 541 | 553 | } |
| 542 | 554 | |
| 543 | 555 | bool a2_16sect_format::supports_save() const |
| r29575 | r29576 | |
| 582 | 594 | { END }, |
| 583 | 595 | }; |
| 584 | 596 | |
| 585 | | |
| 586 | 597 | bool a2_16sect_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) |
| 587 | 598 | { |
| 588 | | /* TODO: rewrite me properly |
| 589 | | UINT8 sector_data[(256)*16]; |
| 590 | | memset(sector_data, 0, sizeof(sector_data)); |
| 599 | m_prodos_order = false; |
| 591 | 600 | |
| 592 | | desc_s sectors[16]; |
| 593 | | int format = 0; |
| 594 | | int pos_data = 0; |
| 601 | int fpos = 0; |
| 602 | for(int track=0; track < 35; track++) { |
| 603 | UINT32 track_data[51090*2]; |
| 604 | UINT8 sector_data[256*16]; |
| 605 | int offset = 0; |
| 595 | 606 | |
| 596 | | int head_count = 1; |
| 607 | io_generic_read(io, sector_data, fpos, 256*16); |
| 597 | 608 | |
| 598 | | for(int track=0; track < 35; track++) { |
| 599 | | for(int head=0; head < head_count; head++) { |
| 600 | | for(int si=0; si<16; si++) { |
| 601 | | UINT8 *data = sector_data + (256)*si; |
| 602 | | sectors[si].data = data; |
| 603 | | sectors[si].size = 256; |
| 604 | | sectors[si].sector_id = si; |
| 605 | | sectors[si].sector_info = format; |
| 606 | | io_generic_read(io, data, pos_data, 256); |
| 607 | | pos_data += 256; |
| 608 | | } |
| 609 | | generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image); |
| 610 | | } |
| 611 | | } |
| 612 | | return true;*/ |
| 613 | | return false; // I hope that throws an error... |
| 609 | if (track == 0 && fpos == 0) |
| 610 | { |
| 611 | // check ProDOS boot block |
| 612 | if (!memcmp("PRODOS", §or_data[0x103], 6)) |
| 613 | { |
| 614 | m_prodos_order = true; |
| 615 | } // check SOS boot block |
| 616 | else if (!memcmp("SOS BOOT", §or_data[0x3], 8)) |
| 617 | { |
| 618 | m_prodos_order = true; |
| 619 | } // check Apple II Pascal |
| 620 | else if (!memcmp("SYSTEM.APPLE", §or_data[0xd7], 12)) |
| 621 | { |
| 622 | unsigned char pascal_block1[4] = { 0x08, 0xa5, 0x0f, 0x29 }; |
| 623 | |
| 624 | // Pascal discs can still be DOS order. |
| 625 | // Check for the second half of the boot code at 0x100 |
| 626 | // (which means ProDOS order) |
| 627 | if (!memcmp(pascal_block1, §or_data[0x100], 4)) |
| 628 | { |
| 629 | m_prodos_order = true; |
| 630 | } |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | fpos += 256*16; |
| 635 | for(int i=0; i<51; i++) |
| 636 | raw_w(track_data, offset, 10, 0x3fc); |
| 637 | for(int i=0; i<16; i++) { |
| 638 | int sector; |
| 639 | |
| 640 | if (m_prodos_order) |
| 641 | { |
| 642 | sector = prodos_skewing[i]; |
| 643 | } |
| 644 | else |
| 645 | { |
| 646 | sector = dos_skewing[i]; |
| 647 | } |
| 648 | |
| 649 | const UINT8 *sdata = sector_data + 256 * sector; |
| 650 | for(int j=0; j<20; j++) |
| 651 | raw_w(track_data, offset, 10, 0x3fc); |
| 652 | raw_w(track_data, offset, 8, 0xff); |
| 653 | raw_w(track_data, offset, 24, 0xd5aa96); |
| 654 | raw_w(track_data, offset, 16, gcr4_encode(0xfe)); |
| 655 | raw_w(track_data, offset, 16, gcr4_encode(track)); |
| 656 | raw_w(track_data, offset, 16, gcr4_encode(i)); |
| 657 | raw_w(track_data, offset, 16, gcr4_encode(0xfe ^ track ^ i)); |
| 658 | raw_w(track_data, offset, 24, 0xdeaaeb); |
| 659 | |
| 660 | for(int j=0; j<4; j++) |
| 661 | raw_w(track_data, offset, 10, 0x3fc); |
| 662 | |
| 663 | raw_w(track_data, offset, 9, 0x01fe); |
| 664 | raw_w(track_data, offset, 24, 0xd5aaad); |
| 665 | |
| 666 | UINT8 pval = 0x00; |
| 667 | for(int i=0; i<342; i++) { |
| 668 | UINT8 nval; |
| 669 | if(i >= 0x56) |
| 670 | nval = sdata[i - 0x56] >> 2; |
| 671 | else { |
| 672 | nval = |
| 673 | ((sdata[i+0x00] & 0x01) << 1) | |
| 674 | ((sdata[i+0x00] & 0x02) >> 1) | |
| 675 | ((sdata[i+0x56] & 0x01) << 3) | |
| 676 | ((sdata[i+0x56] & 0x02) << 1); |
| 677 | if(i < 256-0xac) |
| 678 | nval |= |
| 679 | ((sdata[i+0xac] & 0x01) << 5) | |
| 680 | ((sdata[i+0xac] & 0x02) << 3); |
| 681 | } |
| 682 | raw_w(track_data, offset, 8, translate6[nval ^ pval]); |
| 683 | pval = nval; |
| 684 | } |
| 685 | raw_w(track_data, offset, 8, translate6[pval]); |
| 686 | raw_w(track_data, offset, 24, 0xdeaaeb); |
| 687 | } |
| 688 | raw_w(track_data, offset, 4, 0xff); |
| 689 | assert(offset == 51090); |
| 690 | |
| 691 | generate_track_from_levels(track, 0, track_data, 51090, 0, image); |
| 692 | } |
| 693 | return true; |
| 614 | 694 | } |
| 615 | 695 | |
| 616 | 696 | UINT8 a2_16sect_format::gb(const UINT8 *buf, int ts, int &pos, int &wrap) |
| r29575 | r29576 | |
| 632 | 712 | { |
| 633 | 713 | } |
| 634 | 714 | |
| 715 | //#define VERBOSE_SAVE |
| 716 | |
| 635 | 717 | bool a2_16sect_format::save(io_generic *io, floppy_image *image) |
| 636 | 718 | { |
| 637 | 719 | int g_tracks, g_heads; |
| 638 | 720 | int visualgrid[16][35]; // visualizer grid, cleared/initialized below |
| 721 | |
| 639 | 722 | // lenient addr check: if unset, only accept an addr mark if the checksum was good |
| 640 | 723 | // if set, accept an addr mark if the track and sector values are both sane |
| 641 | 724 | #undef LENIENT_ADDR_CHECK |
| 642 | 725 | // if set, use the old, not as robust logic for choosing which copy of a decoded sector to write |
| 643 | 726 | // to the resulting image if the sector has a bad checksum and/or postamble |
| 644 | 727 | #undef USE_OLD_BEST_SECTOR_PRIORITY |
| 645 | | // select a sector order for resulting file: 0 = logical, 1 = dos3.3, 2 = prodos |
| 646 | | #define SECTOR_ORDER 1 |
| 647 | 728 | // nothing found |
| 648 | 729 | #define NOTFOUND 0 |
| 649 | 730 | // address mark was found |
| r29575 | r29576 | |
| 667 | 748 | |
| 668 | 749 | int pos_data = 0; |
| 669 | 750 | |
| 670 | | for(int track=0; track < 70; track+=2) { |
| 751 | for(int track=0; track < 35; track++) { |
| 671 | 752 | UINT8 sectdata[(256)*16]; |
| 672 | 753 | memset(sectdata, 0, sizeof(sectdata)); |
| 673 | 754 | int nsect = 16; |
| 674 | | UINT8 buf[130000]; // originally 13000, multiread dfi disks need larger |
| 755 | UINT8 buf[10000]; // normal is 51090 cells, e.g. 6387 bytes, add 50% and round up for denser than normal disks |
| 675 | 756 | int ts; |
| 676 | | //fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from physical track %d (logical %d)...", track, track/2); |
| 677 | | //~332 samples per cell, times 3+8+3 (14) for address mark, 24 for sync, 3+343+3 (349) for data mark, 24 for sync is around 743, near 776 expected |
| 678 | | generate_bitstream_from_track(track, head, 200000000/((3004*nsect*6)/2), buf, ts, image); // 3104 needs tweaking |
| 679 | | //fprintf(stderr,"done.\n"); |
| 757 | #ifdef VERBOSE_SAVE |
| 758 | fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from track %d...", track); |
| 759 | #endif |
| 760 | generate_bitstream_from_track(track, head, 3915, buf, ts, image); |
| 761 | #ifdef VERBOSE_SAVE |
| 762 | fprintf(stderr,"done.\n"); |
| 763 | #endif |
| 680 | 764 | int pos = 0; |
| 681 | 765 | int wrap = 0; |
| 682 | 766 | int hb = 0; |
| 683 | 767 | int dosver = 0; // apple dos version; 0 = >=3.3, 1 = <3.3 |
| 684 | 768 | for(;;) { |
| 685 | 769 | UINT8 v = gb(buf, ts, pos, wrap); |
| 686 | | if(v == 0xff) |
| 770 | if(v == 0xff) { |
| 687 | 771 | hb = 1; |
| 688 | | else if(hb == 1 && v == 0xd5) |
| 772 | } |
| 773 | else if(hb == 1 && v == 0xd5){ |
| 689 | 774 | hb = 2; |
| 690 | | else if(hb == 2 && v == 0xaa) |
| 775 | } |
| 776 | else if(hb == 2 && v == 0xaa) { |
| 691 | 777 | hb = 3; |
| 692 | | else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec |
| 778 | } |
| 779 | else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec |
| 693 | 780 | hb = 4; |
| 694 | 781 | if (v == 0xab) dosver = 1; |
| 695 | 782 | } |
| 696 | | else |
| 783 | else |
| 697 | 784 | hb = 0; |
| 698 | 785 | |
| 699 | 786 | if(hb == 4) { |
| 787 | printf("hb = 4\n"); |
| 700 | 788 | UINT8 h[11]; |
| 701 | 789 | for(int i=0; i<11; i++) |
| 702 | 790 | h[i] = gb(buf, ts, pos, wrap); |
| r29575 | r29576 | |
| 706 | 794 | UINT8 se = gcr4_decode(h[4],h[5]); |
| 707 | 795 | UINT8 chk = gcr4_decode(h[6],h[7]); |
| 708 | 796 | UINT32 post = (h[8]<<16)|(h[9]<<8)|h[10]; |
| 797 | #ifdef VERBOSE_SAVE |
| 709 | 798 | printf("Address Mark:\tVolume %d, Track %d, Sector %2d, Checksum %02X: %s, Postamble %03X: %s\n", vl, tr, se, chk, (chk ^ vl ^ tr ^ se)==0?"OK":"BAD", post, (post&0xFFFF00)==0xDEAA00?"OK":"BAD"); |
| 799 | #endif |
| 710 | 800 | // sanity check |
| 711 | | if (tr == track/2 && se < nsect) { |
| 712 | | visualgrid[se][track/2] |= ADDRFOUND; |
| 713 | | visualgrid[se][track/2] |= ((chk ^ vl ^ tr ^ se)==0)?ADDRGOOD:0; |
| 801 | if (tr == track && se < nsect) { |
| 802 | visualgrid[se][track] |= ADDRFOUND; |
| 803 | visualgrid[se][track] |= ((chk ^ vl ^ tr ^ se)==0)?ADDRGOOD:0; |
| 714 | 804 | #ifdef LENIENT_ADDR_CHECK |
| 715 | | if ((visualgrid[se][track/2] & ADDRFOUND) == ADDRFOUND) { |
| 805 | if ((visualgrid[se][track] & ADDRFOUND) == ADDRFOUND) { |
| 716 | 806 | #else |
| 717 | | if ((visualgrid[se][track/2] & ADDRGOOD) == ADDRGOOD) { |
| 807 | if ((visualgrid[se][track] & ADDRGOOD) == ADDRGOOD) { |
| 718 | 808 | #endif |
| 719 | 809 | int opos = pos; |
| 720 | 810 | int owrap = wrap; |
| r29575 | r29576 | |
| 733 | 823 | hb = 0; |
| 734 | 824 | } |
| 735 | 825 | if((hb == 4)&&(dosver == 0)) { |
| 736 | | visualgrid[se][track/2] |= DATAFOUND; |
| 737 | | int sector_translate[16] = { |
| 738 | | #if SECTOR_ORDER == 0 |
| 739 | | // logical order (0-15) |
| 740 | | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 741 | | 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F |
| 742 | | #elif SECTOR_ORDER == 1 |
| 743 | | // DOS order (*.do) |
| 744 | | 0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04, |
| 745 | | 0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F |
| 746 | | #elif SECTOR_ORDER == 2 |
| 747 | | // prodos order (*.po) |
| 748 | | 0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B, |
| 749 | | 0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F |
| 750 | | #endif |
| 751 | | }; |
| 752 | | UINT8 *dest = sectdata+(256)*sector_translate[se]; |
| 826 | visualgrid[se][track] |= DATAFOUND; |
| 827 | UINT8 *dest; |
| 753 | 828 | UINT8 data[0x157]; |
| 754 | 829 | UINT32 dpost = 0; |
| 755 | 830 | UINT8 c = 0; |
| 831 | |
| 832 | if (m_prodos_order) |
| 833 | { |
| 834 | dest = sectdata+(256)*prodos_skewing[se]; |
| 835 | } |
| 836 | else |
| 837 | { |
| 838 | dest = sectdata+(256)*dos_skewing[se]; |
| 839 | } |
| 840 | |
| 756 | 841 | // first read in sector and decode to 6bit form |
| 757 | 842 | for(int i=0; i<0x156; i++) { |
| 758 | 843 | data[i] = gcr6bw_tb[gb(buf, ts, pos, wrap)] ^ c; |
| r29575 | r29576 | |
| 780 | 865 | // if it is set we don't want to overwrite a guaranteed good read with a bad one |
| 781 | 866 | // if past read had a bad checksum or bad postamble... |
| 782 | 867 | #ifndef USE_OLD_BEST_SECTOR_PRIORITY |
| 783 | | if (((visualgrid[se][track/2]&DATAGOOD)==0)||((visualgrid[se][track/2]&DATAPOST)==0)) { |
| 868 | if (((visualgrid[se][track]&DATAGOOD)==0)||((visualgrid[se][track]&DATAPOST)==0)) { |
| 784 | 869 | // if the current read is good, and postamble is good, write it in, no matter what. |
| 785 | 870 | // if the current read is good and the current postamble is bad, write it in unless the postamble was good before |
| 786 | 871 | // if the current read is bad and the current postamble is good and the previous read had neither good, write it in |
| 787 | 872 | // if the current read isn't good and neither is the postamble but nothing better |
| 788 | 873 | // has been written before, write it anyway. |
| 789 | 874 | if ( ((data[0x156] == c) && (dpost&0xFFFF00)==0xDEAA00) || |
| 790 | | (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track/2]&DATAPOST)==0)) || |
| 791 | | (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track/2]&DATAGOOD)==0)&&(visualgrid[se][track/2]&DATAPOST)==0)) || |
| 792 | | (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track/2]&DATAGOOD)==0)&&(visualgrid[se][track/2]&DATAPOST)==0)) |
| 875 | (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track]&DATAPOST)==0)) || |
| 876 | (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0)) || |
| 877 | (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0)) |
| 793 | 878 | ) { |
| 794 | 879 | for(int i=0x56; i<0x156; i++) { |
| 795 | 880 | UINT8 dv = data[i]; |
| r29575 | r29576 | |
| 798 | 883 | } |
| 799 | 884 | } |
| 800 | 885 | #else |
| 801 | | if ((visualgrid[se][track/2]&DATAGOOD)==0) { |
| 886 | if ((visualgrid[se][track]&DATAGOOD)==0) { |
| 802 | 887 | for(int i=0x56; i<0x156; i++) { |
| 803 | 888 | UINT8 dv = data[i]; |
| 804 | 889 | *dest++ = dv; |
| r29575 | r29576 | |
| 806 | 891 | } |
| 807 | 892 | #endif |
| 808 | 893 | // do some checking |
| 894 | #ifdef VERBOSE_SAVE |
| 809 | 895 | if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00) |
| 810 | 896 | fprintf(stderr,"Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n", data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD"); |
| 811 | | if (data[0x156] == c) visualgrid[se][track/2] |= DATAGOOD; |
| 812 | | if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track/2] |= DATAPOST; |
| 897 | #endif |
| 898 | if (data[0x156] == c) visualgrid[se][track] |= DATAGOOD; |
| 899 | if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track] |= DATAPOST; |
| 813 | 900 | } else if ((hb == 4)&&(dosver == 1)) { |
| 814 | 901 | fprintf(stderr,"ERROR: We don't handle dos sectors below 3.3 yet!\n"); |
| 815 | 902 | } else { |
| r29575 | r29576 | |
| 832 | 919 | //printf("\n"); |
| 833 | 920 | } |
| 834 | 921 | // display a little table of which sectors decoded ok |
| 922 | #ifdef VERBOSE_SAVE |
| 835 | 923 | int total_good = 0; |
| 836 | 924 | for (int j = 0; j < 35; j++) { |
| 837 | 925 | printf("T%2d: ",j); |
| r29575 | r29576 | |
| 848 | 936 | printf("\n"); |
| 849 | 937 | } |
| 850 | 938 | printf("Total Good Sectors: %d\n", total_good); |
| 939 | #endif |
| 851 | 940 | |
| 852 | 941 | return true; |
| 853 | 942 | } |