mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
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:
parent
07c987b5bc
commit
389126869f
@ -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
@ -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 */
|
||||
|
297
src/devices/video/ppu2c0x_sh6578.cpp
Normal file
297
src/devices/video/ppu2c0x_sh6578.cpp
Normal 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];
|
||||
}
|
54
src/devices/video/ppu2c0x_sh6578.h
Normal file
54
src/devices/video/ppu2c0x_sh6578.h
Normal 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
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user