diff options
Diffstat (limited to 'src/devices/machine/bl_handhelds_menucontrol.cpp')
-rw-r--r-- | src/devices/machine/bl_handhelds_menucontrol.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/devices/machine/bl_handhelds_menucontrol.cpp b/src/devices/machine/bl_handhelds_menucontrol.cpp new file mode 100644 index 00000000000..18982731069 --- /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() +{ +} |