wozfdc: Warp factor 4 Scotty [O. Galibert]

This commit is contained in:
Olivier Galibert 2015-11-20 22:52:01 +01:00
parent d542c2249f
commit 5b1422965d
2 changed files with 63 additions and 156 deletions

View File

@ -76,22 +76,12 @@ void wozfdc_device::device_start()
save_item(NAME(active));
save_item(NAME(phases));
save_item(NAME(external_io_select));
save_item(NAME(cur_lss.tm));
save_item(NAME(cur_lss.cycles));
save_item(NAME(cur_lss.data_reg));
save_item(NAME(cur_lss.address));
save_item(NAME(cur_lss.write_start_time));
// save_item(NAME(cur_lss.write_buffer));
save_item(NAME(cur_lss.write_position));
save_item(NAME(cur_lss.write_line_active));
save_item(NAME(predicted_lss.tm));
save_item(NAME(predicted_lss.cycles));
save_item(NAME(predicted_lss.data_reg));
save_item(NAME(predicted_lss.address));
save_item(NAME(predicted_lss.write_start_time));
// save_item(NAME(predicted_lss.write_buffer));
save_item(NAME(predicted_lss.write_position));
save_item(NAME(predicted_lss.write_line_active));
save_item(NAME(cycles));
save_item(NAME(data_reg));
save_item(NAME(address));
save_item(NAME(write_start_time));
save_item(NAME(write_position));
save_item(NAME(write_line_active));
save_item(NAME(drvsel));
save_item(NAME(enable1));
}
@ -104,15 +94,17 @@ void wozfdc_device::device_reset()
mode_write = false;
mode_load = false;
last_6502_write = 0x00;
cur_lss.tm = machine().time();
cur_lss.cycles = time_to_cycles(cur_lss.tm);
cur_lss.data_reg = 0x00;
cur_lss.address = 0x00;
cur_lss.write_start_time = attotime::never;
cur_lss.write_position = 0;
cur_lss.write_line_active = false;
predicted_lss.tm = attotime::never;
cycles = time_to_cycles(machine().time());
data_reg = 0x00;
address = 0x00;
write_start_time = attotime::never;
write_position = 0;
write_line_active = false;
external_io_select = false;
// Just a timer to be sure that the lss is updated from time to
// time, so that there's no hiccup when it's talked to again.
timer->adjust(attotime::from_msec(10), 0, attotime::from_msec(10));
}
void wozfdc_device::a3_update_drive_sel()
@ -152,10 +144,8 @@ void wozfdc_device::a3_update_drive_sel()
floppy->mon_w(true);
}
floppy = newflop;
if(active) {
if(active)
floppy->mon_w(false);
lss_predict();
}
}
}
@ -188,9 +178,6 @@ void wozfdc_device::device_timer(emu_timer &timer, device_timer_id id, int param
floppy->mon_w(true);
active = MODE_IDLE;
}
if(active)
lss_predict();
}
/*-------------------------------------------------
@ -201,8 +188,10 @@ READ8_MEMBER(wozfdc_device::read)
{
control(offset);
if(!(offset & 1))
return cur_lss.data_reg;
if(!(offset & 1)) {
lss_sync();
return data_reg;
}
return 0xff;
}
@ -214,8 +203,8 @@ READ8_MEMBER(wozfdc_device::read)
WRITE8_MEMBER(wozfdc_device::write)
{
control(offset);
lss_sync();
last_6502_write = data;
lss_predict();
}
void wozfdc_device::phase(int ph, bool on)
@ -235,8 +224,6 @@ void wozfdc_device::control(int offset)
if(active)
lss_sync();
phase(offset >> 1, offset & 1);
if(active)
lss_predict();
} else
switch(offset) {
@ -262,7 +249,7 @@ void wozfdc_device::control(int offset)
break;
}
break;
case 0xa:
case 0xa:
external_io_select = false;
if(floppy != floppy0->get_device()) {
if(active) {
@ -270,10 +257,8 @@ void wozfdc_device::control(int offset)
floppy->mon_w(true);
}
floppy = floppy0->get_device();
if(active) {
if(active)
floppy->mon_w(false);
lss_predict();
}
}
break;
case 0xb:
@ -287,10 +272,8 @@ void wozfdc_device::control(int offset)
floppy->mon_w(true);
}
floppy = floppy1->get_device();
if(active) {
if(active)
floppy->mon_w(false);
lss_predict();
}
}
}
else
@ -302,47 +285,39 @@ void wozfdc_device::control(int offset)
if(mode_load) {
if(active) {
lss_sync();
cur_lss.address &= ~0x04;
address &= ~0x04;
}
mode_load = false;
if(active)
lss_predict();
}
break;
case 0xd:
if(!mode_load) {
if(active) {
lss_sync();
cur_lss.address |= 0x04;
address |= 0x04;
}
mode_load = true;
if(active)
lss_predict();
}
break;
case 0xe:
if(mode_write) {
if(active) {
lss_sync();
cur_lss.address &= ~0x08;
address &= ~0x08;
}
mode_write = false;
if(active)
lss_predict();
}
break;
case 0xf:
if(!mode_write) {
if(active) {
lss_sync();
cur_lss.address |= 0x08;
cur_lss.write_start_time = machine().time();
address |= 0x08;
write_start_time = machine().time();
if(floppy)
floppy->set_write_splice(cur_lss.write_start_time);
floppy->set_write_splice(write_start_time);
}
mode_write = true;
if(active)
lss_predict();
}
break;
}
@ -365,85 +340,27 @@ attotime wozfdc_device::cycles_to_time(UINT64 cycles)
void wozfdc_device::lss_start()
{
cur_lss.tm = machine().time();
cur_lss.cycles = time_to_cycles(cur_lss.tm);
cur_lss.data_reg = 0x00;
cur_lss.address &= ~0x0e;
cur_lss.write_position = 0;
cur_lss.write_start_time = mode_write ? machine().time() : attotime::never;
cur_lss.write_line_active = false;
cycles = time_to_cycles(machine().time());
data_reg = 0x00;
address &= ~0x0e;
write_position = 0;
write_start_time = mode_write ? machine().time() : attotime::never;
write_line_active = false;
if(mode_write && floppy)
floppy->set_write_splice(cur_lss.write_start_time);
lss_predict();
}
void wozfdc_device::lss_delay(UINT64 cycles, const attotime &tm, UINT8 data_reg, UINT8 address, bool write_line_active)
{
if(data_reg & 0x80)
address |= 0x02;
else
address &= ~0x02;
predicted_lss.cycles = cycles;
predicted_lss.tm = tm;
predicted_lss.data_reg = data_reg;
predicted_lss.address = address;
predicted_lss.write_line_active = write_line_active;
attotime mtm = machine().time();
if(predicted_lss.tm > mtm)
timer->adjust(predicted_lss.tm - mtm);
}
void wozfdc_device::lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active)
{
lss_delay(cycles, cycles_to_time(cycles), data_reg, address, write_line_active);
}
void wozfdc_device::commit_predicted()
{
cur_lss = predicted_lss;
assert(!mode_write || (cur_lss.write_line_active && (cur_lss.address & 0x80)) || ((!cur_lss.write_line_active) && !(cur_lss.address & 0x80)));
if(mode_write) {
if(floppy)
floppy->write_flux(cur_lss.write_start_time, cur_lss.tm, cur_lss.write_position, cur_lss.write_buffer);
cur_lss.write_start_time = cur_lss.tm;
cur_lss.write_position = 0;
}
predicted_lss.tm = attotime::never;
floppy->set_write_splice(write_start_time);
}
void wozfdc_device::lss_sync()
{
attotime tm = machine().time();
if(!predicted_lss.tm.is_never() && predicted_lss.tm <= tm)
commit_predicted();
if(!active)
return;
while(cur_lss.tm < tm) {
lss_predict(tm);
commit_predicted();
}
}
attotime next_flux = floppy ? floppy->get_next_transition(cycles_to_time(cycles) - attotime::from_usec(1)) : attotime::never;
void wozfdc_device::lss_predict(attotime limit)
{
predicted_lss.write_start_time = cur_lss.write_start_time;
predicted_lss.write_position = cur_lss.write_position;
memcpy(predicted_lss.write_buffer, cur_lss.write_buffer, cur_lss.write_position * sizeof(attotime));
bool write_line_active = cur_lss.write_line_active;
attotime next_flux = floppy ? floppy->get_next_transition(cur_lss.tm - attotime::from_usec(1)) : attotime::never;
if(limit == attotime::never)
limit = machine().time() + attotime::from_usec(50);
UINT64 cycles = cur_lss.cycles;
UINT64 cycles_limit = time_to_cycles(limit);
UINT64 cycles_limit = time_to_cycles(machine().time());
UINT64 cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : UINT64(-1);
UINT64 cycles_next_flux_down = cycles_next_flux != UINT64(-1) ? cycles_next_flux+1 : UINT64(-1);
UINT8 address = cur_lss.address;
UINT8 data_reg = cur_lss.data_reg;
if(cycles >= cycles_next_flux && cycles < cycles_next_flux_down)
address &= ~0x10;
else
@ -463,34 +380,35 @@ void wozfdc_device::lss_predict(attotime limit)
if((write_line_active && !(address & 0x80)) ||
(!write_line_active && (address & 0x80))) {
write_line_active = !write_line_active;
assert(predicted_lss.write_position != 32);
predicted_lss.write_buffer[predicted_lss.write_position++] = cycles_to_time(cycles);
assert(write_position != 32);
write_buffer[write_position++] = cycles_to_time(cycles);
}
}
address = (address & 0x1e) | (opcode & 0xc0) | ((opcode & 0x20) >> 5) | ((opcode & 0x10) << 1);
switch(opcode & 0x0f) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
if(data_reg) {
lss_delay(cycles+1, 0x00, address, write_line_active);
return;
}
data_reg = 0x00;
break;
case 0x8: case 0xc:
break;
case 0x9:
lss_delay(cycles+1, data_reg << 1, address, write_line_active);
return;
data_reg <<= 1;
break;
case 0xa: case 0xe:
lss_delay(cycles+1, (data_reg >> 1) | (floppy && floppy->wpt_r() ? 0x80 : 0x00), address, write_line_active);
return;
data_reg = (data_reg >> 1) | (floppy && floppy->wpt_r() ? 0x80 : 0x00);
break;
case 0xb: case 0xf:
lss_delay(cycles+1, last_6502_write, address, write_line_active);
return;
data_reg = last_6502_write;
break;
case 0xd:
lss_delay(cycles+1, (data_reg << 1) | 0x01, address, write_line_active);
return;
data_reg = (data_reg << 1) | 0x01;
break;
}
if(data_reg & 0x80)
address |= 0x02;
else
address &= ~0x02;
cycles++;
}
@ -503,8 +421,6 @@ void wozfdc_device::lss_predict(attotime limit)
cycles_next_flux_down = cycles_next_flux != UINT64(-1) ? cycles_next_flux+1 : UINT64(-1);
}
}
lss_delay(cycles, limit, data_reg, address, write_line_active);
}
// set the two images for the Disk II

View File

@ -51,15 +51,12 @@ private:
MODE_IDLE, MODE_ACTIVE, MODE_DELAY
};
struct lss {
attotime tm;
UINT64 cycles;
UINT8 data_reg, address;
attotime write_start_time;
attotime write_buffer[32];
int write_position;
bool write_line_active;
};
UINT64 cycles;
UINT8 data_reg, address;
attotime write_start_time;
attotime write_buffer[32];
int write_position;
bool write_line_active;
const UINT8 *m_rom_p6;
UINT8 last_6502_write;
@ -70,8 +67,6 @@ private:
bool external_drive_select;
bool external_io_select;
lss cur_lss, predicted_lss;
int drvsel;
int enable1;
@ -82,11 +77,7 @@ private:
void a3_update_drive_sel();
void lss_start();
void lss_delay(UINT64 cycles, const attotime &tm, UINT8 data_reg, UINT8 address, bool write_line_active);
void lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active);
void lss_sync();
void lss_predict(attotime limit = attotime::never);
void commit_predicted();
};
class diskii_fdc : public wozfdc_device