pcp8718 / pcp8728 / bkid218 - make menu controller a shared device (#7270)

This commit is contained in:
David Haywood 2020-09-21 18:17:25 +01:00 committed by GitHub
parent 85cbd20517
commit 04672777eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 304 additions and 176 deletions

View File

@ -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

View File

@ -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

View File

@ -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()
{
}

View File

@ -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

View File

@ -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<bl_handhelds_menucontrol_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