diff options
author | 2014-04-10 11:57:10 +0000 | |
---|---|---|
committer | 2014-04-10 11:57:10 +0000 | |
commit | 3c4620803a67988179a0714ef68cc20e69f5e3b4 (patch) | |
tree | 4f47cacf8bdbd67a14854df7dd3d72dbd56ce18e | |
parent | 39b3fbee05f816629321eb7f2a22a4cfc3cb20a7 (diff) |
Converted SNES PPU to be a device. [Fabio Priuli]
-rw-r--r-- | .gitattributes | 3 | ||||
-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.h | 292 | ||||
-rw-r--r-- | src/emu/video/video.mak | 8 | ||||
-rw-r--r-- | src/mame/drivers/nss.c | 4 | ||||
-rw-r--r-- | src/mame/drivers/sfcbox.c | 7 | ||||
-rw-r--r-- | src/mame/drivers/snesb.c | 7 | ||||
-rw-r--r-- | src/mame/includes/snes.h | 343 | ||||
-rw-r--r-- | src/mame/machine/snes.c | 85 | ||||
-rw-r--r-- | src/mame/mame.mak | 3 | ||||
-rw-r--r-- | src/mess/drivers/snes.c | 16 | ||||
-rw-r--r-- | src/mess/mess.mak | 2 |
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 \ |