From 21d5d9c8fca607e7c184495a0b668159a61a32e7 Mon Sep 17 00:00:00 2001
From: qufb <93520295+qufb@users.noreply.github.com>
Date: Sun, 23 Jun 2024 17:24:47 +0100
Subject: [PATCH] sega/sega_beena.cpp, carbeena.xml: Add Car Beena and BIOS
MIDI PCM ROMs (#12503)
* sega/sega_beena.cpp, carbeena.xml: Add Car Beena and BIOS MIDI PCM ROMs
New working software items (carbeena.xml)
-------------------------
Car Beena Tentou-you Demo 1 [TeamEurope, QUFB]
---
hash/carbeena.xml | 24 +++++
src/mame/mame.lst | 1 +
src/mame/sega/sega_beena.cpp | 170 ++++++++++++++++++++++++++---------
3 files changed, 154 insertions(+), 41 deletions(-)
create mode 100644 hash/carbeena.xml
diff --git a/hash/carbeena.xml b/hash/carbeena.xml
new file mode 100644
index 00000000000..42875a5cad5
--- /dev/null
+++ b/hash/carbeena.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Car Beena Tentou-you Demo 1
+ 2009
+ Sega Toys
+ Info from header
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 9c00836715e..880335e44d7 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -39753,6 +39753,7 @@ sderby2 // (c) 1985
@source:sega/sega_beena.cpp
beena //
tvochken //
+carbeena //
@source:sega/sega_sawatte.cpp
sawatte //
diff --git a/src/mame/sega/sega_beena.cpp b/src/mame/sega/sega_beena.cpp
index 7b47309cc6e..2d12dd8135a 100644
--- a/src/mame/sega/sega_beena.cpp
+++ b/src/mame/sega/sega_beena.cpp
@@ -11,6 +11,8 @@
MIDI audio
Peripherals (including the SD-Card adapter)
Component list / PCB diagram
+ Fix graphical glitches (e.g. 'Car Beena' scrolling background)
+ Fix test mode for 'Car Beena' (fails on 'Test EEP')
Hardware
--------
@@ -125,6 +127,10 @@
Toggling 'Memory Cache' allows the player to observe differences between test failure and success.
+ For 'TV Ocha-Ken', hold down A B C, then power on the system, release all buttons, and press B 3 times.
+
+ For 'Car Beena', hold down all 3 buttons, turn the handle left to full lock, then power on the system.
+
*******************************************************************************/
#include "emu.h"
@@ -1724,12 +1730,51 @@ void sega_9h0_0008_state::sega_9h0_0008(machine_config &config)
}
-class sega_beena_state : public sega_9h0_0008_state
+class sega_9h0_0008_cart_state : public sega_9h0_0008_state
+{
+public:
+ sega_9h0_0008_cart_state(const machine_config &mconfig, device_type type, const char *tag)
+ : sega_9h0_0008_state(mconfig, type, tag)
+ , m_cart(*this, "cartslot")
+ { }
+
+protected:
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
+
+ required_device m_cart;
+};
+
+DEVICE_IMAGE_LOAD_MEMBER(sega_9h0_0008_cart_state::cart_load)
+{
+ uint32_t const size = m_cart->common_get_size("rom");
+
+ m_cart->rom_alloc(size, GENERIC_ROM32_WIDTH, ENDIANNESS_BIG);
+ m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
+
+ if (!image.loaded_through_softlist()) {
+ // loadflags weren't parsed, start by manually applying `endianness="big"`,
+ // taking into consideration the host's endianness.
+ uint32_t *rom32 = reinterpret_cast(m_cart->get_rom_base());
+ for (size_t i = 0; i < size / 4; i++) {
+ rom32[i] = big_endianize_int32(rom32[i]);
+ }
+ // Afterwards apply `load16_word_swap`, regardless of host's endianness,
+ // since this reflects how ROM data was stored, not the CPU's architecture.
+ uint16_t *rom16 = reinterpret_cast(m_cart->get_rom_base());
+ for (size_t i = 0; i < size / 2; i++) {
+ rom16[i] = swapendian_int16(rom16[i]);
+ }
+ }
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+
+class sega_beena_state : public sega_9h0_0008_cart_state
{
public:
sega_beena_state(const machine_config &mconfig, device_type type, const char *tag)
- : sega_9h0_0008_state(mconfig, type, tag)
- , m_cart(*this, "cartslot")
+ : sega_9h0_0008_cart_state(mconfig, type, tag)
, m_io_page_config(*this, "PAGE_CONFIG")
, m_io_page(*this, "PAGE")
, m_io_pad_left(*this, "PAD_LEFT")
@@ -1745,13 +1790,10 @@ public:
virtual DECLARE_CROSSHAIR_MAPPER_MEMBER(pen_y_mapper);
private:
- DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
virtual void install_game_rom() override;
virtual void update_crosshair(screen_device &screen) override;
virtual void update_sensors(offs_t offset) override;
- required_device m_cart;
-
required_ioport m_io_page_config;
required_ioport m_io_page;
required_ioport m_io_pad_left;
@@ -1937,31 +1979,6 @@ void sega_beena_state::update_sensors(offs_t offset)
}
}
-DEVICE_IMAGE_LOAD_MEMBER(sega_beena_state::cart_load)
-{
- uint32_t const size = m_cart->common_get_size("rom");
-
- m_cart->rom_alloc(size, GENERIC_ROM32_WIDTH, ENDIANNESS_BIG);
- m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
-
- if (!image.loaded_through_softlist()) {
- // loadflags weren't parsed, start by manually applying `endianness="big"`,
- // taking into consideration the host's endianness.
- uint32_t *rom32 = reinterpret_cast(m_cart->get_rom_base());
- for (size_t i = 0; i < size / 4; i++) {
- rom32[i] = big_endianize_int32(rom32[i]);
- }
- // Afterwards apply `load16_word_swap`, regardless of host's endianness,
- // since this reflects how ROM data was stored, not the CPU's architecture.
- uint16_t *rom16 = reinterpret_cast(m_cart->get_rom_base());
- for (size_t i = 0; i < size / 2; i++) {
- rom16[i] = swapendian_int16(rom16[i]);
- }
- }
-
- return std::make_pair(std::error_condition(), std::string());
-}
-
CROSSHAIR_MAPPER_MEMBER(sega_beena_state::pen_y_mapper)
{
// TODO: Either remove or adapt for Storyware layout
@@ -2134,6 +2151,58 @@ void tvochken_state::install_game_rom()
}
+class carbeena_state : public sega_9h0_0008_cart_state
+{
+public:
+ carbeena_state(const machine_config &mconfig, device_type type, const char *tag)
+ : sega_9h0_0008_cart_state(mconfig, type, tag)
+ , m_io_buttons(*this, "BUTTONS")
+ { }
+
+ void carbeena(machine_config &config);
+
+ virtual uint32_t io_expansion_r() override;
+
+private:
+ virtual void install_game_rom() override;
+
+ required_ioport m_io_buttons;
+};
+
+void carbeena_state::carbeena(machine_config &config)
+{
+ sega_9h0_0008(config);
+
+ GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "carbeena_cart");
+ m_cart->set_endian(ENDIANNESS_BIG);
+ m_cart->set_width(GENERIC_ROM32_WIDTH);
+ m_cart->set_device_load(FUNC(carbeena_state::cart_load));
+ m_cart->set_must_be_loaded(false);
+
+ SOFTWARE_LIST(config, "cart_list").set_original("carbeena_cart");
+}
+
+uint32_t carbeena_state::io_expansion_r()
+{
+ return m_io_buttons->read() & 0x3f;
+}
+
+void carbeena_state::install_game_rom()
+{
+ // TODO: These mappings are controlled by program code via writes to 0x60020004 and 0x60020010.
+ // Likely only one of them should be mapped at a time (also suggested by test mode, which only
+ // outputs 1 size out of 2 installed ROMs).
+ if (m_cart->exists()) {
+ std::string region_tag;
+ memory_region *cart_rom = m_cart->memregion("cart:rom");
+ m_maincpu->space(AS_PROGRAM).install_rom(ROM_FLASH_BASE, ROM_FLASH_BASE + 0x7fffff, 0x800000, cart_rom->base());
+ }
+
+ // Despite being a flash ROM, it gets mapped on the base address usually assigned to mask ROMs.
+ memory_region *rom = memregion("mainboard_rom");
+ m_maincpu->space(AS_PROGRAM).install_rom(ROM_MASK_BASE, ROM_MASK_BASE + 0x7fffff, 0x800000, rom->base());
+}
+
static INPUT_PORTS_START( sega_9h0_0008 )
PORT_START("VIDEO_CONFIG")
PORT_CONFNAME( 0x80, 0x00, "Video Output" )
@@ -2207,17 +2276,27 @@ static INPUT_PORTS_START( tvochken )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("Scan Card") PORT_WRITE_LINE_MEMBER(tvochken_state, scan_card)
INPUT_PORTS_END
+static INPUT_PORTS_START( carbeena )
+ PORT_INCLUDE( sega_9h0_0008 )
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_NAME("Handle Left")
+ PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_NAME("Handle Limit") // TODO: Likely set when turning the handle to full lock
+ PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("Handle Right")
+ PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Blue Button") // At the right of the center button, despite being mapped to a lower bit
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("Center Button")
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("Yellow Button")
+INPUT_PORTS_END
#define ROM_9H0_0008 \
/* SoC internal BIOS dumped with a JTAG debugger. */ \
ROM_REGION32_BE( 0x20000, "maincpu", 0 ) \
- ROM_LOAD( "9h0-0008.bios.ic1", 0x00000000, 0x20000, CRC(5471aaf8) SHA1(33d756b6c64afb0fa377b3f85ab74505e9ae2f9c) )
-
- // SoC MIDI synthesizer parameters and PCM data.
- // Control ROM doesn't appear to be memory-mapped, so this data will only
- // be usable when the synthesizer gets reverse engineered.
- // ROM_REGION32_BE( 0x8000, "midipcm", 0 )
- // ROM_LOAD( "9h0-0008.midipcm.ic1", 0x00000000, 0x8000, CRC(ed336d29) SHA1(4af7b7cf7fc4fe8b7a514cde91f930a582742509) )
+ ROM_LOAD( "9h0-0008.bios.ic1", 0x00000000, 0x20000, CRC(5471aaf8) SHA1(33d756b6c64afb0fa377b3f85ab74505e9ae2f9c) ) \
+ /* SoC MIDI synthesizer parameters and PCM data. */ \
+ /* Control ROM doesn't appear to be memory-mapped, so this data will only */ \
+ /* be usable when the synthesizer gets reverse engineered. */ \
+ ROM_REGION32_BE( 0x8000, "midipcm", 0 ) \
+ ROM_LOAD( "9h0-0008.midipcm.ic1", 0x00000000, 0x8000, CRC(ed336d29) SHA1(4af7b7cf7fc4fe8b7a514cde91f930a582742509) )
ROM_START( beena )
ROM_9H0_0008
@@ -2230,8 +2309,17 @@ ROM_START( tvochken )
ROM_LOAD16_WORD_SWAP( "m5m29gt320vp-80.u3", 0x00000000, 0x400000, CRC(75c1fbc1) SHA1(b07adcabaadb8b684335f52dd953f4696585c819) )
ROM_END
+ROM_START( carbeena )
+ ROM_9H0_0008
+
+ ROM_REGION32_BE( 0x800000, "mainboard_rom", ROMREGION_ERASEFF )
+ ROM_LOAD16_WORD_SWAP( "en29lv640b.ic9", 0x00000000, 0x800000, CRC(ce6649df) SHA1(e09568b93c9ab0901c6eb32d5e0408e484d4c564) )
+ROM_END
+
} // anonymous namespace
-// year, name, parent, compat, machine, input, class, init, company, fullname, flags
-CONS( 2005, beena, 0, 0, sega_beena, sega_beena, sega_beena_state, empty_init, "Sega", "Advanced Pico BEENA", MACHINE_IMPERFECT_GRAPHICS|MACHINE_IMPERFECT_TIMING|MACHINE_IMPERFECT_SOUND )
-CONS( 2005, tvochken, 0, 0, tvochken, tvochken, tvochken_state, empty_init, "Sega", "TV Ocha-Ken", MACHINE_IMPERFECT_GRAPHICS|MACHINE_IMPERFECT_TIMING|MACHINE_IMPERFECT_SOUND )
+// year, name, parent, compat, machine, input, class, init, company, fullname, flags
+CONS( 2005, beena, 0, 0, sega_beena, sega_beena, sega_beena_state, empty_init, "Sega Toys", "Advanced Pico BEENA", MACHINE_IMPERFECT_GRAPHICS|MACHINE_IMPERFECT_TIMING|MACHINE_IMPERFECT_SOUND )
+CONS( 2005, tvochken, 0, 0, tvochken, tvochken, tvochken_state, empty_init, "Sega Toys", "TV Ocha-Ken", MACHINE_IMPERFECT_GRAPHICS|MACHINE_IMPERFECT_TIMING|MACHINE_IMPERFECT_SOUND )
+// Release date 2009-12: http://products.alpine.co.jp/om/owner/product?P1=1632
+CONS( 2009, carbeena, 0, 0, carbeena, carbeena, carbeena_state, empty_init, "Sega Toys / Alpine Electronics, Inc.", "Car Beena", MACHINE_IMPERFECT_GRAPHICS|MACHINE_IMPERFECT_TIMING|MACHINE_IMPERFECT_SOUND )