kim1: use pwm_display for the 7segs

This commit is contained in:
hap 2021-09-29 17:13:21 +02:00
parent 5c18fd77e8
commit 2d111b1592
2 changed files with 101 additions and 111 deletions

View File

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

View File

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