diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 600c22f2746..ac3cf2b31a1 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -4546,3 +4546,14 @@ if (MACHINES["ALPHA_8921"]~=null) then MAME_DIR .. "src/devices/machine/alpha_8921.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/bl_handhelds_menucontrol.h,MACHINES["BL_HANDHELDS_MENUCONTROL"] = true +--------------------------------------------------- +if (MACHINES["BL_HANDHELDS_MENUCONTROL"]~=null) then + files { + MAME_DIR .. "src/devices/machine/bl_handhelds_menucontrol.cpp", + MAME_DIR .. "src/devices/machine/bl_handhelds_menucontrol.h", + } +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index d4c33c727dd..a2040f202aa 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -779,6 +779,7 @@ MACHINES["XC1700E"] = true MACHINES["EDLC"] = true MACHINES["WTL3132"] = true MACHINES["CXD1185"] = true +MACHINES["BL_HANDHELDS_MENUCONTROL"] = true -------------------------------------------------- -- specify available bus cores diff --git a/src/devices/machine/bl_handhelds_menucontrol.cpp b/src/devices/machine/bl_handhelds_menucontrol.cpp new file mode 100644 index 00000000000..305f90ecfce --- /dev/null +++ b/src/devices/machine/bl_handhelds_menucontrol.cpp @@ -0,0 +1,214 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +// Menu controller, stores / increments menu position etc. used on handhelds that typically have BL on the boot screen (BaoBaoLong?) + +#include "emu.h" +#include "machine/bl_handhelds_menucontrol.h" + +DEFINE_DEVICE_TYPE(BL_HANDHELDS_MENUCONTROL, bl_handhelds_menucontrol_device, "blhandheldmenu", "BaoBaoLong Handhelds Menu Controller") + +bl_handhelds_menucontrol_device::bl_handhelds_menucontrol_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, BL_HANDHELDS_MENUCONTROL, tag, owner, clock), + m_is_unsp_type_hack(false) +{ +} + +READ_LINE_MEMBER(bl_handhelds_menucontrol_device::status_r) +{ + return m_clockstate; +} + +READ_LINE_MEMBER(bl_handhelds_menucontrol_device::data_r) +{ + return m_responsebit; +} + +// is there some 'carry' related behavior on the add / remove, because sometimes calculations are off by 1 eg command 0x05 (subtract) subcommand 0xf0 +// edge cases to test - moving up and left off entry 0, moving next / previous page when on any entry on the first/last pages, moving down/right off last entry, crossing 255/256 game boundary +void bl_handhelds_menucontrol_device::handle_command() +{ + uint8_t command = m_command; + + // additions and subtractions here are likely also meant to be done as high byte and low byte + if (m_menustate == MENU_READY_FOR_COMMAND) + { + if (command == 0x00) + { + m_menustate = MENU_COMMAND_00_IN; + m_response = m_menupos & 0xff; + } + else if (command == 0x01) + { + m_menustate = MENU_COMMAND_01_IN; + m_response = (m_menupos >> 8) & 0xff; + } + else if (command == 0x02) + { + m_menustate = MENU_COMMAND_02_IN; + } + else if (command == 0x03) + { + m_menustate = MENU_COMMAND_03_IN; + } + else if (command == 0x04) + { + m_menustate = MENU_COMMAND_04_IN; + } + else if (command == 0x05) + { + m_menustate = MENU_COMMAND_05_IN; + } + else if (command == 0x09) + { + // ... + } + else if ((command) == 0x10) + { + // this is followed by 0x1b, written if you try to move right off last entry + m_menupos = 0x00; + } + else if (command == 0x30) + { + m_menupos++; + } + else if (command == 0x37) + { + m_menupos--; + } + else if (command == 0x39) + { + m_menupos -= 4; + } + else if (command == 0x2c) + { + m_menupos = 0x01; + } + else + { + logerror("handle_command %02x (unknown)\n", command); + } + } + else if (m_menustate == MENU_COMMAND_00_IN) + { + m_menustate = MENU_READY_FOR_COMMAND; + } + else if (m_menustate == MENU_COMMAND_01_IN) + { + m_menustate = MENU_READY_FOR_COMMAND; + } + else if (m_menustate == MENU_COMMAND_02_IN) + { + m_menupos = (m_menupos & 0xff00) | ((command - 0x8) & 0xff); + m_menustate = MENU_READY_FOR_COMMAND; + } + else if (m_menustate == MENU_COMMAND_03_IN) + { + m_menupos = (m_menupos & 0x00ff) | (((command - 0x9) & 0xff) << 8); + m_menustate = MENU_READY_FOR_COMMAND; + } + else if (m_menustate == MENU_COMMAND_04_IN) + { + // used if you try to scroll up or left past 0 and the value becomes too large (a negative number) + if (m_is_unsp_type_hack) + { + if (command == 0x0d) + m_menupos += 4; + else if (command == 0x0a) + m_menupos += 0; + // used if you try to scroll up or left past 0 and the value becomes too large (a negative number) + // actually writes 0x314 split into 2 commands, so the 2nd write to 0x04 with param then instead 0b/16 sequence of writes instead of 26/0c adds to the high byte? + else if (command == 0x1e) + m_menupos += 0x310; + } + else + { + m_menupos += (command - 0x09); + m_menustate = MENU_READY_FOR_COMMAND; + } + + m_menustate = MENU_READY_FOR_COMMAND; + } + else if (m_menustate == MENU_COMMAND_05_IN) + { + // used if you try to scroll down past the and the value becomes too large + if (m_is_unsp_type_hack) + { + // actually writes 0x313 split into 2 commands, so the 2nd write to 0x05 with param then instead 0b/16 sequence of writes instead of 26/0c subtracts from the high byte? + if (command == 0x0b) + { + m_menupos -= 0xdc; + } + else if (command == 0x0e) + { + m_menupos -= 0x314; + } + } + else + { + if (command != 0xf0) + m_menupos -= (command - 0x0b); + else + m_menupos -= (command - 0x0a); // dphh8630 when pressing 'right' on final menu page + } + + m_menustate = MENU_READY_FOR_COMMAND; + } +} + +WRITE_LINE_MEMBER(bl_handhelds_menucontrol_device::clock_w) +{ + if (state) + { + m_clockstate = 1; + } + else + { + m_clockstate = 0; + m_command <<= 1; + m_command |= ((m_commandbit)); + m_responsebit = (m_response >> (7 - m_datashifterpos)) & 1; + m_datashifterpos++; + + if (m_datashifterpos == 8) + { + m_datashifterpos = 0; + handle_command(); + } + } +} + +WRITE_LINE_MEMBER(bl_handhelds_menucontrol_device::data_w) +{ + m_commandbit = state; +} + +WRITE_LINE_MEMBER(bl_handhelds_menucontrol_device::reset_w) +{ + m_datashifterpos = 0; +} + +void bl_handhelds_menucontrol_device::device_start() +{ + m_responsebit = 0; + m_clockstate = 0; + m_command = 0; + m_datashifterpos = 0; + m_menupos = 0; + m_response = 0; + m_commandbit = 0; + m_menustate = MENU_READY_FOR_COMMAND; + + save_item(NAME(m_menupos)); + save_item(NAME(m_clockstate)); + save_item(NAME(m_datashifterpos)); + save_item(NAME(m_responsebit)); + save_item(NAME(m_response)); + save_item(NAME(m_commandbit)); + save_item(NAME(m_command)); + //save_item(NAME(m_menustate)); +} + +void bl_handhelds_menucontrol_device::device_reset() +{ +} diff --git a/src/devices/machine/bl_handhelds_menucontrol.h b/src/devices/machine/bl_handhelds_menucontrol.h new file mode 100644 index 00000000000..bb3d68677c9 --- /dev/null +++ b/src/devices/machine/bl_handhelds_menucontrol.h @@ -0,0 +1,64 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#ifndef MAME_MACHINE_BL_HANDHELDS_MENUCONTROL_H +#define MAME_MACHINE_BL_HANDHELDS_MENUCONTROL_H + +#pragma once + +DECLARE_DEVICE_TYPE(BL_HANDHELDS_MENUCONTROL, bl_handhelds_menucontrol_device) + +class bl_handhelds_menucontrol_device : public device_t +{ +public: + // construction/destruction + bl_handhelds_menucontrol_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // the chip is the same between systems, but there's some logic not fully understood that is causing off-by-1 errors on some calcs + void set_is_unsp_type_hack() { m_is_unsp_type_hack = true; } + + DECLARE_READ_LINE_MEMBER(status_r); + DECLARE_READ_LINE_MEMBER(data_r); + DECLARE_WRITE_LINE_MEMBER(clock_w); + DECLARE_WRITE_LINE_MEMBER(data_w); + DECLARE_WRITE_LINE_MEMBER(reset_w); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: + // config + bool m_is_unsp_type_hack; + + // internal state + int m_menupos; + + // command handling + int m_clockstate; + int m_datashifterpos; + + int m_responsebit; + uint8_t m_response; + + int m_commandbit; + uint8_t m_command; + + void handle_command(); + + enum menustate : const int + { + MENU_READY_FOR_COMMAND = 0, + + MENU_COMMAND_00_IN, + MENU_COMMAND_01_IN, + MENU_COMMAND_02_IN, + MENU_COMMAND_03_IN, + MENU_COMMAND_04_IN, + MENU_COMMAND_05_IN, + }; + + menustate m_menustate; +}; + +#endif // MAME_MACHINE_BL_HANDHELDS_MENUCONTROL_H diff --git a/src/mame/drivers/generalplus_gpl_unknown.cpp b/src/mame/drivers/generalplus_gpl_unknown.cpp index a64260644e2..fffce35facb 100644 --- a/src/mame/drivers/generalplus_gpl_unknown.cpp +++ b/src/mame/drivers/generalplus_gpl_unknown.cpp @@ -22,12 +22,12 @@ #include "emu.h" #include "cpu/unsp/unsp.h" +#include "machine/bl_handhelds_menucontrol.h" #include "emupal.h" #include "screen.h" #include "speaker.h" - #define LOG_GPL162XX_LCDTYPE (1U << 1) #define LOG_GPL162XX_LCDTYPE_SELECT_SIM (1U << 2) #define LOG_GPL162XX_LCDTYPE_IO_PORT (1U << 3) @@ -50,14 +50,12 @@ public: m_screen(*this, "screen"), m_spirom(*this, "spi"), m_io_in0(*this, "IN0"), - m_io_in1(*this, "IN1") + m_io_in1(*this, "IN1"), + m_menucontrol(*this, "menucontrol") { } void gpl162xx_lcdtype(machine_config &config); - DECLARE_READ_LINE_MEMBER(bit08state_r); - DECLARE_READ_LINE_MEMBER(latchinbit_r); - private: virtual void machine_start() override; virtual void machine_reset() override; @@ -170,33 +168,9 @@ private: uint16_t io_7870_r(); required_ioport m_io_in0; required_ioport m_io_in1; + required_device m_menucontrol; DECLARE_WRITE_LINE_MEMBER(screen_vblank); - - - int m_latchinbit; - void tx_menu_cmd(uint8_t command); - - int m_bit08state; - int m_latchdata; - - int m_latchpos; - int m_menupos; - uint8_t m_datain; - - enum menustate : const int - { - MENU_READY_FOR_COMMAND = 0, - - MENU_COMMAND_00_IN, - MENU_COMMAND_01_IN, - MENU_COMMAND_02_IN, - MENU_COMMAND_03_IN, - MENU_COMMAND_04_IN, - MENU_COMMAND_05_IN, - }; - - menustate m_menustate; }; uint32_t gpl162xx_lcdtype_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) @@ -208,7 +182,7 @@ uint32_t gpl162xx_lcdtype_state::screen_update(screen_device &screen, bitmap_rgb for (int x = 0; x < 320; x++) { - // 8-bit values get pumped through a 256 word table in intenral ROM and converted to words, so it's probably raw 16-bit RGB data? + // 8-bit values get pumped through a 256 word table in internal ROM and converted to words uint16_t dat = m_displaybuffer[(count * 2) + 1] | (m_displaybuffer[(count * 2) + 0] << 8); int b = ((dat >> 0) & 0x1f) << 3; @@ -224,18 +198,6 @@ uint32_t gpl162xx_lcdtype_state::screen_update(screen_device &screen, bitmap_rgb } - -READ_LINE_MEMBER( gpl162xx_lcdtype_state::bit08state_r ) -{ - return m_bit08state; -} - -READ_LINE_MEMBER( gpl162xx_lcdtype_state::latchinbit_r ) -{ - return m_latchinbit; -} - - static INPUT_PORTS_START( gpl162xx_lcdtype ) PORT_START("IN0") PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED ) // causes lag if state is inverted, investigate @@ -245,8 +207,8 @@ static INPUT_PORTS_START( gpl162xx_lcdtype ) PORT_DIPNAME( 0x0004, 0x0000, "Show Vs in Test Mode" ) PORT_DIPSETTING( 0x0000, "0000" ) PORT_DIPSETTING( 0x0004, "0004" ) - PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(gpl162xx_lcdtype_state, bit08state_r) - PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(gpl162xx_lcdtype_state, latchinbit_r) + PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("menucontrol", bl_handhelds_menucontrol_device, status_r) + PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("menucontrol", bl_handhelds_menucontrol_device, data_r) PORT_DIPNAME( 0x0020, 0x0020, "P0:0020" ) PORT_DIPSETTING( 0x0000, "0000" ) PORT_DIPSETTING( 0x0020, "0020" ) @@ -326,136 +288,10 @@ uint16_t gpl162xx_lcdtype_state::io_7860_r() return ret; } -// TODO: make this a device, the unk6502_st2xxx.cpp units use the same thing -void gpl162xx_lcdtype_state::tx_menu_cmd(uint8_t command) -{ - // additions and subtractions here are likely also meant to be done as high byte and low byte - if (m_menustate == MENU_READY_FOR_COMMAND) - { - if (command == 0x00) - { - m_menustate = MENU_COMMAND_00_IN; - m_datain = m_menupos & 0xff; - } - else if (command == 0x01) - { - m_menustate = MENU_COMMAND_01_IN; - m_datain = (m_menupos >> 8) & 0xff; - } - else if (command == 0x02) - { - m_menustate = MENU_COMMAND_02_IN; - } - else if (command == 0x03) - { - m_menustate = MENU_COMMAND_03_IN; - } - else if (command == 0x04) - { - m_menustate = MENU_COMMAND_04_IN; - } - else if (command == 0x05) - { - m_menustate = MENU_COMMAND_05_IN; - } - else if (command == 0x09) - { - // ... - } - else if ((command) == 0x10) - { - // this is followed by 0x1b, written if you try to move right off last entry - m_menupos = 0x00; - } - else if (command == 0x30) - { - m_menupos++; - } - else if (command == 0x37) - { - m_menupos--; - } - else if (command == 0x39) - { - m_menupos -= 4; - } - else if (command == 0x2c) - { - m_menupos = 0x01; - } - else - { - LOGMASKED(LOG_GPL162XX_LCDTYPE_SELECT_SIM, "tx_menu_cmd %02x (unknown)\n", command); - } - } - else if (m_menustate == MENU_COMMAND_00_IN) - { - m_menustate = MENU_READY_FOR_COMMAND; - } - else if (m_menustate == MENU_COMMAND_01_IN) - { - m_menustate = MENU_READY_FOR_COMMAND; - } - else if (m_menustate == MENU_COMMAND_02_IN) - { - m_menupos = (m_menupos & 0xff00) | ((command - 0x8) & 0xff); - m_menustate = MENU_READY_FOR_COMMAND; - } - else if (m_menustate == MENU_COMMAND_03_IN) - { - m_menupos = (m_menupos & 0x00ff) | (((command - 0x9) & 0xff) << 8); - m_menustate = MENU_READY_FOR_COMMAND; - } - else if (m_menustate == MENU_COMMAND_04_IN) - { - if (command == 0x0d) - m_menupos += 4; - else if (command == 0x0a) - m_menupos += 0; - // used if you try to scroll up or left past 0 and the value becomes too large (a negative number) - // actually writes 0x314 split into 2 commands, so the 2nd write to 0x04 with param then instead 0b/16 sequence of writes instead of 26/0c adds to the high byte? - else if (command == 0x1e) - m_menupos += 0x310; - - m_menustate = MENU_READY_FOR_COMMAND; - } - else if (m_menustate == MENU_COMMAND_05_IN) - { - // used if you try to scroll down past the and the value becomes too large - // actually writes 0x313 split into 2 commands, so the 2nd write to 0x05 with param then instead 0b/16 sequence of writes instead of 26/0c subtracts from the high byte? - if (command == 0x0b) - { - m_menupos -= 0xdc; - } - else if (command == 0x0e) - { - m_menupos -= 0x314; - } - - m_menustate = MENU_READY_FOR_COMMAND; - } -} - void gpl162xx_lcdtype_state::io_7860_w(uint16_t data) { - if (data & 0x20) - { - m_bit08state = 1; - } - else - { - m_bit08state = 0; - m_latchdata <<= 1; - m_latchdata |= ((data & 0x10) >> 4); - m_latchinbit = (m_datain >> (7 - m_latchpos)) & 1; - m_latchpos++; - - if (m_latchpos == 8) - { - m_latchpos = 0; - tx_menu_cmd(m_latchdata); - } - } + m_menucontrol->data_w((data & 0x10)>>4); + m_menucontrol->clock_w((data & 0x20)>>5); m_7860 = data; } @@ -469,7 +305,7 @@ void gpl162xx_lcdtype_state::unk_7863_w(uint16_t data) // probably port direction (or 7862 is?) if (data == 0x3cf7) { - m_latchpos = 0; + m_menucontrol->reset_w(1); } } @@ -979,8 +815,6 @@ void gpl162xx_lcdtype_state::machine_reset() // first menu index is stored here // m_spirom[0x16000] = gamenum & 0xff; // m_spirom[0x16001] = (gamenum>>8) & 0xff; - - m_menupos = 0; } WRITE_LINE_MEMBER(gpl162xx_lcdtype_state::screen_vblank) @@ -1012,6 +846,10 @@ void gpl162xx_lcdtype_state::gpl162xx_lcdtype(machine_config &config) m_screen->screen_vblank().set(FUNC(gpl162xx_lcdtype_state::screen_vblank)); PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 0x8000); + + BL_HANDHELDS_MENUCONTROL(config, m_menucontrol, 0); + m_menucontrol->set_is_unsp_type_hack(); + } // pcp8718 and pcp8728 both contain user data (player name?) and will need to be factory defaulted once they work