Plug & Play / sh6578 work (#6447)

* PPU refactoring (nw)

* PPU refactoring (nw)

* start making a new device (nw)

* PPU device refinements (nw)

* tear things down (nw)

* refactoring (nw)

* more refactor and teardown (nw)

* (nw)

* rebuilding (nw)

* (nw)

* (nw)

* (nw)

* (nw)

* checkpoint (nw)
This commit is contained in:
David Haywood 2020-03-15 19:26:47 +00:00 committed by GitHub
parent 07c987b5bc
commit 389126869f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 837 additions and 765 deletions

View File

@ -1150,6 +1150,8 @@ if (VIDEOS["PPU2C0X"]~=null) then
MAME_DIR .. "src/devices/video/ppu2c0x.h",
MAME_DIR .. "src/devices/video/ppu2c0x_vt.cpp",
MAME_DIR .. "src/devices/video/ppu2c0x_vt.h",
MAME_DIR .. "src/devices/video/ppu2c0x_sh6578.cpp",
MAME_DIR .. "src/devices/video/ppu2c0x_sh6578.h",
}
end

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,10 @@
#define PPU_DRAW_BG 0
#define PPU_DRAW_OAM 1
/* constant definitions */
#define VISIBLE_SCREEN_WIDTH (32*8) /* Visible screen width */
#define VISIBLE_SCREEN_HEIGHT (30*8) /* Visible screen height */
#define SPRITERAM_SIZE 0x100 /* spriteram size */
///*************************************************************************
// TYPE DEFINITIONS
@ -81,15 +85,20 @@ public:
virtual void shift_tile_plane_data(uint8_t &pix);
virtual void draw_tile_pixel(uint8_t pix, int color, pen_t back_pen, uint32_t *&dest, const pen_t *color_table);
virtual void draw_tile(uint8_t *line_priority, int color_byte, int color_bits, int address, int start_x, pen_t back_pen, uint32_t *&dest, const pen_t *color_table);
void draw_background( uint8_t *line_priority );
virtual void draw_background( uint8_t *line_priority );
void draw_background_pen();
virtual void read_sprite_plane_data(int address);
virtual void make_sprite_pixel_data(uint8_t &pixel_data, int flipx);
virtual void draw_sprite_pixel(int sprite_xpos, int color, int pixel, uint8_t pixel_data, bitmap_rgb32 &bitmap);
virtual void read_extra_sprite_bits(int sprite_index);
void draw_sprites(uint8_t *line_priority);
virtual void draw_sprites(uint8_t *line_priority);
void render_scanline();
virtual void scanline_increment_fine_ycounter();
void update_visible_enabled_scanline();
void update_visible_disabled_scanline();
void update_visible_scanline();
void update_scanline();
void spriteram_dma(address_space &space, const uint8_t page);
@ -119,6 +128,8 @@ public:
void ppu2c0x(address_map &map);
protected:
ppu2c0x_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock, address_map_constructor internal_map);
// registers definition
enum
{
@ -178,41 +189,44 @@ protected:
int m_scanline; /* scanline count */
std::unique_ptr<uint8_t[]> m_spriteram; /* sprite ram */
int m_line_write_increment_large;
bool m_paletteram_in_ppuspace; // sh6578 doesn't have the palette in PPU space, so various side-effects don't apply
std::vector<uint8_t> m_palette_ram; /* shouldn't be in main memory! */
std::unique_ptr<bitmap_rgb32> m_bitmap; /* target bitmap */
int m_regs[PPU_MAX_REG]; /* registers */
int m_tile_page; /* current tile page */
int m_back_color; /* background color */
int m_refresh_data; /* refresh-related */
int m_x_fine; /* refresh-related */
int m_tilecount; /* MMC5 can change attributes to subsets of the 34 visible tiles */
std::unique_ptr<pen_t[]> m_colortable; /* color table modified at run time */
std::unique_ptr<pen_t[]> m_colortable_mono; /* monochromatic color table modified at run time */
latch_delegate m_latch;
uint8_t readbyte(offs_t address);
private:
static constexpr device_timer_id TIMER_HBLANK = 0;
static constexpr device_timer_id TIMER_NMI = 1;
static constexpr device_timer_id TIMER_SCANLINE = 2;
inline uint8_t readbyte(offs_t address);
inline void writebyte(offs_t address, uint8_t data);
std::unique_ptr<bitmap_rgb32> m_bitmap; /* target bitmap */
std::unique_ptr<pen_t[]> m_colortable; /* color table modified at run time */
std::unique_ptr<pen_t[]> m_colortable_mono; /* monochromatic color table modified at run time */
scanline_delegate m_scanline_callback_proc; /* optional scanline callback */
hblank_delegate m_hblank_callback_proc; /* optional hblank callback */
vidaccess_delegate m_vidaccess_callback_proc; /* optional video access callback */
devcb_write_line m_int_callback; /* nmi access callback from interface */
int m_regs[PPU_MAX_REG]; /* registers */
int m_refresh_data; /* refresh-related */
int m_refresh_latch; /* refresh-related */
int m_x_fine; /* refresh-related */
int m_toggle; /* used to latch hi-lo scroll */
int m_add; /* vram increment amount */
int m_videomem_addr; /* videomem address pointer */
int m_data_latch; /* latched videomem data */
int m_buffered_data;
int m_tile_page; /* current tile page */
int m_sprite_page; /* current sprite page */
int m_back_color; /* background color */
uint8_t m_palette_ram[0x20]; /* shouldn't be in main memory! */
int m_scan_scale; /* scan scale */
int m_tilecount; /* MMC5 can change attributes to subsets of the 34 visible tiles */
int m_draw_phase; /* MMC5 uses different regs for BG and OAM */
latch_delegate m_latch;
// timers
emu_timer *m_hblank_timer; /* hblank period at end of each scanline */

View File

@ -0,0 +1,297 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/******************************************************************************
******************************************************************************/
#include "emu.h"
#include "video/ppu2c0x_sh6578.h"
#define LOG_PPU_EXTRA (1U << 0)
//#define VERBOSE (LOG_PPU_EXTRA)
#define VERBOSE (0)
#include "logmacro.h"
// devices
DEFINE_DEVICE_TYPE(PPU_SH6578, ppu_sh6578_device, "ppu_sh6578", "SH6578 PPU (NTSC)")
DEFINE_DEVICE_TYPE(PPU_SH6578PAL, ppu_sh6578pal_device, "ppu_sh6578pal", "SH6578 PPU (PAL)")
ppu_sh6578_device::ppu_sh6578_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) :
ppu2c0x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(ppu_sh6578_device::ppu_internal_map), this))
{
m_paletteram_in_ppuspace = false;
m_line_write_increment_large = 32;
}
ppu_sh6578_device::ppu_sh6578_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
ppu_sh6578_device(mconfig, PPU_SH6578, tag, owner, clock)
{
}
ppu_sh6578pal_device::ppu_sh6578pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
ppu_sh6578_device(mconfig, PPU_SH6578PAL, tag, owner, clock)
{
m_scanlines_per_frame = PAL_SCANLINES_PER_FRAME;
m_vblank_first_scanline = VBLANK_FIRST_SCANLINE_PALC;
}
// Palette RAM is _NOT_ mapped to PPU space here
void ppu_sh6578_device::ppu_internal_map(address_map& map)
{
map(0x0000, 0x1fff).ram();
map(0x2000, 0x27ff).ram();
map(0x2800, 0x7fff).nopr();
map(0x8000, 0xffff).ram(); // machine specific?
}
void ppu_sh6578_device::device_start()
{
ppu2c0x_device::device_start();
m_palette_ram.resize(0x40);
for (int i = 0; i < 0x40; i++)
m_palette_ram[i] = 0x00;
}
void ppu_sh6578_device::device_reset()
{
ppu2c0x_device::device_reset();
m_colsel_pntstart = 0x00;
}
void ppu_sh6578_device::scanline_increment_fine_ycounter()
{
/* increment the fine y-scroll */
m_refresh_data += 0x1000;
/* if it's rolled, increment the coarse y-scroll */
if (m_refresh_data & 0x8000)
{
uint16_t tmp;
tmp = (m_refresh_data & 0x03e0) + 0x20;
m_refresh_data &= 0x7c1f;
if (tmp == 0x0400)
m_refresh_data ^= 0x0800;
else
m_refresh_data |= (tmp & 0x03e0);
//logerror("updating refresh_data: %04x\n", m_refresh_data);
}
}
void ppu_sh6578_device::read_tile_plane_data(int address, int color)
{
m_planebuf[0] = readbyte(address);
m_planebuf[1] = readbyte(address + 8);
m_extplanebuf[0] = readbyte(address + 16);
m_extplanebuf[1] = readbyte(address + 24);
}
void ppu_sh6578_device::draw_tile(uint8_t* line_priority, int color_byte, int color_bits, int address, int start_x, pen_t back_pen, uint32_t*& dest, const pen_t* color_table)
{
int color = color_byte;
color &= 0xc;
read_tile_plane_data(address, color);
/* render the pixel */
for (int i = 0; i < 8; i++)
{
uint8_t pix;
pix = ((m_planebuf[0] & 0x80) >> 7);
pix |= ((m_planebuf[1] & 0x80) >> 6);
pix |= ((m_extplanebuf[0] & 0x80) >> 5);
pix |= ((m_extplanebuf[1] & 0x80) >> 4);
m_planebuf[0] <<= 1;
m_planebuf[1] <<= 1;
m_extplanebuf[0] <<= 1;
m_extplanebuf[1] <<= 1;
if ((start_x + i) >= 0 && (start_x + i) < VISIBLE_SCREEN_WIDTH)
{
pen_t pen;
uint8_t palval = m_palette_ram[(pix | color << 2)] & 0x3f;
bool trans = false;
if ((palval & 0x1f) == 0x1f)
trans = true;
if (!trans)
{
pen = this->pen(palval);
}
else
{
pen = back_pen;
}
*dest = pen;
// priority marking
if (!trans)
line_priority[start_x + i] |= 0x02;
}
dest++;
}
}
void ppu_sh6578_device::draw_background(uint8_t* line_priority)
{
bitmap_rgb32& bitmap = *m_bitmap;
uint8_t color_mask;
const pen_t* color_table;
/* setup the color mask and colortable to use */
if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
{
color_mask = 0xf0;
color_table = m_colortable_mono.get();
}
else
{
color_mask = 0xff;
color_table = m_colortable.get();
}
/* cache the background pen */
pen_t back_pen = pen(m_back_color & color_mask);
/* determine where in the nametable to start drawing from */
/* based on the current scanline and scroll regs */
uint8_t scroll_x_coarse = m_refresh_data & 0x001f;
uint8_t scroll_y_coarse = (m_refresh_data & 0x03e0) >> 5;
uint16_t nametable = (m_refresh_data & 0x0c00);
uint8_t scroll_y_fine = (m_refresh_data & 0x7000) >> 12;
int x = scroll_x_coarse;
/* get the tile index */
int tile_index = (nametable<<1) + scroll_y_coarse * 64;
/* set up dest */
int start_x = (m_x_fine ^ 0x07) - 7;
uint32_t* dest = &bitmap.pix32(m_scanline, start_x);
m_tilecount = 0;
/* draw the 32 or 33 tiles that make up a line */
while (m_tilecount < 34)
{
int color_byte;
int index1;
int page2, address;
index1 = tile_index + (x << 1);
if (m_colsel_pntstart & 1)
{
index1 &= 0x7ff;
index1 += 0x2000;
}
else
{
index1 &= 0x1fff;
}
// page2 is the output of the nametable read (this section is the FIRST read per tile!)
page2 = readbyte(index1);
/* Figure out which byte in the color table to use */
color_byte = readbyte(index1 + 1);
if (start_x < VISIBLE_SCREEN_WIDTH)
{
address = ((page2 | (color_byte<<8)) & 0x0fff) << 4;
// plus something that accounts for y
address += scroll_y_fine;
draw_tile(line_priority, (color_byte >> 4) & 0xf, 0, address, start_x, back_pen, dest, color_table);
start_x += 8;
/* move to next tile over and toggle the horizontal name table if necessary */
x++;
if (x > 31)
{
x = 0;
tile_index ^= 0x800;
}
}
m_tilecount++;
}
/* if the left 8 pixels for the background are off, blank 'em */
if (!(m_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND_L8))
{
dest = &bitmap.pix32(m_scanline);
for (int i = 0; i < 8; i++)
{
*(dest++) = back_pen;
line_priority[i] ^= 0x02;
}
}
}
void ppu_sh6578_device::draw_sprites(uint8_t* line_priority)
{
}
void ppu_sh6578_device::write(offs_t offset, uint8_t data)
{
if (offset < 0x8)
{
ppu2c0x_device::write(offset, data);
}
else if (offset == 0x8)
{
LOGMASKED(LOG_PPU_EXTRA, "%s: ppu_sh6578_device::write : Color Select & PNT Start Address : %02x\n", machine().describe_context(), data);
m_colsel_pntstart = data;
}
else
{
LOGMASKED(LOG_PPU_EXTRA, "%s: ppu_sh6578_device::write : unhandled offset %02x : %02x\n", machine().describe_context(), offset, data);
}
}
uint8_t ppu_sh6578_device::read(offs_t offset)
{
if (offset < 0x8)
{
return ppu2c0x_device::read(offset);
}
else if (offset == 0x8)
{
LOGMASKED(LOG_PPU_EXTRA, "%s: ppu_sh6578_device::read : Color Select & PNT Start Address\n", machine().describe_context());
return m_colsel_pntstart;
}
else
{
LOGMASKED(LOG_PPU_EXTRA, "%s: ppu_sh6578_device::read : unhandled offset %02x\n", machine().describe_context(), offset);
return 0x00;
}
}
void ppu_sh6578_device::palette_write(offs_t offset, uint8_t data)
{
m_palette_ram[offset] = data;
}
uint8_t ppu_sh6578_device::palette_read(offs_t offset)
{
return m_palette_ram[offset];
}

View File

@ -0,0 +1,54 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/******************************************************************************
******************************************************************************/
#ifndef MAME_VIDEO_PPU_SH6578_H
#define MAME_VIDEO_PPU_SH6578_H
#pragma once
#include "video/ppu2c0x.h"
class ppu_sh6578_device : public ppu2c0x_device
{
public:
ppu_sh6578_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t palette_read(offs_t offset) override;
virtual void palette_write(offs_t offset, uint8_t data) override;
virtual void write(offs_t offset, uint8_t data) override;
virtual uint8_t read(offs_t offset) override;
protected:
ppu_sh6578_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void ppu_internal_map(address_map& map);
private:
virtual void device_start() override;
virtual void device_reset() override;
void scanline_increment_fine_ycounter() override;
void read_tile_plane_data(int address, int color) override;
void draw_tile(uint8_t* line_priority, int color_byte, int color_bits, int address, int start_x, pen_t back_pen, uint32_t*& dest, const pen_t* color_table) override;
virtual void draw_sprites(uint8_t* line_priority) override;
virtual void draw_background(uint8_t* line_priority) override;
uint8_t m_extplanebuf[2];
uint8_t m_colsel_pntstart;
};
class ppu_sh6578pal_device : public ppu_sh6578_device
{
public:
ppu_sh6578pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
};
DECLARE_DEVICE_TYPE(PPU_SH6578, ppu_sh6578_device)
DECLARE_DEVICE_TYPE(PPU_SH6578PAL, ppu_sh6578pal_device)
#endif // MAME_VIDEO_PPU_SH6578_H

View File

@ -11,6 +11,7 @@
*/
#include "emu.h"
#include "video/ppu2c0x_sh6578.h"
#include "cpu/m6502/m6502.h"
#include "sound/nes_apu.h"
#include "emupal.h"
@ -33,11 +34,10 @@ public:
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"),
m_apu(*this, "nesapu"),
m_timer(*this, "timer"),
m_in(*this, "IN%u", 0U)
@ -57,16 +57,13 @@ protected:
private:
required_device<cpu_device> m_maincpu;
required_device<ppu_sh6578_device> m_ppu;
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;
required_device<nesapu_device> m_apu;
required_device<timer_device> m_timer;
rgb_t nespal_to_RGB(int color_intensity, int color_num);
DECLARE_READ8_MEMBER(bankswitch_r);
DECLARE_WRITE8_MEMBER(bankswitch_w);
@ -99,11 +96,6 @@ private:
DECLARE_WRITE8_MEMBER(timer_config_w);
DECLARE_WRITE8_MEMBER(timer_value_w);
DECLARE_WRITE8_MEMBER(write_ppu);
DECLARE_READ8_MEMBER(read_ppu);
DECLARE_WRITE8_MEMBER(write_palette);
DECLARE_READ8_MEMBER(read_palette);
DECLARE_READ8_MEMBER(io0_r);
DECLARE_READ8_MEMBER(io1_r);
DECLARE_WRITE8_MEMBER(io_w);
@ -117,7 +109,6 @@ private:
DECLARE_WRITE_LINE_MEMBER(apu_irq);
int m_iniital_startup_state;
std::vector<uint8_t> m_palette_ram;
uint8_t m_bankswitch[8];
@ -127,29 +118,14 @@ private:
uint8_t m_dma_dest[2];
uint8_t m_dma_length[2];
uint8_t m_2000;
uint8_t m_2001;
uint8_t m_2002;
uint8_t m_2003;
uint8_t m_2004;
uint16_t m_scrollreg;
bool m_scrollreg_firstwrite;
uint16_t m_vramaddr;
uint8_t m_2007;
uint8_t m_irqmask;
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);
uint16_t get_tileaddress(uint8_t x, uint8_t y, bool ishigh);
//uint16_t get_tileaddress(uint8_t x, uint8_t y, bool ishigh);
uint32_t screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect);
@ -163,18 +139,6 @@ private:
required_ioport_array<2> m_in;
};
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)
@ -190,7 +154,7 @@ 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);
m_fullrom->write8(address, data);
}
WRITE8_MEMBER(nes_sh6578_state::sprite_dma_w)
@ -226,6 +190,7 @@ READ8_MEMBER(nes_sh6578_state::dma_r)
void nes_sh6578_state::do_dma()
{
if (m_dma_control & 0x80)
{
uint16_t dma_source = m_dma_source[0] | (m_dma_source[1] << 8);
@ -261,7 +226,7 @@ void nes_sh6578_state::do_dma()
}
else
{
m_vram->write8(realdestaddress, readdat);
m_ppu->space(AS_PROGRAM).write_byte(realdestaddress, readdat);
}
realsourceaddress++;
@ -396,185 +361,6 @@ 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:
LOGMASKED(LOG_PPU, "%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;
}
case 0x01: return m_2001;
case 0x03: return m_2003;
case 0x04: return m_2004;
case 0x07: return m_2007;
default:
LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::read_ppu : unhandled offset %02x\n", machine().describe_context(), offset);
return 0x00;
}
}
WRITE8_MEMBER(nes_sh6578_state::write_ppu)
{
switch (offset)
{
case 0x08:
LOGMASKED(LOG_PPU, "%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; LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data); break;
case 0x01: m_2001 = data; LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data); break;
case 0x02: m_2002 = data; LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data); break;
case 0x03: m_2003 = data; LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data); break;
case 0x04: m_2004 = data; LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data); break;
case 0x05:
{
LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data);
if (m_scrollreg_firstwrite)
{
m_scrollreg = (m_scrollreg & 0xff00) | data;
m_scrollreg_firstwrite = false;
}
else
{
m_scrollreg = (m_scrollreg & 0x00ff) | (data<<8);
m_scrollreg_firstwrite = true;
}
break;
}
case 0x06:
{
LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data);
m_vramaddr <<= 8;
m_vramaddr = (m_vramaddr & 0xff00) | data;
logerror(" vram address is now %04x\n", m_vramaddr);
break;
}
case 0x07:
{
LOGMASKED(LOG_PPU, "%s: nes_sh6578_state::write_ppu offset %02x : %02x\n", machine().describe_context(), offset, data);
m_vram->write8(m_vramaddr, data);
if (m_2000 & 4)
m_vramaddr += 64; // big race and pioneer racing in ts_handy11 need this to be 64, not 32
else
m_vramaddr++;
break;
}
default:
break;
//ppu2c0x_device::write(space, offset, data);
}
}
READ8_MEMBER(nes_sh6578_state::io0_r)
{
@ -649,14 +435,12 @@ READ8_MEMBER(nes_sh6578_state::apu_read_mem)
void nes_sh6578_state::nes_sh6578_map(address_map& map)
{
map(0x0000, 0x1fff).ram();
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(0x2000, 0x2008).rw(m_ppu, FUNC(ppu_sh6578_device::read), FUNC(ppu_sh6578_device::write));
map(0x2040, 0x207f).rw(m_ppu, FUNC(ppu_sh6578_device::palette_read), FUNC(ppu_sh6578_device::palette_write));
map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write));
map(0x4014, 0x4014).r(FUNC(nes_sh6578_state::psg1_4014_r));
map(0x4014, 0x4014).rw(FUNC(nes_sh6578_state::psg1_4014_r), FUNC(nes_sh6578_state::sprite_dma_w));
map(0x4015, 0x4015).rw(FUNC(nes_sh6578_state::psg1_4015_r), FUNC(nes_sh6578_state::psg1_4015_w));
map(0x4016, 0x4016).rw(FUNC(nes_sh6578_state::io0_r), FUNC(nes_sh6578_state::io_w));
map(0x4017, 0x4017).rw(FUNC(nes_sh6578_state::io1_r), FUNC(nes_sh6578_state::psg1_4017_w));
@ -673,7 +457,6 @@ void nes_sh6578_state::nes_sh6578_map(address_map& map)
map(0x4048, 0x404f).rw(FUNC(nes_sh6578_state::dma_r), FUNC(nes_sh6578_state::dma_w));
map(0x5000, 0x57ff).ram();
map(0x5800, 0x7fff).ram(); // cpatrolm seems to expect RAM here too?
@ -712,26 +495,9 @@ 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;
m_bank->set_entry(0);
m_2000 = 0;
m_2001 = 0;
m_2002 = 0;
m_2003 = 0;
m_2004 = 0;
m_2007 = 0;
m_scrollreg = 0x00;
m_scrollreg_firstwrite = true;
m_colsel_pntstart = 0;
m_irqmask = 0xff;
m_timerval = 0x00;
}
@ -750,7 +516,6 @@ void nes_sh6578_state::machine_start()
{
m_isbanked = false;
}
}
// SH6578 can address 20-bit address space (1MB of ROM)
@ -759,122 +524,6 @@ 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(0x2800, 0x7fff).nopr();
map(0x8000, 0xffff).ram();
}
uint16_t nes_sh6578_state::get_tileaddress(uint8_t x, uint8_t y, bool ishigh)
{
if (!ishigh)
{
x &= 0x3f; // can't be bigger than 64x64;
y &= 0x3f;
if (x & 0x20) // right hand side of tilemap
{
x &= 0x1f;
if (y & 0x20) // bottom of tilemap
{
y &= 0x1f;
return 0x1800 + (x * 2) + (y * 0x40);
}
else
{
//y &= 0x1f;
return 0x0800 + (x * 2) + (y * 0x40);
}
}
else // left hand side of tilemap
{
//x &= 0x1f;
if (y & 0x20) // bottom of tilemap
{
y &= 0x1f;
return 0x1000 + (x * 2) + (y * 0x40);
}
else
{
//y &= 0x1f;
return 0x0000 + (x * 2) + (y * 0x40);
}
}
}
else
{
x &= 0x1f;
y &= 0x1f;
return 0x2000 + (x * 2) + (y * 0x40);
}
}
uint32_t nes_sh6578_state::screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect)
{
const pen_t *paldata = m_palette->pens();
// pages are 32 tiles high, not 30 as on NES
for (int scanline = cliprect.min_y; scanline <= cliprect.max_y; scanline++)
{
int xscrollmsb = m_2000 & 0x1;
int yscrollmsb = (m_2000 & 0x2)>>1;
uint16_t yscroll = (m_scrollreg & 0xff00) >> 8;
yscroll |= (yscrollmsb << 8);
uint16_t xscroll = m_scrollreg & 0x00ff;
xscroll |= (xscrollmsb << 8);
int realy = scanline + yscroll;
int y = realy >> 3;
int tileline = realy & 7;
for (int x = 0; x < 32; x++)
{
int xtile = x + (xscroll >> 3);
// nametable base depends on bits in 0x2008, it isn't fixed at 0x2000 as it is on a NES
uint16_t address = get_tileaddress(xtile, y, (m_colsel_pntstart & 1) ? true : false);
// 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;
uint32_t* destptr = &bitmap.pix32(scanline);
uint8_t plane0 = m_vram->read8(tileaddr+0+tileline);
uint8_t plane1 = m_vram->read8(tileaddr+8+tileline);
uint8_t plane2 = m_vram->read8(tileaddr+16+tileline);
uint8_t plane3 = m_vram->read8(tileaddr+24+tileline);
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];
}
}
}
return 0;
}
TIMER_DEVICE_CALLBACK_MEMBER(nes_sh6578_state::timer_expired)
{
if (!(m_irqmask & 0x80))
@ -894,6 +543,11 @@ TIMER_DEVICE_CALLBACK_MEMBER(nes_sh6578_state::timer_expired)
#define PAL_APU_CLOCK (N2A03_PAL_XTAL/16) /* 1.662607 MHz */
#define PALC_APU_CLOCK (N2A03_PAL_XTAL/15) /* 1.77344746666... MHz */
uint32_t nes_sh6578_state::screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect)
{
return m_ppu->screen_update(screen, bitmap, cliprect);
}
void nes_sh6578_state::nes_sh6578(machine_config& config)
{
/* basic machine hardware */
@ -902,22 +556,21 @@ void nes_sh6578_state::nes_sh6578(machine_config& config)
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);
PPU_SH6578(config, m_ppu, N2A03_NTSC_XTAL);
m_ppu->set_cpu_tag(m_maincpu);
m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
/* video hardware */
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_refresh_hz(60.0988);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((113.66/(NTSC_APU_CLOCK.dvalue()/1000000)) *
(ppu2c0x_device::VBLANK_LAST_SCANLINE_NTSC-ppu2c0x_device::VBLANK_FIRST_SCANLINE+1+2)));
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));
m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE);
TIMER(config, m_timer).configure_periodic(FUNC(nes_sh6578_state::timer_expired), attotime::never);
PALETTE(config, m_palette).set_entries(0x40);
/* sound hardware */
SPEAKER(config, "mono").front_center();
@ -935,11 +588,16 @@ void nes_sh6578_state::nes_sh6578_pal(machine_config& config)
m_maincpu->set_clock(PALC_APU_CLOCK);
m_apu->set_clock(PALC_APU_CLOCK);
PPU_SH6578PAL(config.replace(), m_ppu, N2A03_PAL_XTAL);
m_ppu->set_cpu_tag(m_maincpu);
m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_screen->set_refresh_hz(50.0070);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((113.66 / (PALC_APU_CLOCK.dvalue() / 1000000)) *
(310 - 291 + 1 + 2)));
(ppu2c0x_device::VBLANK_LAST_SCANLINE_PAL - ppu2c0x_device::VBLANK_FIRST_SCANLINE_PALC + 1 + 2)));
m_screen->set_size(32 * 8, 312);
m_screen->set_visarea(0 * 8, 32 * 8 - 1, 0 * 8, 30 * 8 - 1);
}
void nes_sh6578_state::init_nes_sh6578()