mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
kim1: use pwm_display for the 7segs
This commit is contained in:
parent
5c18fd77e8
commit
2d111b1592
@ -2,7 +2,9 @@
|
||||
// copyright-holders:David Haywood, Luca Elia, MetalliC
|
||||
/*
|
||||
|
||||
U2 flash rom note
|
||||
Cave CV1000 hardware
|
||||
|
||||
U2 flash rom note:
|
||||
|
||||
Cave often programmed the u2 roms onto defective flash chips, programming around the bad blocks.
|
||||
As a result these are highly susceptible to failure, blocks around the known bad blocks appear to
|
||||
@ -14,32 +16,38 @@ The flash roms do contain a 'bad block' table, so it should be possible to rebui
|
||||
flash ROM for each game by comparing multiple dumps of each game and ensuring no other data has
|
||||
decayed. Naturally this is not an ideal situation for the less common games!
|
||||
|
||||
----
|
||||
|
||||
Cave CV1000 hardware
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Games by Cave ID number:
|
||||
ID is labeled on U13 chip, not always
|
||||
Serial is on a sticker on PCB, eg. "CAVE DS-10104"
|
||||
|
||||
CA011 Mushihime-Sama
|
||||
CA012 Ibara
|
||||
CA012B Ibara Kuro Black Label
|
||||
CA013 Espgaluda II
|
||||
CA014 Pink Sweets: Ibara Sorekara
|
||||
CA015 Mushihime-Sama Futari
|
||||
CA015B Mushihime-Sama Futari Black Label
|
||||
CA016 Muchi Muchi Pork!
|
||||
CA017 Deathsmiles
|
||||
CA017B Deathsmiles Black Label
|
||||
CA019 Do-Don-Pachi Dai-Fukkatsu
|
||||
CA019B Do-Don-Pachi Dai-Fukkatsu Black Label
|
||||
CA021 Akai Katana
|
||||
ID Serial PCB Title
|
||||
-------------------------------------
|
||||
CA011 - B Mushihime-Sama
|
||||
CA??? MHN B Mushihime-Sama Cave Matsuri 1.5
|
||||
CA012 - B Ibara
|
||||
CA012B IB B Ibara Kuro Black Label
|
||||
CA013 E B Espgaluda II
|
||||
CA??? M B Puzzle! Mushihime-Tama
|
||||
CA014 CA B Pink Sweets: Ibara Sorekara
|
||||
CA015 CA B Mushihime-Sama Futari
|
||||
CA015B MFBA/MMB B Mushihime-Sama Futari Black Label
|
||||
CA016 MP B Muchi Muchi Pork!
|
||||
CA017 DS B Deathsmiles
|
||||
CA017B DSB D Deathsmiles Black Label
|
||||
CA019 DD D DoDonPachi DaiFukkatsu
|
||||
CA019B DDB D DoDonPachi DaiFukkatsu Black Label
|
||||
CA021 AK D Akai Katana
|
||||
CA??? SDO D DoDonPachi SaiDaiOuJou
|
||||
|
||||
CMDL01 Medal Mahjong Moukari Bancho
|
||||
?????? Pirates of Gappori: http://web.archive.org/web/20090907145501/http://www.cave.co.jp/gameonline/gappori/
|
||||
?????? Uhauha Ooku: http://web.archive.org/web/20141104001322/http://www.cave.co.jp/gameonline/oooku/
|
||||
CMDL01 - Medal Mahjong Moukari Bancho
|
||||
?????? - Pirates of Gappori: http://web.archive.org/web/20090907145501/http://www.cave.co.jp/gameonline/gappori/
|
||||
?????? - Uhauha Ooku: http://web.archive.org/web/20141104001322/http://www.cave.co.jp/gameonline/oooku/
|
||||
|
||||
Note: CA018 - Deathsmiles II: Makai no Merry Christmas on unknown custom platform
|
||||
CA020 - Do-Don-Pachi Dai-ou-jou Tamashii on PGM2 platform
|
||||
CA020 - DoDonPachi DaiOuJou Tamashii on PGM2 platform
|
||||
|
||||
|
||||
PCB CV1000-B / CV1000-D
|
||||
+--------------------------------------------+
|
||||
@ -140,11 +148,15 @@ Information by The Sheep, rtw, Ex-Cyber, BrianT & Guru
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
To enter service mode in most cases hold down Service (F2) for a few seconds
|
||||
(I believe it's the test button on the PCB)
|
||||
Some games also use the test dipswitch as an alternative method.
|
||||
To enter service mode in most cases hold down Service (F2) for a few seconds
|
||||
(I believe it's the test button on the PCB)
|
||||
Some games also use the test dipswitch as an alternative method.
|
||||
|
||||
ToDo:
|
||||
Common game codes:
|
||||
- During boot hold P1 Right+A+B+C and P2 Left+A+B+C - Forcibly initialise non-volatile data (EEPROM or NAND settings area)
|
||||
- During boot hold P1 A and P2 A - Reset random numbers generator at each game start. Probably was used during testing or/and competition events.
|
||||
|
||||
TODO:
|
||||
|
||||
Improve Blending precision?
|
||||
- I'm not sure what precision the original HW mixes with, source data is 555 RGB with 1 bit transparency (16-bits)
|
||||
@ -166,9 +178,6 @@ Blitter Timing
|
||||
- Correct slowdown emulation and flags (depends on blit mode, and speed of RAM) - could do with the recompiler or alt idle skips on the busy flag wait loops
|
||||
- End of Blit IRQ? (one game has a valid irq routine that looks like it was used for profiling, but nothing depends on it)
|
||||
|
||||
Common game codes:
|
||||
- During boot hold P1 Right+A+B+C and P2 Left+A+B+C - Forcibly initialise non-volatile data (EEPROM or NAND settings area)
|
||||
- During boot hold P1 A and P2 A - Reset random numbers generator at each game start. Probably was used during testing or/and competition events.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -312,7 +321,6 @@ void cv1k_state::flash_io_w(offs_t offset, uint8_t data)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ibarablk uses the rtc to render the clock in the first attract demo
|
||||
// if this code returns bad values it has gfx corruption. the ibarablka set doesn't do this?!
|
||||
uint8_t cv1k_state::serial_rtc_eeprom_r(offs_t offset)
|
||||
@ -351,7 +359,7 @@ void cv1k_state::cv1k_map(address_map &map)
|
||||
map(0x0c000000, 0x0c7fffff).ram().share("mainram");// work RAM
|
||||
map(0x10000000, 0x10000007).rw(FUNC(cv1k_state::flash_io_r), FUNC(cv1k_state::flash_io_w));
|
||||
map(0x10400000, 0x10400007).w("ymz770", FUNC(ymz770_device::write));
|
||||
map(0x10C00000, 0x10C00007).rw(FUNC(cv1k_state::serial_rtc_eeprom_r), FUNC(cv1k_state::serial_rtc_eeprom_w));
|
||||
map(0x10c00000, 0x10c00007).rw(FUNC(cv1k_state::serial_rtc_eeprom_r), FUNC(cv1k_state::serial_rtc_eeprom_w));
|
||||
// map(0x18000000, 0x18000057) // blitter, installed on reset
|
||||
map(0xf0000000, 0xf0ffffff).ram(); // mem mapped cache (sh3 internal?)
|
||||
}
|
||||
@ -362,7 +370,7 @@ void cv1k_state::cv1k_d_map(address_map &map)
|
||||
map(0x0c000000, 0x0cffffff).ram().share("mainram"); // work RAM
|
||||
map(0x10000000, 0x10000007).rw(FUNC(cv1k_state::flash_io_r), FUNC(cv1k_state::flash_io_w));
|
||||
map(0x10400000, 0x10400007).w("ymz770", FUNC(ymz770_device::write));
|
||||
map(0x10C00000, 0x10C00007).rw(FUNC(cv1k_state::serial_rtc_eeprom_r), FUNC(cv1k_state::serial_rtc_eeprom_w));
|
||||
map(0x10c00000, 0x10c00007).rw(FUNC(cv1k_state::serial_rtc_eeprom_r), FUNC(cv1k_state::serial_rtc_eeprom_w));
|
||||
// map(0x18000000, 0x18000057) // blitter, installed on reset
|
||||
map(0xf0000000, 0xf0ffffff).ram(); // mem mapped cache (sh3 internal?)
|
||||
}
|
||||
@ -463,8 +471,8 @@ void cv1k_state::cv1k(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
SH3BE(config, m_maincpu, 12.8_MHz_XTAL*8); // 102.4MHz
|
||||
m_maincpu->set_md(0, 0); // none of this is verified
|
||||
m_maincpu->set_md(1, 0); // (the sh3 is different to the sh4 anyway, should be changed)
|
||||
m_maincpu->set_md(0, 0); // none of this is verified
|
||||
m_maincpu->set_md(1, 0); // (the sh3 is different to the sh4 anyway, should be changed)
|
||||
m_maincpu->set_md(2, 0);
|
||||
m_maincpu->set_md(3, 0);
|
||||
m_maincpu->set_md(4, 0);
|
||||
@ -505,8 +513,8 @@ void cv1k_state::cv1k_d(machine_config &config)
|
||||
|
||||
/* basic machine hardware */
|
||||
SH3BE(config.replace(), m_maincpu, 12.8_MHz_XTAL*8); // 102.4MHz
|
||||
m_maincpu->set_md(0, 0); // none of this is verified
|
||||
m_maincpu->set_md(1, 0); // (the sh3 is different to the sh4 anyway, should be changed)
|
||||
m_maincpu->set_md(0, 0); // none of this is verified
|
||||
m_maincpu->set_md(1, 0); // (the sh3 is different to the sh4 anyway, should be changed)
|
||||
m_maincpu->set_md(2, 0);
|
||||
m_maincpu->set_md(3, 0);
|
||||
m_maincpu->set_md(4, 0);
|
||||
|
@ -64,14 +64,21 @@ Paste test:
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "cpu/m6502/m6502.h"
|
||||
#include "formats/kim1_cas.h"
|
||||
#include "imagedev/cassette.h"
|
||||
#include "machine/mos6530.h"
|
||||
#include "machine/timer.h"
|
||||
#include "imagedev/cassette.h"
|
||||
#include "formats/kim1_cas.h"
|
||||
#include "video/pwm.h"
|
||||
|
||||
#include "speaker.h"
|
||||
|
||||
#include "kim1.lh"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
@ -82,11 +89,11 @@ public:
|
||||
kim1_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_riot2(*this, "miot_u2")
|
||||
, m_miot(*this, "miot%u", 0)
|
||||
, m_digit_pwm(*this, "digit_pwm")
|
||||
, m_cass(*this, "cassette")
|
||||
, m_row(*this, "ROW%u", 0U)
|
||||
, m_special(*this, "SPECIAL")
|
||||
, m_digit(*this, "digit%u", 0U)
|
||||
{ }
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(trigger_reset);
|
||||
@ -104,23 +111,21 @@ private:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kim1_cassette_input);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kim1_update_leds);
|
||||
|
||||
void mem_map(address_map &map);
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<mos6530_device> m_riot2;
|
||||
required_device_array<mos6530_device, 2> m_miot;
|
||||
required_device<pwm_display_device> m_digit_pwm;
|
||||
required_device<cassette_image_device> m_cass;
|
||||
|
||||
required_ioport_array<3> m_row;
|
||||
required_ioport m_special;
|
||||
output_finder<6> m_digit;
|
||||
|
||||
uint8_t m_u2_port_b;
|
||||
uint8_t m_311_output;
|
||||
uint32_t m_cassette_high_count;
|
||||
uint8_t m_led_time[6];
|
||||
};
|
||||
|
||||
|
||||
@ -132,23 +137,24 @@ void kim1_state::mem_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x1fff);
|
||||
map(0x0000, 0x03ff).ram();
|
||||
map(0x1700, 0x173f).rw("miot_u3", FUNC(mos6530_device::read), FUNC(mos6530_device::write));
|
||||
map(0x1740, 0x177f).rw(m_riot2, FUNC(mos6530_device::read), FUNC(mos6530_device::write));
|
||||
map(0x1700, 0x173f).rw(m_miot[1], FUNC(mos6530_device::read), FUNC(mos6530_device::write));
|
||||
map(0x1740, 0x177f).rw(m_miot[0], FUNC(mos6530_device::read), FUNC(mos6530_device::write));
|
||||
map(0x1780, 0x17ff).ram();
|
||||
map(0x1800, 0x1fff).rom().region("maincpu",0);
|
||||
}
|
||||
|
||||
// RS and ST key input
|
||||
INPUT_CHANGED_MEMBER(kim1_state::trigger_reset)
|
||||
{
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE);
|
||||
// RS and ST key input
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(kim1_state::trigger_nmi)
|
||||
{
|
||||
m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE);
|
||||
m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INPUT PORTS
|
||||
//**************************************************************************
|
||||
@ -197,107 +203,79 @@ static INPUT_PORTS_START( kim1 )
|
||||
PORT_BIT( 0x01, 0x00, IPT_UNUSED )
|
||||
INPUT_PORTS_END
|
||||
|
||||
// Read from keyboard
|
||||
uint8_t kim1_state::kim1_u2_read_a()
|
||||
{
|
||||
uint8_t data = 0xff;
|
||||
|
||||
offs_t const sel = ( m_u2_port_b >> 1 ) & 0x0f;
|
||||
if ( 3U > sel )
|
||||
// Read from keyboard
|
||||
offs_t const sel = (m_u2_port_b >> 1) & 0x0f;
|
||||
if (3U > sel)
|
||||
data = m_row[sel]->read();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Write to 7-Segment LEDs
|
||||
void kim1_state::kim1_u2_write_a(uint8_t data)
|
||||
{
|
||||
uint8_t idx = ( m_u2_port_b >> 1 ) & 0x0f;
|
||||
|
||||
if ( idx >= 4 && idx < 10 )
|
||||
{
|
||||
if ( data & 0x80 )
|
||||
{
|
||||
m_digit[idx - 4] = data & 0x7f;
|
||||
m_led_time[idx - 4] = 15;
|
||||
}
|
||||
}
|
||||
// Write to 7-segment LEDs
|
||||
m_digit_pwm->write_mx(data & 0x7f);
|
||||
}
|
||||
|
||||
// Load from cassette
|
||||
uint8_t kim1_state::kim1_u2_read_b()
|
||||
{
|
||||
if ( m_riot2->portb_out_get() & 0x20 )
|
||||
return 0xFF;
|
||||
if (m_miot[0]->portb_out_get() & 0x20)
|
||||
return 0xff;
|
||||
|
||||
return 0x7F | ( m_311_output ^ 0x80 );
|
||||
// Load from cassette
|
||||
return 0x7f | (m_311_output ^ 0x80);
|
||||
}
|
||||
|
||||
// Save to cassette
|
||||
void kim1_state::kim1_u2_write_b(uint8_t data)
|
||||
{
|
||||
m_u2_port_b = data;
|
||||
|
||||
if ( data & 0x20 )
|
||||
/* cassette write/speaker update */
|
||||
m_cass->output(( data & 0x80 ) ? -1.0 : 1.0 );
|
||||
// Select 7-segment LED
|
||||
m_digit_pwm->write_my(1 << (data >> 1 & 0xf) >> 4);
|
||||
|
||||
/* Set IRQ when bit 7 is cleared */
|
||||
// Cassette write/speaker update
|
||||
if (data & 0x20)
|
||||
m_cass->output((data & 0x80) ? -1.0 : 1.0);
|
||||
|
||||
// Set IRQ when bit 7 is cleared
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kim1_state::kim1_cassette_input)
|
||||
{
|
||||
double tap_val = m_cass->input();
|
||||
|
||||
if ( tap_val <= 0 )
|
||||
if (tap_val <= 0)
|
||||
{
|
||||
if ( m_cassette_high_count )
|
||||
if (m_cassette_high_count)
|
||||
{
|
||||
m_311_output = ( m_cassette_high_count < 8 ) ? 0x80 : 0;
|
||||
m_311_output = (m_cassette_high_count < 8) ? 0x80 : 0;
|
||||
m_cassette_high_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tap_val > 0 )
|
||||
if (tap_val > 0)
|
||||
m_cassette_high_count++;
|
||||
}
|
||||
|
||||
// Blank LEDs during cassette operations
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kim1_state::kim1_update_leds)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
{
|
||||
if ( m_led_time[i] )
|
||||
m_led_time[i]--;
|
||||
else
|
||||
m_digit[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Register for save states
|
||||
void kim1_state::machine_start()
|
||||
{
|
||||
m_digit.resolve();
|
||||
|
||||
// Register for save states
|
||||
save_item(NAME(m_u2_port_b));
|
||||
save_item(NAME(m_311_output));
|
||||
save_item(NAME(m_cassette_high_count));
|
||||
save_item(NAME(m_led_time));
|
||||
}
|
||||
|
||||
void kim1_state::machine_reset()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
m_led_time[i] = 0;
|
||||
|
||||
m_311_output = 0;
|
||||
m_cassette_high_count = 0;
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MACHINE DRIVERS
|
||||
//**************************************************************************
|
||||
@ -307,21 +285,20 @@ void kim1_state::kim1(machine_config &config)
|
||||
// basic machine hardware
|
||||
M6502(config, m_maincpu, 1_MHz_XTAL);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &kim1_state::mem_map);
|
||||
config.set_maximum_quantum(attotime::from_hz(60));
|
||||
|
||||
// video hardware
|
||||
PWM_DISPLAY(config, m_digit_pwm).set_size(6, 7);
|
||||
m_digit_pwm->set_segmask(0x3f, 0x7f);
|
||||
config.set_default_layout(layout_kim1);
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
// devices
|
||||
MOS6530(config, m_riot2, 1_MHz_XTAL);
|
||||
m_riot2->in_pa_callback().set(FUNC(kim1_state::kim1_u2_read_a));
|
||||
m_riot2->out_pa_callback().set(FUNC(kim1_state::kim1_u2_write_a));
|
||||
m_riot2->in_pb_callback().set(FUNC(kim1_state::kim1_u2_read_b));
|
||||
m_riot2->out_pb_callback().set(FUNC(kim1_state::kim1_u2_write_b));
|
||||
MOS6530(config, m_miot[0], 1_MHz_XTAL); // u2
|
||||
m_miot[0]->in_pa_callback().set(FUNC(kim1_state::kim1_u2_read_a));
|
||||
m_miot[0]->out_pa_callback().set(FUNC(kim1_state::kim1_u2_write_a));
|
||||
m_miot[0]->in_pb_callback().set(FUNC(kim1_state::kim1_u2_read_b));
|
||||
m_miot[0]->out_pb_callback().set(FUNC(kim1_state::kim1_u2_write_b));
|
||||
|
||||
MOS6530(config, "miot_u3", 1_MHz_XTAL);
|
||||
MOS6530(config, m_miot[1], 1_MHz_XTAL); // u3
|
||||
|
||||
CASSETTE(config, m_cass);
|
||||
m_cass->set_formats(kim1_cassette_formats);
|
||||
@ -329,26 +306,31 @@ void kim1_state::kim1(machine_config &config)
|
||||
m_cass->add_route(ALL_OUTPUTS, "mono", 0.05);
|
||||
m_cass->set_interface ("kim1_cass");
|
||||
|
||||
TIMER(config, "led_timer").configure_periodic(FUNC(kim1_state::kim1_update_leds), attotime::from_hz(60));
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
TIMER(config, "cassette_timer").configure_periodic(FUNC(kim1_state::kim1_cassette_input), attotime::from_hz(44100));
|
||||
|
||||
// software list
|
||||
SOFTWARE_LIST(config, "cass_list").set_original("kim1_cass");
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// ROM DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
ROM_START(kim1)
|
||||
ROM_REGION(0x0800,"maincpu",0)
|
||||
ROM_LOAD("6530-003.bin", 0x0000, 0x0400, CRC(a2a56502) SHA1(60b6e48f35fe4899e29166641bac3e81e3b9d220))
|
||||
ROM_LOAD("6530-002.bin", 0x0400, 0x0400, CRC(2b08e923) SHA1(054f7f6989af3a59462ffb0372b6f56f307b5362))
|
||||
ROM_LOAD("6530-003.bin", 0x0000, 0x0400, CRC(a2a56502) SHA1(60b6e48f35fe4899e29166641bac3e81e3b9d220))
|
||||
ROM_LOAD("6530-002.bin", 0x0400, 0x0400, CRC(2b08e923) SHA1(054f7f6989af3a59462ffb0372b6f56f307b5362))
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// SYSTEM DRIVERS
|
||||
//**************************************************************************
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1975, kim1, 0, 0, kim1, kim1, kim1_state, empty_init, "MOS Technologies", "KIM-1", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE)
|
||||
COMP( 1975, kim1, 0, 0, kim1, kim1, kim1_state, empty_init, "MOS Technologies", "KIM-1", MACHINE_SUPPORTS_SAVE)
|
||||
|
Loading…
Reference in New Issue
Block a user