summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author David Haywood <28625134+DavidHaywood@users.noreply.github.com>2020-03-11 14:42:00 +0000
committer GitHub <noreply@github.com>2020-03-11 10:42:00 -0400
commit4db634dfd908786cad140fa97a49c11a627a9019 (patch)
tree96522b0e7c5c474b0d1cf84aad1adf3b30c90ced
parenta00cd931207746bf37d0903100a12f05d54cc050 (diff)
Plug & Play work (#6426)
* new NOT WORKING ---- Spider-Man Web Master (JAKKS Pacific TV Motion Game) [Sean Riddle, David Haywood] * new WORKING machine ---- Who Wants To Be A Millionaire (UK, Character Options) [Sean Riddle, David Haywood] * sh6578.work (nw) * (nw) * sh6578 work (nw) * main screen turn on (nw) * allow workram writes via DMA (nw)
-rw-r--r--src/devices/video/ppu2c0x.cpp125
-rw-r--r--src/devices/video/ppu2c0x.h1
-rw-r--r--src/mame/drivers/nes_sh6578.cpp560
-rw-r--r--src/mame/drivers/spg2xx.cpp97
-rw-r--r--src/mame/drivers/sunplus_unsp20soc.cpp13
-rw-r--r--src/mame/includes/spg2xx.h20
-rw-r--r--src/mame/mame.lst2
7 files changed, 726 insertions, 92 deletions
diff --git a/src/devices/video/ppu2c0x.cpp b/src/devices/video/ppu2c0x.cpp
index 4f2c6c587e7..664f9cfc7e5 100644
--- a/src/devices/video/ppu2c0x.cpp
+++ b/src/devices/video/ppu2c0x.cpp
@@ -322,15 +322,8 @@ void ppu2c0x_device::init_palette()
init_palette(false);
}
-void ppu2c0x_device::init_palette(bool indirect)
+rgb_t ppu2c0x_device::nespal_to_RGB(int color_intensity, int color_num)
{
- /* This routine builds a palette using a transformation from */
- /* the YUV (Y, B-Y, R-Y) to the RGB color space */
-
- /* The NES has a 64 color palette */
- /* 16 colors, with 4 luminance levels for each color */
- /* The 16 colors circle around the YUV color space, */
-
const double tint = 0.22; /* adjust to taste */
const double hue = 287.0;
@@ -346,6 +339,68 @@ void ppu2c0x_device::init_palette(bool indirect)
{ 0, 0.24, 0.47, 0.77 }
};
+ double sat;
+ double y, u, v;
+ double rad;
+
+ switch (color_num)
+ {
+ case 0:
+ sat = 0; rad = 0;
+ y = brightness[0][color_intensity];
+ break;
+
+ case 13:
+ sat = 0; rad = 0;
+ y = brightness[2][color_intensity];
+ break;
+
+ case 14:
+ case 15:
+ sat = 0; rad = 0; y = 0;
+ break;
+
+ default:
+ sat = tint;
+ rad = M_PI * ((color_num * 30 + hue) / 180.0);
+ y = brightness[1][color_intensity];
+ break;
+ }
+
+ u = sat * cos(rad);
+ v = sat * sin(rad);
+
+ /* Transform to RGB */
+ double R = (y + Kv * v) * 255.0;
+ double G = (y - (Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr)) * 255.0;
+ double B = (y + Ku * u) * 255.0;
+
+ /* Clipping, in case of saturation */
+ if (R < 0)
+ R = 0;
+ if (R > 255)
+ R = 255;
+ if (G < 0)
+ G = 0;
+ if (G > 255)
+ G = 255;
+ if (B < 0)
+ B = 0;
+ if (B > 255)
+ B = 255;
+
+ return rgb_t(floor(R + .5), floor(G + .5), floor(B + .5));
+}
+
+void ppu2c0x_device::init_palette(bool indirect)
+{
+ /* This routine builds a palette using a transformation from */
+ /* the YUV (Y, B-Y, R-Y) to the RGB color space */
+
+ /* The NES has a 64 color palette */
+ /* 16 colors, with 4 luminance levels for each color */
+ /* The 16 colors circle around the YUV color space, */
+
int entry = 0;
/* Loop through the emphasis modes (8 total) */
@@ -375,61 +430,13 @@ void ppu2c0x_device::init_palette(bool indirect)
/* loop through the 16 colors */
for (int color_num = 0; color_num < 16; color_num++)
{
- double sat;
- double y, u, v;
- double rad;
-
- switch (color_num)
- {
- case 0:
- sat = 0; rad = 0;
- y = brightness[0][color_intensity];
- break;
-
- case 13:
- sat = 0; rad = 0;
- y = brightness[2][color_intensity];
- break;
-
- case 14:
- case 15:
- sat = 0; rad = 0; y = 0;
- break;
-
- default:
- sat = tint;
- rad = M_PI * ((color_num * 30 + hue) / 180.0);
- y = brightness[1][color_intensity];
- break;
- }
-
- u = sat * cos(rad);
- v = sat * sin(rad);
-
- /* Transform to RGB */
- double R = (y + Kv * v) * 255.0;
- double G = (y - (Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr)) * 255.0;
- double B = (y + Ku * u) * 255.0;
-
- /* Clipping, in case of saturation */
- if (R < 0)
- R = 0;
- if (R > 255)
- R = 255;
- if (G < 0)
- G = 0;
- if (G > 255)
- G = 255;
- if (B < 0)
- B = 0;
- if (B > 255)
- B = 255;
+ rgb_t col = nespal_to_RGB(color_intensity, color_num);
/* Round, and set the value */
if (indirect)
- set_indirect_color(entry++, rgb_t(floor(R + .5), floor(G + .5), floor(B + .5)));
+ set_indirect_color(entry++, col);
else
- set_pen_color(entry++, floor(R + .5), floor(G + .5), floor(B + .5));
+ set_pen_color(entry++, col);
}
}
}
diff --git a/src/devices/video/ppu2c0x.h b/src/devices/video/ppu2c0x.h
index 5660876674a..1a9900393e2 100644
--- a/src/devices/video/ppu2c0x.h
+++ b/src/devices/video/ppu2c0x.h
@@ -72,6 +72,7 @@ public:
auto int_callback() { return m_int_callback.bind(); }
/* routines */
+ rgb_t nespal_to_RGB(int color_intensity, int color_num);
virtual void init_palette();
void init_palette(bool indirect);
virtual uint32_t palette_entries() const override { return 4*16*8; }
diff --git a/src/mame/drivers/nes_sh6578.cpp b/src/mame/drivers/nes_sh6578.cpp
index fc1bdb757b8..4d6ab147ed7 100644
--- a/src/mame/drivers/nes_sh6578.cpp
+++ b/src/mame/drivers/nes_sh6578.cpp
@@ -4,25 +4,34 @@
/*
SH6578 NES clone hardware
enhanced NES, different to VT / OneBus systems
+
+ video rendering is changed significantly compared to NES so not using NES PPU device
+ has 256x256 pixel pages, attributes are stored next to tile numbers (not in their own table after them) etc.
+
*/
#include "emu.h"
#include "cpu/m6502/n2a03.h"
-#include "video/ppu2c0x.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
+#include "machine/bankdev.h"
+#include "machine/timer.h"
class nes_sh6578_state : public driver_device
{
public:
- nes_sh6578_state(const machine_config &mconfig, device_type type, const char *tag) :
+ nes_sh6578_state(const machine_config& mconfig, device_type type, const char* tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
- m_ppu(*this, "ppu")
+ m_bank(*this, "cartbank"),
+ m_fullrom(*this, "fullrom"),
+ m_vram(*this, "vram"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette")
{ }
-
- void nes_sh6578(machine_config &config);
+
+ void nes_sh6578(machine_config& config);
void init_nes_sh6578();
@@ -35,28 +44,441 @@ protected:
private:
required_device<n2a03_device> m_maincpu;
- required_device<ppu2c0x_device> m_ppu;
-
- void nes_sh6578_map(address_map &map);
+ required_memory_bank m_bank;
+ required_device<address_map_bank_device> m_fullrom;
+ required_device<address_map_bank_device> m_vram;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+
+ rgb_t nespal_to_RGB(int color_intensity, int color_num);
+
+ DECLARE_READ8_MEMBER(bankswitch_r);
+ DECLARE_WRITE8_MEMBER(bankswitch_w);
+
+ DECLARE_READ8_MEMBER(dma_r);
+ DECLARE_WRITE8_MEMBER(dma_w);
+
+ uint8_t bank_r(int bank, uint16_t offset);
+ void bank_w(int bank, uint16_t offset, uint8_t data);
+
+ DECLARE_READ8_MEMBER(bank0_r) { return bank_r(0, offset); }
+ DECLARE_WRITE8_MEMBER(bank0_w) { bank_w(0, offset, data); }
+ DECLARE_READ8_MEMBER(bank1_r) { return bank_r(1, offset); }
+ DECLARE_WRITE8_MEMBER(bank1_w) { bank_w(1, offset, data); }
+ DECLARE_READ8_MEMBER(bank2_r) { return bank_r(2, offset); }
+ DECLARE_WRITE8_MEMBER(bank2_w) { bank_w(2, offset, data); }
+ DECLARE_READ8_MEMBER(bank3_r) { return bank_r(3, offset); }
+ DECLARE_WRITE8_MEMBER(bank3_w) { bank_w(3, offset, data); }
+ DECLARE_READ8_MEMBER(bank4_r) { return bank_r(4, offset); }
+ DECLARE_WRITE8_MEMBER(bank4_w) { bank_w(4, offset, data); }
+ DECLARE_READ8_MEMBER(bank5_r) { return bank_r(5, offset); }
+ DECLARE_WRITE8_MEMBER(bank5_w) { bank_w(5, offset, data); }
+ DECLARE_READ8_MEMBER(bank6_r) { return bank_r(6, offset); }
+ DECLARE_WRITE8_MEMBER(bank6_w) { bank_w(6, offset, data); }
+ DECLARE_READ8_MEMBER(bank7_r) { return bank_r(7, offset); }
+ DECLARE_WRITE8_MEMBER(bank7_w) { bank_w(7, offset, data); }
+
+ DECLARE_WRITE8_MEMBER(timing_setting_control_w);
+ DECLARE_WRITE8_MEMBER(initial_startup_w);
+
+ DECLARE_WRITE8_MEMBER(write_ppu);
+ DECLARE_READ8_MEMBER(read_ppu);
+ DECLARE_WRITE8_MEMBER(write_palette);
+ DECLARE_READ8_MEMBER(read_palette);
+
+ int m_iniital_startup_state;
+ std::vector<uint8_t> m_palette_ram;
+
+ uint8_t m_bankswitch[8];
+
+ uint8_t m_dma_control;
+ uint8_t m_dma_bank;
+ uint8_t m_dma_source[2];
+ uint8_t m_dma_dest[2];
+ uint8_t m_dma_length[2];
+
+ uint8_t m_2000;
+ uint8_t m_colsel_pntstart;
+ TIMER_DEVICE_CALLBACK_MEMBER(scanline);
+
+ void do_dma();
+
+ void rom_map(address_map& map);
+ void vram_map(address_map& map);
+ void nes_sh6578_map(address_map& map);
+
+ uint32_t screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect);
};
+TIMER_DEVICE_CALLBACK_MEMBER(nes_sh6578_state::scanline)
+{
+ int scanline = param;
+
+ if (scanline == 240)
+ {
+ if (m_2000 & 0x80)
+ {
+ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+ }
+ }
+}
+
+
+uint8_t nes_sh6578_state::bank_r(int bank, uint16_t offset)
+{
+ uint32_t address;
+ address = offset & 0x00fff; // 0x00fff part of address
+ address |= (m_bankswitch[bank] & 0xff) << 12; // 0xff000 part of address
+ return m_fullrom->read8(address);
+}
+
+void nes_sh6578_state::bank_w(int bank, uint16_t offset, uint8_t data)
+{
+ uint32_t address;
+ address = offset & 0x00fff; // 0x00fff part of address
+ address |= (m_bankswitch[bank] & 0xff) << 12; // 0xff000 part of address
+ return m_fullrom->write8(address, data);
+}
WRITE8_MEMBER(nes_sh6578_state::sprite_dma_w)
{
- int source = (data & 7);
- m_ppu->spriteram_dma(space, source);
+ // int source = (data & 7);
+}
+
+READ8_MEMBER(nes_sh6578_state::bankswitch_r)
+{
+ return m_bankswitch[offset];
+}
+
+WRITE8_MEMBER(nes_sh6578_state::bankswitch_w)
+{
+ m_bankswitch[offset] = data;
+}
+
+READ8_MEMBER(nes_sh6578_state::dma_r)
+{
+ switch (offset)
+ {
+ case 0x00: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Control : %02x\n", machine().describe_context(), offset); return m_dma_control;
+ case 0x01: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Bank Select : %02x\n", machine().describe_context(), offset); return m_dma_bank;
+ case 0x02: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Source Address Low : %02x\n", machine().describe_context(), offset); return m_dma_source[0];
+ case 0x03: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Source Address High : %02x\n", machine().describe_context(), offset); return m_dma_source[1];
+ case 0x04: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Destination Address Low : %02x\n", machine().describe_context(), offset); return m_dma_dest[0];
+ case 0x05: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Destination Address High : %02x\n", machine().describe_context(), offset); return m_dma_dest[1];
+ case 0x06: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Length Low : %02x\n", machine().describe_context(), offset); return m_dma_length[0];
+ case 0x07: logerror("%s: nes_sh6578_state::dma_r offset %01x : DMA Length High : %02x\n", machine().describe_context(), offset); return m_dma_length[1];
+ }
+ return 0x00;
}
-void nes_sh6578_state::nes_sh6578_map(address_map &map)
+void nes_sh6578_state::do_dma()
+{
+ if (m_dma_control & 0x80)
+ {
+ uint16_t dma_source = m_dma_source[0] | (m_dma_source[1] << 8);
+ uint16_t dma_dest = m_dma_dest[0] | (m_dma_dest[1] << 8);
+ uint16_t dma_length = m_dma_length[0] | (m_dma_length[1] << 8);
+
+ logerror("Doing DMA :%02x bank:%02x: source:%04x dest:%04x length:%04x\n", m_dma_control, m_dma_bank, dma_source, dma_dest, dma_length);
+
+ uint16_t realsourceaddress = dma_source;
+ uint16_t realdestaddress = dma_dest;
+
+ for (int i = 0; i <= dma_length; i++)
+ {
+ uint8_t readdat = 0x00;
+ if (realsourceaddress & 0x8000)
+ {
+ // reading from ROM?
+ uint32_t trueaddress = (realsourceaddress & 0x7fff) | ((m_dma_bank & 0x1f) * 0x8000);
+
+ readdat = m_fullrom->read8(trueaddress);
+ }
+ else
+ {
+ //logerror("reading from system area %04x\n", realsourceaddress);
+ uint32_t trueaddress = (realsourceaddress & 0x7fff);
+ readdat = m_maincpu->space(AS_PROGRAM).read_byte(trueaddress);
+ }
+
+ if (m_dma_control & 0x20)
+ {
+ //logerror("writing to WORK RAM %04x %02x\n", realdestaddress, readdat);
+ m_maincpu->space(AS_PROGRAM).write_byte(realdestaddress, readdat);
+ }
+ else
+ {
+ m_vram->write8(realdestaddress, readdat);
+ }
+
+ realsourceaddress++;
+ realdestaddress++;
+ }
+
+ }
+}
+
+WRITE8_MEMBER(nes_sh6578_state::dma_w)
+{
+ switch (offset)
+ {
+ case 0x0:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Control : %02x\n", machine().describe_context(), offset, data);
+ m_dma_control = data;
+ do_dma();
+ break;
+
+ case 0x1:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Bank Select : %02x\n", machine().describe_context(), offset, data);
+ m_dma_bank = data;
+ break;
+
+ case 0x2:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Source Address Low : %02x\n", machine().describe_context(), offset, data);
+ m_dma_source[0] = data;
+ break;
+
+ case 0x3:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Source Address High : %02x\n", machine().describe_context(), offset, data);
+ m_dma_source[1] = data;
+ break;
+
+ case 0x4:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Destination Address Low : %02x\n", machine().describe_context(), offset, data);
+ m_dma_dest[0] = data;
+ break;
+
+ case 0x5:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Destination Address High : %02x\n", machine().describe_context(), offset, data);
+ m_dma_dest[1] = data;
+ break;
+
+ case 0x6:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Length Low : %02x\n", machine().describe_context(), offset, data);
+ m_dma_length[0] = data;
+ break;
+
+ case 0x7:
+ logerror("%s: nes_sh6578_state::dma_w offset %01x : DMA Length High : %02x\n", machine().describe_context(), offset, data);
+ m_dma_length[1] = data;
+ break;
+ }
+}
+
+
+WRITE8_MEMBER(nes_sh6578_state::initial_startup_w)
+{
+ // there is also a timeframe in which this must happen
+ // if the writes are not correct the system does not operate
+ if (m_iniital_startup_state == 0)
+ {
+ if (data == 0x65)
+ {
+ logerror("initial_startup_w VALID first write (0x65)\n");
+ m_iniital_startup_state = 1;
+ }
+ else
+ {
+ logerror("initial_startup_w invalid first write (not 0x65)\n");
+ m_iniital_startup_state = -1;
+ }
+ }
+ else if (m_iniital_startup_state == 1)
+ {
+ if (data == 0x76)
+ {
+ logerror("initial_startup_w VALID second write (0x76)\n");
+ m_iniital_startup_state = 2;
+ }
+ else
+ {
+ logerror("initial_startup_w invalid second write (not 0x76)\n");
+ m_iniital_startup_state = -1;
+ }
+ }
+ else if (m_iniital_startup_state == 2)
+ {
+ logerror("initial_startup_w invalid write (already passed) (%02x)\n", data);
+ }
+ else if (m_iniital_startup_state == -1)
+ {
+ logerror("initial_startup_w invalid write (already failed) (%02x)\n", data);
+ }
+}
+
+WRITE8_MEMBER(nes_sh6578_state::timing_setting_control_w)
+{
+ logerror("%s: nes_sh6578_state::timing_setting_control_w : %02x\n", machine().describe_context(), data);
+}
+
+// borrowed from ppu2c0x.cpp, doesn't currently handle color emphasis!
+rgb_t nes_sh6578_state::nespal_to_RGB(int color_intensity, int color_num)
+{
+ const double tint = 0.22; /* adjust to taste */
+ const double hue = 287.0;
+
+ const double Kr = 0.2989;
+ const double Kb = 0.1145;
+ const double Ku = 2.029;
+ const double Kv = 1.140;
+
+ static const double brightness[3][4] =
+ {
+ { 0.50, 0.75, 1.0, 1.0 },
+ { 0.29, 0.45, 0.73, 0.9 },
+ { 0, 0.24, 0.47, 0.77 }
+ };
+
+ double sat;
+ double y, u, v;
+ double rad;
+
+ switch (color_num)
+ {
+ case 0:
+ sat = 0; rad = 0;
+ y = brightness[0][color_intensity];
+ break;
+
+ case 13:
+ sat = 0; rad = 0;
+ y = brightness[2][color_intensity];
+ break;
+
+ case 14:
+ case 15:
+ sat = 0; rad = 0; y = 0;
+ break;
+
+ default:
+ sat = tint;
+ rad = M_PI * ((color_num * 30 + hue) / 180.0);
+ y = brightness[1][color_intensity];
+ break;
+ }
+
+ u = sat * cos(rad);
+ v = sat * sin(rad);
+
+ /* Transform to RGB */
+ double R = (y + Kv * v) * 255.0;
+ double G = (y - (Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr)) * 255.0;
+ double B = (y + Ku * u) * 255.0;
+
+ /* Clipping, in case of saturation */
+ if (R < 0)
+ R = 0;
+ if (R > 255)
+ R = 255;
+ if (G < 0)
+ G = 0;
+ if (G > 255)
+ G = 255;
+ if (B < 0)
+ B = 0;
+ if (B > 255)
+ B = 255;
+
+ return rgb_t(floor(R + .5), floor(G + .5), floor(B + .5));
+}
+
+
+READ8_MEMBER(nes_sh6578_state::read_palette)
+{
+ logerror("%s: nes_sh6578_state::read_ppu : Palette Entry %02x\n", machine().describe_context(), offset);
+ return m_palette_ram[offset];
+}
+
+WRITE8_MEMBER(nes_sh6578_state::write_palette)
+{
+ logerror("%s: nes_sh6578_state::write_ppu : Palette Entry %02x : %02x\n", machine().describe_context(), offset, data);
+ m_palette_ram[offset] = data;
+
+ rgb_t col = nespal_to_RGB((data & 0x30) >> 4, data & 0x0f);
+ m_palette->set_pen_color(offset, col);
+}
+
+
+READ8_MEMBER(nes_sh6578_state::read_ppu)
+{
+ switch (offset)
+ {
+ case 0x08:
+ logerror("%s: nes_sh6578_state::read_ppu : Color Select & PNT Start Address\n", machine().describe_context());
+ return m_colsel_pntstart;
+
+ case 0x00:
+ return m_2000;
+
+ case 0x02:
+ {
+ uint8_t ret = 0x00;
+ int vblank = m_screen->vpos() > 239 ? 1 : 0;
+
+ if (vblank) ret |= 0x80;
+
+ return ret;
+ }
+
+ default:
+ //return ppu2c0x_device::read(space, offset);
+ return 0x00;
+ }
+}
+
+WRITE8_MEMBER(nes_sh6578_state::write_ppu)
+{
+ switch (offset)
+ {
+ case 0x08:
+ logerror("%s: nes_sh6578_state::write_ppu : Color Select & PNT Start Address : %02x\n", machine().describe_context(), data);
+ m_colsel_pntstart = data;
+ break;
+
+ case 0x00:
+ m_2000 = data;
+ break;
+
+ default:
+ break;
+ //ppu2c0x_device::write(space, offset, data);
+ }
+}
+
+
+void nes_sh6578_state::nes_sh6578_map(address_map& map)
{
map(0x0000, 0x1fff).ram();
- map(0x2000, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write));
+ map(0x2000, 0x2008).rw(FUNC(nes_sh6578_state::read_ppu), FUNC(nes_sh6578_state::write_ppu));
+
+ map(0x2040, 0x207f).rw(FUNC(nes_sh6578_state::read_palette), FUNC(nes_sh6578_state::write_palette));
+
map(0x4014, 0x4014).w(FUNC(nes_sh6578_state::sprite_dma_w));
+
+ map(0x4020, 0x4020).w(FUNC(nes_sh6578_state::timing_setting_control_w));
+
+ map(0x4031, 0x4031).w(FUNC(nes_sh6578_state::initial_startup_w));
+
+ map(0x4040, 0x4047).rw(FUNC(nes_sh6578_state::bankswitch_r), FUNC(nes_sh6578_state::bankswitch_w));
+
+ map(0x4048, 0x404f).rw(FUNC(nes_sh6578_state::dma_r), FUNC(nes_sh6578_state::dma_w));
+
+
map(0x5000, 0x57ff).ram();
- map(0x8000, 0xffff).rom();
+
+ map(0x5800, 0x7fff).ram(); // cpatrolm seems to expect RAM here too?
+
+ map(0x8000, 0x8fff).rw(FUNC(nes_sh6578_state::bank0_r), FUNC(nes_sh6578_state::bank0_w));
+ map(0x9000, 0x9fff).rw(FUNC(nes_sh6578_state::bank1_r), FUNC(nes_sh6578_state::bank1_w));
+ map(0xa000, 0xafff).rw(FUNC(nes_sh6578_state::bank2_r), FUNC(nes_sh6578_state::bank2_w));
+ map(0xb000, 0xbfff).rw(FUNC(nes_sh6578_state::bank3_r), FUNC(nes_sh6578_state::bank3_w));
+ map(0xc000, 0xcfff).rw(FUNC(nes_sh6578_state::bank4_r), FUNC(nes_sh6578_state::bank4_w));
+ map(0xd000, 0xdfff).rw(FUNC(nes_sh6578_state::bank5_r), FUNC(nes_sh6578_state::bank5_w));
+ map(0xe000, 0xefff).rw(FUNC(nes_sh6578_state::bank6_r), FUNC(nes_sh6578_state::bank6_w));
+ map(0xf000, 0xffff).rw(FUNC(nes_sh6578_state::bank7_r), FUNC(nes_sh6578_state::bank7_w));
}
-static INPUT_PORTS_START( nes_sh6578 )
+static INPUT_PORTS_START(nes_sh6578)
INPUT_PORTS_END
void nes_sh6578_state::video_start()
@@ -65,38 +487,109 @@ void nes_sh6578_state::video_start()
void nes_sh6578_state::machine_reset()
{
-}
+ for (int i = 0; i < 8; i++)
+ m_bankswitch[i] = i;
+
+ m_palette_ram.resize(0x40);
+ for (int i = 0; i < 0x40; i++)
+ m_palette_ram[i] = 0x00;
+
+ m_iniital_startup_state = 0;
+}
void nes_sh6578_state::machine_start()
{
-// m_nt_ram = std::make_unique<uint8_t[]>(0x1000);
-// m_nt_page[0] = m_nt_ram.get();
-// m_nt_page[1] = m_nt_ram.get() + 0x400;
-// m_nt_page[2] = m_nt_ram.get() + 0x800;
-// m_nt_page[3] = m_nt_ram.get() + 0xc00;
+ m_bank->configure_entry(0, memregion("maincpu")->base() + 0x0000000);
+ m_bank->set_entry(0);
+}
+
+// SH6578 can address 20-bit address space (1MB of ROM)
+void nes_sh6578_state::rom_map(address_map& map)
+{
+ map(0x00000, 0xfffff).bankr("cartbank");
+}
+
+void nes_sh6578_state::vram_map(address_map& map)
+{
+ map(0x0000, 0x27ff).ram();
+ map(0x8000, 0xffff).ram();
+}
+
-// m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(*this, FUNC(nes_sh6578_state::nes_sh6578_nt_r)), write8_delegate(*this, FUNC(nes_sh6578_state::nes_sh6578_nt_w)));
-// m_ppu->space(AS_PROGRAM).install_read_bank(0x0000, 0x1fff, "bank1");
-// membank("bank1")->set_base(memregion("gfx1")->base());
+uint32_t nes_sh6578_state::screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect)
+{
+ // nametable base depends on bits in 0x2008, it isn't fixed at 0x2000 as it is on a NES
+ int address = 0;
+ const pen_t *paldata = m_palette->pens();
+
+ // pages are 32 tiles high, not 30 as on NES
+ for (int y = 0; y < 32; y++)
+ {
+ for (int x = 0; x < 32; x++)
+ {
+ // character gfx pointer and palette select are encoded in a pair of bytes, not using separate attribute table for palette
+ uint16_t tileaddr;
+ tileaddr = (m_vram->read8(address) << 0);
+ address++;
+ tileaddr |= (m_vram->read8(address) << 8);
+ address++;
+
+ uint8_t pal = (tileaddr & 0xf000) >> 12;
+ tileaddr &= 0x0fff;
+ tileaddr <<= 4;
+
+ for (int yy = 0; yy < 8; yy++)
+ {
+ uint32_t* destptr = &bitmap.pix32((y*8)+ yy);
+
+ uint8_t plane0 = m_vram->read8(tileaddr+0);
+ uint8_t plane1 = m_vram->read8(tileaddr+8);
+ uint8_t plane2 = m_vram->read8(tileaddr+16);
+ uint8_t plane3 = m_vram->read8(tileaddr+24);
+
+ for (int xx = 0; xx < 8; xx++)
+ {
+ uint8_t pixval = ((plane0 >> (7-xx)) & 1) << 0;
+ pixval |= ((plane1 >> (7-xx)) & 1) << 1;
+ pixval |= ((plane2 >> (7-xx)) & 1) << 2;
+ pixval |= ((plane3 >> (7-xx)) & 1) << 3;
+
+ pixval |= ((pal & 0xc) << 2);
+
+ destptr[(x * 8) + xx] = paldata[pixval];
+ }
+
+ tileaddr++;
+
+ }
+
+ }
+ }
+
+ return 0;
}
-void nes_sh6578_state::nes_sh6578(machine_config &config)
+void nes_sh6578_state::nes_sh6578(machine_config& config)
{
/* basic machine hardware */
N2A03(config, m_maincpu, NTSC_APU_CLOCK);
m_maincpu->set_addrmap(AS_PROGRAM, &nes_sh6578_state::nes_sh6578_map);
+ ADDRESS_MAP_BANK(config, m_fullrom).set_map(&nes_sh6578_state::rom_map).set_options(ENDIANNESS_NATIVE, 8, 20, 0x100000);
+
+ ADDRESS_MAP_BANK(config, m_vram).set_map(&nes_sh6578_state::vram_map).set_options(ENDIANNESS_NATIVE, 8, 16, 0x10000);
+
+ TIMER(config, "scantimer").configure_scanline(FUNC(nes_sh6578_state::scanline), "screen", 0, 1);
+
/* video hardware */
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_size(32*8, 262);
- screen.set_visarea(0*8, 32*8-1, 0*8, 30*8-1);
- screen.set_screen_update("ppu", FUNC(ppu2c0x_device::screen_update));
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_refresh_hz(60);
+ m_screen->set_size(32 * 8, 262);
+ m_screen->set_visarea(0 * 8, 32 * 8 - 1, 0 * 8, 30 * 8 - 1);
+ m_screen->set_screen_update(FUNC(nes_sh6578_state::screen_update));
- PPU_2C02(config, m_ppu);
- m_ppu->set_cpu_tag("maincpu");
- m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
+ PALETTE(config, m_palette).set_entries(0x40);
/* sound hardware */
SPEAKER(config, "mono").front_center();
@@ -110,6 +603,7 @@ void nes_sh6578_state::init_nes_sh6578()
}
+
ROM_START( bandgpad )
ROM_REGION( 0x100000, "maincpu", 0 )
ROM_LOAD( "gamepad.bin", 0x00000, 0x100000, CRC(e2fbb532) SHA1(e9170a7739a8355acbf263fe2b1d291951dc07f0) )
@@ -138,5 +632,5 @@ CONS( 2001, ts_handy11, 0, 0, nes_sh6578, nes_sh6578, nes_sh6578_state, in
CONS( 200?, cpatrolm, 0, 0, nes_sh6578, nes_sh6578, nes_sh6578_state, init_nes_sh6578, "<unknown>", "City Patrolman", MACHINE_NOT_WORKING )
-// this may or may not belong here, it appears to have 4bpp gfx, but unless the banks are scrambled, doesn't fit a standard VT scheme
+// this writes the 0x65 0x76 startup code to 0x4031, but the ROM is larger than expected, extra banking?
CONS( 200?, ablwikid, 0, 0, nes_sh6578, nes_sh6578, nes_sh6578_state, init_nes_sh6578, "Advance Bright Ltd.", "Wikid Joystick", MACHINE_NOT_WORKING ) // or Wik!d Joystick
diff --git a/src/mame/drivers/spg2xx.cpp b/src/mame/drivers/spg2xx.cpp
index fb81413e415..b5a73dc14a5 100644
--- a/src/mame/drivers/spg2xx.cpp
+++ b/src/mame/drivers/spg2xx.cpp
@@ -646,6 +646,49 @@ static INPUT_PORTS_START( abltenni )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END
+static INPUT_PORTS_START( comil )
+ PORT_START("EXTRA0")
+ PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("50:50")
+ PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Phone A Friend")
+ PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("Ask The Audience")
+ PORT_BIT( 0x8, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("Walk Away")
+
+ PORT_START("EXTRA1")
+ PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
+ PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
+ PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
+ PORT_BIT( 0x8, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("D")
+
+ PORT_START("EXTRA2")
+ PORT_BIT( 0xf, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("EXTRA3")
+ PORT_BIT( 0xf, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("EXTRA4")
+ PORT_BIT( 0xf, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("EXTRA5")
+ PORT_BIT( 0xf, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("EXTRA6")
+ PORT_BIT( 0xf, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("EXTRA7")
+ PORT_BIT( 0xf, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("P1")
+ PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) // multiplex select for Port B
+ PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("P2")
+ PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) // multiplexed inputs
+ PORT_BIT( 0xfff0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("P3")
+ PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
static INPUT_PORTS_START( guitarfv )
PORT_START("P1") // Button 1 + 2 and start for service mode
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON1 )
@@ -871,6 +914,53 @@ void spg2xx_game_state::abltenni(machine_config &config)
m_maincpu->portc_in().set_ioport("P3");
}
+READ16_MEMBER(spg2xx_game_comil_state::porta_r)
+{
+ uint16_t data = m_porta_data;
+ logerror("%s: Port A Read: %04x (%04x)\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+WRITE16_MEMBER(spg2xx_game_comil_state::porta_w)
+{
+ logerror("%s: Port A Write: %04x (%04x)\n", machine().describe_context(), data, mem_mask);
+ m_porta_data = data;
+}
+
+READ16_MEMBER(spg2xx_game_comil_state::portb_r)
+{
+ uint16_t data = m_io_p2->read() & 0xfff0;
+
+ if (!(m_porta_data & 0x0001)) data |= (m_extra_in[0]->read() & 0xf);
+ if (!(m_porta_data & 0x0002)) data |= (m_extra_in[1]->read() & 0xf);
+ if (!(m_porta_data & 0x0004)) data |= (m_extra_in[2]->read() & 0xf);
+ if (!(m_porta_data & 0x0008)) data |= (m_extra_in[3]->read() & 0xf);
+ if (!(m_porta_data & 0x0010)) data |= (m_extra_in[4]->read() & 0xf);
+ if (!(m_porta_data & 0x0020)) data |= (m_extra_in[5]->read() & 0xf);
+ if (!(m_porta_data & 0x0040)) data |= (m_extra_in[6]->read() & 0xf);
+ if (!(m_porta_data & 0x0080)) data |= (m_extra_in[7]->read() & 0xf);
+
+ logerror("%s: Port B Read: %04x (%04x)\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void spg2xx_game_comil_state::comil(machine_config &config)
+{
+ SPG28X(config, m_maincpu, XTAL(27'000'000), m_screen);
+ m_maincpu->set_addrmap(AS_PROGRAM, &spg2xx_game_comil_state::mem_map_4m);
+
+ spg2xx_base(config);
+
+ m_maincpu->set_pal(true);
+ m_screen->set_refresh_hz(50);
+
+ m_maincpu->porta_in().set(FUNC(spg2xx_game_comil_state::porta_r));
+ m_maincpu->portb_in().set(FUNC(spg2xx_game_comil_state::portb_r));
+
+ m_maincpu->porta_out().set(FUNC(spg2xx_game_comil_state::porta_w));
+ //m_maincpu->portb_out().set(FUNC(spg2xx_game_comil_state::portb_w));
+}
+
void spg2xx_game_state::guitarfv(machine_config &config)
{
SPG24X(config, m_maincpu, XTAL(27'000'000), m_screen);
@@ -1136,6 +1226,11 @@ ROM_START( abltenni )
ROM_LOAD16_WORD_SWAP( "ablpnpwirelesstennis.bin", 0x000000, 0x400000, CRC(66bd8ef1) SHA1(a83640d5d9e84e10d29a065a61e0d7bbec16c6e4) )
ROM_END
+ROM_START( comil )
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 )
+ ROM_LOAD16_WORD_SWAP( "ukmillionaire.bin", 0x000000, 0x400000, CRC(b7e8e126) SHA1(fc76dba672eb5c4c115e16d8ea4a45a6e859f87c) )
+ROM_END
+
ROM_START( tvsprt10 )
ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "tvsports10in1.bin", 0x000000, 0x400000, CRC(98b79889) SHA1(b0ba534d59b794bb38c071c70ab5bcf711364e06) )
@@ -1251,6 +1346,8 @@ CONS( 2007, rad_fb2, 0, 0, rad_skat, rad_fb2, spg2xx_game_state, ini
// ABL TV Games
CONS( 2006, abltenni, 0, 0, abltenni, abltenni, spg2xx_game_state, empty_init, "Advance Bright Ltd / V-Tac Technology Co Ltd.", "Wireless Tennis (WT2000, ABL TV Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
+CONS( 2008, comil, 0, 0, comil, comil, spg2xx_game_comil_state, empty_init, "Character Options", "Who Wants to Be a Millionaire? (Character Options, Plug and Play, UK)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
+
// same as Excalibur Decathlon? not the same as the ABL game
CONS( 2006, tvsprt10, 0, 0, tvsprt10, tvsprt10, spg2xx_game_state, init_tvsprt10, "Simba / V-Tac Technology Co Ltd.", "TV Sports 10-in-1 / Decathlon Athletic Sport Games", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, decathln, 0, 0, tvsprt10, decathln, spg2xx_game_state, init_tvsprt10, "Advance Bright Ltd / V-Tac Technology Co Ltd.", "Decathlon", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // unit found in Spain
diff --git a/src/mame/drivers/sunplus_unsp20soc.cpp b/src/mame/drivers/sunplus_unsp20soc.cpp
index db9bdc478ef..dc52866dfc2 100644
--- a/src/mame/drivers/sunplus_unsp20soc.cpp
+++ b/src/mame/drivers/sunplus_unsp20soc.cpp
@@ -206,6 +206,9 @@ READ16_MEMBER(jak_s500_game_state::porta_r)
//if (mem.read_word(0x22D6F7) == 0x4846)
// mem.write_word(0x22D6F7, 0x4840); // jak_pf force service mode
+ //if (mem.read_word(0x23E295) == 0x4846)
+ // mem.write_word(0x23E295, 0x4840); // jak_smwm force service mode
+
return data;
}
@@ -1326,6 +1329,15 @@ ROM_START(jak_s500)
ROM_LOAD16_WORD_SWAP("spbwheel.bin", 0x000000, 0x800000, CRC(6ba1d335) SHA1(1bb3e4d02c7b35dd4d336971c6a9f82071cc6ce1) )
ROM_END
+ROM_START(jak_smwm)
+ //ROM_REGION16_BE( 0x40000, "maincpu:internal", ROMREGION_ERASE00 ) // not on this model? (or at least not this size, as CS base is different)
+ //ROM_LOAD16_WORD_SWAP( "internal.rom", 0x00000, 0x40000, NO_DUMP )
+
+ ROM_REGION(0x800000, "maincpu", ROMREGION_ERASE00)
+ ROM_LOAD16_WORD_SWAP("spidersense.bin", 0x000000, 0x800000, CRC(e0676d0e) SHA1(01c01852fe4aea799c09ebbb6870b2f6e92085c4) )
+ROM_END
+
+
ROM_START(jak_pf)
//ROM_REGION16_BE( 0x40000, "maincpu:internal", ROMREGION_ERASE00 ) // not on this model? (or at least not this size, as CS base is different)
//ROM_LOAD16_WORD_SWAP( "internal.rom", 0x00000, 0x40000, NO_DUMP )
@@ -1584,6 +1596,7 @@ CONS(2012, paccon, 0, 0, paccon, paccon, jak_s500_game_state, init_wrlshunt, "Ba
CONS(2009, jak_s500, 0, 0, wrlshunt, jak_s500, jak_s500_game_state, init_wrlshunt, "JAKKS Pacific Inc", "SpongeBob SquarePants Bikini Bottom 500 (JAKKS Pacific TV Motion Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+CONS(2009, jak_smwm, 0, 0, wrlshunt, jak_s500, jak_s500_game_state, init_wrlshunt, "JAKKS Pacific Inc", "Spider-Man Web Master (JAKKS Pacific TV Motion Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
CONS(2010, jak_pf, 0, 0, wrlshunt, jak_s500, jak_s500_game_state, init_wrlshunt, "JAKKS Pacific Inc", "Phineas and Ferb: Best Game Ever! (JAKKS Pacific TV Motion Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // build date is 2009, but onscreen display is 2010
CONS(2009, jak_prft, 0, 0, wrlshunt, jak_s500, jak_s500_game_state, init_wrlshunt, "JAKKS Pacific Inc", "Power Rangers Force In Time (JAKKS Pacific TV Motion Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
CONS(2009, jak_tink, 0, 0, wrlshunt, jak_s500, jak_s500_game_state, init_wrlshunt, "JAKKS Pacific Inc", "Tinker Bell and the Lost Treasure (JAKKS Pacific TV Motion Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
diff --git a/src/mame/includes/spg2xx.h b/src/mame/includes/spg2xx.h
index 3c03a2ac361..d3a7b4c4c0b 100644
--- a/src/mame/includes/spg2xx.h
+++ b/src/mame/includes/spg2xx.h
@@ -40,6 +40,7 @@ public:
void rad_crik(machine_config &config);
void non_spg_base(machine_config &config);
void abltenni(machine_config &config);
+ void comil(machine_config &config);
void tvsprt10(machine_config &config);
void guitarfv(machine_config &config);
void tmntmutm(machine_config &config);
@@ -105,6 +106,25 @@ private:
required_device<eeprom_serial_93cxx_device> m_eeprom;
};
+class spg2xx_game_comil_state : public spg2xx_game_state
+{
+public:
+ spg2xx_game_comil_state(const machine_config &mconfig, device_type type, const char *tag) :
+ spg2xx_game_state(mconfig, type, tag),
+ m_porta_data(0),
+ m_extra_in(*this, "EXTRA%u", 0U)
+ { }
+
+ void comil(machine_config &config);
+
+private:
+ DECLARE_READ16_MEMBER(porta_r);
+ DECLARE_WRITE16_MEMBER(porta_w) override;
+ DECLARE_READ16_MEMBER(portb_r);
+ uint16_t m_porta_data;
+ required_ioport_array<8> m_extra_in;
+};
+
class spg2xx_game_swclone_state : public spg2xx_game_state
{
public:
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index c09a2a86d6f..af0cf007df1 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -37132,6 +37132,7 @@ rad_skatp //
rad_crik //
rad_fb2 //
mattelcs //
+comil //
abltenni //
tvsprt10 //
decathln
@@ -37827,6 +37828,7 @@ starfigh // (c) 1990 SunA
@source:sunplus_unsp20soc.cpp
paccon
jak_s500
+jak_smwm
jak_pf
jak_prft
jak_tink