tx0.c: Modernized cpu core. [Wilbert Pol]

Out of whatsnew:
Also copied over the support for octal in
debugger state from the alto2 branch.
This commit is contained in:
Wilbert Pol 2013-12-25 12:00:22 +00:00
parent 9c03593b09
commit cc74ef9ade
5 changed files with 693 additions and 791 deletions

File diff suppressed because it is too large Load Diff

View File

@ -15,14 +15,103 @@ enum
TX0_CM_SEL, TX0_LR_SEL, TX0_GBL_CM_SEL, TX0_CM_SEL, TX0_LR_SEL, TX0_GBL_CM_SEL,
TX0_STOP_CYC0, TX0_STOP_CYC1, TX0_STOP_CYC0, TX0_STOP_CYC1,
TX0_RUN, TX0_RIM, TX0_RUN, TX0_RIM,
TX0_CYCLE, TX0_IOH, TX0_IOS, TX0_CYCLE, TX0_IOH, TX0_IOS
TX0_RESET, /* hack, do not use directly, use tx0_pulse_reset instead */
TX0_IO_COMPLETE /* hack, do not use directly, use tx0_pulse_io_complete instead */
}; };
struct tx0_reset_param_t #define MCFG_TX0_CONFIG(_cpy_devcb, _r1l_devcb, _dis_devcb, _r3l_devcb, _prt_devcb, _rsv_devcb, _p6h_devcb, _p7h_devcb, _sel_devcb, _res_devcb) \
tx0_device::set_cpy_cb(*device, DEVCB2_##_cpy_devcb); \
tx0_device::set_r1l_cb(*device, DEVCB2_##_r1l_devcb); \
tx0_device::set_dis_cb(*device, DEVCB2_##_dis_devcb); \
tx0_device::set_r3l_cb(*device, DEVCB2_##_r3l_devcb); \
tx0_device::set_prt_cb(*device, DEVCB2_##_prt_devcb); \
tx0_device::set_rsv_cb(*device, DEVCB2_##_rsv_devcb); \
tx0_device::set_p6h_cb(*device, DEVCB2_##_p6h_devcb); \
tx0_device::set_p7h_cb(*device, DEVCB2_##_p7h_devcb); \
tx0_device::set_sel_cb(*device, DEVCB2_##_sel_devcb); \
tx0_device::set_res_cb(*device, DEVCB2_##_res_devcb);
class tx0_device : public cpu_device
{ {
public:
// construction/destruction
tx0_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, int addr_bits, int address_mask, int ir_mask);
// static configuration helpers
template<class _Object> static devcb2_base &set_cpy_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_cpy_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_r1l_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_r1l_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_dis_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_dis_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_r3l_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_r3l_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_prt_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_prt_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_rsv_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_rsv_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_p6h_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_p6h_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_p7h_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_p7h_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_sel_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_sel_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_res_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_io_reset_callback.set_callback(object); }
void pulse_reset();
void io_complete();
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
// device_execute_interface overrides
virtual UINT32 execute_min_cycles() const { return 1; }
virtual UINT32 execute_max_cycles() const { return 3; }
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
protected:
address_space_config m_program_config;
/* processor registers */
int m_mbr; /* memory buffer register (18 bits) */
int m_ac; /* accumulator (18 bits) */
int m_mar; /* memory address register (16 (64kW) or 13 (8kW) bits) */
int m_pc; /* program counter (16 (64kW) or 13 (8kW) bits) */
int m_ir; /* instruction register (2 (64kW) or 5 (8kW) bits) */
int m_lr; /* live register (18 bits) */
int m_xr; /* index register (14 bits) (8kW only) */
int m_pf; /* program flags (6 bits expandable to 10) (8kW only) */
/* operator panel switches */
int m_tbr; /* toggle switch buffer register (18 bits) */
int m_tac; /* toggle switch accumulator (18 bits) */
int m_tss[16]; /* toggle switch storage (18 bits * 16) */
UINT16 m_cm_sel; /* individual cm select (1 bit * 16) */
UINT16 m_lr_sel; /* individual lr select (1 bit * 16) */
unsigned int m_gbl_cm_sel;/* global cm select (1 bit) */
unsigned int m_stop_cyc0; /* stop on cycle 0 */
unsigned int m_stop_cyc1; /* stop on cycle 1 */
/* processor state flip-flops */
unsigned int m_run; /* processor is running */
unsigned int m_rim; /* processor is in read-in mode */
unsigned int m_cycle; /* 0 -> fetch */
/* 1 -> execute (except for taken branches) */
/* 2 -> extra execute cycle for SXA and ADO */
unsigned int m_ioh; /* i-o halt: processor is executing an Input-Output Transfer wait */
unsigned int m_ios; /* i-o synchronizer: set on i-o operation completion */
/* additional emulator state variables */
int m_rim_step; /* current step in rim execution */
int m_address_mask; /* address mask */
int m_ir_mask; /* IR mask */
int m_icount;
address_space *m_program;
/* 8 standard I/O handlers: /* 8 standard I/O handlers:
0: cpy (8kW only) 0: cpy (8kW only)
1: r1l 1: r1l
@ -32,18 +121,57 @@ struct tx0_reset_param_t
5: reserved (for unimplemented typ instruction?) 5: reserved (for unimplemented typ instruction?)
6: p6h 6: p6h
7: p7h */ 7: p7h */
void (*io_handlers[8])(device_t *device); devcb2_write_line m_cpy_handler;
devcb2_write_line m_r1l_handler;
devcb2_write_line m_dis_handler;
devcb2_write_line m_r3l_handler;
devcb2_write_line m_prt_handler;
devcb2_write_line m_rsv_handler;
devcb2_write_line m_p6h_handler;
devcb2_write_line m_p7h_handler;
/* select instruction handler */ /* select instruction handler */
void (*sel_handler)(device_t *device); devcb2_write_line m_sel_handler;
/* callback called when reset line is pulsed: IO devices should reset */ /* callback called when reset line is pulsed: IO devices should reset */
void (*io_reset_callback)(device_t *device); devcb2_write_line m_io_reset_callback;
int tx0_read(offs_t address);
void tx0_write(offs_t address, int data);
void call_io_handler(int io_handler);
void indexed_address_eval();
}; };
/* PUBLIC FUNCTIONS */
DECLARE_LEGACY_CPU_DEVICE(TX0_64KW, tx0_64kw);
DECLARE_LEGACY_CPU_DEVICE(TX0_8KW, tx0_8kw);
CPU_DISASSEMBLE( tx0_64kw ); class tx0_8kw_device : public tx0_device
CPU_DISASSEMBLE( tx0_8kw ); {
public:
// construction/destruction
tx0_8kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
protected:
virtual void execute_run();
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
private:
void execute_instruction_8kw();
};
class tx0_64kw_device : public tx0_device
{
public:
// construction/destruction
tx0_64kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
protected:
virtual void execute_run();
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
private:
void execute_instruction_64kw();
};
extern const device_type TX0_64KW;
extern const device_type TX0_8KW;
#endif /* __TX0_H__ */ #endif /* __TX0_H__ */

View File

@ -248,6 +248,31 @@ astring &device_state_entry::format(astring &dest, const char *string, bool maxo
reset = true; reset = true;
break; break;
// O outputs as octal
case 'O':
if (width == 0)
throw emu_fatalerror("Width required for %%O formats\n");
hitnonzero = false;
while (leadzero && width > 22)
{
dest.cat(" ");
width--;
}
for (int digitnum = 21; digitnum >= 0; digitnum--)
{
int digit = (result >> (3 * digitnum)) & 07;
if (digit != 0)
{
static const char octchars[] = "01234567";
dest.cat(&octchars[digit], 1);
hitnonzero = true;
}
else if (hitnonzero || (leadzero && digitnum < width) || digitnum == 0)
dest.cat("0");
}
reset = true;
break;
// d outputs as signed decimal // d outputs as signed decimal
case 'd': case 'd':
if (width == 0) if (width == 0)

View File

@ -301,31 +301,6 @@ void tx0_state::palette_init()
colortable_entry_set_value(machine().colortable, total_colors_needed + i, tx0_palette[i]); colortable_entry_set_value(machine().colortable, total_colors_needed + i, tx0_palette[i]);
} }
static void tx0_io_cpy(device_t *device);
static void tx0_io_r1l(device_t *device);
static void tx0_io_r3l(device_t *device);
static void tx0_io_p6h(device_t *device);
static void tx0_io_p7h(device_t *device);
static void tx0_io_prt(device_t *device);
static void tx0_io_dis(device_t *device);
static void tx0_sel(device_t *device);
static void tx0_io_reset_callback(device_t *device);
static const tx0_reset_param_t tx0_reset_param =
{
{
tx0_io_cpy,
tx0_io_r1l,
tx0_io_dis,
tx0_io_r3l,
tx0_io_prt,
/*tx0_io_typ*/NULL,
tx0_io_p6h,
tx0_io_p7h
},
tx0_sel,
tx0_io_reset_callback
};
static const crt_interface tx0_crt_interface = static const crt_interface tx0_crt_interface =
{ {
@ -705,51 +680,47 @@ TIMER_CALLBACK_MEMBER(tx0_state::puncher_callback)
/* /*
Initiate read of a 6-bit word from tape Initiate read of a 6-bit word from tape
*/ */
static void tx0_io_r1l(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_r1l )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>(); begin_tape_read( 0);
state->begin_tape_read( 0);
} }
/* /*
Initiate read of a 18-bit word from tape (used in read-in mode) Initiate read of a 18-bit word from tape (used in read-in mode)
*/ */
static void tx0_io_r3l(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_r3l )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>(); begin_tape_read(1);
state->begin_tape_read(1);
} }
/* /*
Write a 7-bit word to tape (7th bit clear) Write a 7-bit word to tape (7th bit clear)
*/ */
static void tx0_io_p6h(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_p6h )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>();
int ac; int ac;
/* read current AC */ /* read current AC */
ac = device->state().state_int(TX0_AC); ac = m_maincpu->state_int(TX0_AC);
/* shuffle and punch 6-bit word */ /* shuffle and punch 6-bit word */
state->tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5)); tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5));
state->m_tape_puncher.timer->adjust(attotime::from_usec(15800)); m_tape_puncher.timer->adjust(attotime::from_usec(15800));
} }
/* /*
Write a 7-bit word to tape (7th bit set) Write a 7-bit word to tape (7th bit set)
*/ */
static void tx0_io_p7h(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_p7h )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>();
int ac; int ac;
/* read current AC */ /* read current AC */
ac = device->state().state_int(TX0_AC); ac = m_maincpu->state_int(TX0_AC);
/* shuffle and punch 6-bit word */ /* shuffle and punch 6-bit word */
state->tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5) | 0100); tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5) | 0100);
state->m_tape_puncher.timer->adjust(attotime::from_usec(15800)); m_tape_puncher.timer->adjust(attotime::from_usec(15800));
} }
@ -793,25 +764,24 @@ void tx0_state::typewriter_out(UINT8 data)
*/ */
TIMER_CALLBACK_MEMBER(tx0_state::prt_callback) TIMER_CALLBACK_MEMBER(tx0_state::prt_callback)
{ {
m_maincpu->set_state_int(TX0_IOS,1); m_maincpu->io_complete();
} }
/* /*
prt io callback prt io callback
*/ */
static void tx0_io_prt(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_prt )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>();
int ac; int ac;
int ch; int ch;
/* read current AC */ /* read current AC */
ac = device->state().state_int(TX0_AC); ac = m_maincpu->state_int(TX0_AC);
/* shuffle and print 6-bit word */ /* shuffle and print 6-bit word */
ch = ((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5); ch = ((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5);
state->typewriter_out(ch); typewriter_out(ch);
state->m_typewriter.prt_timer->adjust(attotime::from_msec(100)); m_typewriter.prt_timer->adjust(attotime::from_msec(100));
} }
@ -820,25 +790,24 @@ static void tx0_io_prt(device_t *device)
*/ */
TIMER_CALLBACK_MEMBER(tx0_state::dis_callback) TIMER_CALLBACK_MEMBER(tx0_state::dis_callback)
{ {
m_maincpu->set_state_int(TX0_IOS,1); m_maincpu->io_complete();
} }
/* /*
Plot one point on crt Plot one point on crt
*/ */
static void tx0_io_dis(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_dis )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>();
int ac; int ac;
int x; int x;
int y; int y;
ac = device->state().state_int(TX0_AC); ac = m_maincpu->state_int(TX0_AC);
x = ac >> 9; x = ac >> 9;
y = ac & 0777; y = ac & 0777;
state->tx0_plot(x, y); tx0_plot(x, y);
state->m_dis_timer->adjust(attotime::from_usec(50)); m_dis_timer->adjust(attotime::from_usec(50));
} }
@ -944,143 +913,142 @@ void tx0_magtape_image_device::call_unload()
} }
} }
static void magtape_callback(device_t *device) void tx0_state::magtape_callback()
{ {
tx0_state *state = device->machine().driver_data<tx0_state>();
UINT8 buf = 0; UINT8 buf = 0;
int lr; int lr;
switch (state->m_magtape.state) switch (m_magtape.state)
{ {
case MTS_UNSELECTING: case MTS_UNSELECTING:
state->m_magtape.state = MTS_UNSELECTED; m_magtape.state = MTS_UNSELECTED;
case MTS_UNSELECTED: case MTS_UNSELECTED:
if (state->m_magtape.sel_pending) if (m_magtape.sel_pending)
{ {
int mar; int mar;
mar = device->state().state_int(TX0_MAR); mar = m_maincpu->state_int(TX0_MAR);
if ((mar & 03) != 1) if ((mar & 03) != 1)
{ /* unimplemented device: remain in unselected state and set rwc { /* unimplemented device: remain in unselected state and set rwc
flag? */ flag? */
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_RWC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_RWC);
} }
else else
{ {
state->m_magtape.state = MTS_SELECTING; m_magtape.state = MTS_SELECTING;
state->m_magtape.command = (mar & 014 >> 2); m_magtape.command = (mar & 014 >> 2);
state->m_magtape.binary_flag = (mar & 020 >> 4); m_magtape.binary_flag = (mar & 020 >> 4);
if (state->m_magtape.img) if (m_magtape.img)
state->schedule_select(); schedule_select();
} }
state->m_magtape.sel_pending = FALSE; m_magtape.sel_pending = FALSE;
device->state().set_state_int(TX0_IOS,1); m_maincpu->io_complete();
} }
break; break;
case MTS_SELECTING: case MTS_SELECTING:
state->m_magtape.state = MTS_SELECTED; m_magtape.state = MTS_SELECTED;
switch (state->m_magtape.command) switch (m_magtape.command)
{ {
case 0: /* backspace */ case 0: /* backspace */
state->m_magtape.long_parity = 0177; m_magtape.long_parity = 0177;
state->m_magtape.u.backspace_state = MTBSS_STATE0; m_magtape.u.backspace_state = MTBSS_STATE0;
break; break;
case 1: /* read */ case 1: /* read */
state->m_magtape.long_parity = 0177; m_magtape.long_parity = 0177;
state->m_magtape.u.read.state = MTRDS_STATE0; m_magtape.u.read.state = MTRDS_STATE0;
break; break;
case 2: /* rewind */ case 2: /* rewind */
break; break;
case 3: /* write */ case 3: /* write */
state->m_magtape.long_parity = 0177; m_magtape.long_parity = 0177;
state->m_magtape.u.write.state = MTWTS_STATE0; m_magtape.u.write.state = MTWTS_STATE0;
switch (state->m_magtape.irg_pos) switch (m_magtape.irg_pos)
{ {
case MTIRGP_START: case MTIRGP_START:
state->m_magtape.u.write.counter = 150; m_magtape.u.write.counter = 150;
break; break;
case MTIRGP_ENDMINUS1: case MTIRGP_ENDMINUS1:
state->m_magtape.u.write.counter = 1; m_magtape.u.write.counter = 1;
break; break;
case MTIRGP_END: case MTIRGP_END:
state->m_magtape.u.write.counter = 0; m_magtape.u.write.counter = 0;
break; break;
} }
break; break;
} }
case MTS_SELECTED: case MTS_SELECTED:
switch (state->m_magtape.command) switch (m_magtape.command)
{ {
case 0: /* backspace */ case 0: /* backspace */
if (state->m_magtape.img->ftell() == 0) if (m_magtape.img->ftell() == 0)
{ /* tape at ldp */ { /* tape at ldp */
state->m_magtape.state = MTS_UNSELECTING; m_magtape.state = MTS_UNSELECTING;
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_RWC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_RWC);
state->schedule_unselect(); schedule_unselect();
} }
else if (state->m_magtape.img->fseek( -1, SEEK_CUR)) else if (m_magtape.img->fseek( -1, SEEK_CUR))
{ /* eject tape */ { /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else if (state->m_magtape.img->fread(&buf, 1) != 1) else if (m_magtape.img->fread(&buf, 1) != 1)
{ /* eject tape */ { /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else if (state->m_magtape.img->fseek( -1, SEEK_CUR)) else if (m_magtape.img->fseek( -1, SEEK_CUR))
{ /* eject tape */ { /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
{ {
buf &= 0x7f; /* 7-bit tape, ignore 8th bit */ buf &= 0x7f; /* 7-bit tape, ignore 8th bit */
state->m_magtape.long_parity ^= buf; m_magtape.long_parity ^= buf;
switch (state->m_magtape.u.backspace_state) switch (m_magtape.u.backspace_state)
{ {
case MTBSS_STATE0: case MTBSS_STATE0:
/* STATE0 -> initial interrecord gap, longitudinal parity; /* STATE0 -> initial interrecord gap, longitudinal parity;
if longitudinal parity was all 0s, gap between longitudinal if longitudinal parity was all 0s, gap between longitudinal
parity and data, first byte of data */ parity and data, first byte of data */
if (buf != 0) if (buf != 0)
state->m_magtape.u.backspace_state = MTBSS_STATE1; m_magtape.u.backspace_state = MTBSS_STATE1;
break; break;
case MTBSS_STATE1: case MTBSS_STATE1:
/* STATE1 -> first byte of gap between longitudinal parity and /* STATE1 -> first byte of gap between longitudinal parity and
data, second byte of data */ data, second byte of data */
if (buf == 0) if (buf == 0)
state->m_magtape.u.backspace_state = MTBSS_STATE2; m_magtape.u.backspace_state = MTBSS_STATE2;
else else
state->m_magtape.u.backspace_state = MTBSS_STATE5; m_magtape.u.backspace_state = MTBSS_STATE5;
break; break;
case MTBSS_STATE2: case MTBSS_STATE2:
/* STATE2 -> second byte of gap between longitudinal parity and /* STATE2 -> second byte of gap between longitudinal parity and
data */ data */
if (buf == 0) if (buf == 0)
state->m_magtape.u.backspace_state = MTBSS_STATE3; m_magtape.u.backspace_state = MTBSS_STATE3;
else else
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
break; break;
case MTBSS_STATE3: case MTBSS_STATE3:
/* STATE3 -> third byte of gap between longitudinal parity and /* STATE3 -> third byte of gap between longitudinal parity and
data */ data */
if (buf == 0) if (buf == 0)
state->m_magtape.u.backspace_state = MTBSS_STATE4; m_magtape.u.backspace_state = MTBSS_STATE4;
else else
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
break; break;
case MTBSS_STATE4: case MTBSS_STATE4:
@ -1088,16 +1056,16 @@ static void magtape_callback(device_t *device)
interrecord gap after data */ interrecord gap after data */
if (buf == 0) if (buf == 0)
{ {
if (state->m_magtape.long_parity) if (m_magtape.long_parity)
logerror("invalid longitudinal parity\n"); logerror("invalid longitudinal parity\n");
/* set EOR and unselect... */ /* set EOR and unselect... */
state->m_magtape.state = MTS_UNSELECTING; m_magtape.state = MTS_UNSELECTING;
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_EOR); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_EOR);
state->schedule_unselect(); schedule_unselect();
state->m_magtape.irg_pos = MTIRGP_ENDMINUS1; m_magtape.irg_pos = MTIRGP_ENDMINUS1;
} }
else else
state->m_magtape.u.backspace_state = MTBSS_STATE5; m_magtape.u.backspace_state = MTBSS_STATE5;
break; break;
case MTBSS_STATE5: case MTBSS_STATE5:
/* STATE5 -> second byte of data word */ /* STATE5 -> second byte of data word */
@ -1105,10 +1073,10 @@ static void magtape_callback(device_t *device)
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
state->m_magtape.u.backspace_state = MTBSS_STATE6; m_magtape.u.backspace_state = MTBSS_STATE6;
break; break;
case MTBSS_STATE6: case MTBSS_STATE6:
/* STATE6 -> third byte of data word */ /* STATE6 -> third byte of data word */
@ -1116,67 +1084,67 @@ static void magtape_callback(device_t *device)
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
state->m_magtape.u.backspace_state = MTBSS_STATE6; m_magtape.u.backspace_state = MTBSS_STATE6;
break; break;
} }
if (state->m_magtape.state != MTS_UNSELECTING) if (m_magtape.state != MTS_UNSELECTING)
state->m_magtape.timer->adjust(attotime::from_usec(66)); m_magtape.timer->adjust(attotime::from_usec(66));
} }
break; break;
case 1: /* read */ case 1: /* read */
if (state->m_magtape.img->fread(&buf, 1) != 1) if (m_magtape.img->fread(&buf, 1) != 1)
{ /* I/O error or EOF? */ { /* I/O error or EOF? */
/* The MAME fileio layer makes it very hard to make the /* The MAME fileio layer makes it very hard to make the
difference... MAME seems to assume that I/O errors never difference... MAME seems to assume that I/O errors never
happen, whereas it is really easy to cause one by happen, whereas it is really easy to cause one by
deconnecting an external drive the image is located on!!! */ deconnecting an external drive the image is located on!!! */
UINT64 offs; UINT64 offs;
offs = state->m_magtape.img->ftell(); offs = m_magtape.img->ftell();
if (state->m_magtape.img->fseek( 0, SEEK_END) || (offs != state->m_magtape.img->ftell())) if (m_magtape.img->fseek( 0, SEEK_END) || (offs != m_magtape.img->ftell()))
{ /* I/O error */ { /* I/O error */
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
{ /* end of tape -> ??? */ { /* end of tape -> ??? */
/* maybe we run past end of tape, so that tape is ejected from /* maybe we run past end of tape, so that tape is ejected from
upper reel and unit becomes unavailable??? */ upper reel and unit becomes unavailable??? */
/*state->m_magtape.img->unload();*/ /*m_magtape.img->unload();*/
/* Or do we stop at EOT mark??? */ /* Or do we stop at EOT mark??? */
state->m_magtape.state = MTS_UNSELECTING; m_magtape.state = MTS_UNSELECTING;
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_EOT); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_EOT);
state->schedule_unselect(); schedule_unselect();
} }
} }
else else
{ {
buf &= 0x7f; /* 7-bit tape, ignore 8th bit */ buf &= 0x7f; /* 7-bit tape, ignore 8th bit */
state->m_magtape.long_parity ^= buf; m_magtape.long_parity ^= buf;
switch (state->m_magtape.u.read.state) switch (m_magtape.u.read.state)
{ {
case MTRDS_STATE0: case MTRDS_STATE0:
/* STATE0 -> interrecord blank or first byte of data */ /* STATE0 -> interrecord blank or first byte of data */
if (buf != 0) if (buf != 0)
{ {
if (state->m_magtape.cpy_pending) if (m_magtape.cpy_pending)
{ /* read command */ { /* read command */
state->m_magtape.u.read.space_flag = FALSE; m_magtape.u.read.space_flag = FALSE;
device->state().set_state_int(TX0_IOS,1); m_maincpu->set_state_int(TX0_IOS,1);
device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333)
| ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2));
/* check parity */ /* check parity */
if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag))
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC);
} }
else else
{ /* space command */ { /* space command */
state->m_magtape.u.read.space_flag = TRUE; m_magtape.u.read.space_flag = TRUE;
} }
state->m_magtape.u.read.state = MTRDS_STATE1; m_magtape.u.read.state = MTRDS_STATE1;
} }
break; break;
case MTRDS_STATE1: case MTRDS_STATE1:
@ -1185,17 +1153,17 @@ static void magtape_callback(device_t *device)
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
if (!state->m_magtape.u.read.space_flag) if (!m_magtape.u.read.space_flag)
{ {
device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333)
| ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2));
/* check parity */ /* check parity */
if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag))
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC);
} }
state->m_magtape.u.read.state = MTRDS_STATE2; m_magtape.u.read.state = MTRDS_STATE2;
break; break;
case MTRDS_STATE2: case MTRDS_STATE2:
/* STATE2 -> third byte of data word */ /* STATE2 -> third byte of data word */
@ -1203,40 +1171,40 @@ static void magtape_callback(device_t *device)
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
if (!state->m_magtape.u.read.space_flag) if (!m_magtape.u.read.space_flag)
{ {
device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333)
| ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2));
/* check parity */ /* check parity */
if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag))
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC);
/* synchronize with cpy instruction */ /* synchronize with cpy instruction */
if (state->m_magtape.cpy_pending) if (m_magtape.cpy_pending)
device->state().set_state_int(TX0_IOS,1); m_maincpu->set_state_int(TX0_IOS,1);
else else
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_RWC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_RWC);
} }
state->m_magtape.u.read.state = MTRDS_STATE3; m_magtape.u.read.state = MTRDS_STATE3;
break; break;
case MTRDS_STATE3: case MTRDS_STATE3:
/* STATE3 -> first byte of new word of data, or first byte /* STATE3 -> first byte of new word of data, or first byte
of gap between data and longitudinal parity */ of gap between data and longitudinal parity */
if (buf != 0) if (buf != 0)
{ {
state->m_magtape.u.read.state = MTRDS_STATE1; m_magtape.u.read.state = MTRDS_STATE1;
if (!state->m_magtape.u.read.space_flag) if (!m_magtape.u.read.space_flag)
{ {
device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333)
| ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2));
/* check parity */ /* check parity */
if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag))
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC);
} }
} }
else else
state->m_magtape.u.read.state = MTRDS_STATE4; m_magtape.u.read.state = MTRDS_STATE4;
break; break;
case MTRDS_STATE4: case MTRDS_STATE4:
/* STATE4 -> second byte of gap between data and /* STATE4 -> second byte of gap between data and
@ -1245,10 +1213,10 @@ static void magtape_callback(device_t *device)
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
state->m_magtape.u.read.state = MTRDS_STATE5; m_magtape.u.read.state = MTRDS_STATE5;
break; break;
case MTRDS_STATE5: case MTRDS_STATE5:
@ -1258,126 +1226,126 @@ static void magtape_callback(device_t *device)
{ {
logerror("tape seems to be corrupt\n"); logerror("tape seems to be corrupt\n");
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
state->m_magtape.u.read.state = MTRDS_STATE6; m_magtape.u.read.state = MTRDS_STATE6;
break; break;
case MTRDS_STATE6: case MTRDS_STATE6:
/* STATE6 -> longitudinal parity */ /* STATE6 -> longitudinal parity */
/* check parity */ /* check parity */
if (state->m_magtape.long_parity) if (m_magtape.long_parity)
{ {
logerror("invalid longitudinal parity\n"); logerror("invalid longitudinal parity\n");
/* no idea if the original tx-0 magtape controller /* no idea if the original tx-0 magtape controller
checks parity, but can't harm if we do */ checks parity, but can't harm if we do */
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC);
} }
/* set EOR and unselect... */ /* set EOR and unselect... */
state->m_magtape.state = MTS_UNSELECTING; m_magtape.state = MTS_UNSELECTING;
device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_EOR); m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_EOR);
state->schedule_unselect(); schedule_unselect();
state->m_magtape.irg_pos = MTIRGP_START; m_magtape.irg_pos = MTIRGP_START;
break; break;
} }
if (state->m_magtape.state != MTS_UNSELECTING) if (m_magtape.state != MTS_UNSELECTING)
state->m_magtape.timer->adjust(attotime::from_usec(66)); m_magtape.timer->adjust(attotime::from_usec(66));
} }
break; break;
case 2: /* rewind */ case 2: /* rewind */
state->m_magtape.state = MTS_UNSELECTING; m_magtape.state = MTS_UNSELECTING;
/* we rewind at 10*read speed (I don't know the real value) */ /* we rewind at 10*read speed (I don't know the real value) */
state->m_magtape.timer->adjust((attotime::from_nsec(6600) * state->m_magtape.img->ftell())); m_magtape.timer->adjust((attotime::from_nsec(6600) * m_magtape.img->ftell()));
//schedule_unselect(state); //schedule_unselect(state);
state->m_magtape.img->fseek( 0, SEEK_END); m_magtape.img->fseek( 0, SEEK_END);
state->m_magtape.irg_pos = MTIRGP_END; m_magtape.irg_pos = MTIRGP_END;
break; break;
case 3: /* write */ case 3: /* write */
switch (state->m_magtape.u.write.state) switch (m_magtape.u.write.state)
{ {
case MTWTS_STATE0: case MTWTS_STATE0:
if (state->m_magtape.u.write.counter != 0) if (m_magtape.u.write.counter != 0)
{ {
state->m_magtape.u.write.counter--; m_magtape.u.write.counter--;
buf = 0; buf = 0;
break; break;
} }
else else
{ {
state->m_magtape.u.write.state = MTWTS_STATE1; m_magtape.u.write.state = MTWTS_STATE1;
} }
case MTWTS_STATE1: case MTWTS_STATE1:
if (state->m_magtape.u.write.counter) if (m_magtape.u.write.counter)
{ {
state->m_magtape.u.write.counter--; m_magtape.u.write.counter--;
lr = device->state().state_int(TX0_LR); lr = m_maincpu->state_int(TX0_LR);
buf = ((lr >> 10) & 040) | ((lr >> 8) & 020) | ((lr >> 6) & 010) | ((lr >> 4) & 004) | ((lr >> 2) & 002) | (lr & 001); buf = ((lr >> 10) & 040) | ((lr >> 8) & 020) | ((lr >> 6) & 010) | ((lr >> 4) & 004) | ((lr >> 2) & 002) | (lr & 001);
buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!state->m_magtape.binary_flag) << 6)) & 0100; buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!m_magtape.binary_flag) << 6)) & 0100;
device->state().set_state_int(TX0_LR, lr >> 1); m_maincpu->set_state_int(TX0_LR, lr >> 1);
} }
else else
{ {
if (state->m_magtape.cpy_pending) if (m_magtape.cpy_pending)
{ {
device->state().set_state_int(TX0_IOS,1); m_maincpu->set_state_int(TX0_IOS,1);
lr = device->state().state_int(TX0_LR); lr = m_maincpu->state_int(TX0_LR);
buf = ((lr >> 10) & 040) | ((lr >> 8) & 020) | ((lr >> 6) & 010) | ((lr >> 4) & 004) | ((lr >> 2) & 002) | (lr & 001); buf = ((lr >> 10) & 040) | ((lr >> 8) & 020) | ((lr >> 6) & 010) | ((lr >> 4) & 004) | ((lr >> 2) & 002) | (lr & 001);
buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!state->m_magtape.binary_flag) << 6)) & 0100; buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!m_magtape.binary_flag) << 6)) & 0100;
device->state().set_state_int(TX0_LR, lr >> 1); m_maincpu->set_state_int(TX0_LR, lr >> 1);
state->m_magtape.u.write.counter = 2; m_magtape.u.write.counter = 2;
break; break;
} }
else else
{ {
state->m_magtape.u.write.state = MTWTS_STATE2; m_magtape.u.write.state = MTWTS_STATE2;
state->m_magtape.u.write.counter = 3; m_magtape.u.write.counter = 3;
} }
} }
case MTWTS_STATE2: case MTWTS_STATE2:
if (state->m_magtape.u.write.counter != 0) if (m_magtape.u.write.counter != 0)
{ {
state->m_magtape.u.write.counter--; m_magtape.u.write.counter--;
buf = 0; buf = 0;
break; break;
} }
else else
{ {
buf = state->m_magtape.long_parity; buf = m_magtape.long_parity;
state->m_magtape.state = (state_t)MTWTS_STATE3; m_magtape.state = (state_t)MTWTS_STATE3;
state->m_magtape.u.write.counter = 150; m_magtape.u.write.counter = 150;
} }
break; break;
case MTWTS_STATE3: case MTWTS_STATE3:
if (state->m_magtape.u.write.counter != 0) if (m_magtape.u.write.counter != 0)
{ {
state->m_magtape.u.write.counter--; m_magtape.u.write.counter--;
buf = 0; buf = 0;
break; break;
} }
else else
{ {
state->m_magtape.state = MTS_UNSELECTING; m_magtape.state = MTS_UNSELECTING;
state->schedule_unselect(); schedule_unselect();
state->m_magtape.irg_pos = MTIRGP_END; m_magtape.irg_pos = MTIRGP_END;
} }
break; break;
} }
if (state->m_magtape.state != MTS_UNSELECTING) if (m_magtape.state != MTS_UNSELECTING)
{ /* write data word */ { /* write data word */
state->m_magtape.long_parity ^= buf; m_magtape.long_parity ^= buf;
if (state->m_magtape.img->fwrite(&buf, 1) != 1) if (m_magtape.img->fwrite(&buf, 1) != 1)
{ /* I/O error */ { /* I/O error */
/* eject tape */ /* eject tape */
state->m_magtape.img->unload(); m_magtape.img->unload();
} }
else else
state->m_magtape.timer->adjust(attotime::from_usec(66)); m_magtape.timer->adjust(attotime::from_usec(66));
} }
break; break;
} }
@ -1385,42 +1353,40 @@ static void magtape_callback(device_t *device)
} }
} }
static void tx0_sel(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_sel )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>(); m_magtape.sel_pending = TRUE;
state->m_magtape.sel_pending = TRUE;
if (state->m_magtape.state == MTS_UNSELECTED) if (m_magtape.state == MTS_UNSELECTED)
{ {
if (0) if (0)
magtape_callback(device); magtape_callback();
state->m_magtape.timer->adjust(attotime::zero); m_magtape.timer->adjust(attotime::zero);
} }
} }
static void tx0_io_cpy(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_cpy )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>(); switch (m_magtape.state)
switch (state->m_magtape.state)
{ {
case MTS_UNSELECTED: case MTS_UNSELECTED:
case MTS_UNSELECTING: case MTS_UNSELECTING:
/* ignore instruction and set rwc flag? */ /* ignore instruction and set rwc flag? */
device->state().set_state_int(TX0_IOS,1); m_maincpu->io_complete();
break; break;
case MTS_SELECTING: case MTS_SELECTING:
case MTS_SELECTED: case MTS_SELECTED:
switch (state->m_magtape.command) switch (m_magtape.command)
{ {
case 0: /* backspace */ case 0: /* backspace */
case 2: /* rewind */ case 2: /* rewind */
/* ignore instruction and set rwc flag? */ /* ignore instruction and set rwc flag? */
device->state().set_state_int(TX0_IOS,1); m_maincpu->io_complete();
break; break;
case 1: /* read */ case 1: /* read */
case 3: /* write */ case 3: /* write */
state->m_magtape.cpy_pending = TRUE; m_magtape.cpy_pending = TRUE;
break; break;
} }
break; break;
@ -1433,21 +1399,20 @@ static void tx0_io_cpy(device_t *device)
IO devices should reset IO devices should reset
*/ */
static void tx0_io_reset_callback(device_t *device) WRITE_LINE_MEMBER( tx0_state::tx0_io_reset_callback )
{ {
tx0_state *state = device->machine().driver_data<tx0_state>(); m_tape_reader.rcl = m_tape_reader.rc = 0;
state->m_tape_reader.rcl = state->m_tape_reader.rc = 0; if (m_tape_reader.timer)
if (state->m_tape_reader.timer) m_tape_reader.timer->enable(0);
state->m_tape_reader.timer->enable(0);
if (state->m_tape_puncher.timer) if (m_tape_puncher.timer)
state->m_tape_puncher.timer->enable(0); m_tape_puncher.timer->enable(0);
if (state->m_typewriter.prt_timer) if (m_typewriter.prt_timer)
state->m_typewriter.prt_timer->enable(0); m_typewriter.prt_timer->enable(0);
if (state->m_dis_timer) if (m_dis_timer)
state->m_dis_timer->enable(0); m_dis_timer->enable(0);
} }
@ -1537,7 +1502,7 @@ INTERRUPT_GEN_MEMBER(tx0_state::tx0_interrupt)
} }
if (control_transitions & tx0_read_in) if (control_transitions & tx0_read_in)
{ /* set cpu to read instructions from perforated tape */ { /* set cpu to read instructions from perforated tape */
m_maincpu->set_state_int(TX0_RESET, (UINT64)0); m_maincpu->pulse_reset();
m_maincpu->set_state_int(TX0_RUN, (UINT64)0); m_maincpu->set_state_int(TX0_RUN, (UINT64)0);
m_maincpu->set_state_int(TX0_RIM, 1); m_maincpu->set_state_int(TX0_RIM, 1);
} }
@ -1600,7 +1565,18 @@ static MACHINE_CONFIG_START( tx0_64kw, tx0_state )
/* basic machine hardware */ /* basic machine hardware */
/* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is approximately 6usec) */ /* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is approximately 6usec) */
MCFG_CPU_ADD("maincpu", TX0_64KW, 166667) MCFG_CPU_ADD("maincpu", TX0_64KW, 166667)
MCFG_CPU_CONFIG(tx0_reset_param) MCFG_TX0_CONFIG(
WRITELINE( tx0_state, tx0_io_cpy ),
WRITELINE( tx0_state, tx0_io_r1l ),
WRITELINE( tx0_state, tx0_io_dis ),
WRITELINE( tx0_state, tx0_io_r3l ),
WRITELINE( tx0_state, tx0_io_prt ),
NULL,
WRITELINE( tx0_state, tx0_io_p6h ),
WRITELINE( tx0_state, tx0_io_p7h ),
WRITELINE( tx0_state, tx0_sel ),
WRITELINE( tx0_state, tx0_io_reset_callback )
)
MCFG_CPU_PROGRAM_MAP(tx0_64kw_map) MCFG_CPU_PROGRAM_MAP(tx0_64kw_map)
/* dummy interrupt: handles input */ /* dummy interrupt: handles input */
MCFG_CPU_VBLANK_INT_DRIVER("screen", tx0_state, tx0_interrupt) MCFG_CPU_VBLANK_INT_DRIVER("screen", tx0_state, tx0_interrupt)
@ -1632,7 +1608,6 @@ static MACHINE_CONFIG_DERIVED( tx0_8kw, tx0_64kw )
/* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is /* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is
approximately 6usec) */ approximately 6usec) */
MCFG_CPU_MODIFY("maincpu") MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_CONFIG(tx0_reset_param)
MCFG_CPU_PROGRAM_MAP(tx0_8kw_map) MCFG_CPU_PROGRAM_MAP(tx0_8kw_map)
/*MCFG_CPU_PORTS(readport, writeport)*/ /*MCFG_CPU_PORTS(readport, writeport)*/
MACHINE_CONFIG_END MACHINE_CONFIG_END

View File

@ -8,6 +8,7 @@
#define TX0_H_ #define TX0_H_
#include "video/crt.h" #include "video/crt.h"
#include "cpu/pdp1/tx0.h"
enum state_t enum state_t
{ {
@ -161,7 +162,7 @@ public:
TIMER_CALLBACK_MEMBER(prt_callback); TIMER_CALLBACK_MEMBER(prt_callback);
TIMER_CALLBACK_MEMBER(dis_callback); TIMER_CALLBACK_MEMBER(dis_callback);
void tx0_machine_stop(); void tx0_machine_stop();
required_device<cpu_device> m_maincpu; required_device<tx0_device> m_maincpu;
inline void tx0_plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color); inline void tx0_plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);
void tx0_plot(int x, int y); void tx0_plot(int x, int y);
void tx0_draw_led(bitmap_ind16 &bitmap, int x, int y, int state); void tx0_draw_led(bitmap_ind16 &bitmap, int x, int y, int state);
@ -183,6 +184,16 @@ public:
void schedule_select(); void schedule_select();
void schedule_unselect(); void schedule_unselect();
void tx0_keyboard(); void tx0_keyboard();
DECLARE_WRITE_LINE_MEMBER(tx0_io_cpy);
DECLARE_WRITE_LINE_MEMBER(tx0_io_r1l);
DECLARE_WRITE_LINE_MEMBER(tx0_io_r3l);
DECLARE_WRITE_LINE_MEMBER(tx0_io_p6h);
DECLARE_WRITE_LINE_MEMBER(tx0_io_p7h);
DECLARE_WRITE_LINE_MEMBER(tx0_io_prt);
DECLARE_WRITE_LINE_MEMBER(tx0_io_dis);
DECLARE_WRITE_LINE_MEMBER(tx0_sel);
DECLARE_WRITE_LINE_MEMBER(tx0_io_reset_callback);
void magtape_callback();
}; };
/* defines for each bit and mask in input port "CSW" */ /* defines for each bit and mask in input port "CSW" */