cothello: add coin handling and sound

This commit is contained in:
hap 2023-02-01 23:31:48 +01:00
parent acc7d534af
commit dbaf7b376d
3 changed files with 117 additions and 21 deletions

View File

@ -65,7 +65,7 @@ void beep_device::sound_stream_update(sound_stream &stream, std::vector<read_str
clock = m_frequency;
/* if we're not enabled, just fill with 0 */
if ( !m_enable || clock == 0 )
if (!m_enable || clock == 0)
{
buffer.fill(0);
return;

View File

@ -57,10 +57,11 @@
emulates an unmodified PCB, you can enable the hacks in the DRIVER
CONFIGURATION menu.
B&W cabinet versions also exist.
Versions of Tomahawk using the Astro Fighter PROM have been seen,
see notes in ROM loading.
****************************************************************************/

View File

@ -12,27 +12,32 @@ and is presumed to be on the same base hardware as the arcade version.
Hardware notes:
- PCB label: COG CPU
- M58710S (8080A), ?MHz XTAL
- M58710S (8080A), 3.579545MHz XTAL
- 3*1KB M58732S 2708 ROM, 4th socket is empty
- 256 bytes RAM (2*M58722P 2111A), 0.5KB DRAM (M58755S)
- M58741P Color TV Interface, 64*64 1bpp video
- 7seg time counter (not software controlled)
- beeper
TODO:
- verify XTAL
- verify video timing
- coin
- sound
- is there a button select, or is current input emulation correct where for
example P1 can move P2 cursor? (the only unique P2 button is the Set button)
- unknown if the screen is color or B&W + overlay, but since the video chip is
meant for a color tv, let's assume the green tint is from the screen itself
- beeper duration and base frequency is approximated (divisor is correct)
- CPU speed is wrong, it's likely running at 1.79MHz. But that's way too fast
compared to videos of the game. 0.9MHz(XTAL/4) is also too fast. It's probably
due to the M58741P HOLD pin halting the 8080, which is not emulated.
- Is there a button select somewhere? I really can't find any. Or is current
input emulation correct where for example P1 can move P2 cursor? (the only
unique P2 button is the Set button)
- It's not known if the screen is color or B&W + overlay, but since the video
chip is meant for a color tv, let's assume the green tint is from the screen
itself. Photos of the home version also show a green tint.
*******************************************************************************/
#include "emu.h"
#include "cpu/i8085/i8085.h"
#include "sound/beep.h"
#include "screen.h"
#include "speaker.h"
@ -50,26 +55,52 @@ public:
m_maincpu(*this, "maincpu"),
m_screen(*this, "screen"),
m_vram(*this, "vram"),
m_inputs(*this, "IN.%u", 0)
m_beeper(*this, "beeper"),
m_inputs(*this, "IN.%u", 0),
m_digits(*this, "digit%u", 0U)
{ }
void cothello(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(insert_coin);
protected:
virtual void machine_start() override;
private:
required_device<cpu_device> m_maincpu;
required_device<screen_device> m_screen;
required_shared_ptr<u8> m_vram;
required_ioport_array<3> m_inputs;
required_device<beep_device> m_beeper;
required_ioport_array<4> m_inputs;
output_finder<4> m_digits;
void main_map(address_map &map);
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
u8 input_r();
u8 coin_r();
u8 input_r();
void sound_w(u8 data);
TIMER_CALLBACK_MEMBER(counter_tick);
TIMER_CALLBACK_MEMBER(beeper_off) { m_beeper->set_state(0); }
u16 m_counter = 0;
emu_timer *m_counter_timer;
emu_timer *m_beeper_off;
};
void cothello_state::machine_start()
{
m_digits.resolve();
m_counter_timer = timer_alloc(FUNC(cothello_state::counter_tick), this);
m_beeper_off = timer_alloc(FUNC(cothello_state::beeper_off), this);
save_item(NAME(m_counter));
}
/*******************************************************************************
@ -96,6 +127,46 @@ u32 cothello_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, c
I/O
*******************************************************************************/
INPUT_CHANGED_MEMBER(cothello_state::insert_coin)
{
if (!newval || m_counter_timer->enabled())
return;
// reset counter
m_counter = ~0;
m_counter_timer->adjust(attotime::zero);
}
TIMER_CALLBACK_MEMBER(cothello_state::counter_tick)
{
m_counter++;
// highest digit is compared to a digit wheel setting
u8 max = std::clamp(int(m_inputs[3]->read()), 1, 9);
u8 high = (m_counter / 100) % 10;
if (high == 0 || high == max)
m_maincpu->set_input_line(0, HOLD_LINE);
if (high != max)
m_counter_timer->adjust(attotime::from_seconds(1));
// output counter to 7segs
static const u8 led_map[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f };
m_digits[0] = led_map[m_counter % 10];
m_digits[1] = led_map[(m_counter / 10) % 10];
m_digits[2] = led_map[high];
}
u8 cothello_state::coin_r()
{
// d0-d2: coin status
// d3: ?
// d4-d7: unused
return m_counter_timer->enabled() ? 0xfb : 0xff;
}
u8 cothello_state::input_r()
{
u8 data = 0xff;
@ -106,14 +177,22 @@ u8 cothello_state::input_r()
return data;
}
u8 cothello_state::coin_r()
{
return 0xfb;
}
void cothello_state::sound_w(u8 data)
{
//printf("%X ",data);
if (data & 0x80)
{
// d3: beeper start
if (data & 8)
{
m_beeper->set_state(1);
m_beeper_off->adjust(attotime::from_msec(80));
}
// d0-d2: beeper frequency
u8 freq = (data & 0x7) + 1;
const u32 base = 3500;
m_beeper->set_clock(base / freq);
}
}
@ -164,6 +243,21 @@ static INPUT_PORTS_START( cothello )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL PORT_NAME("P2 Pass")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_NAME("P2 Set")
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.3")
PORT_CONFNAME( 0x0f, 0x05, "Time" )
PORT_DIPSETTING( 0x01, "100 seconds" )
PORT_DIPSETTING( 0x02, "200 seconds" )
PORT_DIPSETTING( 0x03, "300 seconds" )
PORT_DIPSETTING( 0x04, "400 seconds" )
PORT_DIPSETTING( 0x05, "500 seconds" )
PORT_DIPSETTING( 0x06, "600 seconds" )
PORT_DIPSETTING( 0x07, "700 seconds" )
PORT_DIPSETTING( 0x08, "800 seconds" )
PORT_DIPSETTING( 0x09, "900 seconds" )
PORT_START("COIN")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, cothello_state, insert_coin, 0)
INPUT_PORTS_END
@ -176,7 +270,6 @@ void cothello_state::cothello(machine_config &config)
{
// basic machine hardware
I8080A(config, m_maincpu, 750000);
m_maincpu->set_vblank_int("screen", FUNC(cothello_state::irq0_line_hold));
m_maincpu->set_addrmap(AS_PROGRAM, &cothello_state::main_map);
// video hardware
@ -188,6 +281,8 @@ void cothello_state::cothello(machine_config &config)
m_screen->set_screen_update(FUNC(cothello_state::screen_update));
// sound hardware
SPEAKER(config, "mono").front_center();
BEEP(config, m_beeper, 0).add_route(ALL_OUTPUTS, "mono", 0.25);
}
@ -212,4 +307,4 @@ ROM_END
******************************************************************************/
// YEAR NAME PARENT MACHINE INPUT CLASS INIT SCREEN COMPANY, FULLNAME, FLAGS
GAMEL(1978, cothello, 0, cothello, cothello, cothello_state, empty_init, ROT0, "Nintendo", "Computer Othello", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING | MACHINE_NO_SOUND, layout_cothello )
GAMEL(1978, cothello, 0, cothello, cothello, cothello_state, empty_init, ROT0, "Nintendo", "Computer Othello", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND, layout_cothello )