mirror of
https://github.com/holub/mame
synced 2025-06-25 22:04:15 +03:00
cothello: add coin handling and sound
This commit is contained in:
parent
acc7d534af
commit
dbaf7b376d
@ -57,10 +57,11 @@
|
|||||||
emulates an unmodified PCB, you can enable the hacks in the DRIVER
|
emulates an unmodified PCB, you can enable the hacks in the DRIVER
|
||||||
CONFIGURATION menu.
|
CONFIGURATION menu.
|
||||||
|
|
||||||
|
B&W cabinet versions also exist.
|
||||||
|
|
||||||
Versions of Tomahawk using the Astro Fighter PROM have been seen,
|
Versions of Tomahawk using the Astro Fighter PROM have been seen,
|
||||||
see notes in ROM loading.
|
see notes in ROM loading.
|
||||||
|
|
||||||
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,27 +12,32 @@ and is presumed to be on the same base hardware as the arcade version.
|
|||||||
|
|
||||||
Hardware notes:
|
Hardware notes:
|
||||||
- PCB label: COG CPU
|
- PCB label: COG CPU
|
||||||
- M58710S (8080A), ?MHz XTAL
|
- M58710S (8080A), 3.579545MHz XTAL
|
||||||
- 3*1KB M58732S 2708 ROM, 4th socket is empty
|
- 3*1KB M58732S 2708 ROM, 4th socket is empty
|
||||||
- 256 bytes RAM (2*M58722P 2111A), 0.5KB DRAM (M58755S)
|
- 256 bytes RAM (2*M58722P 2111A), 0.5KB DRAM (M58755S)
|
||||||
- M58741P Color TV Interface, 64*64 1bpp video
|
- M58741P Color TV Interface, 64*64 1bpp video
|
||||||
|
- 7seg time counter (not software controlled)
|
||||||
- beeper
|
- beeper
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- verify XTAL
|
|
||||||
- verify video timing
|
- verify video timing
|
||||||
- coin
|
- beeper duration and base frequency is approximated (divisor is correct)
|
||||||
- sound
|
- CPU speed is wrong, it's likely running at 1.79MHz. But that's way too fast
|
||||||
- is there a button select, or is current input emulation correct where for
|
compared to videos of the game. 0.9MHz(XTAL/4) is also too fast. It's probably
|
||||||
example P1 can move P2 cursor? (the only unique P2 button is the Set button)
|
due to the M58741P HOLD pin halting the 8080, which is not emulated.
|
||||||
- unknown if the screen is color or B&W + overlay, but since the video chip is
|
- Is there a button select somewhere? I really can't find any. Or is current
|
||||||
meant for a color tv, let's assume the green tint is from the screen itself
|
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 "emu.h"
|
||||||
|
|
||||||
#include "cpu/i8085/i8085.h"
|
#include "cpu/i8085/i8085.h"
|
||||||
|
#include "sound/beep.h"
|
||||||
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "speaker.h"
|
#include "speaker.h"
|
||||||
@ -50,26 +55,52 @@ public:
|
|||||||
m_maincpu(*this, "maincpu"),
|
m_maincpu(*this, "maincpu"),
|
||||||
m_screen(*this, "screen"),
|
m_screen(*this, "screen"),
|
||||||
m_vram(*this, "vram"),
|
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);
|
void cothello(machine_config &config);
|
||||||
|
|
||||||
|
DECLARE_INPUT_CHANGED_MEMBER(insert_coin);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void machine_start() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
required_device<cpu_device> m_maincpu;
|
required_device<cpu_device> m_maincpu;
|
||||||
required_device<screen_device> m_screen;
|
required_device<screen_device> m_screen;
|
||||||
required_shared_ptr<u8> m_vram;
|
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);
|
void main_map(address_map &map);
|
||||||
|
|
||||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||||
|
|
||||||
u8 input_r();
|
|
||||||
u8 coin_r();
|
u8 coin_r();
|
||||||
|
u8 input_r();
|
||||||
void sound_w(u8 data);
|
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
|
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 cothello_state::input_r()
|
||||||
{
|
{
|
||||||
u8 data = 0xff;
|
u8 data = 0xff;
|
||||||
@ -106,14 +177,22 @@ u8 cothello_state::input_r()
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 cothello_state::coin_r()
|
|
||||||
{
|
|
||||||
return 0xfb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cothello_state::sound_w(u8 data)
|
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( 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( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_NAME("P2 Set")
|
||||||
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
|
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
|
INPUT_PORTS_END
|
||||||
|
|
||||||
|
|
||||||
@ -176,7 +270,6 @@ void cothello_state::cothello(machine_config &config)
|
|||||||
{
|
{
|
||||||
// basic machine hardware
|
// basic machine hardware
|
||||||
I8080A(config, m_maincpu, 750000);
|
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);
|
m_maincpu->set_addrmap(AS_PROGRAM, &cothello_state::main_map);
|
||||||
|
|
||||||
// video hardware
|
// video hardware
|
||||||
@ -188,6 +281,8 @@ void cothello_state::cothello(machine_config &config)
|
|||||||
m_screen->set_screen_update(FUNC(cothello_state::screen_update));
|
m_screen->set_screen_update(FUNC(cothello_state::screen_update));
|
||||||
|
|
||||||
// sound hardware
|
// 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
|
// 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 )
|
||||||
|
Loading…
Reference in New Issue
Block a user