* new WORKING machine

----
MTU-130 [Olivier Galibert, David Williams, Disk Blitz, Eric Wright]
This commit is contained in:
Olivier Galibert 2022-09-03 23:55:53 +02:00
parent 6563dfe9cf
commit ef8ac6eee8
10 changed files with 2863 additions and 6 deletions

View File

@ -1575,6 +1575,7 @@ end
--@src/devices/cpu/m6502/m740.h,CPUS["M6502"] = true
--@src/devices/cpu/m6502/m3745x.h,CPUS["M6502"] = true
--@src/devices/cpu/m6502/m5074x.h,CPUS["M6502"] = true
--@src/devices/cpu/m6502/m6502mtu.h,CPUS["M6502"] = true
--@src/devices/cpu/m6502/st2xxx.h,CPUS["ST2XXX"] = true
--@src/devices/cpu/m6502/st2204.h,CPUS["ST2XXX"] = true
--@src/devices/cpu/m6502/st2205u.h,CPUS["ST2XXX"] = true
@ -1592,6 +1593,8 @@ if CPUS["M6502"] then
MAME_DIR .. "src/devices/cpu/m6502/m4510.h",
MAME_DIR .. "src/devices/cpu/m6502/m6502.cpp",
MAME_DIR .. "src/devices/cpu/m6502/m6502.h",
MAME_DIR .. "src/devices/cpu/m6502/m6502mtu.cpp",
MAME_DIR .. "src/devices/cpu/m6502/m6502mtu.h",
MAME_DIR .. "src/devices/cpu/m6502/m65c02.cpp",
MAME_DIR .. "src/devices/cpu/m6502/m65c02.h",
MAME_DIR .. "src/devices/cpu/m6502/m65ce02.cpp",
@ -1634,6 +1637,7 @@ if CPUS["M6502"] then
{ MAME_DIR .. "src/devices/cpu/m6502/odeco16.lst", GEN_DIR .. "emu/cpu/m6502/deco16.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/ddeco16.lst" }, {"@echo Generating deco16 instruction source file...", PYTHON .. " $(1) s deco16 $(<) $(2) $(@)" }},
{ MAME_DIR .. "src/devices/cpu/m6502/om4510.lst", GEN_DIR .. "emu/cpu/m6502/m4510.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm4510.lst" }, {"@echo Generating m4510 instruction source file...", PYTHON .. " $(1) s m4510 $(<) $(2) $(@)" }},
{ MAME_DIR .. "src/devices/cpu/m6502/om6502.lst", GEN_DIR .. "emu/cpu/m6502/m6502.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm6502.lst" }, {"@echo Generating m6502 instruction source file...", PYTHON .. " $(1) s m6502 $(<) $(2) $(@)" }},
{ MAME_DIR .. "src/devices/cpu/m6502/om6502mtu.lst", GEN_DIR .. "emu/cpu/m6502/m6502mtu.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm6502mtu.lst" }, {"@echo Generating m6502 MTU instruction source file...", PYTHON .. " $(1) s m6502mtu $(<) $(2) $(@)" }},
{ MAME_DIR .. "src/devices/cpu/m6502/om65c02.lst", GEN_DIR .. "emu/cpu/m6502/m65c02.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm65c02.lst" }, {"@echo Generating m65c02 instruction source file...", PYTHON .. " $(1) s m65c02 $(<) $(2) $(@)" }},
{ MAME_DIR .. "src/devices/cpu/m6502/om65ce02.lst", GEN_DIR .. "emu/cpu/m6502/m65ce02.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm65ce02.lst" }, {"@echo Generating m65ce02 instruction source file...", PYTHON .. " $(1) s m65ce02 $(<) $(2) $(@)" }},
{ MAME_DIR .. "src/devices/cpu/m6502/om6509.lst", GEN_DIR .. "emu/cpu/m6502/m6509.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm6509.lst" }, {"@echo Generating m6509 instruction source file...", PYTHON .. " $(1) s m6509 $(<) $(2) $(@)" }},
@ -1649,6 +1653,7 @@ if CPUS["M6502"] then
{ MAME_DIR .. "src/devices/cpu/m6502/deco16.cpp", GEN_DIR .. "emu/cpu/m6502/deco16.hxx" },
{ MAME_DIR .. "src/devices/cpu/m6502/m4510.cpp", GEN_DIR .. "emu/cpu/m6502/m4510.hxx" },
{ MAME_DIR .. "src/devices/cpu/m6502/m6502.cpp", GEN_DIR .. "emu/cpu/m6502/m6502.hxx" },
{ MAME_DIR .. "src/devices/cpu/m6502/m6502mtu.cpp", GEN_DIR .. "emu/cpu/m6502/m6502mtu.hxx" },
{ MAME_DIR .. "src/devices/cpu/m6502/m65c02.cpp", GEN_DIR .. "emu/cpu/m6502/m65c02.hxx" },
{ MAME_DIR .. "src/devices/cpu/m6502/m65ce02.cpp", GEN_DIR .. "emu/cpu/m6502/m65ce02.hxx" },
{ MAME_DIR .. "src/devices/cpu/m6502/m6509.cpp", GEN_DIR .. "emu/cpu/m6502/m6509.hxx" },

View File

@ -0,0 +1,20 @@
# license:BSD-3-Clause
# copyright-holders:Olivier Galibert
# m6502 MTU - external circuitry for transparent banking handling
brk_mtu_imp ora_mtu_idx kil_mtu_non slo_mtu_idx nop_mtu_zpg ora_mtu_zpg asl_mtu_zpg slo_mtu_zpg php_mtu_imp ora_mtu_imm asl_mtu_acc anc_mtu_imm nop_mtu_aba ora_mtu_aba asl_mtu_aba slo_mtu_aba
bpl_mtu_rel ora_mtu_idy kil_mtu_non slo_mtu_idy nop_mtu_zpx ora_mtu_zpx asl_mtu_zpx slo_mtu_zpx clc_mtu_imp ora_mtu_aby nop_mtu_imp slo_mtu_aby nop_mtu_abx ora_mtu_abx asl_mtu_abx slo_mtu_abx
jsr_mtu_adr and_mtu_idx kil_mtu_non rla_mtu_idx bit_mtu_zpg and_mtu_zpg rol_mtu_zpg rla_mtu_zpg plp_mtu_imp and_mtu_imm rol_mtu_acc anc_mtu_imm bit_mtu_aba and_mtu_aba rol_mtu_aba rla_mtu_aba
bmi_mtu_rel and_mtu_idy kil_mtu_non rla_mtu_idy nop_mtu_zpx and_mtu_zpx rol_mtu_zpx rla_mtu_zpx sec_mtu_imp and_mtu_aby nop_mtu_imp rla_mtu_aby nop_mtu_abx and_mtu_abx rol_mtu_abx rla_mtu_abx
rti_mtu_imp eor_mtu_idx kil_mtu_non sre_mtu_idx nop_mtu_zpg eor_mtu_zpg lsr_mtu_zpg sre_mtu_zpg pha_mtu_imp eor_mtu_imm lsr_mtu_acc asr_mtu_imm jmp_mtu_adr eor_mtu_aba lsr_mtu_aba sre_mtu_aba
bvc_mtu_rel eor_mtu_idy kil_mtu_non sre_mtu_idy nop_mtu_zpx eor_mtu_zpx lsr_mtu_zpx sre_mtu_zpx cli_mtu_imp eor_mtu_aby nop_mtu_imp sre_mtu_aby nop_mtu_abx eor_mtu_abx lsr_mtu_abx sre_mtu_abx
rts_mtu_imp adc_mtu_idx kil_mtu_non rra_mtu_idx nop_mtu_zpg adc_mtu_zpg ror_mtu_zpg rra_mtu_zpg pla_mtu_imp adc_mtu_imm ror_mtu_acc arr_mtu_imm jmp_mtu_ind adc_mtu_aba ror_mtu_aba rra_mtu_aba
bvs_mtu_rel adc_mtu_idy kil_mtu_non rra_mtu_idy nop_mtu_zpx adc_mtu_zpx ror_mtu_zpx rra_mtu_zpx sei_mtu_imp adc_mtu_aby nop_mtu_imp rra_mtu_aby nop_mtu_abx adc_mtu_abx ror_mtu_abx rra_mtu_abx
nop_mtu_imm sta_mtu_idx nop_mtu_imm sax_mtu_idx sty_mtu_zpg sta_mtu_zpg stx_mtu_zpg sax_mtu_zpg dey_mtu_imp nop_mtu_imm txa_mtu_imp ane_mtu_imm sty_mtu_aba sta_mtu_aba stx_mtu_aba sax_mtu_aba
bcc_mtu_rel sta_mtu_idy kil_mtu_non sha_mtu_idy sty_mtu_zpx sta_mtu_zpx stx_mtu_zpy sax_mtu_zpy tya_mtu_imp sta_mtu_aby txs_mtu_imp shs_mtu_aby shy_mtu_abx sta_mtu_abx shx_mtu_aby sha_mtu_aby
ldy_mtu_imm lda_mtu_idx ldx_mtu_imm lax_mtu_idx ldy_mtu_zpg lda_mtu_zpg ldx_mtu_zpg lax_mtu_zpg tay_mtu_imp lda_mtu_imm tax_mtu_imp lxa_mtu_imm ldy_mtu_aba lda_mtu_aba ldx_mtu_aba lax_mtu_aba
bcs_mtu_rel lda_mtu_idy kil_mtu_non lax_mtu_idy ldy_mtu_zpx lda_mtu_zpx ldx_mtu_zpy lax_mtu_zpy clv_mtu_imp lda_mtu_aby tsx_mtu_imp las_mtu_aby ldy_mtu_abx lda_mtu_abx ldx_mtu_aby lax_mtu_aby
cpy_mtu_imm cmp_mtu_idx nop_mtu_imm dcp_mtu_idx cpy_mtu_zpg cmp_mtu_zpg dec_mtu_zpg dcp_mtu_zpg iny_mtu_imp cmp_mtu_imm dex_mtu_imp sbx_mtu_imm cpy_mtu_aba cmp_mtu_aba dec_mtu_aba dcp_mtu_aba
bne_mtu_rel cmp_mtu_idy kil_mtu_non dcp_mtu_idy nop_mtu_zpx cmp_mtu_zpx dec_mtu_zpx dcp_mtu_zpx cld_mtu_imp cmp_mtu_aby nop_mtu_imp dcp_mtu_aby nop_mtu_abx cmp_mtu_abx dec_mtu_abx dcp_mtu_abx
cpx_mtu_imm sbc_mtu_idx nop_mtu_imm isb_mtu_idx cpx_mtu_zpg sbc_mtu_zpg inc_mtu_zpg isb_mtu_zpg inx_mtu_imp sbc_mtu_imm nop_mtu_imp sbc_mtu_imm cpx_mtu_aba sbc_mtu_aba inc_mtu_aba isb_mtu_aba
beq_mtu_rel sbc_mtu_idy kil_mtu_non isb_mtu_idy nop_mtu_zpx sbc_mtu_zpx inc_mtu_zpx isb_mtu_zpx sed_mtu_imp sbc_mtu_aby nop_mtu_imp isb_mtu_aby nop_mtu_abx sbc_mtu_abx inc_mtu_abx isb_mtu_abx
reset_mtu

View File

@ -43,12 +43,14 @@ void m6502_device::device_start()
void m6502_device::init()
{
space(AS_PROGRAM).cache(mintf->cprogram);
space(has_space(AS_OPCODES) ? AS_OPCODES : AS_PROGRAM).cache(mintf->csprogram);
if(space(AS_PROGRAM).addr_width() > 14)
space(AS_PROGRAM).specific(mintf->program);
else
space(AS_PROGRAM).specific(mintf->program14);
if(mintf) {
space(AS_PROGRAM).cache(mintf->cprogram);
space(has_space(AS_OPCODES) ? AS_OPCODES : AS_PROGRAM).cache(mintf->csprogram);
if(space(AS_PROGRAM).addr_width() > 14)
space(AS_PROGRAM).specific(mintf->program);
else
space(AS_PROGRAM).specific(mintf->program14);
}
sync_w.resolve_safe();

View File

@ -0,0 +1,76 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
m6502mtu.cpp
M6502 with MTU external banking hardware
***************************************************************************/
#include "emu.h"
#include "m6502mtu.h"
DEFINE_DEVICE_TYPE(M6502MTU, m6502mtu_device, "m6502mtu", "M6502 with MTU banking")
m6502mtu_device::m6502mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
m6502_device(mconfig, M6502MTU, tag, owner, clock)
{
program_config.m_addr_width = 18;
sprogram_config.m_addr_width = 18;
}
void m6502mtu_device::device_start()
{
mintf = nullptr;
space(AS_PROGRAM).specific(cprogram);
space(has_space(AS_OPCODES) ? AS_OPCODES : AS_PROGRAM).specific(csprogram);
save_item(NAME(low_instruction));
save_item(NAME(interrupt_mode));
save_item(NAME(pbank));
save_item(NAME(dbank));
init();
}
void m6502mtu_device::device_reset()
{
m6502_device::device_reset();
pbank = 0;
dbank = 0;
low_instruction = false;
interrupt_mode = false;
}
void m6502mtu_device::prefetchd()
{
sync = true;
sync_w(ASSERT_LINE);
NPC = PC;
low_instruction = PC < 0x200;
IR = csprogram.read_byte(low_instruction || interrupt_mode ? PC : PC | pbank);
sync = false;
sync_w(CLEAR_LINE);
if((nmi_pending || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) {
irq_taken = true;
IR = 0x00;
} else
PC++;
}
void m6502mtu_device::prefetchd_noirq()
{
sync = true;
sync_w(ASSERT_LINE);
NPC = PC;
low_instruction = PC < 0x200;
IR = csprogram.read_byte(low_instruction || interrupt_mode ? PC : PC | pbank);
sync = false;
sync_w(CLEAR_LINE);
PC++;
}
#include "cpu/m6502/m6502mtu.hxx"

View File

@ -0,0 +1,151 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
m6502mtu.h
M6502 with MTU external banking hardware
***************************************************************************/
#ifndef MAME_CPU_M6502_M6502MTU_H
#define MAME_CPU_M6502_M6502MTU_H
#include "m6502.h"
class m6502mtu_device : public m6502_device {
public:
m6502mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void do_exec_full() override;
virtual void do_exec_partial() override;
void set_pbank(u32 bank) { pbank = bank << 16; }
void set_dbank(u32 bank) { dbank = bank << 16; }
protected:
virtual void device_start() override;
virtual void device_reset() override;
memory_access<18, 0, 0, ENDIANNESS_LITTLE>::specific cprogram;
memory_access<18, 0, 0, ENDIANNESS_LITTLE>::specific csprogram;
bool low_instruction, interrupt_mode;
u32 pbank, dbank;
uint8_t readd(uint16_t adr) { return cprogram.read_byte(low_instruction || interrupt_mode ? adr : adr | pbank); }
void writed(uint16_t adr, uint8_t val) { cprogram.write_byte(low_instruction || interrupt_mode ? adr : adr | pbank, val); }
uint8_t readi(uint16_t adr) { return cprogram.read_byte(adr | dbank); }
void writei(uint16_t adr, uint8_t val) { cprogram.write_byte(adr | dbank, val); }
uint8_t readil(uint16_t adr) { return cprogram.read_byte(low_instruction ? adr | dbank : adr); }
void writeil(uint16_t adr, uint8_t val) { cprogram.write_byte(low_instruction ? adr | dbank : adr, val); }
uint8_t readd_arg(uint16_t adr) { return readd(adr); }
uint8_t readd_pc() { return readd(PC++); }
uint8_t readd_pc_noinc() { return readd(PC); }
void prefetchd();
void prefetchd_noirq();
void interrupt_mode_on() { interrupt_mode = true; }
void interrupt_mode_off() { interrupt_mode = false; }
#define O(o) void o ## _full(); void o ## _partial()
// NMOS 6502 opcodes
// documented opcodes
O(adc_mtu_aba); O(adc_mtu_abx); O(adc_mtu_aby); O(adc_mtu_idx); O(adc_mtu_idy); O(adc_mtu_imm); O(adc_mtu_zpg); O(adc_mtu_zpx);
O(and_mtu_aba); O(and_mtu_abx); O(and_mtu_aby); O(and_mtu_imm); O(and_mtu_idx); O(and_mtu_idy); O(and_mtu_zpg); O(and_mtu_zpx);
O(asl_mtu_aba); O(asl_mtu_abx); O(asl_mtu_acc); O(asl_mtu_zpg); O(asl_mtu_zpx);
O(bcc_mtu_rel);
O(bcs_mtu_rel);
O(beq_mtu_rel);
O(bit_mtu_aba); O(bit_mtu_zpg);
O(bmi_mtu_rel);
O(bne_mtu_rel);
O(bpl_mtu_rel);
O(brk_mtu_imp);
O(bvc_mtu_rel);
O(bvs_mtu_rel);
O(clc_mtu_imp);
O(cld_mtu_imp);
O(cli_mtu_imp);
O(clv_mtu_imp);
O(cmp_mtu_aba); O(cmp_mtu_abx); O(cmp_mtu_aby); O(cmp_mtu_idx); O(cmp_mtu_idy); O(cmp_mtu_imm); O(cmp_mtu_zpg); O(cmp_mtu_zpx);
O(cpx_mtu_aba); O(cpx_mtu_imm); O(cpx_mtu_zpg);
O(cpy_mtu_aba); O(cpy_mtu_imm); O(cpy_mtu_zpg);
O(dec_mtu_aba); O(dec_mtu_abx); O(dec_mtu_zpg); O(dec_mtu_zpx);
O(dex_mtu_imp);
O(dey_mtu_imp);
O(eor_mtu_aba); O(eor_mtu_abx); O(eor_mtu_aby); O(eor_mtu_idx); O(eor_mtu_idy); O(eor_mtu_imm); O(eor_mtu_zpg); O(eor_mtu_zpx);
O(inc_mtu_aba); O(inc_mtu_abx); O(inc_mtu_zpg); O(inc_mtu_zpx);
O(inx_mtu_imp);
O(iny_mtu_imp);
O(jmp_mtu_adr); O(jmp_mtu_ind);
O(jsr_mtu_adr);
O(lda_mtu_aba); O(lda_mtu_abx); O(lda_mtu_aby); O(lda_mtu_idx); O(lda_mtu_idy); O(lda_mtu_imm); O(lda_mtu_zpg); O(lda_mtu_zpx);
O(ldx_mtu_aba); O(ldx_mtu_aby); O(ldx_mtu_imm); O(ldx_mtu_zpg); O(ldx_mtu_zpy);
O(ldy_mtu_aba); O(ldy_mtu_abx); O(ldy_mtu_imm); O(ldy_mtu_zpg); O(ldy_mtu_zpx);
O(lsr_mtu_aba); O(lsr_mtu_abx); O(lsr_mtu_acc); O(lsr_mtu_zpg); O(lsr_mtu_zpx);
O(nop_mtu_imp);
O(ora_mtu_aba); O(ora_mtu_abx); O(ora_mtu_aby); O(ora_mtu_imm); O(ora_mtu_idx); O(ora_mtu_idy); O(ora_mtu_zpg); O(ora_mtu_zpx);
O(pha_mtu_imp);
O(php_mtu_imp);
O(pla_mtu_imp);
O(plp_mtu_imp);
O(rol_mtu_aba); O(rol_mtu_abx); O(rol_mtu_acc); O(rol_mtu_zpg); O(rol_mtu_zpx);
O(ror_mtu_aba); O(ror_mtu_abx); O(ror_mtu_acc); O(ror_mtu_zpg); O(ror_mtu_zpx);
O(rti_mtu_imp);
O(rts_mtu_imp);
O(sbc_mtu_aba); O(sbc_mtu_abx); O(sbc_mtu_aby); O(sbc_mtu_idx); O(sbc_mtu_idy); O(sbc_mtu_imm); O(sbc_mtu_zpg); O(sbc_mtu_zpx);
O(sec_mtu_imp);
O(sed_mtu_imp);
O(sei_mtu_imp);
O(sta_mtu_aba); O(sta_mtu_abx); O(sta_mtu_aby); O(sta_mtu_idx); O(sta_mtu_idy); O(sta_mtu_zpg); O(sta_mtu_zpx);
O(stx_mtu_aba); O(stx_mtu_zpg); O(stx_mtu_zpy);
O(sty_mtu_aba); O(sty_mtu_zpg); O(sty_mtu_zpx);
O(tax_mtu_imp);
O(tay_mtu_imp);
O(tsx_mtu_imp);
O(txa_mtu_imp);
O(txs_mtu_imp);
O(tya_mtu_imp);
// exceptions
O(reset_mtu);
// undocumented reliable instructions
O(dcp_mtu_aba); O(dcp_mtu_abx); O(dcp_mtu_aby); O(dcp_mtu_idx); O(dcp_mtu_idy); O(dcp_mtu_zpg); O(dcp_mtu_zpx);
O(isb_mtu_aba); O(isb_mtu_abx); O(isb_mtu_aby); O(isb_mtu_idx); O(isb_mtu_idy); O(isb_mtu_zpg); O(isb_mtu_zpx);
O(lax_mtu_aba); O(lax_mtu_aby); O(lax_mtu_idx); O(lax_mtu_idy); O(lax_mtu_zpg); O(lax_mtu_zpy);
O(rla_mtu_aba); O(rla_mtu_abx); O(rla_mtu_aby); O(rla_mtu_idx); O(rla_mtu_idy); O(rla_mtu_zpg); O(rla_mtu_zpx);
O(rra_mtu_aba); O(rra_mtu_abx); O(rra_mtu_aby); O(rra_mtu_idx); O(rra_mtu_idy); O(rra_mtu_zpg); O(rra_mtu_zpx);
O(sax_mtu_aba); O(sax_mtu_idx); O(sax_mtu_zpg); O(sax_mtu_zpy);
O(sbx_mtu_imm);
O(sha_mtu_aby); O(sha_mtu_idy);
O(shs_mtu_aby);
O(shx_mtu_aby);
O(shy_mtu_abx);
O(slo_mtu_aba); O(slo_mtu_abx); O(slo_mtu_aby); O(slo_mtu_idx); O(slo_mtu_idy); O(slo_mtu_zpg); O(slo_mtu_zpx);
O(sre_mtu_aba); O(sre_mtu_abx); O(sre_mtu_aby); O(sre_mtu_idx); O(sre_mtu_idy); O(sre_mtu_zpg); O(sre_mtu_zpx);
// undocumented unreliable instructions
// behaviour differs between visual6502 and online docs, which
// is a clear sign reliability is not to be expected
// implemented version follows visual6502
O(anc_mtu_imm);
O(ane_mtu_imm);
O(arr_mtu_imm);
O(asr_mtu_imm);
O(las_mtu_aby);
O(lxa_mtu_imm);
// nop variants
O(nop_mtu_imm); O(nop_mtu_aba); O(nop_mtu_abx); O(nop_mtu_zpg); O(nop_mtu_zpx);
// system killers
O(kil_mtu_non);
#undef O
};
DECLARE_DEVICE_TYPE(M6502MTU, m6502mtu_device);
#endif // MAME_CPU_M6502_M6502MTU_H

File diff suppressed because it is too large Load Diff

View File

@ -548,6 +548,8 @@ uint8_t upd765_family_device::fifo_r()
uint8_t r = 0xff;
switch(main_phase) {
case PHASE_CMD:
if(machine().side_effects_disabled())
return 0x00;
if(command_pos)
fifo_w(0xff);
LOGFIFO("fifo_r in command phase\n");

View File

@ -102,6 +102,7 @@ const double XTAL::known_xtals[] = {
3'579'000, /* 3.579_MHz_XTAL BeebOPL */
3'579'545, /* 3.579545_MHz_XTAL NTSC color subcarrier, extremely common, used on 100's of PCBs (Keytronic custom part #48-300-010 is equivalent) */
3'579'575, /* 3.579575_MHz_XTAL Atari 2600 NTSC */
3'680'000, /* 3.68_MHz_XTAL Resonator - Baud rate clock for the 6551 in the MTU-130 */
3'686'400, /* 3.6864_MHz_XTAL Baud rate clock for MC68681 and similar UARTs */
3'840'000, /* 3.84_MHz_XTAL Fairlight CMI Alphanumeric Keyboard */
3'900'000, /* 3.9_MHz_XTAL Resonator - Used on some Fidelity boards */

View File

@ -44838,3 +44838,6 @@ sc203 // SC203 - Modular Z180 Computer
@source:vtech/phusion.cpp
phusion //
@source:misc/mtu130.cpp
mtu130

590
src/mame/misc/mtu130.cpp Normal file
View File

@ -0,0 +1,590 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
// Micro Technology Unlimited MTU-130
// Silently boots to floppy, so nothing will happen if you don't have
// a bootable disk in the drive.
// Unimplemented:
// - MTUTAPE, a kind of digital tape?
// - MTUNET, some proprietary network
// - EPROM support (we don't have any image, maps at c000+)
// - Sound on user via cb2, it's weird
// - Light pen, need working demo code
// Unimplemented extension boards:
// - DATAMOVER, a 68k-based board, used by BASIC 1.5 to accelerate floating point operations
// - PROGRAMMOVER, a z80-based board
// Need to add the extra PROMs once they're dumped.
// Note that we hardcoded the ram in bank 3 BASIC 1.5 needs, it should
// be added by DATAMOVER (or PROGRAMMOVER after some reconfiguration).
// Probable bug somewhere making the BASIC (light pen, game) demos
// fail in the demonstration disk, possibly in the customized 6502
// core.
#include "emu.h"
#include "cpu/m6502/m6502mtu.h"
#include "imagedev/floppy.h"
#include "machine/6522via.h"
#include "machine/input_merger.h"
#include "machine/mos6551.h"
#include "machine/upd765.h"
#include "bus/rs232/rs232.h"
#include "sound/dac.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
class mtu130_state: public driver_device
{
public:
mtu130_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_user_6522(*this, "user_6522"),
m_sys1_6522(*this, "sys1_6522"),
m_sys2_6522(*this, "sys2_6522"),
m_acia(*this, "acia"),
m_irq_merger(*this, "irq_merger"),
m_rs232(*this, "rs232"),
m_fdc(*this, "fdc"),
m_floppy(*this, "fdc:%d", 0U),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_dac(*this, "dac"),
m_speaker(*this, "mono"),
m_io_view(*this, "io_view"),
m_se_view(*this, "sw_view"),
m_rom_view(*this, "rom_view"),
m_rof_view(*this, "rof_view"),
m_mainram(*this, "mainram"),
m_fdcram(*this, "fdcram"),
m_videoram(*this, "videoram"),
m_keyboard(*this, "K%X", 0L),
m_keyboard_meta(*this, "KM")
{ }
void mtu130(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(nmi_w);
DECLARE_INPUT_CHANGED_MEMBER(reset_w);
DECLARE_INPUT_CHANGED_MEMBER(break_w);
protected:
virtual void machine_start() override;
virtual void video_start() override;
private:
required_device<m6502mtu_device> m_maincpu;
required_device<via6522_device> m_user_6522;
required_device<via6522_device> m_sys1_6522;
required_device<via6522_device> m_sys2_6522;
required_device<mos6551_device> m_acia;
required_device<input_merger_device> m_irq_merger;
required_device<rs232_port_device> m_rs232;
required_device<upd765a_device> m_fdc;
required_device_array<floppy_connector, 4> m_floppy;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<dac_byte_interface> m_dac;
required_device<speaker_device> m_speaker;
memory_view m_io_view;
memory_view m_se_view;
memory_view m_rom_view;
memory_view m_rof_view;
required_shared_ptr<u8> m_mainram;
required_shared_ptr<u8> m_fdcram;
required_shared_ptr<u8> m_videoram;
required_ioport_array<16> m_keyboard;
required_ioport m_keyboard_meta;
uint16_t m_dma_adr;
u8 m_keyboard_col;
u8 m_dac_level;
u8 m_cpuid;
bool m_dma_direction;
bool m_video_unblank;
bool m_video_bw;
bool m_fdc_irq_enabled;
static void floppies(device_slot_interface &device);
void map(address_map &map);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
u8 fdc_ctrl_r();
void fdc_ctrl_w(u8 data);
void fdc_irq_w(int state);
void dma_adr_w(u8 data);
DECLARE_WRITE_LINE_MEMBER(dma_drq_w);
void keyboard_col_clear_w(u8);
void user_cb2_w(int line);
void sys1_pb_w(u8 data);
u8 sys1_pa_r();
void sys1_ca2_w(int line);
void sys2_pa_w(u8 data);
void cpuid_reset_w(u8);
u8 cpuid_r();
void io_enable_w(u8);
void io_disable_w(u8);
};
void mtu130_state::machine_start()
{
m_dma_adr = 0;
m_dma_direction = false;
m_keyboard_col = 0;
m_dac_level = 0x80;
m_cpuid = 0;
m_video_unblank = true;
m_video_bw = true;
m_fdc_irq_enabled = false;
save_item(NAME(m_dma_adr));
save_item(NAME(m_dma_direction));
save_item(NAME(m_keyboard_col));
save_item(NAME(m_dac_level));
save_item(NAME(m_cpuid));
save_item(NAME(m_video_unblank));
save_item(NAME(m_video_bw));
save_item(NAME(m_fdc_irq_enabled));
m_fdc->set_rate(500000);
m_io_view.select(1);
m_se_view.select(0);
m_rom_view.disable();
m_rof_view.disable();
}
void mtu130_state::video_start()
{
m_palette->set_pen_color(0, 0, 0, 0);
m_palette->set_pen_color(1, 85, 85, 85);
m_palette->set_pen_color(2, 170, 170, 170);
m_palette->set_pen_color(3, 255, 255, 255);
}
uint32_t mtu130_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if(m_video_unblank && m_video_bw) {
int x0 = cliprect.left() - 120;
int x1 = cliprect.right() - 120;
for(int y = cliprect.top(); y <= cliprect.bottom(); y++) {
const u8 *src = m_videoram + 60 * y + (x0 >> 3);
u16 *dest = &bitmap.pix(y, cliprect.left());
u8 v = 0;
if(x0 & 7)
v = *src++;
for(int x = x0; x <= x1; x++) {
if(!(x & 7))
v = *src++;
*dest++ = ((v >> (7 - (x & 7))) & 1) ? 3 : 0;
}
}
} else if(m_video_unblank) {
int x0 = cliprect.left() - 120;
int x1 = cliprect.right() - 120;
for(int y = cliprect.top(); y <= cliprect.bottom(); y++) {
const u8 *src = m_videoram + 60 * y + (x0 >> 4);
u16 *dest = &bitmap.pix(y, cliprect.left());
u8 v = 0;
if(x0 & 15)
v = *src++;
for(int x = x0; x <= x1; x++) {
if(!(x & 15))
v = *src++;
*dest++ = (v >> (6 - 2*((x >> 1) & 3))) & 3;
}
}
} else
bitmap.fill(0, cliprect);
return 0;
}
u8 mtu130_state::fdc_ctrl_r()
{
return m_fdc->get_irq() ? 0x00 : 0x80;
}
void mtu130_state::fdc_ctrl_w(u8 data)
{
m_dma_direction = data & 1;
if(data & 2)
m_rof_view.select(1);
else
m_rof_view.disable();
m_fdc_irq_enabled = data & 4;
m_irq_merger->in_w<0>(m_fdc_irq_enabled && m_fdc->get_irq());
}
void mtu130_state::fdc_irq_w(int state)
{
m_irq_merger->in_w<0>(m_fdc_irq_enabled && state);
}
void mtu130_state::dma_adr_w(u8 data)
{
m_dma_adr = data << 6;
}
WRITE_LINE_MEMBER(mtu130_state::dma_drq_w)
{
while(m_fdc->get_drq()) {
if(m_dma_direction) {
// Read from floppy
u8 data = m_fdc->dma_r();
m_fdcram[m_dma_adr & 0x3fff] = data;
m_dma_adr ++;
} else {
// Write to floppy
u8 data = m_fdcram[m_dma_adr & 0x3fff];
m_fdc->dma_w(data);
m_dma_adr ++;
}
}
}
void mtu130_state::cpuid_reset_w(u8)
{
m_cpuid = 0;
}
u8 mtu130_state::cpuid_r()
{
static u8 cpuid[] = { 0,
0, 0, 0, 0, 0, // Vendor
0, 0, 0, 0, 0, // Group
0, 0, 1, 7, 5, // User, BASIC and others tend to check that one
};
u8 res = cpuid[m_cpuid & 15];
m_cpuid++;
return res;
}
void mtu130_state::user_cb2_w(int line)
{
logerror("%s user cb2 %d\n", machine().time().to_string(), line);
}
void mtu130_state::sys1_pb_w(u8 data)
{
m_maincpu->set_dbank((~data) & 3);
m_maincpu->set_pbank((~data >> 2) & 3);
if(data & 0x80)
m_rom_view.disable();
else
m_rom_view.select(1);
bool video_bw = data & 0x10;
bool video_unblank = data & 0x20;
if(video_bw != m_video_bw || video_unblank != m_video_unblank) {
m_screen->update_now();
m_video_bw = video_bw;
m_video_unblank = video_unblank;
}
}
u8 mtu130_state::sys1_pa_r()
{
// A capacitor is used to pretend the MOD key is pressed at power-on time.
return m_keyboard[m_keyboard_col & 0xf]->read() |
((m_keyboard_meta->read() & 0x04) || (machine().time().as_double() < 0.1) ? 1 : 0);
}
void mtu130_state::sys2_pa_w(u8 data)
{
m_dac_level = data;
m_dac->write(data);
}
void mtu130_state::sys1_ca2_w(int state)
{
if(state)
m_keyboard_col ++;
}
void mtu130_state::io_enable_w(u8)
{
m_io_view.select(1);
}
void mtu130_state::io_disable_w(u8)
{
m_io_view.disable();
}
INPUT_CHANGED_MEMBER(mtu130_state::nmi_w)
{
m_maincpu->set_input_line(m6502_device::NMI_LINE, newval ? ASSERT_LINE : CLEAR_LINE);
}
INPUT_CHANGED_MEMBER(mtu130_state::reset_w)
{
if(newval == 0)
reset();
}
INPUT_CHANGED_MEMBER(mtu130_state::break_w)
{
m_sys1_6522->write_ca1(newval);
}
void mtu130_state::keyboard_col_clear_w(u8)
{
m_keyboard_col = 0;
}
void mtu130_state::map(address_map &map)
{
map(0x00000, 0x0bfff).ram().share(m_mainram); // Main ram, in a single block
map(0x08000, 0x0bfff).view(m_rom_view); // View to write-protect the top of the main ram
m_rom_view[1](0x08000, 0x0bfff).nopw();
map(0x0be00, 0x0bfff).view(m_io_view); // I/O dynamically overrides part of the main ram
m_io_view[1](0x0be00, 0x0bfff).unmaprw(); // Fully mask out the ram when active
m_io_view[1](0x0bfc3, 0x0bfc3).r(FUNC(mtu130_state::cpuid_r));
m_io_view[1](0x0bfc5, 0x0bfc5).w(FUNC(mtu130_state::keyboard_col_clear_w));
m_io_view[1](0x0bfc7, 0x0bfc7).w(FUNC(mtu130_state::cpuid_reset_w));
m_io_view[1](0x0bfc8, 0x0bfcb).rw(m_acia, FUNC(mos6551_device::read), FUNC(mos6551_device::write));
m_io_view[1](0x0bfd0, 0x0bfdf).m(m_user_6522, FUNC(via6522_device::map));
m_io_view[1](0x0bfe0, 0x0bfef).m(m_sys1_6522, FUNC(via6522_device::map));
m_io_view[1](0x0bff0, 0x0bfff).m(m_sys2_6522, FUNC(via6522_device::map));
map(0x0c000, 0x0ffff).view(m_se_view); // System (fdc)/External view
m_se_view[0](0x0c000, 0x0ffff).ram().share(m_fdcram); // FDC ram is a single 16K block, fully adressible by the dma
m_se_view[0](0x0e000, 0x0ffff).view(m_rof_view); // View to write-protect the top half of the fdc ram
m_rof_view[1](0x0e000, 0x0ffff).nopw();
m_se_view[0](0x0ff00, 0x0ffff).rom().region("ipl", 0).unmapw(); // Bootrom overrides the end of the ram
m_se_view[0](0x0ffe8, 0x0ffef).unmaprw(); // Hole in the prom access for floppy i/o
m_se_view[0](0x0ffe8, 0x0ffe8).rw(FUNC(mtu130_state::fdc_ctrl_r), FUNC(mtu130_state::fdc_ctrl_w));
m_se_view[0](0x0ffea, 0x0ffea).w(FUNC(mtu130_state::dma_adr_w));
m_se_view[0](0x0ffee, 0x0ffef).m(m_fdc, FUNC(upd765a_device::map));
map(0x0fffe, 0x0fffe).w(FUNC(mtu130_state::io_enable_w));
map(0x0ffff, 0x0ffff).w(FUNC(mtu130_state::io_disable_w));
map(0x1c000, 0x1ffff).ram().share(m_videoram); // 16k of video ram
map(0x30000, 0x3ffff).ram(); // Basic 1.5 wants more ram, comes from an extension board
}
void mtu130_state::floppies(device_slot_interface &device)
{
device.option_add("8ssdd", FLOPPY_8_SSDD);
device.option_add("8dsdd", FLOPPY_8_DSDD);
}
void mtu130_state::mtu130(machine_config &config)
{
M6502MTU(config, m_maincpu, 10_MHz_XTAL/10);
m_maincpu->set_addrmap(AS_PROGRAM, &mtu130_state::map);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// HSync is between 40 and 79, VSync between 256 and 259, boundaries included
m_screen->set_raw(10_MHz_XTAL, 620, 120, 600, 269, 0, 256);
m_screen->set_screen_update(FUNC(mtu130_state::screen_update));
m_screen->set_palette(m_palette);
m_screen->screen_vblank().set(m_sys2_6522, FUNC(via6522_device::write_ca2));
PALETTE(config, m_palette).set_entries(4);
MOS6522(config, m_user_6522, 10_MHz_XTAL/10);
m_user_6522->irq_handler().set(m_irq_merger, FUNC(input_merger_device::in_w<1>));
m_user_6522->cb2_handler().set(FUNC(mtu130_state::user_cb2_w));
MOS6522(config, m_sys1_6522, 10_MHz_XTAL/10);
m_sys1_6522->irq_handler().set(m_irq_merger, FUNC(input_merger_device::in_w<2>));
m_sys1_6522->readpa_handler().set(FUNC(mtu130_state::sys1_pa_r));
m_sys1_6522->writepb_handler().set(FUNC(mtu130_state::sys1_pb_w));
m_sys1_6522->ca2_handler().set(FUNC(mtu130_state::sys1_ca2_w));
MOS6522(config, m_sys2_6522, 10_MHz_XTAL/10);
m_sys2_6522->irq_handler().set(m_irq_merger, FUNC(input_merger_device::in_w<3>));
m_sys2_6522->writepa_handler().set(FUNC(mtu130_state::sys2_pa_w));
MOS6551(config, m_acia, 3.68_MHz_XTAL/2);
m_acia->irq_handler().set(m_irq_merger, FUNC(input_merger_device::in_w<4>));
m_acia->txd_handler().set(m_rs232, FUNC(rs232_port_device::write_txd));
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
m_rs232->rxd_handler().set(m_acia, FUNC(mos6551_device::write_rxd));
m_rs232->dcd_handler().set(m_acia, FUNC(mos6551_device::write_dcd));
m_rs232->dsr_handler().set(m_acia, FUNC(mos6551_device::write_dsr));
m_rs232->cts_handler().set(m_acia, FUNC(mos6551_device::write_cts));
INPUT_MERGER_ANY_HIGH(config, m_irq_merger).output_handler().set_inputline(m_maincpu, m6502_device::IRQ_LINE);
UPD765A(config, m_fdc, 10_MHz_XTAL/10*8, true, true); // *8 done through a PLL
m_fdc->intrq_wr_callback().set(FUNC(mtu130_state::fdc_irq_w));
m_fdc->drq_wr_callback().set(FUNC(mtu130_state::dma_drq_w));
FLOPPY_CONNECTOR(config, m_floppy[0], mtu130_state::floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
FLOPPY_CONNECTOR(config, m_floppy[1], mtu130_state::floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
FLOPPY_CONNECTOR(config, m_floppy[2], mtu130_state::floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
FLOPPY_CONNECTOR(config, m_floppy[3], mtu130_state::floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, m_speaker, 1.0);
SPEAKER(config, m_speaker).front_center();
}
static INPUT_PORTS_START(mtu130)
PORT_START("K0")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("RIGHT SHIFT")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("LEFT SHIFT")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("CTRL")
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("REPEAT")
PORT_START("K1")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("Keypad -")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
PORT_START("K2")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("Keypad 6")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
PORT_START("K3")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("Keypad +")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
PORT_START("K4")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_NAME("Keypad /")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
PORT_START("K5")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Keypad 5")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
PORT_START("K6")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME("Keypad *")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
PORT_START("K7")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("Keypad 9")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
PORT_START("K8")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF2")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
PORT_START("K9")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Keypad 1")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
PORT_START("KA")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Keypad 4")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
PORT_START("KB")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("Keypad 3")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Keypad ENTER")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
PORT_START("KC")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("Keypad 7")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
PORT_START("KD")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF1")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
PORT_START("KE")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("Keypad 8")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("RETURN")
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LINE FEED")
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
PORT_START("KF")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Keypad 2")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("Keypad 0")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_NAME("Keypad .")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RUBOUT")
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
PORT_START("KM")
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("INT") PORT_CHANGED_MEMBER(DEVICE_SELF, mtu130_state, nmi_w, 0)
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("MOD")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CHANGED_MEMBER(DEVICE_SELF, mtu130_state, reset_w, 0)
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("BREAK") PORT_CHANGED_MEMBER(DEVICE_SELF, mtu130_state, break_w, 0)
INPUT_PORTS_END
ROM_START(mtu130)
ROM_REGION(0x800, "ipl", 0)
ROM_LOAD("ipl_prom.u6", 0, 0x100, CRC(edb1525a) SHA1(a16cce3b096f0fea9ac5c6993ee4241e4af1efde))
ROM_END
COMP(1981, mtu130, 0, 0, mtu130, mtu130, mtu130_state, empty_init, "Micro Technology Unlimited", "MTU-130", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND)