summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine
diff options
context:
space:
mode:
author David Haywood <28625134+DavidHaywood@users.noreply.github.com>2020-09-21 18:17:25 +0100
committer GitHub <noreply@github.com>2020-09-21 13:17:25 -0400
commit04672777eb9cb388d37150d2be4db25ae71b6ca3 (patch)
tree853aa0565e7869e2ee1788f7004980eb02cac610 /src/devices/machine
parent85cbd20517a127845fea795ec0b3330aae33ea0a (diff)
pcp8718 / pcp8728 / bkid218 - make menu controller a shared device (#7270)
Diffstat (limited to 'src/devices/machine')
-rw-r--r--src/devices/machine/bl_handhelds_menucontrol.cpp214
-rw-r--r--src/devices/machine/bl_handhelds_menucontrol.h64
2 files changed, 278 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..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