From 4db634dfd908786cad140fa97a49c11a627a9019 Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Wed, 11 Mar 2020 14:42:00 +0000 Subject: 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) --- src/devices/video/ppu2c0x.cpp | 125 ++++---- src/devices/video/ppu2c0x.h | 1 + src/mame/drivers/nes_sh6578.cpp | 560 +++++++++++++++++++++++++++++++-- src/mame/drivers/spg2xx.cpp | 97 ++++++ src/mame/drivers/sunplus_unsp20soc.cpp | 13 + src/mame/includes/spg2xx.h | 20 ++ src/mame/mame.lst | 2 + 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 m_maincpu; - required_device m_ppu; - - void nes_sh6578_map(address_map &map); + required_memory_bank m_bank; + required_device m_fullrom; + required_device m_vram; + required_device m_screen; + required_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 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(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, "", "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 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 -- cgit v1.2.3