summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Fabio Priuli <etabeta78@users.noreply.github.com>2014-04-10 11:57:10 +0000
committer Fabio Priuli <etabeta78@users.noreply.github.com>2014-04-10 11:57:10 +0000
commit3c4620803a67988179a0714ef68cc20e69f5e3b4 (patch)
tree4f47cacf8bdbd67a14854df7dd3d72dbd56ce18e
parent39b3fbee05f816629321eb7f2a22a4cfc3cb20a7 (diff)
Converted SNES PPU to be a device. [Fabio Priuli]
-rw-r--r--.gitattributes3
-rw-r--r--src/emu/video/snes_ppu.c (renamed from src/mame/video/snes.c)520
-rw-r--r--src/emu/video/snes_ppu.h292
-rw-r--r--src/emu/video/video.mak8
-rw-r--r--src/mame/drivers/nss.c4
-rw-r--r--src/mame/drivers/sfcbox.c7
-rw-r--r--src/mame/drivers/snesb.c7
-rw-r--r--src/mame/includes/snes.h343
-rw-r--r--src/mame/machine/snes.c85
-rw-r--r--src/mame/mame.mak3
-rw-r--r--src/mess/drivers/snes.c16
-rw-r--r--src/mess/mess.mak2
12 files changed, 686 insertions, 604 deletions
diff --git a/.gitattributes b/.gitattributes
index 49aae50188c..c0905f4aeaa 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3220,6 +3220,8 @@ src/emu/video/sed1330.c svneol=native#text/plain
src/emu/video/sed1330.h svneol=native#text/plain
src/emu/video/sed1520.c svneol=native#text/plain
src/emu/video/sed1520.h svneol=native#text/plain
+src/emu/video/snes_ppu.c svneol=native#text/plain
+src/emu/video/snes_ppu.h svneol=native#text/plain
src/emu/video/stvvdp1.c svneol=native#text/plain
src/emu/video/stvvdp2.c svneol=native#text/plain
src/emu/video/t6a04.c svneol=native#text/plain
@@ -7272,7 +7274,6 @@ src/mame/video/skykid.c svneol=native#text/plain
src/mame/video/skyraid.c svneol=native#text/plain
src/mame/video/slapfght.c svneol=native#text/plain
src/mame/video/slapshot.c svneol=native#text/plain
-src/mame/video/snes.c svneol=native#text/plain
src/mame/video/snk.c svneol=native#text/plain
src/mame/video/snk6502.c svneol=native#text/plain
src/mame/video/snk68.c svneol=native#text/plain
diff --git a/src/mame/video/snes.c b/src/emu/video/snes_ppu.c
index 2908b84507b..dbbd4b901f6 100644
--- a/src/mame/video/snes.c
+++ b/src/emu/video/snes_ppu.c
@@ -71,7 +71,7 @@
***************************************************************************/
#include "emu.h"
-#include "includes/snes.h"
+#include "video/snes_ppu.h"
#define SNES_MAINSCREEN 0
#define SNES_SUBSCREEN 1
@@ -80,6 +80,79 @@
#define SNES_CLIP_OUT 2
#define SNES_CLIP_ALWAYS 3
+#define SNES_VRAM_SIZE 0x20000 /* 128kb of video ram */
+#define SNES_CGRAM_SIZE 0x202 /* 256 16-bit colours + 1 tacked on 16-bit colour for fixed colour */
+#define SNES_OAM_SIZE 0x440 /* 1088 bytes of Object Attribute Memory */
+#define FIXED_COLOUR 256 /* Position in cgram for fixed colour */
+
+
+/* Definitions for PPU Memory-Mapped registers */
+#define INIDISP 0x2100
+#define OBSEL 0x2101
+#define OAMADDL 0x2102
+#define OAMADDH 0x2103
+#define OAMDATA 0x2104
+#define BGMODE 0x2105 /* abcdefff = abcd: bg4-1 tile size | e: BG3 high priority | f: mode */
+#define MOSAIC 0x2106 /* xxxxabcd = x: pixel size | abcd: affects bg 1-4 */
+#define BG1SC 0x2107
+#define BG2SC 0x2108
+#define BG3SC 0x2109
+#define BG4SC 0x210A
+#define BG12NBA 0x210B
+#define BG34NBA 0x210C
+#define BG1HOFS 0x210D
+#define BG1VOFS 0x210E
+#define BG2HOFS 0x210F
+#define BG2VOFS 0x2110
+#define BG3HOFS 0x2111
+#define BG3VOFS 0x2112
+#define BG4HOFS 0x2113
+#define BG4VOFS 0x2114
+#define VMAIN 0x2115 /* i---ffrr = i: Increment timing | f: Full graphic | r: increment rate */
+#define VMADDL 0x2116 /* aaaaaaaa = a: LSB of vram address */
+#define VMADDH 0x2117 /* aaaaaaaa = a: MSB of vram address */
+#define VMDATAL 0x2118 /* dddddddd = d: data to be written */
+#define VMDATAH 0x2119 /* dddddddd = d: data to be written */
+#define M7SEL 0x211A /* ab----yx = a: screen over | y: vertical flip | x: horizontal flip */
+#define M7A 0x211B /* aaaaaaaa = a: COSINE rotate angle / X expansion */
+#define M7B 0x211C /* aaaaaaaa = a: SINE rotate angle / X expansion */
+#define M7C 0x211D /* aaaaaaaa = a: SINE rotate angle / Y expansion */
+#define M7D 0x211E /* aaaaaaaa = a: COSINE rotate angle / Y expansion */
+#define M7X 0x211F
+#define M7Y 0x2120
+#define CGADD 0x2121
+#define CGDATA 0x2122
+#define W12SEL 0x2123
+#define W34SEL 0x2124
+#define WOBJSEL 0x2125
+#define WH0 0x2126 /* pppppppp = p: Left position of window 1 */
+#define WH1 0x2127 /* pppppppp = p: Right position of window 1 */
+#define WH2 0x2128 /* pppppppp = p: Left position of window 2 */
+#define WH3 0x2129 /* pppppppp = p: Right position of window 2 */
+#define WBGLOG 0x212A /* aabbccdd = a: BG4 params | b: BG3 params | c: BG2 params | d: BG1 params */
+#define WOBJLOG 0x212B /* ----ccoo = c: Colour window params | o: Object window params */
+#define TM 0x212C
+#define TS 0x212D
+#define TMW 0x212E
+#define TSW 0x212F
+#define CGWSEL 0x2130
+#define CGADSUB 0x2131
+#define COLDATA 0x2132
+#define SETINI 0x2133
+#define MPYL 0x2134
+#define MPYM 0x2135
+#define MPYH 0x2136
+#define SLHV 0x2137
+#define ROAMDATA 0x2138
+#define RVMDATAL 0x2139
+#define RVMDATAH 0x213A
+#define RCGDATA 0x213B
+#define OPHCT 0x213C
+#define OPVCT 0x213D
+#define STAT77 0x213E
+#define STAT78 0x213F
+
+
#if SNES_LAYER_DEBUG
/* red green blue purple yellow cyan grey white */
static const UINT16 dbg_mode_colours[8] = { 0x1f, 0x3e0, 0x7c00, 0x7c1f, 0x3ff, 0x7fe0, 0x4210, 0x7fff };
@@ -109,13 +182,207 @@ enum
#define PPU_REG(a) m_regs[a - 0x2100]
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type SNES_PPU = &device_creator<snes_ppu_device>;
+
+
+//**************************************************************************
+// live device
+//**************************************************************************
+
+//-------------------------------------------------
+// snes_ppu_device - constructor
+//-------------------------------------------------
+
+snes_ppu_device::snes_ppu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SNES_PPU, "SNES PPU", tag, owner, clock, "snes_ppu", __FILE__),
+ device_video_interface(mconfig, *this),
+ m_openbus_cb(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void snes_ppu_device::device_start()
+{
+ m_openbus_cb.resolve_safe(0);
+
+#if SNES_LAYER_DEBUG
+ memset(&m_debug_options, 0, sizeof(m_debug_options));
+#endif
+
+ m_vram = auto_alloc_array(machine(), UINT8, SNES_VRAM_SIZE);
+ m_cgram = auto_alloc_array(machine(), UINT16, SNES_CGRAM_SIZE/2);
+ m_oam_ram = auto_alloc_array(machine(), UINT16, SNES_OAM_SIZE/2);
+
+ /* Inititialize registers/variables */
+ m_update_windows = 1;
+ m_beam.latch_vert = 0;
+ m_beam.latch_horz = 0;
+ m_beam.current_vert = 0;
+ m_beam.current_horz = 0;
+ m_beam.last_visible_line = 225; /* TODO: PAL setting */
+ m_mode = 0;
+ m_ppu1_version = 1; // 5C77 chip version number, read by STAT77, only '1' is known
+ m_ppu2_version = 3; // 5C78 chip version number, read by STAT78, only '2' & '3' encountered so far.
+
+ m_cgram_address = 0;
+ m_read_ophct = 0;
+ m_read_opvct = 0;
+
+ PPU_REG(VMAIN) = 0x80;
+ // what about other regs?
+
+ /* Inititialize mosaic table */
+ for (int j = 0; j < 16; j++)
+ {
+ for (int i = 0; i < 4096; i++)
+ m_mosaic_table[j][i] = (i / (j + 1)) * (j + 1);
+ }
+
+ /* Init VRAM */
+ memset(m_vram, 0, SNES_VRAM_SIZE);
+
+ /* Init Palette RAM */
+ memset((UINT8 *)m_cgram, 0, SNES_CGRAM_SIZE);
+
+ /* Init oam RAM */
+ memset((UINT8 *)m_oam_ram, 0xff, SNES_OAM_SIZE);
+
+ for (int i = 0; i < 2; i++)
+ {
+ save_item(NAME(m_scanlines[i].enable), i);
+ save_item(NAME(m_scanlines[i].clip), i);
+ save_item(NAME(m_scanlines[i].buffer), i);
+ save_item(NAME(m_scanlines[i].priority), i);
+ save_item(NAME(m_scanlines[i].layer), i);
+ save_item(NAME(m_scanlines[i].blend_exception), i);
+ }
+
+ for (int i = 0; i < 6; i++)
+ {
+ save_item(NAME(m_layer[i].window1_enabled), i);
+ save_item(NAME(m_layer[i].window1_invert), i);
+ save_item(NAME(m_layer[i].window2_enabled), i);
+ save_item(NAME(m_layer[i].window2_invert), i);
+ save_item(NAME(m_layer[i].wlog_mask), i);
+ save_item(NAME(m_layer[i].color_math), i);
+ save_item(NAME(m_layer[i].charmap), i);
+ save_item(NAME(m_layer[i].tilemap), i);
+ save_item(NAME(m_layer[i].tilemap_size), i);
+ save_item(NAME(m_layer[i].tile_size), i);
+ save_item(NAME(m_layer[i].mosaic_enabled), i);
+ save_item(NAME(m_layer[i].main_window_enabled), i);
+ save_item(NAME(m_layer[i].sub_window_enabled), i);
+ save_item(NAME(m_layer[i].main_bg_enabled), i);
+ save_item(NAME(m_layer[i].sub_bg_enabled), i);
+ save_item(NAME(m_layer[i].hoffs), i);
+ save_item(NAME(m_layer[i].voffs), i);
+
+ save_item(NAME(m_clipmasks[i]), i);
+ }
+
+ save_item(NAME(m_oam.address_low));
+ save_item(NAME(m_oam.address_high));
+ save_item(NAME(m_oam.saved_address_low));
+ save_item(NAME(m_oam.saved_address_high));
+ save_item(NAME(m_oam.address));
+ save_item(NAME(m_oam.priority_rotation));
+ save_item(NAME(m_oam.next_charmap));
+ save_item(NAME(m_oam.next_size));
+ save_item(NAME(m_oam.size));
+ save_item(NAME(m_oam.next_name_select));
+ save_item(NAME(m_oam.name_select));
+ save_item(NAME(m_oam.first_sprite));
+ save_item(NAME(m_oam.flip));
+ save_item(NAME(m_oam.write_latch));
+
+ save_item(NAME(m_beam.latch_horz));
+ save_item(NAME(m_beam.latch_vert));
+ save_item(NAME(m_beam.current_horz));
+ save_item(NAME(m_beam.current_vert));
+ save_item(NAME(m_beam.last_visible_line));
+ save_item(NAME(m_beam.interlace_count));
+
+ save_item(NAME(m_mode7.repeat));
+ save_item(NAME(m_mode7.hflip));
+ save_item(NAME(m_mode7.vflip));
+ save_item(NAME(m_mode7.matrix_a));
+ save_item(NAME(m_mode7.matrix_b));
+ save_item(NAME(m_mode7.matrix_c));
+ save_item(NAME(m_mode7.matrix_d));
+ save_item(NAME(m_mode7.origin_x));
+ save_item(NAME(m_mode7.origin_y));
+ save_item(NAME(m_mode7.hor_offset));
+ save_item(NAME(m_mode7.ver_offset));
+ save_item(NAME(m_mode7.extbg));
+
+ save_item(NAME(m_mosaic_size));
+ save_item(NAME(m_clip_to_black));
+ save_item(NAME(m_prevent_color_math));
+ save_item(NAME(m_sub_add_mode));
+ save_item(NAME(m_bg3_priority_bit));
+ save_item(NAME(m_direct_color));
+ save_item(NAME(m_ppu_last_scroll));
+ save_item(NAME(m_mode7_last_scroll));
+
+ save_item(NAME(m_ppu1_open_bus));
+ save_item(NAME(m_ppu2_open_bus));
+ save_item(NAME(m_ppu1_version));
+ save_item(NAME(m_ppu2_version));
+ save_item(NAME(m_window1_left));
+ save_item(NAME(m_window1_right));
+ save_item(NAME(m_window2_left));
+ save_item(NAME(m_window2_right));
+
+ save_item(NAME(m_update_windows));
+ save_item(NAME(m_update_offsets));
+ save_item(NAME(m_update_oam_list));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_interlace));
+ save_item(NAME(m_obj_interlace));
+ save_item(NAME(m_screen_brightness));
+ save_item(NAME(m_screen_disabled));
+ save_item(NAME(m_pseudo_hires));
+ save_item(NAME(m_color_modes));
+ save_item(NAME(m_stat77));
+ save_item(NAME(m_stat78));
+
+ save_item(NAME(m_htmult));
+ save_item(NAME(m_cgram_address));
+ save_item(NAME(m_read_ophct));
+ save_item(NAME(m_read_opvct));
+ save_item(NAME(m_vram_fgr_high));
+ save_item(NAME(m_vram_fgr_increment));
+ save_item(NAME(m_vram_fgr_count));
+ save_item(NAME(m_vram_fgr_mask));
+ save_item(NAME(m_vram_fgr_shift));
+ save_item(NAME(m_vram_read_buffer));
+ save_item(NAME(m_vmadd));
+
+ save_item(NAME(m_regs));
+
+ save_pointer(NAME(m_vram), SNES_VRAM_SIZE);
+ save_pointer(NAME(m_cgram), SNES_CGRAM_SIZE/2);
+ save_pointer(NAME(m_oam_ram), SNES_OAM_SIZE/2);
+}
+
+
+
/*****************************************
* get_bgcolor()
*
* Get the proper color (direct or from cgram)
*****************************************/
-inline UINT16 snes_ppu_class::get_bgcolor( UINT8 direct_colors, UINT16 palette, UINT8 color )
+inline UINT16 snes_ppu_device::get_bgcolor( UINT8 direct_colors, UINT16 palette, UINT8 color )
{
UINT16 c = 0;
@@ -139,7 +406,7 @@ inline UINT16 snes_ppu_class::get_bgcolor( UINT8 direct_colors, UINT16 palette,
* proper scanline
*****************************************/
-inline void snes_ppu_class::set_scanline_pixel( int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend )
+inline void snes_ppu_device::set_scanline_pixel( int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend )
{
m_scanlines[screen].buffer[x] = color;
m_scanlines[screen].priority[x] = priority;
@@ -170,7 +437,7 @@ inline void snes_ppu_class::set_scanline_pixel( int screen, INT16 x, UINT16 colo
* or lores)
*****************************************/
-inline void snes_ppu_class::draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority )
+inline void snes_ppu_device::draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority )
{
int screen;
UINT16 c;
@@ -204,7 +471,7 @@ inline void snes_ppu_class::draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colo
}
}
-inline void snes_ppu_class::draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority )
+inline void snes_ppu_device::draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority )
{
int screen;
UINT16 c;
@@ -239,7 +506,7 @@ inline void snes_ppu_class::draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colo
}
}
-inline void snes_ppu_class::draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority )
+inline void snes_ppu_device::draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority )
{
int screen;
int blend;
@@ -282,7 +549,7 @@ inline void snes_ppu_class::draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UI
* (depending on layer and resolution)
*****************************************/
-inline void snes_ppu_class::draw_tile( UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires )
+inline void snes_ppu_device::draw_tile( UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires )
{
UINT8 plane[8];
INT16 ii, jj;
@@ -365,7 +632,7 @@ inline void snes_ppu_class::draw_tile( UINT8 planes, UINT8 layer, UINT32 tileadd
* Find the address in VRAM of the tile (x,y)
*********************************************/
-inline UINT32 snes_ppu_class::get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y )
+inline UINT32 snes_ppu_device::get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y )
{
UINT32 res = base;
x >>= (3 + tile_size);
@@ -388,7 +655,7 @@ inline UINT32 snes_ppu_class::get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT3
* Update an entire line of tiles.
*********************************************/
-inline void snes_ppu_class::update_line( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors )
+inline void snes_ppu_device::update_line( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors )
{
UINT32 tmap, tile, xoff, yoff, charaddr, addr;
UINT16 ii = 0, vflip, hflip, pal, pal_direct, tilemap;
@@ -573,7 +840,7 @@ inline void snes_ppu_class::update_line( UINT16 curline, UINT8 layer, UINT8 prio
#define MODE7_CLIP(x) (((x) & 0x2000) ? ((x) | ~0x03ff) : ((x) & 0x03ff))
-void snes_ppu_class::update_line_mode7( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a )
+void snes_ppu_device::update_line_mode7( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a )
{
UINT32 tiled;
INT16 ma, mb, mc, md;
@@ -779,7 +1046,7 @@ void snes_ppu_class::update_line_mode7( UINT16 curline, UINT8 layer, UINT8 prior
* Update sprite settings for next line.
*********************************************/
-void snes_ppu_class::update_obsel( void )
+void snes_ppu_device::update_obsel( void )
{
m_layer[SNES_OAM].charmap = m_oam.next_charmap;
m_oam.name_select = m_oam.next_name_select;
@@ -797,7 +1064,7 @@ void snes_ppu_class::update_obsel( void )
* Build a list of the available obj in OAM ram.
*********************************************/
-void snes_ppu_class::oam_list_build( void )
+void snes_ppu_device::oam_list_build( void )
{
UINT8 *oamram = (UINT8 *)m_oam_ram;
INT16 oam = 0x1ff;
@@ -884,7 +1151,7 @@ void snes_ppu_class::oam_list_build( void )
* scanline
*********************************************/
-int snes_ppu_class::is_sprite_on_scanline( UINT16 curline, UINT8 sprite )
+int snes_ppu_device::is_sprite_on_scanline( UINT16 curline, UINT8 sprite )
{
//if sprite is entirely offscreen and doesn't wrap around to the left side of the screen,
//then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen.
@@ -909,7 +1176,7 @@ int snes_ppu_class::is_sprite_on_scanline( UINT16 curline, UINT8 sprite )
* scanline.
*********************************************/
-void snes_ppu_class::update_objects_rto( UINT16 curline )
+void snes_ppu_device::update_objects_rto( UINT16 curline )
{
int ii, jj, active_sprite;
UINT8 range_over, time_over;
@@ -1023,7 +1290,7 @@ void snes_ppu_class::update_objects_rto( UINT16 curline )
* Update an entire line of sprites.
*********************************************/
-void snes_ppu_class::update_objects( UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3 )
+void snes_ppu_device::update_objects( UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3 )
{
UINT8 pri, priority[4];
UINT32 charaddr;
@@ -1084,7 +1351,7 @@ void snes_ppu_class::update_objects( UINT8 priority_oam0, UINT8 priority_oam1, U
* Update Mode X line.
*********************************************/
-void snes_ppu_class::update_mode_0( UINT16 curline )
+void snes_ppu_device::update_mode_0( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[0])
@@ -1098,7 +1365,7 @@ void snes_ppu_class::update_mode_0( UINT16 curline )
update_line(curline, SNES_BG4, 1, 4, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0);
}
-void snes_ppu_class::update_mode_1( UINT16 curline )
+void snes_ppu_device::update_mode_1( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[1])
@@ -1121,7 +1388,7 @@ void snes_ppu_class::update_mode_1( UINT16 curline )
}
}
-void snes_ppu_class::update_mode_2( UINT16 curline )
+void snes_ppu_device::update_mode_2( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[2])
@@ -1133,7 +1400,7 @@ void snes_ppu_class::update_mode_2( UINT16 curline )
update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_MODE2, 0);
}
-void snes_ppu_class::update_mode_3( UINT16 curline )
+void snes_ppu_device::update_mode_3( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[3])
@@ -1145,7 +1412,7 @@ void snes_ppu_class::update_mode_3( UINT16 curline )
update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0);
}
-void snes_ppu_class::update_mode_4( UINT16 curline )
+void snes_ppu_device::update_mode_4( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[4])
@@ -1157,7 +1424,7 @@ void snes_ppu_class::update_mode_4( UINT16 curline )
update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_MODE4, 0);
}
-void snes_ppu_class::update_mode_5( UINT16 curline )
+void snes_ppu_device::update_mode_5( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[5])
@@ -1169,7 +1436,7 @@ void snes_ppu_class::update_mode_5( UINT16 curline )
update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 1, SNES_OPT_NONE, 0);
}
-void snes_ppu_class::update_mode_6( UINT16 curline )
+void snes_ppu_device::update_mode_6( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[6])
@@ -1180,7 +1447,7 @@ void snes_ppu_class::update_mode_6( UINT16 curline )
update_line(curline, SNES_BG1, 2, 5, SNES_COLOR_DEPTH_4BPP, 1, SNES_OPT_MODE6, 0);
}
-void snes_ppu_class::update_mode_7( UINT16 curline )
+void snes_ppu_device::update_mode_7( UINT16 curline )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.mode_disabled[7])
@@ -1206,7 +1473,7 @@ void snes_ppu_class::update_mode_7( UINT16 curline )
* Draw the whole screen (Mode 0 -> 7).
*********************************************/
-void snes_ppu_class::draw_screens( UINT16 curline )
+void snes_ppu_device::draw_screens( UINT16 curline )
{
switch (m_mode)
{
@@ -1234,7 +1501,7 @@ void snes_ppu_class::draw_screens( UINT16 curline )
* XNOR: ###...##...### ...###..###...
*********************************************/
-void snes_ppu_class::update_windowmasks( void )
+void snes_ppu_device::update_windowmasks( void )
{
UINT16 ii, jj;
INT8 w1, w2;
@@ -1308,7 +1575,7 @@ void snes_ppu_class::update_windowmasks( void )
* possibly be handy for some minor optimization
*********************************************/
-void snes_ppu_class::update_offsets( void )
+void snes_ppu_device::update_offsets( void )
{
int ii;
for (ii = 0; ii < 4; ii++)
@@ -1325,7 +1592,7 @@ void snes_ppu_class::update_offsets( void )
* color math.
*****************************************/
-inline void snes_ppu_class::draw_blend( UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens )
+inline void snes_ppu_device::draw_blend( UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens )
{
#if SNES_LAYER_DEBUG
if (m_debug_options.colormath_disabled)
@@ -1453,7 +1720,7 @@ inline void snes_ppu_class::draw_blend( UINT16 offset, UINT16 *colour, UINT8 pre
* the optimized averaging algorithm.
*********************************************/
-void snes_ppu_class::refresh_scanline( running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline )
+void snes_ppu_device::refresh_scanline( running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline )
{
UINT16 ii;
int x;
@@ -1612,172 +1879,6 @@ void snes_ppu_class::refresh_scanline( running_machine &machine, bitmap_rgb32 &b
g_profiler.stop();
}
-void snes_ppu_class::ppu_start(screen_device &screen,snes_state *state)
-{
- m_screen = &screen;
- running_machine &machine = screen.machine();
- m_state = state;
-#if SNES_LAYER_DEBUG
- memset(&m_debug_options, 0, sizeof(m_debug_options));
-#endif
-
- m_vram = auto_alloc_array(machine, UINT8, SNES_VRAM_SIZE);
- m_cgram = auto_alloc_array(machine, UINT16, SNES_CGRAM_SIZE/2);
- m_oam_ram = auto_alloc_array(machine, UINT16, SNES_OAM_SIZE/2);
-
- /* Inititialize registers/variables */
- m_update_windows = 1;
- m_beam.latch_vert = 0;
- m_beam.latch_horz = 0;
- m_beam.current_vert = 0;
- m_beam.current_horz = 0;
- m_beam.last_visible_line = 225; /* TODO: PAL setting */
- m_mode = 0;
- m_ppu1_version = 1; // 5C77 chip version number, read by STAT77, only '1' is known
- m_ppu2_version = 3; // 5C78 chip version number, read by STAT78, only '2' & '3' encountered so far.
-
- m_cgram_address = 0;
- m_read_ophct = 0;
- m_read_opvct = 0;
-
- PPU_REG(VMAIN) = 0x80;
- // what about other regs?
-
- /* Inititialize mosaic table */
- for (int j = 0; j < 16; j++)
- {
- for (int i = 0; i < 4096; i++)
- m_mosaic_table[j][i] = (i / (j + 1)) * (j + 1);
- }
-
- /* Init VRAM */
- memset(m_vram, 0, SNES_VRAM_SIZE);
-
- /* Init Palette RAM */
- memset((UINT8 *)m_cgram, 0, SNES_CGRAM_SIZE);
-
- /* Init oam RAM */
- memset((UINT8 *)m_oam_ram, 0xff, SNES_OAM_SIZE);
-
-
- for (int i = 0; i < 2; i++)
- {
- state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].enable);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].clip);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].buffer);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].priority);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].layer);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].blend_exception);
- }
-
- for (int i = 0; i < 6; i++)
- {
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window1_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window1_invert);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window2_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window2_invert);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].wlog_mask);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].color_math);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].charmap);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tilemap);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tilemap_size);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tile_size);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].mosaic_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].main_window_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].sub_window_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].main_bg_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].sub_bg_enabled);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].hoffs);
- state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].voffs);
-
- state_save_register_item_array(machine, "snes_ppu", NULL, i, m_clipmasks[i]);
- }
-
- machine.save().save_item(NAME(m_oam.address_low));
- machine.save().save_item(NAME(m_oam.address_high));
- machine.save().save_item(NAME(m_oam.saved_address_low));
- machine.save().save_item(NAME(m_oam.saved_address_high));
- machine.save().save_item(NAME(m_oam.address));
- machine.save().save_item(NAME(m_oam.priority_rotation));
- machine.save().save_item(NAME(m_oam.next_charmap));
- machine.save().save_item(NAME(m_oam.next_size));
- machine.save().save_item(NAME(m_oam.size));
- machine.save().save_item(NAME(m_oam.next_name_select));
- machine.save().save_item(NAME(m_oam.name_select));
- machine.save().save_item(NAME(m_oam.first_sprite));
- machine.save().save_item(NAME(m_oam.flip));
- machine.save().save_item(NAME(m_oam.write_latch));
-
- machine.save().save_item(NAME(m_beam.latch_horz));
- machine.save().save_item(NAME(m_beam.latch_vert));
- machine.save().save_item(NAME(m_beam.current_horz));
- machine.save().save_item(NAME(m_beam.current_vert));
- machine.save().save_item(NAME(m_beam.last_visible_line));
- machine.save().save_item(NAME(m_beam.interlace_count));
-
- machine.save().save_item(NAME(m_mode7.repeat));
- machine.save().save_item(NAME(m_mode7.hflip));
- machine.save().save_item(NAME(m_mode7.vflip));
- machine.save().save_item(NAME(m_mode7.matrix_a));
- machine.save().save_item(NAME(m_mode7.matrix_b));
- machine.save().save_item(NAME(m_mode7.matrix_c));
- machine.save().save_item(NAME(m_mode7.matrix_d));
- machine.save().save_item(NAME(m_mode7.origin_x));
- machine.save().save_item(NAME(m_mode7.origin_y));
- machine.save().save_item(NAME(m_mode7.hor_offset));
- machine.save().save_item(NAME(m_mode7.ver_offset));
- machine.save().save_item(NAME(m_mode7.extbg));
-
- machine.save().save_item(NAME(m_mosaic_size));
- machine.save().save_item(NAME(m_clip_to_black));
- machine.save().save_item(NAME(m_prevent_color_math));
- machine.save().save_item(NAME(m_sub_add_mode));
- machine.save().save_item(NAME(m_bg3_priority_bit));
- machine.save().save_item(NAME(m_direct_color));
- machine.save().save_item(NAME(m_ppu_last_scroll));
- machine.save().save_item(NAME(m_mode7_last_scroll));
-
- machine.save().save_item(NAME(m_ppu1_open_bus));
- machine.save().save_item(NAME(m_ppu2_open_bus));
- machine.save().save_item(NAME(m_ppu1_version));
- machine.save().save_item(NAME(m_ppu2_version));
- machine.save().save_item(NAME(m_window1_left));
- machine.save().save_item(NAME(m_window1_right));
- machine.save().save_item(NAME(m_window2_left));
- machine.save().save_item(NAME(m_window2_right));
-
- machine.save().save_item(NAME(m_update_windows));
- machine.save().save_item(NAME(m_update_offsets));
- machine.save().save_item(NAME(m_update_oam_list));
- machine.save().save_item(NAME(m_mode));
- machine.save().save_item(NAME(m_interlace));
- machine.save().save_item(NAME(m_obj_interlace));
- machine.save().save_item(NAME(m_screen_brightness));
- machine.save().save_item(NAME(m_screen_disabled));
- machine.save().save_item(NAME(m_pseudo_hires));
- machine.save().save_item(NAME(m_color_modes));
- machine.save().save_item(NAME(m_stat77));
- machine.save().save_item(NAME(m_stat78));
-
- machine.save().save_item(NAME(m_htmult));
- machine.save().save_item(NAME(m_cgram_address));
- machine.save().save_item(NAME(m_read_ophct));
- machine.save().save_item(NAME(m_read_opvct));
- machine.save().save_item(NAME(m_vram_fgr_high));
- machine.save().save_item(NAME(m_vram_fgr_increment));
- machine.save().save_item(NAME(m_vram_fgr_count));
- machine.save().save_item(NAME(m_vram_fgr_mask));
- machine.save().save_item(NAME(m_vram_fgr_shift));
- machine.save().save_item(NAME(m_vram_read_buffer));
- machine.save().save_item(NAME(m_vmadd));
-
- machine.save().save_item(NAME(m_regs));
-
- machine.save().save_pointer(NAME(m_vram), SNES_VRAM_SIZE);
- machine.save().save_pointer(NAME(m_cgram), SNES_CGRAM_SIZE/2);
- machine.save().save_pointer(NAME(m_oam_ram), SNES_OAM_SIZE/2);
-}
-
/* CPU <-> PPU comms */
@@ -1787,7 +1888,7 @@ static const UINT16 vram_fgr_inccnts[4] = { 0, 32, 64, 128 };
static const UINT16 vram_fgr_shiftab[4] = { 0, 5, 6, 7 };
// utility function - latches the H/V counters. Used by IRQ, writes to WRIO, etc.
-void snes_ppu_class::latch_counters( running_machine &machine )
+void snes_ppu_device::latch_counters( running_machine &machine )
{
m_beam.current_horz = machine.first_screen()->hpos() / m_htmult;
m_beam.latch_vert = machine.first_screen()->vpos();
@@ -1798,7 +1899,7 @@ void snes_ppu_class::latch_counters( running_machine &machine )
// printf("latched @ H %d V %d\n", m_beam.latch_horz, m_beam.latch_vert);
}
-void snes_ppu_class::dynamic_res_change( running_machine &machine )
+void snes_ppu_device::dynamic_res_change( running_machine &machine )
{
rectangle visarea = machine.first_screen()->visible_area();
attoseconds_t refresh;
@@ -1842,7 +1943,7 @@ void snes_ppu_class::dynamic_res_change( running_machine &machine )
when interlace is active.
*************************************************/
-inline UINT32 snes_ppu_class::get_vram_address( running_machine &machine )
+inline UINT32 snes_ppu_device::get_vram_address( running_machine &machine )
{
UINT32 addr = m_vmadd;
@@ -1856,7 +1957,7 @@ inline UINT32 snes_ppu_class::get_vram_address( running_machine &machine )
return addr << 1;
}
-READ8_MEMBER( snes_ppu_class::vram_read )
+READ8_MEMBER( snes_ppu_device::vram_read )
{
UINT8 res = 0;
offset &= 0xffff; // only 64KB are present on SNES
@@ -1892,7 +1993,7 @@ READ8_MEMBER( snes_ppu_class::vram_read )
return res;
}
-WRITE8_MEMBER( snes_ppu_class::vram_write )
+WRITE8_MEMBER( snes_ppu_device::vram_write )
{
offset &= 0xffff; // only 64KB are present on SNES, Robocop 3 relies on this
@@ -1907,7 +2008,7 @@ WRITE8_MEMBER( snes_ppu_class::vram_write )
if (h <= 4)
m_vram[offset] = data;
else if (h == 6)
- m_vram[offset] = m_state->snes_open_bus_r(space, 0);
+ m_vram[offset] = m_openbus_cb(space, 0);
else
{
//printf("%d %d VRAM write, CHECK!\n",h,v);
@@ -1957,7 +2058,7 @@ WRITE8_MEMBER( snes_ppu_class::vram_write )
to choose the high/low byte of the snes_oam word.
*************************************************/
-READ8_MEMBER( snes_ppu_class::oam_read )
+READ8_MEMBER( snes_ppu_device::oam_read )
{
offset &= 0x1ff;
@@ -1975,7 +2076,7 @@ READ8_MEMBER( snes_ppu_class::oam_read )
return (m_oam_ram[offset] >> (PPU_REG(OAMDATA) << 3)) & 0xff;
}
-WRITE8_MEMBER( snes_ppu_class::oam_write )
+WRITE8_MEMBER( snes_ppu_device::oam_write )
{
offset &= 0x1ff;
@@ -2017,7 +2118,7 @@ WRITE8_MEMBER( snes_ppu_class::oam_write )
solution adopted by BSNES without enabling it.
*************************************************/
-READ8_MEMBER( snes_ppu_class::cgram_read )
+READ8_MEMBER( snes_ppu_device::cgram_read )
{
UINT8 res = 0;
offset &= 0x1ff;
@@ -2043,7 +2144,7 @@ READ8_MEMBER( snes_ppu_class::cgram_read )
return res;
}
-WRITE8_MEMBER( snes_ppu_class::cgram_write )
+WRITE8_MEMBER( snes_ppu_device::cgram_write )
{
offset &= 0x1ff;
@@ -2069,7 +2170,7 @@ WRITE8_MEMBER( snes_ppu_class::cgram_write )
((UINT8 *)m_cgram)[offset] = data;
}
-UINT8 snes_ppu_class::read(address_space &space, UINT32 offset, UINT8 wrio_bit7)
+UINT8 snes_ppu_device::read(address_space &space, UINT32 offset, UINT8 wrio_bit7)
{
UINT8 value;
@@ -2118,7 +2219,8 @@ UINT8 snes_ppu_class::read(address_space &space, UINT32 offset, UINT8 wrio_bit7)
}
case SLHV: /* Software latch for H/V counter */
latch_counters(space.machine());
- return m_state->snes_open_bus_r(space, 0); /* Return value is meaningless */
+ return m_openbus_cb(space, 0); /* Return value is meaningless */
+
case ROAMDATA: /* Read data from OAM (DR) */
m_ppu1_open_bus = oam_read(space, m_oam.address);
PPU_REG(OAMDATA) = (PPU_REG(OAMDATA) + 1) % 2;
@@ -2213,11 +2315,11 @@ UINT8 snes_ppu_class::read(address_space &space, UINT32 offset, UINT8 wrio_bit7)
}
/* note: remaining registers (Namely TM in Super Kick Boxing) returns MDR open bus, not PPU Open Bus! */
- return m_state->snes_open_bus_r(space, 0);
+ return m_openbus_cb(space, 0);
}
-void snes_ppu_class::write(address_space &space, UINT32 offset, UINT8 data)
+void snes_ppu_device::write(address_space &space, UINT32 offset, UINT8 data)
{
switch (offset)
{
@@ -2635,7 +2737,7 @@ void snes_ppu_class::write(address_space &space, UINT32 offset, UINT8 data)
popmessage MSG2; \
}
-UINT8 snes_ppu_class::dbg_video( running_machine &machine, UINT16 curline )
+UINT8 snes_ppu_device::dbg_video( running_machine &machine, UINT16 curline )
{
int i;
UINT8 toggles = machine.root_device().ioport("DEBUG1")->read_safe(0);
diff --git a/src/emu/video/snes_ppu.h b/src/emu/video/snes_ppu.h
new file mode 100644
index 00000000000..b16e12a16d2
--- /dev/null
+++ b/src/emu/video/snes_ppu.h
@@ -0,0 +1,292 @@
+/***************************************************************************
+
+ SNES PPU
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __SNES_PPU_H__
+#define __SNES_PPU_H__
+
+
+#define MCLK_NTSC (21477272) /* verified */
+#define MCLK_PAL (21218370) /* verified */
+
+#define DOTCLK_NTSC (MCLK_NTSC/4)
+#define DOTCLK_PAL (MCLK_PAL/4)
+
+#define SNES_SCR_WIDTH 256 /* 32 characters 8 pixels wide */
+#define SNES_SCR_HEIGHT_NTSC 225 /* Can be 224 or 240 height */
+#define SNES_SCR_HEIGHT_PAL 240 /* ??? */
+#define SNES_VTOTAL_NTSC 262 /* Maximum number of lines for NTSC systems */
+#define SNES_VTOTAL_PAL 312 /* Maximum number of lines for PAL systems */
+#define SNES_HTOTAL 341 /* Maximum number pixels per line (incl. hblank) */
+
+#define SNES_NTSC 0x00
+#define SNES_PAL 0x10
+
+
+#define SNES_LAYER_DEBUG 0
+
+
+/* offset-per-tile modes */
+enum
+{
+ SNES_OPT_NONE = 0,
+ SNES_OPT_MODE2,
+ SNES_OPT_MODE4,
+ SNES_OPT_MODE6
+};
+
+/* layers */
+enum
+{
+ SNES_BG1 = 0,
+ SNES_BG2,
+ SNES_BG3,
+ SNES_BG4,
+ SNES_OAM,
+ SNES_COLOR
+};
+
+
+struct SNES_SCANLINE
+{
+ int enable, clip;
+
+ UINT16 buffer[SNES_SCR_WIDTH];
+ UINT8 priority[SNES_SCR_WIDTH];
+ UINT8 layer[SNES_SCR_WIDTH];
+ UINT8 blend_exception[SNES_SCR_WIDTH];
+};
+
+// ======================> snes_ppu_device
+
+class snes_ppu_device : public device_t,
+ public device_video_interface
+{
+public:
+ // construction/destruction
+ snes_ppu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ template<class _Object> static devcb2_base &static_set_open_bus_callback(device_t &device, _Object object) { return downcast<snes_ppu_device &>(device).m_openbus_cb.set_callback(object); }
+
+ UINT8 m_regs[0x40];
+
+ SNES_SCANLINE m_scanlines[2];
+
+ struct
+ {
+ /* clipmasks */
+ UINT8 window1_enabled, window1_invert;
+ UINT8 window2_enabled, window2_invert;
+ UINT8 wlog_mask;
+ /* color math enabled */
+ UINT8 color_math;
+
+ UINT8 charmap;
+ UINT8 tilemap;
+ UINT8 tilemap_size;
+
+ UINT8 tile_size;
+ UINT8 mosaic_enabled; // actually used only for layers 0->3!
+
+ UINT8 main_window_enabled;
+ UINT8 sub_window_enabled;
+ UINT8 main_bg_enabled;
+ UINT8 sub_bg_enabled;
+
+ UINT16 hoffs;
+ UINT16 voffs;
+ } m_layer[6]; // this is for the BG1 - BG2 - BG3 - BG4 - OBJ - color layers
+
+ struct
+ {
+ UINT8 address_low;
+ UINT8 address_high;
+ UINT8 saved_address_low;
+ UINT8 saved_address_high;
+ UINT16 address;
+ UINT16 priority_rotation;
+ UINT8 next_charmap;
+ UINT8 next_size;
+ UINT8 size;
+ UINT32 next_name_select;
+ UINT32 name_select;
+ UINT8 first_sprite;
+ UINT8 flip;
+ UINT16 write_latch;
+ } m_oam;
+
+ struct
+ {
+ UINT16 latch_horz;
+ UINT16 latch_vert;
+ UINT16 current_horz;
+ UINT16 current_vert;
+ UINT8 last_visible_line;
+ UINT8 interlace_count;
+ } m_beam;
+
+ struct
+ {
+ UINT8 repeat;
+ UINT8 hflip;
+ UINT8 vflip;
+ INT16 matrix_a;
+ INT16 matrix_b;
+ INT16 matrix_c;
+ INT16 matrix_d;
+ INT16 origin_x;
+ INT16 origin_y;
+ UINT16 hor_offset;
+ UINT16 ver_offset;
+ UINT8 extbg;
+ } m_mode7;
+
+ struct OAM
+ {
+ UINT16 tile;
+ INT16 x, y;
+ UINT8 size, vflip, hflip, priority_bits, pal;
+ int height, width;
+ };
+
+ struct OAM m_oam_spritelist[SNES_SCR_WIDTH / 2];
+
+ UINT8 m_oam_itemlist[32];
+
+ struct TILELIST {
+ INT16 x;
+ UINT16 priority, pal, tileaddr;
+ int hflip;
+ };
+
+ struct TILELIST m_oam_tilelist[34];
+
+#if SNES_LAYER_DEBUG
+ struct DEBUGOPTS
+ {
+ UINT8 bg_disabled[5];
+ UINT8 mode_disabled[8];
+ UINT8 draw_subscreen;
+ UINT8 windows_disabled;
+ UINT8 mosaic_disabled;
+ UINT8 colormath_disabled;
+ UINT8 sprite_reversed;
+ UINT8 select_pri[5];
+ };
+ struct DEBUGOPTS m_debug_options;
+#endif
+
+ UINT8 m_mosaic_size;
+ UINT8 m_clip_to_black;
+ UINT8 m_prevent_color_math;
+ UINT8 m_sub_add_mode;
+ UINT8 m_bg3_priority_bit;
+ UINT8 m_direct_color;
+ UINT8 m_ppu_last_scroll; /* as per Anomie's doc and Theme Park, all scroll regs shares (but mode 7 ones) the same
+ 'previous' scroll value */
+ UINT8 m_mode7_last_scroll; /* as per Anomie's doc mode 7 scroll regs use a different value, shared with mode 7 matrix! */
+
+ UINT8 m_ppu1_open_bus, m_ppu2_open_bus;
+ UINT8 m_ppu1_version, m_ppu2_version;
+ UINT8 m_window1_left, m_window1_right, m_window2_left, m_window2_right;
+
+ UINT16 m_mosaic_table[16][4096];
+ UINT8 m_clipmasks[6][SNES_SCR_WIDTH];
+ UINT8 m_update_windows;
+ UINT8 m_update_offsets;
+ UINT8 m_update_oam_list;
+ UINT8 m_mode;
+ UINT8 m_interlace; //doubles the visible resolution
+ UINT8 m_obj_interlace;
+ UINT8 m_screen_brightness;
+ UINT8 m_screen_disabled;
+ UINT8 m_pseudo_hires;
+ UINT8 m_color_modes;
+ UINT8 m_stat77;
+ UINT8 m_stat78;
+
+ UINT16 m_htmult; /* in 512 wide, we run HTOTAL double and halve it on latching */
+ UINT16 m_cgram_address; /* CGRAM address */
+ UINT8 m_read_ophct;
+ UINT8 m_read_opvct;
+ UINT16 m_vram_fgr_high;
+ UINT16 m_vram_fgr_increment;
+ UINT16 m_vram_fgr_count;
+ UINT16 m_vram_fgr_mask;
+ UINT16 m_vram_fgr_shift;
+ UINT16 m_vram_read_buffer;
+ UINT16 m_vmadd;
+
+ inline UINT16 get_bgcolor(UINT8 direct_colors, UINT16 palette, UINT8 color);
+ inline void set_scanline_pixel(int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend);
+ inline void draw_bgtile_lores(UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority);
+ inline void draw_bgtile_hires(UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority);
+ inline void draw_oamtile(INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority);
+ inline void draw_tile(UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires);
+ inline UINT32 get_tmap_addr(UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y);
+ inline void update_line(UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors);
+ void update_line_mode7(UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a);
+ void update_obsel(void);
+ void oam_list_build(void);
+ int is_sprite_on_scanline(UINT16 curline, UINT8 sprite);
+ void update_objects_rto(UINT16 curline);
+ void update_objects(UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3);
+ void update_mode_0(UINT16 curline);
+ void update_mode_1(UINT16 curline);
+ void update_mode_2(UINT16 curline);
+ void update_mode_3(UINT16 curline);
+ void update_mode_4(UINT16 curline);
+ void update_mode_5(UINT16 curline);
+ void update_mode_6(UINT16 curline);
+ void update_mode_7(UINT16 curline);
+ void draw_screens(UINT16 curline);
+ void update_windowmasks(void);
+ void update_offsets(void);
+ inline void draw_blend(UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens);
+ void refresh_scanline(running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline);
+
+ void latch_counters(running_machine &machine);
+ void dynamic_res_change(running_machine &machine);
+ inline UINT32 get_vram_address(running_machine &machine);
+ UINT8 dbg_video(running_machine &machine, UINT16 curline);
+
+ UINT8 read(address_space &space, UINT32 offset, UINT8 wrio_bit7);
+ void write(address_space &space, UINT32 offset, UINT8 data);
+
+ DECLARE_READ8_MEMBER( oam_read );
+ DECLARE_WRITE8_MEMBER( oam_write );
+ DECLARE_READ8_MEMBER( cgram_read );
+ DECLARE_WRITE8_MEMBER( cgram_write );
+ DECLARE_READ8_MEMBER( vram_read );
+ DECLARE_WRITE8_MEMBER( vram_write );
+ UINT16 *m_oam_ram; /* Object Attribute Memory */
+ UINT16 *m_cgram; /* Palette RAM */
+ UINT8 *m_vram; /* Video RAM (TODO: Should be 16-bit, but it's easier this way) */
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset() {};
+
+private:
+ devcb2_read16 m_openbus_cb;
+};
+
+
+// device type definition
+extern const device_type SNES_PPU;
+
+
+/***************************************************************************
+ INTERFACE CONFIGURATION MACROS
+ ***************************************************************************/
+
+#define MCFG_SNES_PPU_OPENBUS_CB(_read) \
+ devcb = &snes_ppu_device::static_set_open_bus_callback(*device, DEVCB2_##_read);
+
+#endif
diff --git a/src/emu/video/video.mak b/src/emu/video/video.mak
index 63403ed5289..5313c3a1f3b 100644
--- a/src/emu/video/video.mak
+++ b/src/emu/video/video.mak
@@ -447,6 +447,14 @@ endif
#-------------------------------------------------
#
+#@src/emu/video/snes_ppu.h,VIDEOS += SNES_PPU
+#-------------------------------------------------
+ifneq ($(filter SNES_PPU,$(VIDEOS)),)
+VIDEOOBJS+= $(VIDEOOBJ)/snes_ppu.o
+endif
+
+#-------------------------------------------------
+#
#@src/emu/video/stvvdp1.h,VIDEOS += STVVDP
#@src/emu/video/stvvdp2.h,VIDEOS += STVVDP
#-------------------------------------------------
diff --git a/src/mame/drivers/nss.c b/src/mame/drivers/nss.c
index 6cb63b3d935..3625b5b3c50 100644
--- a/src/mame/drivers/nss.c
+++ b/src/mame/drivers/nss.c
@@ -844,6 +844,10 @@ static MACHINE_CONFIG_START( nss, nss_state )
MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
+ MCFG_DEVICE_ADD("ppu", SNES_PPU, 0)
+ MCFG_SNES_PPU_OPENBUS_CB(READ8(snes_state, snes_open_bus_r))
+ MCFG_VIDEO_SET_SCREEN("screen")
+
// NSS
MCFG_SCREEN_ADD("osd", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
diff --git a/src/mame/drivers/sfcbox.c b/src/mame/drivers/sfcbox.c
index 0eb65859615..ce11e4e4519 100644
--- a/src/mame/drivers/sfcbox.c
+++ b/src/mame/drivers/sfcbox.c
@@ -116,13 +116,10 @@ How does the Super Famicom Box operates
***************************************************************************/
#include "emu.h"
-#include "cpu/spc700/spc700.h"
-#include "cpu/g65816/g65816.h"
#include "cpu/z180/z180.h"
#include "machine/s3520cf.h"
#include "video/mb90082.h"
#include "includes/snes.h"
-#include "audio/snes_snd.h"
#include "rendlay.h"
class sfcbox_state : public snes_state
@@ -477,6 +474,10 @@ static MACHINE_CONFIG_START( sfcbox, sfcbox_state )
MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
+ MCFG_DEVICE_ADD("ppu", SNES_PPU, 0)
+ MCFG_SNES_PPU_OPENBUS_CB(READ8(snes_state, snes_open_bus_r))
+ MCFG_VIDEO_SET_SCREEN("screen")
+
// SFCBOX
MCFG_SCREEN_ADD("osd", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
diff --git a/src/mame/drivers/snesb.c b/src/mame/drivers/snesb.c
index acd20e3071a..1f66015ea00 100644
--- a/src/mame/drivers/snesb.c
+++ b/src/mame/drivers/snesb.c
@@ -144,10 +144,7 @@ Iron PCB (same as Final Fight 2?)
#include "emu.h"
-#include "cpu/spc700/spc700.h"
-#include "cpu/g65816/g65816.h"
#include "includes/snes.h"
-#include "audio/snes_snd.h"
class snesb_state : public snes_state
@@ -634,6 +631,10 @@ static MACHINE_CONFIG_START( kinstb, snesb_state )
MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
+ MCFG_DEVICE_ADD("ppu", SNES_PPU, 0)
+ MCFG_SNES_PPU_OPENBUS_CB(READ8(snes_state, snes_open_bus_r))
+ MCFG_VIDEO_SET_SCREEN("screen")
+
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("spc700", SNES, 0)
diff --git a/src/mame/includes/snes.h b/src/mame/includes/snes.h
index 1e2371d3467..04f697e439d 100644
--- a/src/mame/includes/snes.h
+++ b/src/mame/includes/snes.h
@@ -3,8 +3,8 @@
#include "cpu/spc700/spc700.h"
#include "cpu/g65816/g65816.h"
-#include "cpu/upd7725/upd7725.h"
#include "audio/snes_snd.h"
+#include "video/snes_ppu.h"
/*
SNES timing theory:
@@ -19,31 +19,7 @@
This is because 2 dots are "long" dots that last 6 MC ticks, resulting in 1 extra dot per line.
*/
-#define MCLK_NTSC (21477272) /* verified */
-#define MCLK_PAL (21218370) /* verified */
-
-#define DOTCLK_NTSC (MCLK_NTSC/4)
-#define DOTCLK_PAL (MCLK_PAL/4)
-
-#define SNES_LAYER_DEBUG 0
-
-/* Debug definitions */
-#ifdef MAME_DEBUG
-/* #define SNES_DBG_GENERAL*/ /* Display general debug info */
-/* #define SNES_DBG_VIDEO */ /* Display video debug info */
-/* #define SNES_DBG_DMA*/ /* Display DMA debug info */
-/* #define SNES_DBG_HDMA*/ /* Display HDMA debug info */
-/* #define SNES_DBG_REG_R*/ /* Display register read info */
-/* #define SNES_DBG_REG_W*/ /* Display register write info */
-#endif /* MAME_DEBUG */
-
-/* Useful definitions */
-#define SNES_SCR_WIDTH 256 /* 32 characters 8 pixels wide */
-#define SNES_SCR_HEIGHT_NTSC 225 /* Can be 224 or 240 height */
-#define SNES_SCR_HEIGHT_PAL 240 /* ??? */
-#define SNES_VTOTAL_NTSC 262 /* Maximum number of lines for NTSC systems */
-#define SNES_VTOTAL_PAL 312 /* Maximum number of lines for PAL systems */
-#define SNES_HTOTAL 341 /* Maximum number pixels per line (incl. hblank) */
+// Useful definitions
#define SNES_DMA_BASE 0x4300 /* Base DMA register address */
#define SNES_MODE_20 0x01 /* Lo-ROM cart */
#define SNES_MODE_21 0x02 /* Hi-ROM cart */
@@ -53,87 +29,28 @@
#define SNES_MODE_BSLO 0x20
#define SNES_MODE_BSHI 0x40
#define SNES_MODE_ST 0x80
-#define SNES_NTSC 0x00
-#define SNES_PAL 0x10
-#define SNES_VRAM_SIZE 0x20000 /* 128kb of video ram */
-#define SNES_CGRAM_SIZE 0x202 /* 256 16-bit colours + 1 tacked on 16-bit colour for fixed colour */
-#define SNES_OAM_SIZE 0x440 /* 1088 bytes of Object Attribute Memory */
#define SNES_EXROM_START 0x1000000
-#define FIXED_COLOUR 256 /* Position in cgram for fixed colour */
-/* Definitions for PPU Memory-Mapped registers */
+
+// some PPU registers we still use in machine/snes.c
#define INIDISP 0x2100
-#define OBSEL 0x2101
#define OAMADDL 0x2102
#define OAMADDH 0x2103
-#define OAMDATA 0x2104
-#define BGMODE 0x2105 /* abcdefff = abcd: bg4-1 tile size | e: BG3 high priority | f: mode */
-#define MOSAIC 0x2106 /* xxxxabcd = x: pixel size | abcd: affects bg 1-4 */
-#define BG1SC 0x2107
-#define BG2SC 0x2108
-#define BG3SC 0x2109
-#define BG4SC 0x210A
-#define BG12NBA 0x210B
-#define BG34NBA 0x210C
-#define BG1HOFS 0x210D
-#define BG1VOFS 0x210E
-#define BG2HOFS 0x210F
-#define BG2VOFS 0x2110
-#define BG3HOFS 0x2111
-#define BG3VOFS 0x2112
-#define BG4HOFS 0x2113
-#define BG4VOFS 0x2114
-#define VMAIN 0x2115 /* i---ffrr = i: Increment timing | f: Full graphic | r: increment rate */
-#define VMADDL 0x2116 /* aaaaaaaa = a: LSB of vram address */
-#define VMADDH 0x2117 /* aaaaaaaa = a: MSB of vram address */
-#define VMDATAL 0x2118 /* dddddddd = d: data to be written */
-#define VMDATAH 0x2119 /* dddddddd = d: data to be written */
-#define M7SEL 0x211A /* ab----yx = a: screen over | y: vertical flip | x: horizontal flip */
-#define M7A 0x211B /* aaaaaaaa = a: COSINE rotate angle / X expansion */
-#define M7B 0x211C /* aaaaaaaa = a: SINE rotate angle / X expansion */
-#define M7C 0x211D /* aaaaaaaa = a: SINE rotate angle / Y expansion */
-#define M7D 0x211E /* aaaaaaaa = a: COSINE rotate angle / Y expansion */
-#define M7X 0x211F
-#define M7Y 0x2120
-#define CGADD 0x2121
-#define CGDATA 0x2122
-#define W12SEL 0x2123
-#define W34SEL 0x2124
-#define WOBJSEL 0x2125
-#define WH0 0x2126 /* pppppppp = p: Left position of window 1 */
-#define WH1 0x2127 /* pppppppp = p: Right position of window 1 */
-#define WH2 0x2128 /* pppppppp = p: Left position of window 2 */
-#define WH3 0x2129 /* pppppppp = p: Right position of window 2 */
-#define WBGLOG 0x212A /* aabbccdd = a: BG4 params | b: BG3 params | c: BG2 params | d: BG1 params */
-#define WOBJLOG 0x212B /* ----ccoo = c: Colour window params | o: Object window params */
-#define TM 0x212C
-#define TS 0x212D
-#define TMW 0x212E
-#define TSW 0x212F
-#define CGWSEL 0x2130
-#define CGADSUB 0x2131
-#define COLDATA 0x2132
#define SETINI 0x2133
#define MPYL 0x2134
#define MPYM 0x2135
#define MPYH 0x2136
-#define SLHV 0x2137
-#define ROAMDATA 0x2138
-#define RVMDATAL 0x2139
-#define RVMDATAH 0x213A
-#define RCGDATA 0x213B
-#define OPHCT 0x213C
-#define OPVCT 0x213D
-#define STAT77 0x213E
-#define STAT78 0x213F
+
#define APU00 0x2140
#define APU01 0x2141
#define APU02 0x2142
#define APU03 0x2143
+
#define WMDATA 0x2180
#define WMADDL 0x2181
#define WMADDM 0x2182
#define WMADDH 0x2183
-/* Definitions for CPU Memory-Mapped registers */
+
+// Definitions for CPU Memory-Mapped registers
#define OLDJOY1 0x4016
#define OLDJOY2 0x4017
#define NMITIMEN 0x4200
@@ -363,224 +280,6 @@
#define SNES_CPU_REG(a) m_cpu_regs[a - 0x4200] // regs 0x4200-0x421f
-/* (PPU) Video related */
-
-struct SNES_SCANLINE
-{
- int enable, clip;
-
- UINT16 buffer[SNES_SCR_WIDTH];
- UINT8 priority[SNES_SCR_WIDTH];
- UINT8 layer[SNES_SCR_WIDTH];
- UINT8 blend_exception[SNES_SCR_WIDTH];
-};
-
-class snes_state;
-
-class snes_ppu_class /* once all the regs are saved in this structure, it would be better to reorganize it a bit... */
-{
-public:
- UINT8 m_regs[0x40];
-
- SNES_SCANLINE m_scanlines[2];
-
- struct
- {
- /* clipmasks */
- UINT8 window1_enabled, window1_invert;
- UINT8 window2_enabled, window2_invert;
- UINT8 wlog_mask;
- /* color math enabled */
- UINT8 color_math;
-
- UINT8 charmap;
- UINT8 tilemap;
- UINT8 tilemap_size;
-
- UINT8 tile_size;
- UINT8 mosaic_enabled; // actually used only for layers 0->3!
-
- UINT8 main_window_enabled;
- UINT8 sub_window_enabled;
- UINT8 main_bg_enabled;
- UINT8 sub_bg_enabled;
-
- UINT16 hoffs;
- UINT16 voffs;
- } m_layer[6]; // this is for the BG1 - BG2 - BG3 - BG4 - OBJ - color layers
-
- struct
- {
- UINT8 address_low;
- UINT8 address_high;
- UINT8 saved_address_low;
- UINT8 saved_address_high;
- UINT16 address;
- UINT16 priority_rotation;
- UINT8 next_charmap;
- UINT8 next_size;
- UINT8 size;
- UINT32 next_name_select;
- UINT32 name_select;
- UINT8 first_sprite;
- UINT8 flip;
- UINT16 write_latch;
- } m_oam;
-
- struct
- {
- UINT16 latch_horz;
- UINT16 latch_vert;
- UINT16 current_horz;
- UINT16 current_vert;
- UINT8 last_visible_line;
- UINT8 interlace_count;
- } m_beam;
-
- struct
- {
- UINT8 repeat;
- UINT8 hflip;
- UINT8 vflip;
- INT16 matrix_a;
- INT16 matrix_b;
- INT16 matrix_c;
- INT16 matrix_d;
- INT16 origin_x;
- INT16 origin_y;
- UINT16 hor_offset;
- UINT16 ver_offset;
- UINT8 extbg;
- } m_mode7;
-
- struct OAM
- {
- UINT16 tile;
- INT16 x, y;
- UINT8 size, vflip, hflip, priority_bits, pal;
- int height, width;
- };
-
- struct OAM m_oam_spritelist[SNES_SCR_WIDTH / 2];
-
- UINT8 m_oam_itemlist[32];
-
- struct TILELIST {
- INT16 x;
- UINT16 priority, pal, tileaddr;
- int hflip;
- };
-
- struct TILELIST m_oam_tilelist[34];
-
- #if SNES_LAYER_DEBUG
- struct DEBUGOPTS
- {
- UINT8 bg_disabled[5];
- UINT8 mode_disabled[8];
- UINT8 draw_subscreen;
- UINT8 windows_disabled;
- UINT8 mosaic_disabled;
- UINT8 colormath_disabled;
- UINT8 sprite_reversed;
- UINT8 select_pri[5];
- };
- struct DEBUGOPTS m_debug_options;
- #endif
-
- screen_device *m_screen;
-
- UINT8 m_mosaic_size;
- UINT8 m_clip_to_black;
- UINT8 m_prevent_color_math;
- UINT8 m_sub_add_mode;
- UINT8 m_bg3_priority_bit;
- UINT8 m_direct_color;
- UINT8 m_ppu_last_scroll; /* as per Anomie's doc and Theme Park, all scroll regs shares (but mode 7 ones) the same
- 'previous' scroll value */
- UINT8 m_mode7_last_scroll; /* as per Anomie's doc mode 7 scroll regs use a different value, shared with mode 7 matrix! */
-
- UINT8 m_ppu1_open_bus, m_ppu2_open_bus;
- UINT8 m_ppu1_version, m_ppu2_version;
- UINT8 m_window1_left, m_window1_right, m_window2_left, m_window2_right;
-
- UINT16 m_mosaic_table[16][4096];
- UINT8 m_clipmasks[6][SNES_SCR_WIDTH];
- UINT8 m_update_windows;
- UINT8 m_update_offsets;
- UINT8 m_update_oam_list;
- UINT8 m_mode;
- UINT8 m_interlace; //doubles the visible resolution
- UINT8 m_obj_interlace;
- UINT8 m_screen_brightness;
- UINT8 m_screen_disabled;
- UINT8 m_pseudo_hires;
- UINT8 m_color_modes;
- UINT8 m_stat77;
- UINT8 m_stat78;
-
- UINT16 m_htmult; /* in 512 wide, we run HTOTAL double and halve it on latching */
- UINT16 m_cgram_address; /* CGRAM address */
- UINT8 m_read_ophct;
- UINT8 m_read_opvct;
- UINT16 m_vram_fgr_high;
- UINT16 m_vram_fgr_increment;
- UINT16 m_vram_fgr_count;
- UINT16 m_vram_fgr_mask;
- UINT16 m_vram_fgr_shift;
- UINT16 m_vram_read_buffer;
- UINT16 m_vmadd;
-
- inline UINT16 get_bgcolor(UINT8 direct_colors, UINT16 palette, UINT8 color);
- inline void set_scanline_pixel(int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend);
- inline void draw_bgtile_lores(UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority);
- inline void draw_bgtile_hires(UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority);
- inline void draw_oamtile(INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority);
- inline void draw_tile(UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires);
- inline UINT32 get_tmap_addr(UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y);
- inline void update_line(UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors);
- void update_line_mode7(UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a);
- void update_obsel(void);
- void oam_list_build(void);
- int is_sprite_on_scanline(UINT16 curline, UINT8 sprite);
- void update_objects_rto(UINT16 curline);
- void update_objects(UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3);
- void update_mode_0(UINT16 curline);
- void update_mode_1(UINT16 curline);
- void update_mode_2(UINT16 curline);
- void update_mode_3(UINT16 curline);
- void update_mode_4(UINT16 curline);
- void update_mode_5(UINT16 curline);
- void update_mode_6(UINT16 curline);
- void update_mode_7(UINT16 curline);
- void draw_screens(UINT16 curline);
- void update_windowmasks(void);
- void update_offsets(void);
- inline void draw_blend(UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens);
- void refresh_scanline(running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline);
-
- void latch_counters(running_machine &machine);
- void dynamic_res_change(running_machine &machine);
- inline UINT32 get_vram_address(running_machine &machine);
- UINT8 dbg_video(running_machine &machine, UINT16 curline);
-
- void ppu_start(screen_device &screen,snes_state *state);
- UINT8 read(address_space &space, UINT32 offset, UINT8 wrio_bit7);
- void write(address_space &space, UINT32 offset, UINT8 data);
-
- DECLARE_READ8_MEMBER( oam_read );
- DECLARE_WRITE8_MEMBER( oam_write );
- DECLARE_READ8_MEMBER( cgram_read );
- DECLARE_WRITE8_MEMBER( cgram_write );
- DECLARE_READ8_MEMBER( vram_read );
- DECLARE_WRITE8_MEMBER( vram_write );
- UINT16 *m_oam_ram; /* Object Attribute Memory */
- UINT16 *m_cgram; /* Palette RAM */
- UINT8 *m_vram; /* Video RAM (TODO: Should be 16-bit, but it's easier this way) */
-
- snes_state *m_state;
-};
-
struct snes_cart_info
{
UINT8 *m_rom;
@@ -613,7 +312,7 @@ public:
m_maincpu(*this, "maincpu"),
m_soundcpu(*this, "soundcpu"),
m_spc700(*this, "spc700"),
- m_superfx(*this, "superfx"),
+ m_ppu(*this, "ppu"),
m_screen(*this, "screen") { }
/* misc */
@@ -670,14 +369,13 @@ public:
snes_cart_info m_cart; // used by NSS/SFCBox only! to be moved in a derived class!
void rom_map_setup(UINT32 size);
- snes_ppu_class m_ppu;
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
/* devices */
required_device<_5a22_device> m_maincpu;
required_device<spc700_device> m_soundcpu;
required_device<snes_sound_device> m_spc700;
- optional_device<cpu_device> m_superfx;
+ required_device<snes_ppu_device> m_ppu;
required_device<screen_device> m_screen;
@@ -728,7 +426,6 @@ public:
DECLARE_WRITE_LINE_MEMBER(snes_extern_irq_w);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(snes_cart);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(sufami_cart);
- virtual void video_start();
void snes_init_timers();
virtual void machine_start();
virtual void machine_reset();
@@ -760,24 +457,4 @@ enum
HAS_UNK
};
-/* offset-per-tile modes */
-enum
-{
- SNES_OPT_NONE = 0,
- SNES_OPT_MODE2,
- SNES_OPT_MODE4,
- SNES_OPT_MODE6
-};
-
-/* layers */
-enum
-{
- SNES_BG1 = 0,
- SNES_BG2,
- SNES_BG3,
- SNES_BG4,
- SNES_OAM,
- SNES_COLOR
-};
-
#endif /* _SNES_H_ */
diff --git a/src/mame/machine/snes.c b/src/mame/machine/snes.c
index 30b09c62bc6..02fc958fd63 100644
--- a/src/mame/machine/snes.c
+++ b/src/mame/machine/snes.c
@@ -23,25 +23,16 @@
#define __MACHINE_SNES_C
#include "emu.h"
-#include "cpu/superfx/superfx.h"
-#include "cpu/g65816/g65816.h"
-#include "cpu/upd7725/upd7725.h"
#include "includes/snes.h"
-#include "audio/snes_snd.h"
#define DMA_REG(a) m_dma_regs[a - 0x4300] // regs 0x4300-0x437f
-void snes_state::video_start()
-{
- m_ppu.ppu_start(m_screen,this);
-}
-
UINT32 snes_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
/* NTSC SNES draw range is 1-225. */
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
- m_ppu.refresh_scanline(machine(), bitmap, y + 1);
+ m_ppu->refresh_scanline(machine(), bitmap, y + 1);
return 0;
}
@@ -96,7 +87,7 @@ void snes_state::hirq_tick()
{
// latch the counters and pull IRQ
// (don't need to switch to the 65816 context, we don't do anything dependant on it)
- m_ppu.latch_counters(machine());
+ m_ppu->latch_counters(machine());
SNES_CPU_REG(TIMEUP) = 0x80; /* Indicate that irq occurred */
m_maincpu->set_input_line(G65816_LINE_IRQ, ASSERT_LINE);
@@ -114,11 +105,11 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_reset_oam_address)
// make sure we're in the 65816's context since we're messing with the OAM and stuff
address_space &space = m_maincpu->space(AS_PROGRAM);
- if (!(m_ppu.m_screen_disabled)) //Reset OAM address, byuu says it happens at H=10
+ if (!(m_ppu->m_screen_disabled)) //Reset OAM address, byuu says it happens at H=10
{
- space.write_byte(OAMADDL, m_ppu.m_oam.saved_address_low); /* Reset oam address */
- space.write_byte(OAMADDH, m_ppu.m_oam.saved_address_high);
- m_ppu.m_oam.first_sprite = m_ppu.m_oam.priority_rotation ? (m_ppu.m_oam.address >> 1) & 127 : 0;
+ space.write_byte(OAMADDL, m_ppu->m_oam.saved_address_low); /* Reset oam address */
+ space.write_byte(OAMADDH, m_ppu->m_oam.saved_address_high);
+ m_ppu->m_oam.first_sprite = m_ppu->m_oam.priority_rotation ? (m_ppu->m_oam.address >> 1) & 127 : 0;
}
}
@@ -139,7 +130,7 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_update_io)
TIMER_CALLBACK_MEMBER(snes_state::snes_scanline_tick)
{
/* Increase current line - we want to latch on this line during it, not after it */
- m_ppu.m_beam.current_vert = m_screen->vpos();
+ m_ppu->m_beam.current_vert = m_screen->vpos();
// not in hblank
SNES_CPU_REG(HVBJOY) &= ~0x40;
@@ -147,11 +138,11 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_scanline_tick)
/* Vertical IRQ timer - only if horizontal isn't also enabled! */
if ((SNES_CPU_REG(NMITIMEN) & 0x20) && !(SNES_CPU_REG(NMITIMEN) & 0x10))
{
- if (m_ppu.m_beam.current_vert == m_vtime)
+ if (m_ppu->m_beam.current_vert == m_vtime)
{
SNES_CPU_REG(TIMEUP) = 0x80; /* Indicate that irq occurred */
// IRQ latches the counters, do it now
- m_ppu.latch_counters(machine());
+ m_ppu->latch_counters(machine());
m_maincpu->set_input_line(G65816_LINE_IRQ, ASSERT_LINE );
}
}
@@ -164,7 +155,7 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_scanline_tick)
// is the HIRQ on a specific scanline?
if (SNES_CPU_REG(NMITIMEN) & 0x20)
{
- if (m_ppu.m_beam.current_vert != m_vtime)
+ if (m_ppu->m_beam.current_vert != m_vtime)
{
setirq = 0;
}
@@ -172,22 +163,22 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_scanline_tick)
if (setirq)
{
-// printf("HIRQ @ %d, %d\n", pixel * m_ppu.m_htmult, m_ppu.m_beam.current_vert);
+// printf("HIRQ @ %d, %d\n", pixel * m_ppu->m_htmult, m_ppu->m_beam.current_vert);
if (pixel == 0)
{
hirq_tick();
}
else
{
- m_hirq_timer->adjust(m_screen->time_until_pos(m_ppu.m_beam.current_vert, pixel * m_ppu.m_htmult));
+ m_hirq_timer->adjust(m_screen->time_until_pos(m_ppu->m_beam.current_vert, pixel * m_ppu->m_htmult));
}
}
}
/* Start of VBlank */
- if (m_ppu.m_beam.current_vert == m_ppu.m_beam.last_visible_line)
+ if (m_ppu->m_beam.current_vert == m_ppu->m_beam.last_visible_line)
{
- timer_set(m_screen->time_until_pos(m_ppu.m_beam.current_vert, 10), TIMER_RESET_OAM_ADDRESS);
+ timer_set(m_screen->time_until_pos(m_ppu->m_beam.current_vert, 10), TIMER_RESET_OAM_ADDRESS);
SNES_CPU_REG(HVBJOY) |= 0x81; /* Set vblank bit to on & indicate controllers being read */
SNES_CPU_REG(RDNMI) |= 0x80; /* Set NMI occurred bit */
@@ -199,30 +190,30 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_scanline_tick)
}
/* three lines after start of vblank we update the controllers (value from snes9x) */
- m_io_timer->adjust(m_screen->time_until_pos(m_ppu.m_beam.current_vert + 2, m_hblank_offset * m_ppu.m_htmult));
+ m_io_timer->adjust(m_screen->time_until_pos(m_ppu->m_beam.current_vert + 2, m_hblank_offset * m_ppu->m_htmult));
}
// hdma reset happens at scanline 0, H=~6
- if (m_ppu.m_beam.current_vert == 0)
+ if (m_ppu->m_beam.current_vert == 0)
{
address_space &cpu0space = m_maincpu->space(AS_PROGRAM);
hdma_init(cpu0space);
}
- if (m_ppu.m_beam.current_vert == 0)
+ if (m_ppu->m_beam.current_vert == 0)
{ /* VBlank is over, time for a new frame */
SNES_CPU_REG(HVBJOY) &= 0x7f; /* Clear vblank bit */
SNES_CPU_REG(RDNMI) &= 0x7f; /* Clear nmi occurred bit */
- m_ppu.m_stat78 ^= 0x80; /* Toggle field flag */
- m_ppu.m_stat77 &= 0x3f; /* Clear Time Over and Range Over bits */
+ m_ppu->m_stat78 ^= 0x80; /* Toggle field flag */
+ m_ppu->m_stat77 &= 0x3f; /* Clear Time Over and Range Over bits */
m_maincpu->set_input_line(G65816_LINE_NMI, CLEAR_LINE );
}
m_scanline_timer->adjust(attotime::never);
- m_hblank_timer->adjust(m_screen->time_until_pos(m_ppu.m_beam.current_vert, m_hblank_offset * m_ppu.m_htmult));
+ m_hblank_timer->adjust(m_screen->time_until_pos(m_ppu->m_beam.current_vert, m_hblank_offset * m_ppu->m_htmult));
-// printf("%02x %d\n",SNES_CPU_REG(HVBJOY),m_ppu.m_beam.current_vert);
+// printf("%02x %d\n",SNES_CPU_REG(HVBJOY),m_ppu->m_beam.current_vert);
}
/* This is called at the start of hblank *before* the scanline indicated in current_vert! */
@@ -231,13 +222,13 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_hblank_tick)
address_space &cpu0space = m_maincpu->space(AS_PROGRAM);
int nextscan;
- m_ppu.m_beam.current_vert = m_screen->vpos();
+ m_ppu->m_beam.current_vert = m_screen->vpos();
/* make sure we halt */
m_hblank_timer->adjust(attotime::never);
/* draw a scanline */
- if (m_ppu.m_beam.current_vert <= m_ppu.m_beam.last_visible_line)
+ if (m_ppu->m_beam.current_vert <= m_ppu->m_beam.last_visible_line)
{
if (m_screen->vpos() > 0)
{
@@ -245,7 +236,7 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_hblank_tick)
if (SNES_CPU_REG(HDMAEN))
hdma(cpu0space);
- m_screen->update_partial((m_ppu.m_interlace == 2) ? (m_ppu.m_beam.current_vert * m_ppu.m_interlace) : m_ppu.m_beam.current_vert - 1);
+ m_screen->update_partial((m_ppu->m_interlace == 2) ? (m_ppu->m_beam.current_vert * m_ppu->m_interlace) : m_ppu->m_beam.current_vert - 1);
}
}
@@ -253,8 +244,8 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_hblank_tick)
SNES_CPU_REG(HVBJOY) |= 0x40;
/* kick off the start of scanline timer */
- nextscan = m_ppu.m_beam.current_vert + 1;
- if (nextscan >= (((m_ppu.m_stat78 & 0x10) == SNES_NTSC) ? SNES_VTOTAL_NTSC : SNES_VTOTAL_PAL))
+ nextscan = m_ppu->m_beam.current_vert + 1;
+ if (nextscan >= (((m_ppu->m_stat78 & 0x10) == SNES_NTSC) ? SNES_VTOTAL_NTSC : SNES_VTOTAL_PAL))
{
nextscan = 0;
}
@@ -402,7 +393,7 @@ READ8_MEMBER( snes_state::snes_r_io )
// PPU accesses are from 2100 to 213f
if (offset >= INIDISP && offset < APU00)
{
- return m_ppu.read(space, offset, SNES_CPU_REG(WRIO) & 0x80);
+ return m_ppu->read(space, offset, SNES_CPU_REG(WRIO) & 0x80);
}
// APU is mirrored from 2140 to 217f
@@ -490,7 +481,7 @@ WRITE8_MEMBER( snes_state::snes_w_io )
// PPU accesses are from 2100 to 213f
if (offset >= INIDISP && offset < APU00)
{
- m_ppu.write(space, offset, data);
+ m_ppu->write(space, offset, data);
return;
}
@@ -548,7 +539,7 @@ WRITE8_MEMBER( snes_state::snes_w_io )
if (!(SNES_CPU_REG(WRIO) & 0x80) && (data & 0x80))
{
// external latch
- m_ppu.latch_counters(space.machine());
+ m_ppu->latch_counters(space.machine());
}
SNES_CPU_REG(WRIO) = data;
return;
@@ -574,7 +565,7 @@ WRITE8_MEMBER( snes_state::snes_w_io )
return;
case HDMAEN: /* HDMA channel designation */
if (data) //if a HDMA is enabled, data is inited at the next scanline
- timer_set(m_screen->time_until_pos(m_ppu.m_beam.current_vert + 1), TIMER_RESET_HDMA);
+ timer_set(m_screen->time_until_pos(m_ppu->m_beam.current_vert + 1), TIMER_RESET_HDMA);
SNES_CPU_REG(HDMAEN) = data;
return;
case TIMEUP: // IRQ Flag is cleared on both read and write
@@ -1042,7 +1033,7 @@ void snes_state::snes_init_timers()
// SNES hcounter has a 0-339 range. hblank starts at counter 260.
// clayfighter sets an HIRQ at 260, apparently it wants it to be before hdma kicks off, so we'll delay 2 pixels.
m_hblank_offset = 274;
- m_hblank_timer->adjust(m_screen->time_until_pos(((m_ppu.m_stat78 & 0x10) == SNES_NTSC) ? SNES_VTOTAL_NTSC - 1 : SNES_VTOTAL_PAL - 1, m_hblank_offset));
+ m_hblank_timer->adjust(m_screen->time_until_pos(((m_ppu->m_stat78 & 0x10) == SNES_NTSC) ? SNES_VTOTAL_NTSC - 1 : SNES_VTOTAL_PAL - 1, m_hblank_offset));
}
void snes_state::snes_init_ram()
@@ -1069,9 +1060,9 @@ void snes_state::snes_init_ram()
// init frame counter so first line is 0
if (ATTOSECONDS_TO_HZ(m_screen->frame_period().attoseconds) >= 59)
- m_ppu.m_beam.current_vert = SNES_VTOTAL_NTSC;
+ m_ppu->m_beam.current_vert = SNES_VTOTAL_NTSC;
else
- m_ppu.m_beam.current_vert = SNES_VTOTAL_PAL;
+ m_ppu->m_beam.current_vert = SNES_VTOTAL_PAL;
}
void snes_state::machine_start()
@@ -1135,18 +1126,18 @@ void snes_state::machine_reset()
/* Set STAT78 to NTSC or PAL */
if (ATTOSECONDS_TO_HZ(m_screen->frame_period().attoseconds) >= 59.0f)
- m_ppu.m_stat78 = SNES_NTSC;
+ m_ppu->m_stat78 = SNES_NTSC;
else /* if (ATTOSECONDS_TO_HZ(m_screen->frame_period().attoseconds) == 50.0f) */
- m_ppu.m_stat78 = SNES_PAL;
+ m_ppu->m_stat78 = SNES_PAL;
// reset does this to these registers
SNES_CPU_REG(NMITIMEN) = 0;
m_htime = 0x1ff;
m_vtime = 0x1ff;
- m_ppu.m_htmult = 1;
- m_ppu.m_interlace = 1;
- m_ppu.m_obj_interlace = 1;
+ m_ppu->m_htmult = 1;
+ m_ppu->m_interlace = 1;
+ m_ppu->m_obj_interlace = 1;
}
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index c90c5d726db..71a5c4da451 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -309,6 +309,7 @@ VIDEOS += PSX
VIDEOS += RAMDAC
VIDEOS += SAA5050
#VIDEOS += SED1330
+VIDEOS += SNES_PPU
VIDEOS += STVVDP
VIDEOS += TLC34076
VIDEOS += TMS34061
@@ -1426,7 +1427,7 @@ $(MAMEOBJ)/nintendo.a: \
$(DRIVERS)/mario.o $(AUDIO)/mario.o $(VIDEO)/mario.o \
$(DRIVERS)/multigam.o \
$(DRIVERS)/n8080.o $(AUDIO)/n8080.o $(VIDEO)/n8080.o \
- $(DRIVERS)/nss.o $(MACHINE)/snes.o $(AUDIO)/snes_snd.o $(VIDEO)/snes.o \
+ $(DRIVERS)/nss.o $(MACHINE)/snes.o $(AUDIO)/snes_snd.o \
$(DRIVERS)/playch10.o $(MACHINE)/playch10.o $(VIDEO)/playch10.o \
$(DRIVERS)/popeye.o $(VIDEO)/popeye.o \
$(DRIVERS)/punchout.o $(VIDEO)/punchout.o \
diff --git a/src/mess/drivers/snes.c b/src/mess/drivers/snes.c
index 23e7b8fab05..8e1e6c21085 100644
--- a/src/mess/drivers/snes.c
+++ b/src/mess/drivers/snes.c
@@ -1461,7 +1461,7 @@ CUSTOM_INPUT_MEMBER( snes_console_state::sscope_offscreen_input )
INT16 y = ioport(portnames[port][2])->read();
/* these are the theoretical boundaries, but we currently are always onscreen... */
- if (x < 0 || x >= SNES_SCR_WIDTH || y < 0 || y >= m_ppu.m_beam.last_visible_line)
+ if (x < 0 || x >= SNES_SCR_WIDTH || y < 0 || y >= m_ppu->m_beam.last_visible_line)
m_scope[port].offscreen = 1;
else
m_scope[port].offscreen = 0;
@@ -1480,12 +1480,12 @@ void snes_console_state::gun_latch(INT16 x, INT16 y)
if (y < 0)
y = 0;
- if (y > (m_ppu.m_beam.last_visible_line - 1))
- y = m_ppu.m_beam.last_visible_line - 1;
+ if (y > (m_ppu->m_beam.last_visible_line - 1))
+ y = m_ppu->m_beam.last_visible_line - 1;
- m_ppu.m_beam.latch_horz = x;
- m_ppu.m_beam.latch_vert = y;
- m_ppu.m_stat78 |= 0x40;
+ m_ppu->m_beam.latch_horz = x;
+ m_ppu->m_beam.latch_vert = y;
+ m_ppu->m_stat78 |= 0x40;
}
void snes_console_state::input_read_sscope(int port)
@@ -1957,6 +1957,10 @@ static MACHINE_CONFIG_START( snes, snes_console_state )
MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC * 2, SNES_HTOTAL * 2, 0, SNES_SCR_WIDTH * 2, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
+ MCFG_DEVICE_ADD("ppu", SNES_PPU, 0)
+ MCFG_SNES_PPU_OPENBUS_CB(READ8(snes_state, snes_open_bus_r))
+ MCFG_VIDEO_SET_SCREEN("screen")
+
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("spc700", SNES, 0)
diff --git a/src/mess/mess.mak b/src/mess/mess.mak
index 49efa08c064..1fd8ec20290 100644
--- a/src/mess/mess.mak
+++ b/src/mess/mess.mak
@@ -301,6 +301,7 @@ VIDEOS += SAA5050
VIDEOS += SED1200
VIDEOS += SED1330
VIDEOS += SED1520
+VIDEOS += SNES_PPU
VIDEOS += STVVDP
VIDEOS += T6A04
#VIDEOS += TLC34076
@@ -795,7 +796,6 @@ $(MESSOBJ)/mame.a: \
$(MAME_VIDEO)/ppu2c0x.o \
$(MAME_AUDIO)/snes_snd.o \
$(MAME_MACHINE)/snes.o \
- $(MAME_VIDEO)/snes.o \
$(MAME_MACHINE)/n64.o \
$(MAME_VIDEO)/n64.o \
$(MAME_VIDEO)/rdpblend.o \