mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
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:
parent
9c03593b09
commit
cc74ef9ade
File diff suppressed because it is too large
Load Diff
@ -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__ */
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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" */
|
||||||
|
Loading…
Reference in New Issue
Block a user