From 3170abda99ac64c48f09d327447e6d6f298c8127 Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 17 Sep 2024 11:49:03 +0200 Subject: [PATCH 01/13] hitachi/bmjr.cpp: implement MP-1710 color features --- src/mame/hitachi/bmjr.cpp | 134 ++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 48 deletions(-) diff --git a/src/mame/hitachi/bmjr.cpp b/src/mame/hitachi/bmjr.cpp index 220732ac529..0d2e1df8e9b 100644 --- a/src/mame/hitachi/bmjr.cpp +++ b/src/mame/hitachi/bmjr.cpp @@ -6,7 +6,7 @@ Basic Master Jr. (MB-6885) (c) 1982? Hitachi TODO: - Memory view control at $efd0; -- Color adapter (Jr specific); +- Convert MP-1710 color adapter to device (bmjr specific); - Sound DAC; - Keyboard eats inputs if typed relatively fast (verify, particularly with emu.keypost); - Break key is unemulated (tied with the NMI); @@ -18,7 +18,7 @@ Basic Master Jr. (MB-6885) (c) 1982? Hitachi #include "cpu/m6800/m6800.h" #include "imagedev/cassette.h" #include "machine/timer.h" -#include "sound/beep.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" @@ -33,14 +33,16 @@ class bmjr_state : public driver_device : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_cass(*this, "cassette") - , m_beep(*this, "beeper") - , m_workram(*this, "work_ram") + , m_work_ram(*this, "work_ram") , m_p_chargen(*this, "chargen") , m_io_keyboard(*this, "KEY%d", 0U) { } void bmjr(machine_config &config); +protected: + virtual void video_start() override; + virtual void video_reset() override; private: u8 key_r(); void key_w(u8 data); @@ -50,11 +52,11 @@ class bmjr_state : public driver_device void tape_w(u8 data); u8 tape_stop_r(); u8 tape_start_r(); - void xor_display_w(u8 data); + void screen_reverse_w(u8 data); u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void main_map(address_map &map); bool m_tape_switch = 0; - u8 m_xor_display = 0U; + u8 m_screen_reverse = 0U; u8 m_key_select = 0U; u16 m_casscnt = 0U; bool m_cassold = 0, m_cassbit = 0; @@ -63,43 +65,58 @@ class bmjr_state : public driver_device virtual void machine_reset() override; required_device m_maincpu; required_device m_cass; - required_device m_beep; - required_shared_ptr m_workram; + required_shared_ptr m_work_ram; required_region_ptr m_p_chargen; required_ioport_array<16> m_io_keyboard; + + std::unique_ptr m_color_ram; + u8 m_color_mode = 0; + u8 m_tile_latch = 0; + u8 m_screen_mode = 0; + void mp1710_map(address_map &map); + void screen_mode_w(u8 data); }; +void bmjr_state::video_start() +{ + m_color_ram = std::make_unique(0x300); + save_item(NAME(m_screen_mode)); + save_item(NAME(m_screen_reverse)); + save_item(NAME(m_color_mode)); + save_pointer(NAME(m_color_ram), 0x300); +} +void bmjr_state::video_reset() +{ + m_tile_latch = 0x07; + m_screen_reverse = 0; + m_screen_mode = 0; +} u32 bmjr_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - u8 fg=4; - u16 sy=0,ma=0x100; - u8 const inv = (m_xor_display) ? 0xff : 0; + const u8 fg_shift = m_screen_reverse ? 4 : 0; + const u8 bg_shift = m_screen_reverse ? 0 : 4; + const u16 screen_bank_offset = 0x900 + ((m_screen_mode & 0xf) << 9); - for(u8 y = 0; y < 24; y++ ) + // TODO: convert to scanline based renderer + for(int y = cliprect.min_y; y <= cliprect.max_y; y++ ) { - for (u8 ra = 0; ra < 8; ra++) + for (int x = cliprect.min_x; x <= cliprect.max_x; x+= 8) { - u16 *p = &bitmap.pix(sy++); - - for (u16 x = ma; x < ma + 32; x++) + const u16 tile_offset = (x >> 3) + ((y >> 3) * 32); + const u16 tile = m_work_ram[0x100 + tile_offset] << 3; + const u8 gfx_data = BIT(m_screen_mode, 7) ? m_work_ram[screen_bank_offset + (x >> 3) + (y * 32)] : m_p_chargen[tile | (y & 7)]; + const u8 attr = BIT(m_color_mode, 0) ? m_color_ram[tile_offset] : 0x07; + const u8 fg_color = (attr >> fg_shift) & 7; + const u8 bg_color = (attr >> bg_shift) & 7; + + for (int xi = 0; xi < 8; xi++) { - u8 const chr = m_workram[x]; - u8 const gfx = m_p_chargen[(chr<<3) | ra] ^ inv; - - /* Display a scanline of a character */ - *p++ = BIT(gfx, 7) ? fg : 0; - *p++ = BIT(gfx, 6) ? fg : 0; - *p++ = BIT(gfx, 5) ? fg : 0; - *p++ = BIT(gfx, 4) ? fg : 0; - *p++ = BIT(gfx, 3) ? fg : 0; - *p++ = BIT(gfx, 2) ? fg : 0; - *p++ = BIT(gfx, 1) ? fg : 0; - *p++ = BIT(gfx, 0) ? fg : 0; + const u8 pen = BIT(gfx_data, 7 - xi) ? fg_color : bg_color; + bitmap.pix(y, x + xi) = pen; } } - ma+=32; } return 0; @@ -140,8 +157,7 @@ TIMER_DEVICE_CALLBACK_MEMBER( bmjr_state::kansas_r ) m_cassbit = (m_casscnt < 12) ? 1 : 0; m_casscnt = 0; } - else - if (m_casscnt > 32) + else if (m_casscnt > 32) { m_casscnt = 32; m_cassbit = 0; @@ -160,7 +176,7 @@ void bmjr_state::tape_w(u8 data) if(!m_tape_switch) { // TODO: to five bit DAC, --xx xxx- - m_beep->set_state(!BIT(data, 7)); + //m_beep->set_state(!BIT(data, 7)); } else { @@ -184,9 +200,27 @@ u8 bmjr_state::tape_start_r() return 0x01; } -void bmjr_state::xor_display_w(u8 data) +void bmjr_state::screen_reverse_w(u8 data) +{ + m_screen_reverse = data; +} + +void bmjr_state::screen_mode_w(u8 data) { - m_xor_display = data; + m_screen_mode = data; +} + +void bmjr_state::mp1710_map(address_map &map) +{ + map(0x00, 0x00).lrw8( + NAME([this] (offs_t offset) { return m_tile_latch; }), + NAME([this] (offs_t offset, u8 data) { m_tile_latch = data; }) + ); + //map(0x01, 0x01) border color? + map(0x02, 0x02).lrw8( + NAME([this] (offs_t offset) { return m_color_mode; }), + NAME([this] (offs_t offset, u8 data) { m_color_mode = data; }) + ); } void bmjr_state::main_map(address_map &map) @@ -196,6 +230,14 @@ void bmjr_state::main_map(address_map &map) //0x0900, 0x20ff vram, modes 0x40 / 0xc0 //0x2100, 0x38ff vram, modes 0x44 / 0xcc map(0x0000, 0xafff).ram().share("work_ram"); + // overlay for MP-1710 tile latches + map(0x0100, 0x03ff).lrw8( + NAME([this] (offs_t offset) { return m_work_ram[offset + 0x100]; }), + NAME([this] (offs_t offset, u8 data) { + m_work_ram[offset + 0x100] = data; + m_color_ram[offset] = m_tile_latch; + }) + ); map(0xb000, 0xdfff).rom().region("basic", 0); map(0xe000, 0xe7ff).rom().region("printer", 0); // 0xe800-0xedff expansion I/O @@ -204,17 +246,18 @@ void bmjr_state::main_map(address_map &map) // map(0xe890, 0xe890) W MP-1710 tile color // map(0xe891, 0xe891) W MP-1710 background color // map(0xe892, 0xe892) W MP-1710 monochrome / color setting + map(0xe890, 0xe89f).m(*this, FUNC(bmjr_state::mp1710_map)); // 0xee00-0xefff system I/O map(0xee00, 0xee00).r(FUNC(bmjr_state::tape_stop_r)); //R stop tape map(0xee20, 0xee20).r(FUNC(bmjr_state::tape_start_r)); //R start tape - map(0xee40, 0xee40).w(FUNC(bmjr_state::xor_display_w)); //W Picture reverse + map(0xee40, 0xee40).w(FUNC(bmjr_state::screen_reverse_w)); //W Picture reverse map(0xee80, 0xee80).rw(FUNC(bmjr_state::tape_r), FUNC(bmjr_state::tape_w));//RW tape input / output map(0xeec0, 0xeec0).rw(FUNC(bmjr_state::key_r), FUNC(bmjr_state::key_w));//RW keyboard map(0xef00, 0xef00).r(FUNC(bmjr_state::ff_r)); // R timer map(0xef40, 0xef40).r(FUNC(bmjr_state::ff_r)); // R unknown map(0xef80, 0xef80).r(FUNC(bmjr_state::unk_r)); // TODO: to break key // map(0xefd0, 0xefd0) memory bank + timer control -// map(0xefe0, 0xefe0) W screen mode + map(0xefe0, 0xefe0).w(FUNC(bmjr_state::screen_mode_w)); map(0xf000, 0xffff).rom().region("monitor", 0); } @@ -343,7 +386,6 @@ GFXDECODE_END void bmjr_state::machine_start() { save_item(NAME(m_tape_switch)); - save_item(NAME(m_xor_display)); save_item(NAME(m_key_select)); save_item(NAME(m_casscnt)); save_item(NAME(m_cassold)); @@ -352,9 +394,8 @@ void bmjr_state::machine_start() void bmjr_state::machine_reset() { - m_beep->set_state(0); + //m_beep->set_state(0); m_tape_switch = 0; - m_xor_display = 0; m_key_select = 0; m_cass->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR); } @@ -366,7 +407,10 @@ void bmjr_state::bmjr(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &bmjr_state::main_map); m_maincpu->set_vblank_int("screen", FUNC(bmjr_state::irq0_line_hold)); - /* video hardware */ + CASSETTE(config, m_cass); + m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); + TIMER(config, "kansas_r").configure_periodic(FUNC(bmjr_state::kansas_r), attotime::from_hz(40000)); + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen.set_refresh_hz(60); screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ @@ -378,14 +422,8 @@ void bmjr_state::bmjr(machine_config &config) PALETTE(config, "palette", palette_device::BRG_3BIT); GFXDECODE(config, "gfxdecode", "palette", gfx_bmjr); - /* Audio */ SPEAKER(config, "mono").front_center(); - BEEP(config, "beeper", 1200).add_route(ALL_OUTPUTS, "mono", 0.50); // guesswork - - /* Devices */ - CASSETTE(config, m_cass); - m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); - TIMER(config, "kansas_r").configure_periodic(FUNC(bmjr_state::kansas_r), attotime::from_hz(40000)); + // TODO: DAC_5BIT_? } /* ROM definition */ @@ -409,4 +447,4 @@ ROM_END // 1979 Basic Master MB-6880 (retroactively Level 1) // 1979 Basic Master Level 2 MB-6880L2 // 1980 Basic Master Level 2 II MB-6881 -COMP( 1981, bmjr, 0, 0, bmjr, bmjr, bmjr_state, empty_init, "Hitachi", "Basic Master Jr. (MB-6885)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) +COMP( 1981, bmjr, 0, 0, bmjr, bmjr, bmjr_state, empty_init, "Hitachi", "Basic Master Jr. (MB-6885)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) From e885371543af23a7502324c112774ee4bc81e131 Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 17 Sep 2024 11:20:29 -0400 Subject: [PATCH 02/13] wy85: Add beeper --- src/devices/bus/wysekbd/wysegakb.cpp | 4 ++-- src/mame/wyse/wy85.cpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/devices/bus/wysekbd/wysegakb.cpp b/src/devices/bus/wysekbd/wysegakb.cpp index 4397805a87a..7edc3ea2f39 100644 --- a/src/devices/bus/wysekbd/wysegakb.cpp +++ b/src/devices/bus/wysekbd/wysegakb.cpp @@ -243,8 +243,8 @@ ioport_constructor wy85_keyboard_device::device_input_ports() const u8 wy85_keyboard_device::wysekbd_get_id() { - // Apparently doesn't have an ID - return 0xff; + // Original LSTTL version definitely lacks an ID; gate array version has this ID according to https://geekhack.org/index.php?topic=51079.0 + return 0x60 ^ 0xff; } diff --git a/src/mame/wyse/wy85.cpp b/src/mame/wyse/wy85.cpp index f96968eb322..a2d48653e00 100644 --- a/src/mame/wyse/wy85.cpp +++ b/src/mame/wyse/wy85.cpp @@ -16,8 +16,10 @@ #include "cpu/mcs51/mcs51.h" #include "machine/er1400.h" #include "machine/mc68681.h" +#include "sound/beep.h" #include "video/scn2674.h" #include "screen.h" +#include "speaker.h" namespace { @@ -32,6 +34,7 @@ class wy85_state : public driver_device , m_kybd(*this, "kybd") , m_pvtc(*this, "pvtc") , m_duart(*this, "duart") + , m_beeper(*this, "beeper") , m_comm(*this, "comm") , m_pr(*this, "pr") , m_chargen(*this, "chargen") @@ -82,6 +85,7 @@ class wy85_state : public driver_device required_device m_kybd; required_device m_pvtc; required_device m_duart; + required_device m_beeper; required_device m_comm; required_device m_pr; @@ -229,6 +233,8 @@ void wy85_state::p1_w(u8 data) m_pr->write_rts(BIT(data, 3)); m_clr_rb = !BIT(data, 1); + + m_beeper->set_state(BIT(data, 5)); } u8 wy85_state::p3_r() @@ -342,6 +348,9 @@ void wy85_state::wy85(machine_config &config) m_duart->outport_cb().set(FUNC(wy85_state::duart_op_w)); m_duart->irq_cb().set_inputline(m_maincpu, MCS51_INT1_LINE); + SPEAKER(config, "speaker").front_center(); + BEEP(config, m_beeper, 1000).add_route(ALL_OUTPUTS, "speaker", 0.10); // FIXME: not accurate; actually uses same circuit as WY-50 with 74LS14 Schmitt triggers and discrete components + RS232_PORT(config, m_comm, default_rs232_devices, nullptr); // RS423 port, also RS232 compatible m_comm->rxd_handler().set(m_duart, FUNC(scn2681_device::rx_a_w)); m_comm->cts_handler().set(m_duart, FUNC(scn2681_device::ip0_w)); @@ -369,4 +378,4 @@ ROM_END } // anonymous namespace -COMP(1985, wy85, 0, 0, wy85, wy85, wy85_state, empty_init, "Wyse Technology", "WY-85", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND) +COMP(1985, wy85, 0, 0, wy85, wy85, wy85_state, empty_init, "Wyse Technology", "WY-85", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND) From 5a700fc2c9ba78c68e15333f2b72f89a92d7ff38 Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 17 Sep 2024 19:54:22 +0200 Subject: [PATCH 03/13] hitachi/bmjr.cpp: implement memory views --- src/mame/commodore/c65.cpp | 4 -- src/mame/hitachi/bmjr.cpp | 80 ++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/src/mame/commodore/c65.cpp b/src/mame/commodore/c65.cpp index 822205db28b..0ae69cadd4d 100644 --- a/src/mame/commodore/c65.cpp +++ b/src/mame/commodore/c65.cpp @@ -1411,7 +1411,6 @@ void c65_state::cpu_w(uint8_t data) void c65_state::c65(machine_config &config) { - /* basic machine hardware */ M4510(config, m_maincpu, MAIN_C65_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &c65_state::c65_map); m_maincpu->read_callback().set(FUNC(c65_state::cpu_r)); @@ -1443,8 +1442,6 @@ void c65_state::c65(machine_config &config) // m_cia[1]->pa_rd_callback().set(FUNC(c65_state::c65_cia1_port_a_r)); m_cia[1]->pa_wr_callback().set(FUNC(c65_state::cia1_porta_w)); - - /* video hardware */ SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_screen_update(FUNC(c65_state::screen_update)); // TODO: stub parameters @@ -1456,7 +1453,6 @@ void c65_state::c65(machine_config &config) PALETTE(config, m_palette, FUNC(c65_state::palette_init), 0x100); - /* sound hardware */ SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); // 8580 SID diff --git a/src/mame/hitachi/bmjr.cpp b/src/mame/hitachi/bmjr.cpp index 0d2e1df8e9b..51191ac5061 100644 --- a/src/mame/hitachi/bmjr.cpp +++ b/src/mame/hitachi/bmjr.cpp @@ -34,6 +34,9 @@ class bmjr_state : public driver_device , m_maincpu(*this, "maincpu") , m_cass(*this, "cassette") , m_work_ram(*this, "work_ram") + , m_basic_view(*this, "basic_view") + , m_printer_view(*this, "printer_view") + , m_monitor_view(*this, "monitor_view") , m_p_chargen(*this, "chargen") , m_io_keyboard(*this, "KEY%d", 0U) { } @@ -66,13 +69,20 @@ class bmjr_state : public driver_device required_device m_maincpu; required_device m_cass; required_shared_ptr m_work_ram; + memory_view m_basic_view; + memory_view m_printer_view; + memory_view m_monitor_view; required_region_ptr m_p_chargen; required_ioport_array<16> m_io_keyboard; + u8 m_bank_mode = 0U; + u8 bank_mode_r(); + void bank_mode_w(u8 data); + std::unique_ptr m_color_ram; - u8 m_color_mode = 0; - u8 m_tile_latch = 0; - u8 m_screen_mode = 0; + u8 m_color_mode = 0U; + u8 m_tile_latch = 0U; + u8 m_screen_mode = 0U; void mp1710_map(address_map &map); void screen_mode_w(u8 data); }; @@ -200,11 +210,46 @@ u8 bmjr_state::tape_start_r() return 0x01; } +u8 bmjr_state::bank_mode_r() +{ + return m_bank_mode; +} + +/* + * ---x ---- timer enable? + * ---- -x-- maps $f000-$ffff to work RAM + * ---- --x- maps $e000-$edff to work RAM + * ---- ---x maps $b000-$dfff to work RAM + */ +void bmjr_state::bank_mode_w(u8 data) +{ + m_bank_mode = data; + if (BIT(data, 0)) + m_basic_view.disable(); + else + m_basic_view.select(0); + + if (BIT(data, 1)) + m_printer_view.disable(); + else + m_printer_view.select(0); + + if (BIT(data, 2)) + m_monitor_view.disable(); + else + m_monitor_view.select(0); +} + void bmjr_state::screen_reverse_w(u8 data) { m_screen_reverse = data; } +/* + * x--- ---- enable bitmap mode + * -?-- ---- + * ---- xxxx bank base for bitmap mode + */ void bmjr_state::screen_mode_w(u8 data) { m_screen_mode = data; @@ -226,10 +271,7 @@ void bmjr_state::mp1710_map(address_map &map) void bmjr_state::main_map(address_map &map) { map.unmap_value_high(); - //0x0100, 0x03ff basic vram - //0x0900, 0x20ff vram, modes 0x40 / 0xc0 - //0x2100, 0x38ff vram, modes 0x44 / 0xcc - map(0x0000, 0xafff).ram().share("work_ram"); + map(0x0000, 0xffff).ram().share("work_ram"); // overlay for MP-1710 tile latches map(0x0100, 0x03ff).lrw8( NAME([this] (offs_t offset) { return m_work_ram[offset + 0x100]; }), @@ -238,16 +280,14 @@ void bmjr_state::main_map(address_map &map) m_color_ram[offset] = m_tile_latch; }) ); - map(0xb000, 0xdfff).rom().region("basic", 0); - map(0xe000, 0xe7ff).rom().region("printer", 0); + map(0xb000, 0xdfff).view(m_basic_view); + m_basic_view[0](0xb000, 0xdfff).rom().region("basic", 0); + map(0xe000, 0xefff).view(m_printer_view); + m_printer_view[0](0xe000, 0xe7ff).rom().region("printer", 0); // 0xe800-0xedff expansion I/O - // TODO: view selectable thru $efd0 // map(0xe800, 0xe803) 6820 or 6821 PIA -// map(0xe890, 0xe890) W MP-1710 tile color -// map(0xe891, 0xe891) W MP-1710 background color -// map(0xe892, 0xe892) W MP-1710 monochrome / color setting - map(0xe890, 0xe89f).m(*this, FUNC(bmjr_state::mp1710_map)); - // 0xee00-0xefff system I/O + m_printer_view[0](0xe890, 0xe89f).m(*this, FUNC(bmjr_state::mp1710_map)); + // 0xee00-0xefff system I/O (ignored by printer view enabled) map(0xee00, 0xee00).r(FUNC(bmjr_state::tape_stop_r)); //R stop tape map(0xee20, 0xee20).r(FUNC(bmjr_state::tape_start_r)); //R start tape map(0xee40, 0xee40).w(FUNC(bmjr_state::screen_reverse_w)); //W Picture reverse @@ -256,9 +296,10 @@ void bmjr_state::main_map(address_map &map) map(0xef00, 0xef00).r(FUNC(bmjr_state::ff_r)); // R timer map(0xef40, 0xef40).r(FUNC(bmjr_state::ff_r)); // R unknown map(0xef80, 0xef80).r(FUNC(bmjr_state::unk_r)); // TODO: to break key -// map(0xefd0, 0xefd0) memory bank + timer control + map(0xefd0, 0xefd0).rw(FUNC(bmjr_state::bank_mode_r), FUNC(bmjr_state::bank_mode_w)); map(0xefe0, 0xefe0).w(FUNC(bmjr_state::screen_mode_w)); - map(0xf000, 0xffff).rom().region("monitor", 0); + map(0xf000, 0xffff).view(m_monitor_view); + m_monitor_view[0](0xf000, 0xffff).rom().region("monitor", 0); } @@ -398,6 +439,11 @@ void bmjr_state::machine_reset() m_tape_switch = 0; m_key_select = 0; m_cass->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR); + m_bank_mode = 0; + m_basic_view.select(0); + m_printer_view.select(0); + m_monitor_view.select(0); + m_maincpu->reset(); } void bmjr_state::bmjr(machine_config &config) From 31efb55ddfa36bf140e54bd5f34d0caad67378fa Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 17 Sep 2024 20:19:18 +0200 Subject: [PATCH 04/13] hitachi/bmjr.cpp: preliminary DAC sound --- src/mame/hitachi/bmjr.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/mame/hitachi/bmjr.cpp b/src/mame/hitachi/bmjr.cpp index 51191ac5061..5da41592624 100644 --- a/src/mame/hitachi/bmjr.cpp +++ b/src/mame/hitachi/bmjr.cpp @@ -5,12 +5,11 @@ Basic Master Jr. (MB-6885) (c) 1982? Hitachi TODO: -- Memory view control at $efd0; -- Convert MP-1710 color adapter to device (bmjr specific); -- Sound DAC; +- Identify and improve Sound DAC details; - Keyboard eats inputs if typed relatively fast (verify, particularly with emu.keypost); - Break key is unemulated (tied with the NMI); -- Downgrade for earlier variants (needs dump first); +- Downgrade for earlier variants (needs dump first), convert MP-1710 color adapter to device + (bmjr specific); **************************************************************************************************/ @@ -18,6 +17,7 @@ Basic Master Jr. (MB-6885) (c) 1982? Hitachi #include "cpu/m6800/m6800.h" #include "imagedev/cassette.h" #include "machine/timer.h" +#include "sound/dac.h" #include "emupal.h" #include "screen.h" @@ -33,6 +33,7 @@ class bmjr_state : public driver_device : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_cass(*this, "cassette") + , m_dac(*this, "dac") , m_work_ram(*this, "work_ram") , m_basic_view(*this, "basic_view") , m_printer_view(*this, "printer_view") @@ -68,6 +69,7 @@ class bmjr_state : public driver_device virtual void machine_reset() override; required_device m_maincpu; required_device m_cass; + required_device m_dac; required_shared_ptr m_work_ram; memory_view m_basic_view; memory_view m_printer_view; @@ -185,8 +187,7 @@ void bmjr_state::tape_w(u8 data) { if(!m_tape_switch) { - // TODO: to five bit DAC, --xx xxx- - //m_beep->set_state(!BIT(data, 7)); + m_dac->write((data >> 1) & 0x1f); } else { @@ -469,7 +470,8 @@ void bmjr_state::bmjr(machine_config &config) GFXDECODE(config, "gfxdecode", "palette", gfx_bmjr); SPEAKER(config, "mono").front_center(); - // TODO: DAC_5BIT_? + // TODO: unknown DAC type, likely connected to discrete circuitry. + DAC_5BIT_BINARY_WEIGHTED(config, m_dac).add_route(ALL_OUTPUTS, "mono", 0.25); } /* ROM definition */ @@ -493,4 +495,4 @@ ROM_END // 1979 Basic Master MB-6880 (retroactively Level 1) // 1979 Basic Master Level 2 MB-6880L2 // 1980 Basic Master Level 2 II MB-6881 -COMP( 1981, bmjr, 0, 0, bmjr, bmjr, bmjr_state, empty_init, "Hitachi", "Basic Master Jr. (MB-6885)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) +COMP( 1981, bmjr, 0, 0, bmjr, bmjr, bmjr_state, empty_init, "Hitachi", "Basic Master Jr. (MB-6885)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) From 4ce2bfcb63a52ddb613fed246a876f6fb275106e Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 17 Sep 2024 20:31:21 +0200 Subject: [PATCH 05/13] hitachi/bmjr.cpp: hookup break key --- src/mame/hitachi/bmjr.cpp | 138 +++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/src/mame/hitachi/bmjr.cpp b/src/mame/hitachi/bmjr.cpp index 5da41592624..6c35fe8df96 100644 --- a/src/mame/hitachi/bmjr.cpp +++ b/src/mame/hitachi/bmjr.cpp @@ -7,7 +7,6 @@ Basic Master Jr. (MB-6885) (c) 1982? Hitachi TODO: - Identify and improve Sound DAC details; - Keyboard eats inputs if typed relatively fast (verify, particularly with emu.keypost); -- Break key is unemulated (tied with the NMI); - Downgrade for earlier variants (needs dump first), convert MP-1710 color adapter to device (bmjr specific); @@ -33,7 +32,7 @@ class bmjr_state : public driver_device : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_cass(*this, "cassette") - , m_dac(*this, "dac") + , m_dac(*this, "dac") , m_work_ram(*this, "work_ram") , m_basic_view(*this, "basic_view") , m_printer_view(*this, "printer_view") @@ -43,6 +42,7 @@ class bmjr_state : public driver_device { } void bmjr(machine_config &config); + DECLARE_INPUT_CHANGED_MEMBER(break_key_pressed); protected: virtual void video_start() override; @@ -51,7 +51,6 @@ class bmjr_state : public driver_device u8 key_r(); void key_w(u8 data); u8 ff_r(); - u8 unk_r(); u8 tape_r(); void tape_w(u8 data); u8 tape_stop_r(); @@ -69,7 +68,7 @@ class bmjr_state : public driver_device virtual void machine_reset() override; required_device m_maincpu; required_device m_cass; - required_device m_dac; + required_device m_dac; required_shared_ptr m_work_ram; memory_view m_basic_view; memory_view m_printer_view; @@ -152,11 +151,6 @@ u8 bmjr_state::ff_r() return 0xff; } -u8 bmjr_state::unk_r() -{ - return 0x30; -} - TIMER_DEVICE_CALLBACK_MEMBER( bmjr_state::kansas_r ) { /* cassette - turn pulses into a bit */ @@ -187,7 +181,7 @@ void bmjr_state::tape_w(u8 data) { if(!m_tape_switch) { - m_dac->write((data >> 1) & 0x1f); + m_dac->write((data >> 1) & 0x1f); } else { @@ -296,92 +290,96 @@ void bmjr_state::main_map(address_map &map) map(0xeec0, 0xeec0).rw(FUNC(bmjr_state::key_r), FUNC(bmjr_state::key_w));//RW keyboard map(0xef00, 0xef00).r(FUNC(bmjr_state::ff_r)); // R timer map(0xef40, 0xef40).r(FUNC(bmjr_state::ff_r)); // R unknown - map(0xef80, 0xef80).r(FUNC(bmjr_state::unk_r)); // TODO: to break key + map(0xef80, 0xef80).portr("BREAK"); map(0xefd0, 0xefd0).rw(FUNC(bmjr_state::bank_mode_r), FUNC(bmjr_state::bank_mode_w)); map(0xefe0, 0xefe0).w(FUNC(bmjr_state::screen_mode_w)); map(0xf000, 0xffff).view(m_monitor_view); m_monitor_view[0](0xf000, 0xffff).rom().region("monitor", 0); } +INPUT_CHANGED_MEMBER(bmjr_state::break_key_pressed) +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? ASSERT_LINE : CLEAR_LINE); +} static INPUT_PORTS_START( bmjr ) PORT_START("KEY0") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_START("KEY1") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("2 \"") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('\"') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 \"") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('\"') PORT_START("KEY2") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_START("KEY3") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_START("KEY4") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_START("KEY5") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("6 &") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 &") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_START("KEY6") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("7 \'") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 \'") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') PORT_START("KEY7") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("8 (") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 (") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_START("KEY8") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("9 )") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 )") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_START("KEY9") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_START("KEY10") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_UNUSED ) - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("@ Up") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('@') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("- =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') + PORT_BIT(0x01,IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(": *") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("@ Up") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('@') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("- =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') PORT_START("KEY11") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("[ Down") PORT_CODE(KEYCODE_OPENBRACE) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('[') - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("^ Right") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('^') + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("[ Down") PORT_CODE(KEYCODE_OPENBRACE) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('[') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("^ Right") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('^') PORT_START("KEY12") - PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_UNUSED) - PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) - PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) - PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(u8"¥ / Left") PORT_CODE(KEYCODE_4_PAD) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"¥ / Left") PORT_CODE(KEYCODE_4_PAD) PORT_START("KEY13") PORT_DIPNAME( 0x01, 0x01, "D" ) @@ -404,10 +402,14 @@ static INPUT_PORTS_START( bmjr ) PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("KEYMOD") /* Note: you should press Normal to return from a Kana state and vice-versa */ - PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(DEF_STR( Normal )) PORT_CODE(KEYCODE_LCONTROL) - PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) - PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Kana Shift") PORT_CODE(KEYCODE_LALT) - PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Kana") PORT_CODE(KEYCODE_RCONTROL) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(DEF_STR( Normal )) PORT_CODE(KEYCODE_LCONTROL) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Kana Shift") PORT_CODE(KEYCODE_LALT) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Kana") PORT_CODE(KEYCODE_RCONTROL) + + PORT_START("BREAK") + PORT_BIT(0x7f, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Break") PORT_CHANGED_MEMBER(DEVICE_SELF, bmjr_state, break_key_pressed, 0) INPUT_PORTS_END static const gfx_layout bmjr_charlayout = @@ -470,7 +472,7 @@ void bmjr_state::bmjr(machine_config &config) GFXDECODE(config, "gfxdecode", "palette", gfx_bmjr); SPEAKER(config, "mono").front_center(); - // TODO: unknown DAC type, likely connected to discrete circuitry. + // TODO: unknown DAC type, likely connected to discrete circuitry. DAC_5BIT_BINARY_WEIGHTED(config, m_dac).add_route(ALL_OUTPUTS, "mono", 0.25); } From df57ed17713a78275d387491b5def582d3d40a0f Mon Sep 17 00:00:00 2001 From: angelosa Date: Tue, 17 Sep 2024 20:36:38 +0200 Subject: [PATCH 06/13] hitachi/bml3.cpp: add note to break key --- src/mame/hitachi/bml3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mame/hitachi/bml3.cpp b/src/mame/hitachi/bml3.cpp index 31047fd8ec6..f3f7c59282e 100644 --- a/src/mame/hitachi/bml3.cpp +++ b/src/mame/hitachi/bml3.cpp @@ -587,6 +587,7 @@ INPUT_PORTS_END INPUT_CHANGED_MEMBER(bml3_state::nmi_button) { + // TODO: isn't this supposed to actually raise an NMI, just like earlier Basic Master LV1/2? m_nmi = newval ? 0x80 : 0; } From 900e2769bfb01201e7348c424eb4ab3088ac36db Mon Sep 17 00:00:00 2001 From: AJR Date: Tue, 17 Sep 2024 21:34:40 -0400 Subject: [PATCH 07/13] wy85: Add character attributes and cursor; tweak some key definitions --- src/devices/bus/wysekbd/wysegakb.cpp | 8 ++++---- src/mame/wyse/wy85.cpp | 28 ++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/devices/bus/wysekbd/wysegakb.cpp b/src/devices/bus/wysekbd/wysegakb.cpp index 7edc3ea2f39..a425b1587eb 100644 --- a/src/devices/bus/wysekbd/wysegakb.cpp +++ b/src/devices/bus/wysekbd/wysegakb.cpp @@ -161,8 +161,8 @@ static INPUT_PORTS_START(wy85_keyboard) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F17)) PORT_CODE(KEYCODE_F17) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Do") PORT_CHAR(UCHAR_MAMEKEY(F16)) PORT_CODE(KEYCODE_F16) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CHAR(UCHAR_MAMEKEY(F15)) PORT_CODE(KEYCODE_F15) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F14 (Home)") PORT_CHAR(UCHAR_MAMEKEY(F14)) PORT_CODE(KEYCODE_F14) - PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F13 (LF)") PORT_CHAR(UCHAR_MAMEKEY(F13)) PORT_CODE(KEYCODE_F13) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F14 (Home)") PORT_CHAR(UCHAR_MAMEKEY(F14), UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F14) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F13 (LF)") PORT_CHAR(UCHAR_MAMEKEY(F13), 0x0a) PORT_CODE(KEYCODE_F13) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Compose Character") PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT) PORT_START("R6") @@ -179,7 +179,7 @@ static INPUT_PORTS_START(wy85_keyboard) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"\u232B (Delete)") PORT_CODE(KEYCODE_BACKSPACE) // ⌫ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Insert Here") PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_HOME) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL) @@ -233,7 +233,7 @@ static INPUT_PORTS_START(wy85_keyboard) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D) - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F12 (BS)") PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F12 (BS)") PORT_CHAR(UCHAR_MAMEKEY(F12), 0x08) PORT_CODE(KEYCODE_F12) INPUT_PORTS_END ioport_constructor wy85_keyboard_device::device_input_ports() const diff --git a/src/mame/wyse/wy85.cpp b/src/mame/wyse/wy85.cpp index a2d48653e00..e6f26591d28 100644 --- a/src/mame/wyse/wy85.cpp +++ b/src/mame/wyse/wy85.cpp @@ -40,6 +40,7 @@ class wy85_state : public driver_device , m_chargen(*this, "chargen") , m_mainram(*this, "mainram") , m_clr_rb(false) + , m_tru_inv(false) , m_lc(0) { } @@ -96,6 +97,7 @@ class wy85_state : public driver_device std::unique_ptr m_fontram; bool m_clr_rb; + bool m_tru_inv; u8 m_lc; }; @@ -108,6 +110,8 @@ void wy85_state::machine_start() save_pointer(NAME(m_fontram), 0x800); save_item(NAME(m_clr_rb)); + save_item(NAME(m_tru_inv)); + save_item(NAME(m_lc)); } void wy85_state::machine_reset() @@ -117,13 +121,28 @@ void wy85_state::machine_reset() SCN2672_DRAW_CHARACTER_MEMBER(wy85_state::draw_character) { - u16 a = bitswap<2>(attrcode, 5, 6) << 11 | ((charcode & 0x7f) << 4) | ((m_lc + (m_clr_rb ? 0 : linecount)) & 0xf); - u8 c = a >= 0x1800 ? m_fontram[a - 0x1800] : m_chargen[a]; + if (BIT(attrcode, 0, 2) == 0) + { + std::fill_n(&bitmap.pix(y, x), 10, rgb_t::black()); + return; + } + + u8 lc = m_lc + (m_clr_rb ? 0 : linecount); + u16 a = bitswap<2>(attrcode, 5, 6) << 11 | ((charcode & 0x7f) << 4) | (lc & 0xf); + u16 c = BIT(attrcode, 3) && (lc & 9) == 9 ? 0x3ff : a >= 0x1800 ? m_fontram[a - 0x1800] << 2 : m_chargen[a] << 2; + + rgb_t fg = !BIT(attrcode, 1) || (BIT(attrcode, 4) && blink) ? rgb_t(0xc0, 0xc0, 0xc0) : rgb_t::white(); + bool inv = (BIT(attrcode, 2) != cursor) == m_tru_inv; + if (inv && BIT(c, 2)) + c |= 3; + if (BIT(attrcode, 0, 2) == 3) + c |= c >> 1; + if (inv) + c ^= 0x3ff; - // TODO: attributes for (int i = 0; i < 10; i++) { - bitmap.pix(y, x++) = BIT(c, 7) ? rgb_t::white() : rgb_t::black(); + bitmap.pix(y, x++) = BIT(c, 9) ? fg : rgb_t::black(); c <<= 1; } } @@ -233,6 +252,7 @@ void wy85_state::p1_w(u8 data) m_pr->write_rts(BIT(data, 3)); m_clr_rb = !BIT(data, 1); + m_tru_inv = BIT(data, 6); m_beeper->set_state(BIT(data, 5)); } From 2ed61834a09f771979e78de97ecec967414eb00f Mon Sep 17 00:00:00 2001 From: tim lindner Date: Tue, 17 Sep 2024 19:56:22 -0700 Subject: [PATCH 08/13] trs/coco3.cpp: Extend display from 639 to 640 pixels (#12780) --- src/mame/trs/coco3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mame/trs/coco3.cpp b/src/mame/trs/coco3.cpp index d3dae6e1711..c5f3db9674e 100644 --- a/src/mame/trs/coco3.cpp +++ b/src/mame/trs/coco3.cpp @@ -311,7 +311,7 @@ void coco3_state::coco3(machine_config &config) // monitor SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(28.636363_MHz_XTAL/2, 912, 0, 640-1, 262, 1, 241-1); + m_screen->set_raw(28.636363_MHz_XTAL/2, 912, 0, 640, 262, 1, 241-1); m_screen->set_screen_update(FUNC(coco3_state::screen_update)); // internal ram From 4c02f05dd2013d5e8b5f8236fe99d5464b98d218 Mon Sep 17 00:00:00 2001 From: angelosa Date: Wed, 18 Sep 2024 11:48:51 +0200 Subject: [PATCH 09/13] Systems promoted to working --------------------------- Hitachi Basic Master Jr. (MB-6885) [Angelo Salese] --- src/mame/hitachi/bmjr.cpp | 107 +++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 47 deletions(-) diff --git a/src/mame/hitachi/bmjr.cpp b/src/mame/hitachi/bmjr.cpp index 6c35fe8df96..19e531dd155 100644 --- a/src/mame/hitachi/bmjr.cpp +++ b/src/mame/hitachi/bmjr.cpp @@ -6,9 +6,15 @@ Basic Master Jr. (MB-6885) (c) 1982? Hitachi TODO: - Identify and improve Sound DAC details; -- Keyboard eats inputs if typed relatively fast (verify, particularly with emu.keypost); -- Downgrade for earlier variants (needs dump first), convert MP-1710 color adapter to device - (bmjr specific); +- Keyboard eats inputs if typed relatively fast (verify); +- Add kana mappings to keyboard; +- Timer control (needs SW that bothers with it); +- Downgrade for earlier variants (needs dump first), convert MP-1710 color adapter to expansion + bus device (bmjr specific); +- Floppy adapter MP-1803, thru expansion bus; +- Border color for MP-1710; +- Printer, MP-1041/MP-1045; +- Hookup SW list; **************************************************************************************************/ @@ -43,29 +49,17 @@ class bmjr_state : public driver_device void bmjr(machine_config &config); DECLARE_INPUT_CHANGED_MEMBER(break_key_pressed); + static constexpr feature_type unemulated_features() { return feature::PRINTER; } protected: virtual void video_start() override; virtual void video_reset() override; -private: - u8 key_r(); - void key_w(u8 data); - u8 ff_r(); - u8 tape_r(); - void tape_w(u8 data); - u8 tape_stop_r(); - u8 tape_start_r(); - void screen_reverse_w(u8 data); - u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void main_map(address_map &map); - bool m_tape_switch = 0; - u8 m_screen_reverse = 0U; - u8 m_key_select = 0U; - u16 m_casscnt = 0U; - bool m_cassold = 0, m_cassbit = 0; - TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); + virtual void machine_start() override; virtual void machine_reset() override; +private: + void main_map(address_map &map); + required_device m_maincpu; required_device m_cass; required_device m_dac; @@ -76,9 +70,24 @@ class bmjr_state : public driver_device required_region_ptr m_p_chargen; required_ioport_array<16> m_io_keyboard; + bool m_tape_switch = 0; + u8 m_screen_reverse = 0U; + u8 m_key_select = 0U; + u8 m_nmi_enable = 0U; + u16 m_casscnt = 0U; + bool m_cassold = 0, m_cassbit = 0; u8 m_bank_mode = 0U; + u8 bank_mode_r(); void bank_mode_w(u8 data); + u8 key_r(); + void key_w(u8 data); + u8 timer_r(); + u8 tape_r(); + void tape_w(u8 data); + u8 tape_stop_r(); + u8 tape_start_r(); + TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); std::unique_ptr m_color_ram; u8 m_color_mode = 0U; @@ -86,6 +95,8 @@ class bmjr_state : public driver_device u8 m_screen_mode = 0U; void mp1710_map(address_map &map); void screen_mode_w(u8 data); + void screen_reverse_w(u8 data); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); }; void bmjr_state::video_start() @@ -94,6 +105,7 @@ void bmjr_state::video_start() save_item(NAME(m_screen_mode)); save_item(NAME(m_screen_reverse)); save_item(NAME(m_color_mode)); + save_item(NAME(m_tile_latch)); save_pointer(NAME(m_color_ram), 0x300); } @@ -142,11 +154,17 @@ void bmjr_state::key_w(u8 data) { m_key_select = data & 0xf; - // TODO: bit 7: NMI enable + m_nmi_enable = BIT(data, 7); + if (!m_nmi_enable) + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); } - -u8 bmjr_state::ff_r() +/* + * x--- ---- checked in irq routine + * 1--- ---- routes to 1 second timer at $000c (TIME 3) + * 0--- ---- routes to $000a-$000b (TIME 1/TIME 2), likely enabled thru $efd0 bit 4 high + */ +u8 bmjr_state::timer_r() { return 0xff; } @@ -218,6 +236,7 @@ u8 bmjr_state::bank_mode_r() */ void bmjr_state::bank_mode_w(u8 data) { + logerror("bank_mode_w %02x\n", data); m_bank_mode = data; if (BIT(data, 0)) m_basic_view.disable(); @@ -237,12 +256,12 @@ void bmjr_state::bank_mode_w(u8 data) void bmjr_state::screen_reverse_w(u8 data) { - m_screen_reverse = data; + m_screen_reverse = BIT(data, 7); } /* * x--- ---- enable bitmap mode - * -?-- ---- + * -?-- ---- * ---- xxxx bank base for bitmap mode */ void bmjr_state::screen_mode_w(u8 data) @@ -288,8 +307,7 @@ void bmjr_state::main_map(address_map &map) map(0xee40, 0xee40).w(FUNC(bmjr_state::screen_reverse_w)); //W Picture reverse map(0xee80, 0xee80).rw(FUNC(bmjr_state::tape_r), FUNC(bmjr_state::tape_w));//RW tape input / output map(0xeec0, 0xeec0).rw(FUNC(bmjr_state::key_r), FUNC(bmjr_state::key_w));//RW keyboard - map(0xef00, 0xef00).r(FUNC(bmjr_state::ff_r)); // R timer - map(0xef40, 0xef40).r(FUNC(bmjr_state::ff_r)); // R unknown + map(0xef00, 0xef00).r(FUNC(bmjr_state::timer_r)); map(0xef80, 0xef80).portr("BREAK"); map(0xefd0, 0xefd0).rw(FUNC(bmjr_state::bank_mode_r), FUNC(bmjr_state::bank_mode_w)); map(0xefe0, 0xefe0).w(FUNC(bmjr_state::screen_mode_w)); @@ -299,7 +317,8 @@ void bmjr_state::main_map(address_map &map) INPUT_CHANGED_MEMBER(bmjr_state::break_key_pressed) { - m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? ASSERT_LINE : CLEAR_LINE); + if (newval && m_nmi_enable) + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); } static INPUT_PORTS_START( bmjr ) @@ -364,36 +383,26 @@ static INPUT_PORTS_START( bmjr ) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_START("KEY10") - PORT_BIT(0x01,IP_ACTIVE_LOW, IPT_UNUSED ) + // NOTE: works on kana / shift only + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("_") PORT_CHAR('_') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(": *") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("@ Up") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('@') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"@ \u2191") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('@') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("- =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') PORT_START("KEY11") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("[ Down") PORT_CODE(KEYCODE_OPENBRACE) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('[') - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("^ Right") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('^') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"[ \u2193") PORT_CODE(KEYCODE_OPENBRACE) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('[') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"^ \u2192") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('^') PORT_START("KEY12") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"¥ / Left") PORT_CODE(KEYCODE_4_PAD) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"¥ \u2190") PORT_CODE(KEYCODE_4_PAD) PORT_START("KEY13") - PORT_DIPNAME( 0x01, 0x01, "D" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("KEY14") PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) @@ -408,7 +417,7 @@ static INPUT_PORTS_START( bmjr ) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Kana") PORT_CODE(KEYCODE_RCONTROL) PORT_START("BREAK") - PORT_BIT(0x7f, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT(0x7f, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // TODO: read by timer irq service PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Break") PORT_CHANGED_MEMBER(DEVICE_SELF, bmjr_state, break_key_pressed, 0) INPUT_PORTS_END @@ -434,6 +443,8 @@ void bmjr_state::machine_start() save_item(NAME(m_casscnt)); save_item(NAME(m_cassold)); save_item(NAME(m_cassbit)); + save_item(NAME(m_nmi_enable)); + save_item(NAME(m_bank_mode)); } void bmjr_state::machine_reset() @@ -454,8 +465,10 @@ void bmjr_state::bmjr(machine_config &config) // 750khz gets the cassette sound close to a normal kansas city 300 baud M6800(config, m_maincpu, 754'560); // TODO: HD46800, derive from actual clock / divider m_maincpu->set_addrmap(AS_PROGRAM, &bmjr_state::main_map); + // NOTE: checked by using TIME commands, which implies a separate thread than the actual timer control m_maincpu->set_vblank_int("screen", FUNC(bmjr_state::irq0_line_hold)); + // TRQ237/TRQ359 CASSETTE(config, m_cass); m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); TIMER(config, "kansas_r").configure_periodic(FUNC(bmjr_state::kansas_r), attotime::from_hz(40000)); @@ -497,4 +510,4 @@ ROM_END // 1979 Basic Master MB-6880 (retroactively Level 1) // 1979 Basic Master Level 2 MB-6880L2 // 1980 Basic Master Level 2 II MB-6881 -COMP( 1981, bmjr, 0, 0, bmjr, bmjr, bmjr_state, empty_init, "Hitachi", "Basic Master Jr. (MB-6885)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +COMP( 1981, bmjr, 0, 0, bmjr, bmjr, bmjr_state, empty_init, "Hitachi", "Basic Master Jr. (MB-6885)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) From 2d74a4e86658fac539ca914d86d262fe5dcb4480 Mon Sep 17 00:00:00 2001 From: hap Date: Tue, 17 Sep 2024 23:15:58 +0200 Subject: [PATCH 10/13] kchamp: remove duplicate function --- src/mame/dataeast/kchamp.cpp | 5 ++-- src/mame/dataeast/kchamp.h | 3 +-- src/mame/dataeast/kchamp_v.cpp | 47 ++++++---------------------------- 3 files changed, 12 insertions(+), 43 deletions(-) diff --git a/src/mame/dataeast/kchamp.cpp b/src/mame/dataeast/kchamp.cpp index ea7514edd65..f1af8bc53f1 100644 --- a/src/mame/dataeast/kchamp.cpp +++ b/src/mame/dataeast/kchamp.cpp @@ -149,6 +149,7 @@ void kchamp_state::kchampvs_sound_io_map(address_map &map) /******************** * 1 Player Version * ********************/ + uint8_t kchamp_state::sound_reset_r() { if (!machine().side_effects_disabled()) @@ -160,12 +161,12 @@ void kchamp_state::kc_sound_control_w(offs_t offset, uint8_t data) { if (offset == 0) { - m_sound_nmi_enable = ((data >> 7) & 1); + m_sound_nmi_enable = BIT(data, 7); if (!m_sound_nmi_enable) m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); } else - m_dac->set_output_gain(0, BIT(data,0) ? 1.0 : 0); + m_dac->set_output_gain(0, BIT(data, 0) ? 1.0 : 0); } void kchamp_state::kchamp_map(address_map &map) diff --git a/src/mame/dataeast/kchamp.h b/src/mame/dataeast/kchamp.h index 70969b3a544..4d0d17b1d72 100644 --- a/src/mame/dataeast/kchamp.h +++ b/src/mame/dataeast/kchamp.h @@ -88,8 +88,7 @@ class kchamp_state : public driver_device uint32_t screen_update_kchamp(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void vblank_irq(int state); INTERRUPT_GEN_MEMBER(sound_int); - void kchamp_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - void kchampvs_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int dx, int dy); void decrypt_code(); void msmint(int state); void decrypted_opcodes_map(address_map &map); diff --git a/src/mame/dataeast/kchamp_v.cpp b/src/mame/dataeast/kchamp_v.cpp index 38ef03fc38c..030da4d9403 100644 --- a/src/mame/dataeast/kchamp_v.cpp +++ b/src/mame/dataeast/kchamp_v.cpp @@ -60,49 +60,18 @@ void kchamp_state::video_start() 3 XXXXXXXX */ -void kchamp_state::kchamp_draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) +void kchamp_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int dx, int dy) { - uint8_t *spriteram = m_spriteram; - int offs; - - for (offs = 0; offs < 0x100; offs += 4) - { - int attr = spriteram[offs + 2]; - int bank = 1 + ((attr & 0x60) >> 5); - int code = spriteram[offs + 1] + ((attr & 0x10) << 4); - int color = attr & 0x0f; - int flipx = 0; - int flipy = attr & 0x80; - int sx = spriteram[offs + 3] - 8; - int sy = 247 - spriteram[offs]; - - if (flip_screen()) - { - sx = 240 - sx; - sy = 240 - sy; - flipx = !flipx; - flipy = !flipy; - } - - m_gfxdecode->gfx(bank)->transpen(bitmap,cliprect, code, color, flipx, flipy, sx, sy, 0); - } -} - -void kchamp_state::kchampvs_draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) -{ - uint8_t *spriteram = m_spriteram; - int offs; - - for (offs = 0; offs < 0x100; offs += 4) + for (int offs = 0; offs < 0x100; offs += 4) { - int attr = spriteram[offs + 2]; + int attr = m_spriteram[offs + 2]; int bank = 1 + ((attr & 0x60) >> 5); - int code = spriteram[offs + 1] + ((attr & 0x10) << 4); + int code = m_spriteram[offs + 1] + ((attr & 0x10) << 4); int color = attr & 0x0f; int flipx = 0; int flipy = attr & 0x80; - int sx = spriteram[offs + 3]; - int sy = 240 - spriteram[offs]; + int sx = m_spriteram[offs + 3] + dx; + int sy = 240 - m_spriteram[offs] + dy; if (flip_screen()) { @@ -120,13 +89,13 @@ void kchamp_state::kchampvs_draw_sprites( bitmap_ind16 &bitmap, const rectangle uint32_t kchamp_state::screen_update_kchamp(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); - kchamp_draw_sprites(bitmap, cliprect); + draw_sprites(bitmap, cliprect, -8, 7); return 0; } uint32_t kchamp_state::screen_update_kchampvs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); - kchampvs_draw_sprites(bitmap, cliprect); + draw_sprites(bitmap, cliprect, 0, 0); return 0; } From 819379be1e044c5f9cd8c9f238f16179d45dc310 Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 18 Sep 2024 00:48:13 +0200 Subject: [PATCH 11/13] hmcs400: add i/o ports --- src/devices/cpu/hmcs40/hmcs40.cpp | 63 ++++++++++--------- src/devices/cpu/hmcs40/hmcs40.h | 25 ++++---- src/devices/cpu/hmcs40/hmcs40op.cpp | 18 +++--- src/devices/cpu/hmcs400/hmcs400.cpp | 88 ++++++++++++++++++++++++++- src/devices/cpu/hmcs400/hmcs400.h | 26 +++++++- src/devices/cpu/hmcs400/hmcs400op.cpp | 30 ++++++++- 6 files changed, 194 insertions(+), 56 deletions(-) diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp index 723934604ac..a10d31fca36 100644 --- a/src/devices/cpu/hmcs40/hmcs40.cpp +++ b/src/devices/cpu/hmcs40/hmcs40.cpp @@ -247,13 +247,8 @@ void hmcs40_cpu_device::device_reset() m_iri = m_irt = 0; m_if[0] = m_if[1] = m_tf = 1; - // clear i/o - m_d = m_polarity; - for (int i = 0; i < 16; i++) - hmcs40_cpu_device::write_d(i, m_polarity); - - for (int i = 0; i < 8; i++) - hmcs40_cpu_device::write_r(i, m_polarity & 0xf); + // all I/O ports set to input + reset_io(); } @@ -325,13 +320,22 @@ device_memory_interface::space_config_vector hmcs40_cpu_device::memory_space_con //------------------------------------------------- -// i/o handling +// i/o ports //------------------------------------------------- -u8 hmcs40_cpu_device::read_r(int index) +void hmcs40_cpu_device::reset_io() +{ + m_d = m_polarity; + m_write_d(m_polarity); + + for (int i = 0; i < 8; i++) + hmcs40_cpu_device::write_r(i, m_polarity); +} + +u8 hmcs40_cpu_device::read_r(u8 index) { index &= 7; - u8 inp = m_read_r[index](index, 0xff); + u8 inp = m_read_r[index](index); if (m_polarity) return (inp & m_r[index]) & 0xf; @@ -339,38 +343,39 @@ u8 hmcs40_cpu_device::read_r(int index) return (inp | m_r[index]) & 0xf; } -void hmcs40_cpu_device::write_r(int index, u8 data) +void hmcs40_cpu_device::write_r(u8 index, u8 data) { index &= 7; data &= 0xf; m_r[index] = data; - m_write_r[index](index, data, 0xff); + m_write_r[index](index, data); } -int hmcs40_cpu_device::read_d(int index) +int hmcs40_cpu_device::read_d(u8 index) { - index &= 15; + index &= 0xf; + u16 inp = m_read_d(0, 1 << index); if (m_polarity) - return (m_read_d(index, 0xffff) & m_d) >> index & 1; + return BIT(inp & m_d, index); else - return (m_read_d(index, 0xffff) | m_d) >> index & 1; + return BIT(inp | m_d, index); } -void hmcs40_cpu_device::write_d(int index, int state) +void hmcs40_cpu_device::write_d(u8 index, int state) { - index &= 15; - state = (state) ? 1 : 0; + index &= 0xf; + u16 mask = 1 << index; - m_d = (m_d & ~(1 << index)) | state << index; - m_write_d(index, m_d, 0xffff); + m_d = (m_d & ~mask) | (state ? mask : 0); + m_write_d(0, m_d, mask); } // HMCS43: // R0 is input-only, R1 is i/o, R2,R3 are output-only, no R4-R7 // D0-D3 are i/o, D4-D15 are output-only -u8 hmcs43_cpu_device::read_r(int index) +u8 hmcs43_cpu_device::read_r(u8 index) { index &= 7; @@ -380,7 +385,7 @@ u8 hmcs43_cpu_device::read_r(int index) return hmcs40_cpu_device::read_r(index); } -void hmcs43_cpu_device::write_r(int index, u8 data) +void hmcs43_cpu_device::write_r(u8 index, u8 data) { index &= 7; @@ -390,7 +395,7 @@ void hmcs43_cpu_device::write_r(int index, u8 data) logerror("ineffective write to port R%d = $%X at $%04X\n", index, data & 0xf, m_prev_pc); } -int hmcs43_cpu_device::read_d(int index) +int hmcs43_cpu_device::read_d(u8 index) { index &= 15; @@ -404,7 +409,7 @@ int hmcs43_cpu_device::read_d(int index) // R0-R3 are i/o, R4,R5 are extra registers, no R6,R7 // D0-D15 are i/o -u8 hmcs44_cpu_device::read_r(int index) +u8 hmcs44_cpu_device::read_r(u8 index) { index &= 7; @@ -414,7 +419,7 @@ u8 hmcs44_cpu_device::read_r(int index) return hmcs40_cpu_device::read_r(index); } -void hmcs44_cpu_device::write_r(int index, u8 data) +void hmcs44_cpu_device::write_r(u8 index, u8 data) { index &= 7; @@ -428,7 +433,7 @@ void hmcs44_cpu_device::write_r(int index, u8 data) // R0-R5 are i/o, R6 is output-only, no R7 // D0-D15 are i/o -u8 hmcs45_cpu_device::read_r(int index) +u8 hmcs45_cpu_device::read_r(u8 index) { index &= 7; @@ -438,7 +443,7 @@ u8 hmcs45_cpu_device::read_r(int index) return hmcs40_cpu_device::read_r(index); } -void hmcs45_cpu_device::write_r(int index, u8 data) +void hmcs45_cpu_device::write_r(u8 index, u8 data) { index &= 7; @@ -450,7 +455,7 @@ void hmcs45_cpu_device::write_r(int index, u8 data) //------------------------------------------------- -// interrupt/timer handling +// interrupt/timer //------------------------------------------------- void hmcs40_cpu_device::do_interrupt() diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h index c9316bbe69a..833b5891cd2 100644 --- a/src/devices/cpu/hmcs40/hmcs40.h +++ b/src/devices/cpu/hmcs40/hmcs40.h @@ -12,7 +12,7 @@ #pragma once -// I/O ports setup +// input lines enum { @@ -195,10 +195,11 @@ class hmcs40_cpu_device : public cpu_device void pop_stack(); void push_stack(); - virtual u8 read_r(int index); - virtual void write_r(int index, u8 data); - virtual int read_d(int index); - virtual void write_d(int index, int state); + virtual void reset_io(); + virtual u8 read_r(u8 index); + virtual void write_r(u8 index, u8 data); + virtual int read_d(u8 index); + virtual void write_d(u8 index, int state); void cycle(); void increment_tc(); @@ -309,9 +310,9 @@ class hmcs43_cpu_device : public hmcs40_cpu_device hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity); // overrides - virtual u8 read_r(int index) override; - virtual void write_r(int index, u8 data) override; - virtual int read_d(int index) override; + virtual u8 read_r(u8 index) override; + virtual void write_r(u8 index, u8 data) override; + virtual int read_d(u8 index) override; }; class hd38750_device : public hmcs43_cpu_device @@ -345,8 +346,8 @@ class hmcs44_cpu_device : public hmcs40_cpu_device hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity); // overrides - virtual u8 read_r(int index) override; - virtual void write_r(int index, u8 data) override; + virtual u8 read_r(u8 index) override; + virtual void write_r(u8 index, u8 data) override; }; class hd38800_device : public hmcs44_cpu_device @@ -380,8 +381,8 @@ class hmcs45_cpu_device : public hmcs40_cpu_device hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity); // overrides - virtual u8 read_r(int index) override; - virtual void write_r(int index, u8 data) override; + virtual u8 read_r(u8 index) override; + virtual void write_r(u8 index, u8 data) override; }; class hd38820_device : public hmcs45_cpu_device diff --git a/src/devices/cpu/hmcs40/hmcs40op.cpp b/src/devices/cpu/hmcs40/hmcs40op.cpp index a2c201946cb..262e82f1d48 100644 --- a/src/devices/cpu/hmcs40/hmcs40op.cpp +++ b/src/devices/cpu/hmcs40/hmcs40op.cpp @@ -663,24 +663,24 @@ void hmcs40_cpu_device::op_lrb() void hmcs40_cpu_device::op_p() { + // P p: Pattern Generation cycle(); - // P p: Pattern Generation u16 address = m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9 | (m_pc & ~0x3f); - u16 o = m_program->read_word(address & m_prgmask); + u16 data = m_program->read_word(address & m_prgmask); // destination is determined by the 2 highest bits - if (o & 0x100) + if (data & 0x100) { // B3 B2 B1 B0 A0 A1 A2 A3 - m_a = bitswap<4>(o,0,1,2,3); - m_b = o >> 4 & 0xf; + m_a = bitswap<4>(data,0,1,2,3); + m_b = data >> 4 & 0xf; } - if (o & 0x200) + if (data & 0x200) { // R20 R21 R22 R23 R30 R31 R32 R33 - o = bitswap<8>(o,0,1,2,3,4,5,6,7); - write_r(2, o & 0xf); - write_r(3, o >> 4 & 0xf); + data = bitswap<8>(data,0,1,2,3,4,5,6,7); + write_r(2, data & 0xf); + write_r(3, data >> 4 & 0xf); } } diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp index 261e482ac8c..0c8cc8d4a9c 100644 --- a/src/devices/cpu/hmcs400/hmcs400.cpp +++ b/src/devices/cpu/hmcs400/hmcs400.cpp @@ -18,6 +18,8 @@ removed (interrupt flags are via memory-mapped I/O). way to save this register when using interrupts - what happens when accessing ROM/RAM out of address range? Hitachi documentation says 'unused', but maybe it's mirrored? +- current I/O ports are hardcoded for HMS402/4/8, which will need to be changed + when other MCU types are added */ @@ -73,7 +75,11 @@ hmcs400_cpu_device::hmcs400_cpu_device(const machine_config &mconfig, device_typ m_rom_size(rom_size), m_ram_size(ram_size), m_has_div(false), - m_divider(8) + m_divider(8), + m_read_r(*this, 0), + m_write_r(*this), + m_read_d(*this, 0), + m_write_d(*this) { } hmcs400_cpu_device::~hmcs400_cpu_device() { } @@ -185,8 +191,6 @@ void hmcs400_cpu_device::device_start() save_item(NAME(m_prev_pc)); save_item(NAME(m_sp)); save_item(NAME(m_op)); - save_item(NAME(m_param)); - save_item(NAME(m_i)); save_item(NAME(m_a)); save_item(NAME(m_b)); @@ -198,6 +202,9 @@ void hmcs400_cpu_device::device_start() save_item(NAME(m_st)); save_item(NAME(m_ca)); + save_item(NAME(m_r)); + save_item(NAME(m_d)); + // register state for debugger state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow(); state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow(); @@ -225,6 +232,9 @@ void hmcs400_cpu_device::device_reset() m_pc = 0; m_sp = 0x3ff; m_st = 1; + + // all I/O ports set to input + reset_io(); } @@ -278,6 +288,78 @@ device_memory_interface::space_config_vector hmcs400_cpu_device::memory_space_co } +//------------------------------------------------- +// i/o ports +//------------------------------------------------- + +void hmcs400_cpu_device::reset_io() +{ + // D4-D15 are high-voltage + m_d_mask = m_d = 0x000f; + m_write_d(m_d_mask); + + for (int i = 0; i < 10; i++) + { + // R0-R2 and RA are high-voltage + u8 mask = (i >= 3 && i <= 9) ? 0xf : 0; + + m_r_mask[i] = m_r[i] = mask; + m_write_r[i](i, mask); + } +} + +u8 hmcs400_cpu_device::read_r(u8 index) +{ + // reads from write-only or non-existent ports are invalid + bool write_only = index == 0 || (index >= 6 && index <= 8); + if (write_only || index > 10) + { + logerror("read from %s port R%X at $%04X\n", write_only ? "output" : "unknown", index, m_prev_pc); + return 0xf; + } + + u8 inp = m_read_r[index].isunset() ? m_r_mask[index] : m_read_r[index](index); + u8 mask = (index == 10) ? 3 : 0xf; // port A is 2-bit + + if (m_r_mask[index]) + return (inp & m_r[index]) & mask; + else + return (inp | m_r[index]) & mask; +} + +void hmcs400_cpu_device::write_r(u8 index, u8 data) +{ + // ignore writes to read-only or non-existent ports + if (index > 8) + return; + + data &= 0xf; + m_r[index] = data; + m_write_r[index](index, data); +} + +int hmcs400_cpu_device::read_d(u8 index) +{ + index &= 0xf; + u16 mask = 1 << index; + u16 inp = m_read_d.isunset() ? m_d_mask : m_read_d(0, mask); + + if (m_d_mask & mask) + return BIT(inp & m_d, index); + else + return BIT(inp | m_d, index); +} + +void hmcs400_cpu_device::write_d(u8 index, int state) +{ + index &= 0xf; + u16 mask = 1 << index; + + m_d = (m_d & ~mask) | (state ? mask : 0); + m_write_d(0, m_d, mask); +} + + //------------------------------------------------- // execute //------------------------------------------------- diff --git a/src/devices/cpu/hmcs400/hmcs400.h b/src/devices/cpu/hmcs400/hmcs400.h index 965131df530..c8572fe0192 100644 --- a/src/devices/cpu/hmcs400/hmcs400.h +++ b/src/devices/cpu/hmcs400/hmcs400.h @@ -19,6 +19,14 @@ class hmcs400_cpu_device : public cpu_device // configuration helpers + // 10 4-bit R ports (port A is 2-bit) + template auto read_r() { return m_read_r[N].bind(); } + template auto write_r() { return m_write_r[N].bind(); } + + // 16-bit discrete + auto read_d() { return m_read_d.bind(); } + auto write_d() { return m_write_d.bind(); } + // system clock divider mask option (only for HMCS408, HMCS414, HMCS424) // valid options: 4, 8, 16, default to 8 auto &set_divider(u8 div) { assert(m_has_div); m_divider = div; return *this; } @@ -81,7 +89,16 @@ class hmcs400_cpu_device : public cpu_device u8 m_st; // status flag u8 m_ca; // carry flag - u16 fetch(); + u8 m_r[10]; // R outputs state + u8 m_r_mask[10]; + u16 m_d; // D pins state + u16 m_d_mask; + + // I/O handlers + devcb_read8::array<8> m_read_r; + devcb_write8::array<8> m_write_r; + devcb_read16 m_read_d; + devcb_write16 m_write_d; // misc internal helpers u8 ram_r(u8 mem_mask = 0xf); @@ -89,7 +106,14 @@ class hmcs400_cpu_device : public cpu_device void pop_stack(); void push_stack(); + void reset_io(); + u8 read_r(u8 index); + void write_r(u8 index, u8 data); + int read_d(u8 index); + void write_d(u8 index, int state); + void cycle(); + u16 fetch(); // opcode handlers void op_illegal(); diff --git a/src/devices/cpu/hmcs400/hmcs400op.cpp b/src/devices/cpu/hmcs400/hmcs400op.cpp index b9656db83b5..0fb1ea015c5 100644 --- a/src/devices/cpu/hmcs400/hmcs400op.cpp +++ b/src/devices/cpu/hmcs400/hmcs400op.cpp @@ -534,9 +534,9 @@ void hmcs400_cpu_device::op_cal() // CAL a: Subroutine Jump on Status 1 if (m_st) { + cycle(); push_stack(); m_pc = m_op & 0x3f; - cycle(); } else m_st = 1; @@ -563,9 +563,9 @@ void hmcs400_cpu_device::op_tbr() void hmcs400_cpu_device::op_rtn() { // RTN: Return from Subroutine - pop_stack(); cycle(); cycle(); + pop_stack(); } void hmcs400_cpu_device::op_rtni() @@ -580,56 +580,82 @@ void hmcs400_cpu_device::op_rtni() void hmcs400_cpu_device::op_sed() { // SED: Set Discrete I/O Latch + write_d(m_y, 1); } void hmcs400_cpu_device::op_sedd() { // SEDD m: Set Discrete I/O Latch Direct + write_d(m_i, 1); } void hmcs400_cpu_device::op_red() { // RED: Reset Discrete I/O Latch + write_d(m_y, 0); } void hmcs400_cpu_device::op_redd() { // REDD m: Reset Discrete I/O Latch Direct + write_d(m_i, 0); } void hmcs400_cpu_device::op_td() { // TD: Test Discrete I/O Latch + m_st = read_d(m_y); } void hmcs400_cpu_device::op_tdd() { // TDD m: Test Discrete I/O Latch Direct + m_st = read_d(m_i); } void hmcs400_cpu_device::op_lar() { // LAR m: Load A from R Port Register + m_a = read_r(m_i); } void hmcs400_cpu_device::op_lbr() { // LBR m: Load B from R Port Register + m_b = read_r(m_i); } void hmcs400_cpu_device::op_lra() { // LRA m: Load R Port Register from A + write_r(m_i, m_a); } void hmcs400_cpu_device::op_lrb() { // LRB m: Load R Port Register from B + write_r(m_i, m_b); } void hmcs400_cpu_device::op_p() { // P p: Pattern Generation + cycle(); + u16 data = m_program->read_word(m_i << 8 | m_b << 4 | m_a); + + // destination is determined by the 2 highest bits + if (data & 0x100) + { + // to A/B registers + m_a = data & 0xf; + m_b = data >> 4 & 0xf; + } + if (data & 0x200) + { + // to R1/R2 ports + write_r(1, data & 0xf); + write_r(2, data >> 4 & 0xf); + } } From 8f39f074e3e3d242dfdb822a11c77a24a008e781 Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 18 Sep 2024 12:13:07 +0200 Subject: [PATCH 12/13] hmcs400: add logerror for unmapped ports --- src/devices/cpu/hmcs400/hmcs400.cpp | 25 ++++++++++++++++++++++--- src/devices/cpu/hmcs400/hmcs400.h | 1 + src/devices/cpu/hmcs400/hmcs400op.cpp | 9 +++++++++ src/mame/ussr/debut.cpp | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp index 0c8cc8d4a9c..06a3270cfd3 100644 --- a/src/devices/cpu/hmcs400/hmcs400.cpp +++ b/src/devices/cpu/hmcs400/hmcs400.cpp @@ -318,8 +318,14 @@ u8 hmcs400_cpu_device::read_r(u8 index) return 0xf; } - u8 inp = m_read_r[index].isunset() ? m_r_mask[index] : m_read_r[index](index); u8 mask = (index == 10) ? 3 : 0xf; // port A is 2-bit + u8 inp = m_read_r[index](index); + + if (m_read_r[index].isunset()) + { + inp = m_r_mask[index]; + logerror("read from unmapped port R%X at $%04X\n", index, m_prev_pc); + } if (m_r_mask[index]) return (inp & m_r[index]) & mask; @@ -329,11 +335,15 @@ u8 hmcs400_cpu_device::read_r(u8 index) void hmcs400_cpu_device::write_r(u8 index, u8 data) { + data &= 0xf; + // ignore writes to read-only or non-existent ports if (index > 8) return; - data &= 0xf; + if (m_write_r[index].isunset()) + logerror("write $%X to unmapped port R%d at $%04X\n", data, index, m_prev_pc); + m_r[index] = data; m_write_r[index](index, data); } @@ -342,7 +352,13 @@ int hmcs400_cpu_device::read_d(u8 index) { index &= 0xf; u16 mask = 1 << index; - u16 inp = m_read_d.isunset() ? m_d_mask : m_read_d(0, mask); + u16 inp = m_read_d(0, mask); + + if (m_read_d.isunset()) + { + inp = m_d_mask; + logerror("read from unmapped port D%d at $%04X\n", index, m_prev_pc); + } if (m_d_mask & mask) return BIT(inp & m_d, index); @@ -355,6 +371,9 @@ void hmcs400_cpu_device::write_d(u8 index, int state) index &= 0xf; u16 mask = 1 << index; + if (m_write_d.isunset()) + logerror("write %d to unmapped port D%d at $%04X\n", state, index, m_prev_pc); + m_d = (m_d & ~mask) | (state ? mask : 0); m_write_d(0, m_d, mask); } diff --git a/src/devices/cpu/hmcs400/hmcs400.h b/src/devices/cpu/hmcs400/hmcs400.h index c8572fe0192..f09c37734c5 100644 --- a/src/devices/cpu/hmcs400/hmcs400.h +++ b/src/devices/cpu/hmcs400/hmcs400.h @@ -117,6 +117,7 @@ class hmcs400_cpu_device : public cpu_device // opcode handlers void op_illegal(); + void op_todo(); void op_lai(); void op_lbi(); diff --git a/src/devices/cpu/hmcs400/hmcs400op.cpp b/src/devices/cpu/hmcs400/hmcs400op.cpp index 0fb1ea015c5..676cca73115 100644 --- a/src/devices/cpu/hmcs400/hmcs400op.cpp +++ b/src/devices/cpu/hmcs400/hmcs400op.cpp @@ -58,6 +58,11 @@ void hmcs400_cpu_device::op_illegal() logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc); } +void hmcs400_cpu_device::op_todo() +{ + logerror("unimplemented opcode $%03X at $%04X\n", m_op, m_prev_pc); +} + // immediate instructions @@ -572,6 +577,7 @@ void hmcs400_cpu_device::op_rtni() { // RTNI: Return from Interrupt op_rtn(); + op_todo(); } @@ -664,14 +670,17 @@ void hmcs400_cpu_device::op_p() void hmcs400_cpu_device::op_sts() { // STS: Start Serial + op_todo(); } void hmcs400_cpu_device::op_sby() { // SBY: Standby Mode + op_todo(); } void hmcs400_cpu_device::op_stop() { // STOP: Stop Mode + op_todo(); } diff --git a/src/mame/ussr/debut.cpp b/src/mame/ussr/debut.cpp index 1a42c38362a..cf4f7b80c4d 100644 --- a/src/mame/ussr/debut.cpp +++ b/src/mame/ussr/debut.cpp @@ -211,7 +211,7 @@ static INPUT_PORTS_START( debutm ) PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_NAME(u8"ИНТ (Switch 1P/2P)") PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_P) PORT_NAME(u8"ПОЗ (Position Mode)") PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_NAME(u8"ВФ (Select Piece)") - PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME(u8"ВП (Take Back)") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) PORT_NAME(u8"ВП (Take Back)") PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME(u8"УР (Level)") PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) PORT_NAME(u8"ВВ (Enter Position)") From 9a593dd7f03bbe619ee1fabb1e70af9683dd8901 Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 18 Sep 2024 12:30:18 +0200 Subject: [PATCH 13/13] misc: Added proper error messages to COM quickload (MT 08915) [Robbbert] --- src/mame/altos/altos5.cpp | 35 +++++++++++++++--------------- src/mame/ausnz/aussiebyte.cpp | 40 ++++++++++++++++++----------------- src/mame/kaypro/kaypro_m.cpp | 24 ++++++++++++--------- src/mame/ncr/dmv.cpp | 23 ++++++++++---------- src/mame/sony/smc777.cpp | 33 +++++++++++++++-------------- src/mame/trs/coco3.cpp | 2 +- src/mame/xerox/xerox820.cpp | 32 +++++++++++++++------------- 7 files changed, 100 insertions(+), 89 deletions(-) diff --git a/src/mame/altos/altos5.cpp b/src/mame/altos/altos5.cpp index ce80a963dc1..12cf53d0300 100644 --- a/src/mame/altos/altos5.cpp +++ b/src/mame/altos/altos5.cpp @@ -302,37 +302,38 @@ void altos5_state::port09_w(uint8_t data) QUICKLOAD_LOAD_MEMBER(altos5_state::quickload_cb) { - address_space& prog_space = m_maincpu->space(AS_PROGRAM); - - if (image.length() >= 0xfd00) - return std::make_pair(image_error::INVALIDLENGTH, std::string()); - setup_banks(2); - /* Avoid loading a program if CP/M-80 is not in memory */ + address_space& prog_space = m_maincpu->space(AS_PROGRAM); + + // Avoid loading a program if CP/M-80 is not in memory if ((prog_space.read_byte(0) != 0xc3) || (prog_space.read_byte(5) != 0xc3)) { machine_reset(); - return std::make_pair(image_error::UNSUPPORTED, std::string()); + return std::make_pair(image_error::UNSUPPORTED, "CP/M must already be running"); } - /* Load image to the TPA (Transient Program Area) */ + const int mem_avail = 256 * prog_space.read_byte(7) + prog_space.read_byte(6) - 512; + if (mem_avail < image.length()) + return std::make_pair(image_error::UNSPECIFIED, "Insufficient memory available"); + + // Load image to the TPA (Transient Program Area) uint16_t quickload_size = image.length(); for (uint16_t i = 0; i < quickload_size; i++) { uint8_t data; - - if (image.fread( &data, 1) != 1) - return std::make_pair(image_error::UNSPECIFIED, std::string()); - prog_space.write_byte(i+0x100, data); + if (image.fread(&data, 1) != 1) + return std::make_pair(image_error::BADSOFTWARE, "Problem reading the image at offset " + std::to_string(i)); + prog_space.write_byte(i + 0x100, data); } - /* clear out command tail */ - prog_space.write_byte(0x80, 0); prog_space.write_byte(0x81, 0); + // clear out command tail + prog_space.write_byte(0x80, 0); + prog_space.write_byte(0x81, 0); - /* Roughly set SP basing on the BDOS position */ - m_maincpu->set_state_int(Z80_SP, 256 * prog_space.read_byte(7) - 300); - m_maincpu->set_pc(0x100); // start program + // Roughly set SP basing on the BDOS position + m_maincpu->set_state_int(Z80_SP, mem_avail + 384); + m_maincpu->set_pc(0x100); // start program return std::make_pair(std::error_condition(), std::string()); } diff --git a/src/mame/ausnz/aussiebyte.cpp b/src/mame/ausnz/aussiebyte.cpp index 1a350bca67d..0745691357e 100644 --- a/src/mame/ausnz/aussiebyte.cpp +++ b/src/mame/ausnz/aussiebyte.cpp @@ -398,40 +398,42 @@ static void aussiebyte_floppies(device_slot_interface &device) QUICKLOAD_LOAD_MEMBER(aussiebyte_state::quickload_cb) { - address_space& prog_space = m_maincpu->space(AS_PROGRAM); - - if (image.length() >= 0xfd00) - return std::make_pair(image_error::INVALIDLENGTH, std::string()); - - /* RAM must be banked in */ - m_port15 = true; // disable boot rom + // RAM must be banked in + m_port15 = true; // disable boot rom m_port1a = 4; - m_bankr0->set_entry(m_port1a); /* enable correct program bank */ + m_bankr0->set_entry(m_port1a); // enable correct program bank m_bankw0->set_entry(m_port1a); - /* Avoid loading a program if CP/M-80 is not in memory */ + address_space& prog_space = m_maincpu->space(AS_PROGRAM); + + // Avoid loading a program if CP/M-80 is not in memory if ((prog_space.read_byte(0) != 0xc3) || (prog_space.read_byte(5) != 0xc3)) { machine_reset(); - return std::make_pair(image_error::UNSUPPORTED, std::string()); + return std::make_pair(image_error::UNSUPPORTED, "CP/M must already be running"); } - /* Load image to the TPA (Transient Program Area) */ + const int mem_avail = 256 * prog_space.read_byte(7) + prog_space.read_byte(6) - 512; + if (mem_avail < image.length()) + return std::make_pair(image_error::UNSPECIFIED, "Insufficient memory available"); + + // Load image to the TPA (Transient Program Area) u16 quickload_size = image.length(); for (u16 i = 0; i < quickload_size; i++) { u8 data; - if (image.fread( &data, 1) != 1) - return std::make_pair(image_error::UNSPECIFIED, std::string()); - prog_space.write_byte(i+0x100, data); + if (image.fread(&data, 1) != 1) + return std::make_pair(image_error::BADSOFTWARE, "Problem reading the image at offset " + std::to_string(i)); + prog_space.write_byte(i + 0x100, data); } - /* clear out command tail */ - prog_space.write_byte(0x80, 0); prog_space.write_byte(0x81, 0); + // clear out command tail + prog_space.write_byte(0x80, 0); + prog_space.write_byte(0x81, 0); - /* Roughly set SP basing on the BDOS position */ - m_maincpu->set_state_int(Z80_SP, 256 * prog_space.read_byte(7) - 0x400); - m_maincpu->set_pc(0x100); // start program + // Roughly set SP basing on the BDOS position + m_maincpu->set_state_int(Z80_SP, mem_avail + 384); + m_maincpu->set_pc(0x100); // start program return std::make_pair(std::error_condition(), std::string()); } diff --git a/src/mame/kaypro/kaypro_m.cpp b/src/mame/kaypro/kaypro_m.cpp index 2bda040f82f..8bb754cc115 100644 --- a/src/mame/kaypro/kaypro_m.cpp +++ b/src/mame/kaypro/kaypro_m.cpp @@ -300,27 +300,31 @@ QUICKLOAD_LOAD_MEMBER(kaypro_state::quickload_cb) address_space& prog_space = m_maincpu->space(AS_PROGRAM); - /* Avoid loading a program if CP/M-80 is not in memory */ + // Avoid loading a program if CP/M-80 is not in memory if ((prog_space.read_byte(0) != 0xc3) || (prog_space.read_byte(5) != 0xc3)) - return std::make_pair(image_error::UNSUPPORTED, std::string()); + return std::make_pair(image_error::UNSUPPORTED, "CP/M must already be running"); - if (image.length() >= 0xfd00) - return std::make_pair(image_error::INVALIDLENGTH, std::string()); + // Check for sufficient RAM based on position of CPM + const int mem_avail = 256 * prog_space.read_byte(7) + prog_space.read_byte(6) - 512; + if (mem_avail < image.length()) + return std::make_pair(image_error::UNSPECIFIED, "Insufficient memory available"); - /* Load image to the TPA (Transient Program Area) */ + // Load image to the TPA (Transient Program Area) u16 quickload_size = image.length(); for (u16 i = 0; i < quickload_size; i++) { u8 data; if (image.fread(&data, 1) != 1) - return std::make_pair(image_error::UNSPECIFIED, std::string()); - prog_space.write_byte(i+0x100, data); + return std::make_pair(image_error::BADSOFTWARE, "Problem reading the image at offset " + std::to_string(i)); + prog_space.write_byte(i + 0x100, data); } - prog_space.write_byte(0x80, 0); prog_space.write_byte(0x81, 0); // clear out command tail + // clear out command tail + prog_space.write_byte(0x80, 0); + prog_space.write_byte(0x81, 0); - m_maincpu->set_pc(0x100); // start program - m_maincpu->set_state_int(Z80_SP, 256 * prog_space.read_byte(7) - 300); // put the stack a bit before BDOS + m_maincpu->set_state_int(Z80_SP, mem_avail + 384); // put the stack a bit before BDOS + m_maincpu->set_pc(0x100); // start program return std::make_pair(std::error_condition(), std::string()); } diff --git a/src/mame/ncr/dmv.cpp b/src/mame/ncr/dmv.cpp index 69237aa5400..1e8cda6b882 100644 --- a/src/mame/ncr/dmv.cpp +++ b/src/mame/ncr/dmv.cpp @@ -402,27 +402,28 @@ UPD7220_DRAW_TEXT_LINE_MEMBER( dmv_state::hgdc_draw_text ) QUICKLOAD_LOAD_MEMBER(dmv_state::quickload_cb) { - /* Avoid loading a program if CP/M-80 is not in memory */ + // Avoid loading a program if CP/M-80 is not in memory if ((m_ram->base()[0] != 0xc3) || (m_ram->base()[5] != 0xc3)) - return std::make_pair(image_error::UNSUPPORTED, std::string()); + return std::make_pair(image_error::UNSUPPORTED, "CP/M must already be running"); - if (image.length() >= 0xfd00) - return std::make_pair(image_error::INVALIDLENGTH, std::string()); + const int mem_avail = 256 * m_ram->base()[7] + m_ram->base()[6] - 512; + if (mem_avail < image.length()) + return std::make_pair(image_error::UNSPECIFIED, "Insufficient memory available"); - /* Load image to the TPA (Transient Program Area) */ + // Load image to the TPA (Transient Program Area) uint16_t quickload_size = image.length(); for (uint16_t i = 0; i < quickload_size; i++) { uint8_t data; - if (image.fread( &data, 1) != 1) - return std::make_pair(image_error::UNSPECIFIED, std::string()); - m_ram->base()[i+0x100] = data; + if (image.fread(&data, 1) != 1) + return std::make_pair(image_error::BADSOFTWARE, "Problem reading the image at offset " + std::to_string(i)); + m_ram->base()[i + 0x100] = data; } - m_ram->base()[0x80] = m_ram->base()[0x81] = 0; // clear out command tail + m_ram->base()[0x80] = m_ram->base()[0x81] = 0; // clear out command tail - m_maincpu->set_pc(0x100); // start program - m_maincpu->set_state_int(Z80_SP, 256 * m_ram->base()[7] - 300); // put the stack a bit before BDOS + m_maincpu->set_state_int(Z80_SP, mem_avail + 384); // put the stack a bit before BDOS + m_maincpu->set_pc(0x100); // start program return std::make_pair(std::error_condition(), std::string()); } diff --git a/src/mame/sony/smc777.cpp b/src/mame/sony/smc777.cpp index 8d338056b5f..b1a6c6c2cc6 100644 --- a/src/mame/sony/smc777.cpp +++ b/src/mame/sony/smc777.cpp @@ -419,34 +419,35 @@ QUICKLOAD_LOAD_MEMBER(smc777_state::quickload_cb) { address_space& prog_space = m_maincpu->space(AS_PROGRAM); - if (image.length() >= 0xfd00) - return std::make_pair(image_error::INVALIDLENGTH, std::string()); - - /* The right RAM bank must be active */ - - /* Avoid loading a program if CP/M-80 is not in memory */ + // Avoid loading a program if CP/M-80 is not in memory if ((prog_space.read_byte(0) != 0xc3) || (prog_space.read_byte(5) != 0xc3)) { machine_reset(); - return std::make_pair(image_error::UNSUPPORTED, std::string()); + return std::make_pair(image_error::UNSUPPORTED, "CP/M must already be running"); } - /* Load image to the TPA (Transient Program Area) */ + // Check for sufficient RAM based on position of CPM + const int mem_avail = 256 * prog_space.read_byte(7) + prog_space.read_byte(6) - 512; + if (mem_avail < image.length()) + return std::make_pair(image_error::UNSPECIFIED, "Insufficient memory available"); + + // Load image to the TPA (Transient Program Area) uint16_t quickload_size = image.length(); for (uint16_t i = 0; i < quickload_size; i++) { uint8_t data; - if (image.fread( &data, 1) != 1) - return std::make_pair(image_error::UNSPECIFIED, std::string()); - prog_space.write_byte(i+0x100, data); + if (image.fread(&data, 1) != 1) + return std::make_pair(image_error::BADSOFTWARE, "Problem reading the image at offset " + std::to_string(i)); + prog_space.write_byte(i + 0x100, data); } - /* clear out command tail */ - prog_space.write_byte(0x80, 0); prog_space.write_byte(0x81, 0); + // clear out command tail */ + prog_space.write_byte(0x80, 0); + prog_space.write_byte(0x81, 0); - /* Roughly set SP basing on the BDOS position */ - m_maincpu->set_state_int(Z80_SP, 256 * prog_space.read_byte(7) - 300); - m_maincpu->set_pc(0x100); // start program + // Roughly set SP basing on the BDOS position + m_maincpu->set_state_int(Z80_SP, mem_avail + 384); + m_maincpu->set_pc(0x100); // start program return std::make_pair(std::error_condition(), std::string()); } diff --git a/src/mame/trs/coco3.cpp b/src/mame/trs/coco3.cpp index c5f3db9674e..6d5af8e936c 100644 --- a/src/mame/trs/coco3.cpp +++ b/src/mame/trs/coco3.cpp @@ -311,7 +311,7 @@ void coco3_state::coco3(machine_config &config) // monitor SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(28.636363_MHz_XTAL/2, 912, 0, 640, 262, 1, 241-1); + m_screen->set_raw(28.636363_MHz_XTAL/2, 912, 0, 640, 262, 1, 240); m_screen->set_screen_update(FUNC(coco3_state::screen_update)); // internal ram diff --git a/src/mame/xerox/xerox820.cpp b/src/mame/xerox/xerox820.cpp index b984140ce8a..00373b7916d 100644 --- a/src/mame/xerox/xerox820.cpp +++ b/src/mame/xerox/xerox820.cpp @@ -380,36 +380,38 @@ static const z80_daisy_config xerox820_daisy_chain[] = QUICKLOAD_LOAD_MEMBER(xerox820_state::quickload_cb) { - if (image.length() >= 0xfd00) - return std::make_pair(image_error::INVALIDLENGTH, std::string()); + m_view.select(0); address_space &prog_space = m_maincpu->space(AS_PROGRAM); - m_view.select(0); - - /* Avoid loading a program if CP/M-80 is not in memory */ + // Avoid loading a program if CP/M-80 is not in memory if ((prog_space.read_byte(0) != 0xc3) || (prog_space.read_byte(5) != 0xc3)) { machine_reset(); - return std::make_pair(image_error::UNSUPPORTED, std::string()); + return std::make_pair(image_error::UNSUPPORTED, "CP/M must already be running"); } - /* Load image to the TPA (Transient Program Area) */ + const int mem_avail = 256 * prog_space.read_byte(7) + prog_space.read_byte(6) - 512; + if (mem_avail < image.length()) + return std::make_pair(image_error::UNSPECIFIED, "Insufficient memory available"); + + // Load image to the TPA (Transient Program Area) uint16_t quickload_size = image.length(); for (uint16_t i = 0; i < quickload_size; i++) { uint8_t data; - if (image.fread( &data, 1) != 1) - return std::make_pair(image_error::UNSPECIFIED, std::string()); - prog_space.write_byte(i+0x100, data); + if (image.fread(&data, 1) != 1) + return std::make_pair(image_error::BADSOFTWARE, "Problem reading the image at offset " + std::to_string(i)); + prog_space.write_byte(i + 0x100, data); } - /* clear out command tail */ - prog_space.write_byte(0x80, 0); prog_space.write_byte(0x81, 0); + // clear out command tail */ + prog_space.write_byte(0x80, 0); + prog_space.write_byte(0x81, 0); - /* Roughly set SP basing on the BDOS position */ - m_maincpu->set_state_int(Z80_SP, 256 * prog_space.read_byte(7) - 300); - m_maincpu->set_pc(0x100); // start program + // Roughly set SP basing on the BDOS position + m_maincpu->set_state_int(Z80_SP, mem_avail + 384); + m_maincpu->set_pc(0x100); // start program return std::make_pair(std::error_condition(), std::string()); }