mirror of
https://github.com/holub/mame
synced 2025-05-25 15:25:33 +03:00
[SNES] Improved Mode 7 math precision (but still some issues remain) and added a few elements to PPU struct
This commit is contained in:
parent
e8a98bf880
commit
0102fbe6ab
@ -422,6 +422,7 @@ struct SNES_PPU_STRUCT
|
||||
UINT32 map;
|
||||
UINT8 map_size;
|
||||
UINT8 tile_size;
|
||||
UINT8 mosaic_enabled; // actually used only for layers 0->3!
|
||||
struct
|
||||
{
|
||||
UINT16 horizontal;
|
||||
@ -462,13 +463,23 @@ struct SNES_PPU_STRUCT
|
||||
} beam;
|
||||
struct
|
||||
{
|
||||
INT16 matrix_a;
|
||||
INT16 matrix_b;
|
||||
INT16 matrix_c;
|
||||
INT16 matrix_d;
|
||||
INT16 origin_x;
|
||||
INT16 origin_y;
|
||||
UINT8 repeat;
|
||||
UINT8 hflip;
|
||||
UINT8 vflip;
|
||||
UINT16 matrix_a;
|
||||
UINT16 matrix_b;
|
||||
UINT16 matrix_c;
|
||||
UINT16 matrix_d;
|
||||
UINT16 origin_x;
|
||||
UINT16 origin_y;
|
||||
} mode7;
|
||||
UINT8 mosaic_size;
|
||||
UINT8 main_color_mask;
|
||||
UINT8 sub_color_mask;
|
||||
UINT8 sub_add_mode;
|
||||
UINT8 direct_color;
|
||||
|
||||
UINT16 mosaic_table[16][4096];
|
||||
UINT8 clipmasks[6][SNES_SCR_WIDTH + 8];
|
||||
UINT8 update_windows;
|
||||
UINT8 update_offsets;
|
||||
|
@ -739,6 +739,11 @@ WRITE8_HANDLER( snes_w_io )
|
||||
break;
|
||||
case MOSAIC: /* Size and screen designation for mosaic */
|
||||
/* FIXME: We don't support horizontal mosaic yet */
|
||||
snes_ppu.mosaic_size = (data & 0xf0) >> 4;
|
||||
snes_ppu.layer[0].mosaic_enabled = data & 0x01;
|
||||
snes_ppu.layer[1].mosaic_enabled = data & 0x02;
|
||||
snes_ppu.layer[2].mosaic_enabled = data & 0x04;
|
||||
snes_ppu.layer[3].mosaic_enabled = data & 0x08;
|
||||
break;
|
||||
case BG1SC: /* Address for storing SC data BG1 SC size designation */
|
||||
case BG2SC: /* Address for storing SC data BG2 SC size designation */
|
||||
@ -889,6 +894,9 @@ WRITE8_HANDLER( snes_w_io )
|
||||
}
|
||||
return;
|
||||
case M7SEL: /* Mode 7 initial settings */
|
||||
snes_ppu.mode7.repeat = (data >> 6) & 3;
|
||||
snes_ppu.mode7.vflip = data & 0x02;
|
||||
snes_ppu.mode7.hflip = data & 0x01;
|
||||
break;
|
||||
case M7A: /* Mode 7 COS angle/x expansion (DW) */
|
||||
snes_ppu.mode7.matrix_a = ((snes_ppu.mode7.matrix_a >> 8) & 0xff) + (data << 8);
|
||||
@ -936,6 +944,10 @@ WRITE8_HANDLER( snes_w_io )
|
||||
break;
|
||||
case CGWSEL: /* Initial settings for Fixed colour addition or screen addition */
|
||||
/* FIXME: We don't support direct select for modes 3 & 4 or subscreen window stuff */
|
||||
snes_ppu.main_color_mask = (data >> 6) & 0x03;
|
||||
snes_ppu.sub_color_mask = (data >> 4) & 0x03;
|
||||
snes_ppu.sub_add_mode = data & 0x02;
|
||||
snes_ppu.direct_color = data & 0x01;
|
||||
#ifdef SNES_DBG_REG_W
|
||||
if( (data & 0x2) != (snes_ram[CGWSEL] & 0x2) )
|
||||
mame_printf_debug( "Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour" );
|
||||
@ -1538,7 +1550,7 @@ WRITE8_HANDLER( snes_w_bank7 )
|
||||
static void snes_init_ram(running_machine *machine)
|
||||
{
|
||||
const address_space *cpu0space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
/* Init DSP1 */
|
||||
DSP1_reset(machine);
|
||||
@ -1571,6 +1583,15 @@ static void snes_init_ram(running_machine *machine)
|
||||
vram_read_offset = 2;
|
||||
joy1l = joy1h = joy2l = joy2h = joy3l = joy3h = 0;
|
||||
|
||||
/* Inititialize mosaic table */
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
for (i = 0; i < 4096; i++)
|
||||
{
|
||||
snes_ppu.mosaic_table[j][i] = (i / (j + 1)) * (j + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// set up some known register power-up defaults
|
||||
snes_ram[WRIO] = 0xff;
|
||||
snes_ram[VMAIN] = 0x80;
|
||||
|
@ -154,7 +154,7 @@ INLINE void snes_draw_blend(UINT16 offset, UINT16 *colour, UINT8 mode, UINT8 cli
|
||||
UINT16 r, g, b;
|
||||
if( mode == SNES_BLEND_ADD )
|
||||
{
|
||||
if( snes_ram[CGWSEL] & 0x2 ) /* Subscreen*/
|
||||
if( snes_ppu.sub_add_mode ) /* Subscreen*/
|
||||
{
|
||||
r = (*colour & 0x1f) + (scanlines[SUBSCREEN].buffer[offset] & 0x1f);
|
||||
g = ((*colour & 0x3e0) >> 5) + ((scanlines[SUBSCREEN].buffer[offset] & 0x3e0) >> 5);
|
||||
@ -185,7 +185,7 @@ INLINE void snes_draw_blend(UINT16 offset, UINT16 *colour, UINT8 mode, UINT8 cli
|
||||
}
|
||||
else if( mode == SNES_BLEND_SUB )
|
||||
{
|
||||
if( snes_ram[CGWSEL] & 0x2 ) /* Subscreen */
|
||||
if( snes_ppu.sub_add_mode ) /* Subscreen */
|
||||
{
|
||||
r = (*colour & 0x1f) - (scanlines[SUBSCREEN].buffer[offset] & 0x1f);
|
||||
g = ((*colour & 0x3e0) >> 5) - ((scanlines[SUBSCREEN].buffer[offset] & 0x3e0) >> 5);
|
||||
@ -276,12 +276,12 @@ INLINE void snes_draw_tile(UINT8 screen, UINT8 planes, UINT8 layer, UINT16 tilea
|
||||
c = snes_cgram[pal + colour];
|
||||
if (screen == MAINSCREEN) /* Only blend main screens */
|
||||
snes_draw_blend(ii, &c, snes_ppu.layer[layer].blend, (snes_ram[CGWSEL] & 0x30) >> 4);
|
||||
if (snes_ram[MOSAIC] & (1 << layer)) // handle horizontal mosaic
|
||||
if (snes_ppu.layer[layer].mosaic_enabled) // handle horizontal mosaic
|
||||
{
|
||||
int x_mos;
|
||||
|
||||
//TODO: 512 modes has the h values doubled.
|
||||
for (x_mos = 0; x_mos < (((snes_ram[MOSAIC] & 0xf0) >> 4) + 1) ; x_mos++)
|
||||
for (x_mos = 0; x_mos < (snes_ppu.mosaic_size + 1) ; x_mos++)
|
||||
{
|
||||
scanlines[screen].buffer[ii + x_mos] = c;
|
||||
scanlines[screen].zbuf[ii + x_mos] = priority;
|
||||
@ -459,6 +459,8 @@ INLINE void snes_update_line( UINT8 screen, UINT8 color_depth, UINT8 hires, UINT
|
||||
/* scrolling */
|
||||
UINT32 basevmap;
|
||||
UINT16 vscroll, hscroll, vtilescroll;
|
||||
// UINT16 offset_per_tile_valid;
|
||||
// UINT8 offset_per_tile_mode;
|
||||
UINT8 vshift, hshift, tile_size;
|
||||
/* variables depending on color_depth */
|
||||
UINT8 color_shift = 0;
|
||||
@ -499,6 +501,7 @@ INLINE void snes_update_line( UINT8 screen, UINT8 color_depth, UINT8 hires, UINT
|
||||
|
||||
/* Jump to base map address */
|
||||
tmap = snes_ppu.layer[layer].map;
|
||||
|
||||
/* Offset vertically */
|
||||
tmap += table_vscroll[snes_ppu.layer[layer].map_size & 3][(vtilescroll >> 5) & 3];
|
||||
/* Scroll vertically */
|
||||
@ -555,7 +558,6 @@ INLINE void snes_update_line( UINT8 screen, UINT8 color_depth, UINT8 hires, UINT
|
||||
pal += (layer << 5);
|
||||
}
|
||||
|
||||
|
||||
tile_line = line;
|
||||
if (vflip)
|
||||
{
|
||||
@ -625,11 +627,13 @@ INLINE void snes_update_line( UINT8 screen, UINT8 color_depth, UINT8 hires, UINT
|
||||
* 2009-08: Missing MOSAIC in Mode 7
|
||||
* (different behaviors in BG1 & BG2)
|
||||
*********************************************/
|
||||
#define MODE7_CLIP(x) (((x) & 0x2000) ? ((x) | ~0x03ff) : ((x) & 0x03ff))
|
||||
|
||||
static void snes_update_line_mode7(UINT8 screen, UINT8 priority_a, UINT8 priority_b, UINT8 layer, UINT16 curline )
|
||||
{
|
||||
UINT32 tiled;
|
||||
INT16 ma, mb, mc, md;
|
||||
INT16 xc, yc, tx, ty, sx, sy, hs, vs, xpos, xdir;
|
||||
INT32 xc, yc, tx, ty, sx, sy, hs, vs, xpos, xdir;
|
||||
UINT8 priority = priority_a;
|
||||
UINT8 colour = 0;
|
||||
|
||||
@ -651,23 +655,23 @@ static void snes_update_line_mode7(UINT8 screen, UINT8 priority_a, UINT8 priorit
|
||||
vs = snes_ppu.layer[layer].offset.vertical;
|
||||
|
||||
/* Sign extend */
|
||||
xc <<= 3;
|
||||
xc >>= 3;
|
||||
yc <<= 3;
|
||||
yc >>= 3;
|
||||
hs <<= 3;
|
||||
hs >>= 3;
|
||||
vs <<= 3;
|
||||
vs >>= 3;
|
||||
xc <<= 19;
|
||||
xc >>= 19;
|
||||
yc <<= 19;
|
||||
yc >>= 19;
|
||||
hs <<= 19;
|
||||
hs >>= 19;
|
||||
vs <<= 19;
|
||||
vs >>= 19;
|
||||
|
||||
/* Vertical flip */
|
||||
if (snes_ram[M7SEL] & 0x2)
|
||||
if (snes_ppu.mode7.vflip)
|
||||
sy = 255 - curline;
|
||||
else
|
||||
sy = curline;
|
||||
|
||||
/* Horizontal flip */
|
||||
if (snes_ram[M7SEL] & 0x1)
|
||||
if (snes_ppu.mode7.hflip)
|
||||
{
|
||||
xpos = 255;
|
||||
xdir = -1;
|
||||
@ -681,37 +685,34 @@ static void snes_update_line_mode7(UINT8 screen, UINT8 priority_a, UINT8 priorit
|
||||
/* Let's do some mode7 drawing huh? */
|
||||
for (sx = 0; sx < 256; sx++, xpos += xdir)
|
||||
{
|
||||
tx = (((ma * ((sx + hs) - xc)) + (mb * ((sy + vs) - yc))) >> 8) + xc;
|
||||
ty = (((mc * ((sx + hs) - xc)) + (md * ((sy + vs) - yc))) >> 8) + yc;
|
||||
switch (snes_ram[M7SEL] & 0xc0)
|
||||
tx = (((ma * MODE7_CLIP(hs - xc)) & ~0x3f) + ((mb * MODE7_CLIP(vs - yc)) & ~0x3f) + (xc << 8) + ((ma * sx) & ~0x3f) + ((mb * sy) & ~0x3f)) >> 8;
|
||||
ty = (((mc * MODE7_CLIP(hs - xc)) & ~0x3f) + ((md * MODE7_CLIP(vs - yc)) & ~0x3f) + (yc << 8) + ((mc * sx) & ~0x3f) + ((md * sy) & ~0x3f)) >> 8;
|
||||
|
||||
switch (snes_ppu.mode7.repeat)
|
||||
{
|
||||
case 0x00: /* Repeat if outside screen area */
|
||||
case 0x01: /* Repeat if outside screen area */
|
||||
tx &= 0x3ff;
|
||||
ty &= 0x3ff;
|
||||
tiled = snes_vram[((tx >> 3) * 2) + ((ty >> 3) * 128 * 2)] << 7;
|
||||
colour = snes_vram[tiled + ((tx & 0x7) * 2) + ((ty & 0x7) * 16) + 1];
|
||||
tiled = snes_vram[(((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2] << 7;
|
||||
colour = snes_vram[tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1];
|
||||
break;
|
||||
case 0x80: /* Single colour backdrop screen if outside screen area */
|
||||
if ((tx & 0x7fff) < 1024 && (ty & 0x7fff) < 1024)
|
||||
case 0x02: /* Single colour backdrop screen if outside screen area */
|
||||
if ((tx > 0) && (tx < 1024) && (ty > 0) && (ty < 1024))
|
||||
{
|
||||
tiled = snes_vram[((tx >> 3) * 2) + ((ty >> 3) * 128 * 2)] << 7;
|
||||
colour = snes_vram[tiled + ((tx & 0x7) * 2) + ((ty & 0x7) * 16) + 1];
|
||||
tiled = snes_vram[(((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2] << 7;
|
||||
colour = snes_vram[tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
colour = 0;
|
||||
}
|
||||
break;
|
||||
case 0xc0: /* Character 0x00 repeat if outside screen area */
|
||||
if ((tx & 0x7fff) < 1024 && (ty & 0x7fff) < 1024)
|
||||
{
|
||||
tiled = snes_vram[(((tx & 0x3ff) >> 3) * 2) + (((ty & 0x3ff) >> 3) * 128 * 2)] << 7;
|
||||
colour = snes_vram[tiled + ((tx & 0x7) * 2) + ((ty & 0x7) * 16) + 1];
|
||||
}
|
||||
case 0x03: /* Character 0x00 repeat if outside screen area */
|
||||
if ((tx > 0) && (tx < 1024) && (ty > 0) && (ty < 1024))
|
||||
tiled = snes_vram[(((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2] << 7;
|
||||
else
|
||||
{
|
||||
colour = snes_vram[((sx & 0x7) * 2) + ((sy & 0x7) * 16) + 1];
|
||||
}
|
||||
tiled = 0;
|
||||
|
||||
colour = snes_vram[tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1];
|
||||
break;
|
||||
}
|
||||
|
||||
@ -722,14 +723,14 @@ static void snes_update_line_mode7(UINT8 screen, UINT8 priority_a, UINT8 priorit
|
||||
colour &= 0x7f;
|
||||
}
|
||||
|
||||
colour &= snes_ppu.clipmasks[0][xpos];
|
||||
colour &= snes_ppu.clipmasks[layer][xpos];
|
||||
|
||||
/* Draw pixel if appropriate */
|
||||
if (scanlines[screen].zbuf[xpos] < priority && colour > 0)
|
||||
if (scanlines[screen].zbuf[xpos] <= priority && colour > 0)
|
||||
{
|
||||
UINT16 clr;
|
||||
/* Direct select, but only outside EXTBG! */
|
||||
if (snes_ram[CGWSEL] & 0x1 && layer == 1)
|
||||
if (snes_ppu.direct_color && layer == 1)
|
||||
clr = ((colour & 0x7) << 2) | ((colour & 0x38) << 4) | ((colour & 0xc0) << 7);
|
||||
else
|
||||
clr = snes_cgram[colour];
|
||||
|
Loading…
Reference in New Issue
Block a user