summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/gba.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/video/gba.c')
-rw-r--r--src/mess/video/gba.c1811
1 files changed, 1811 insertions, 0 deletions
diff --git a/src/mess/video/gba.c b/src/mess/video/gba.c
new file mode 100644
index 00000000000..b0500ddc11a
--- /dev/null
+++ b/src/mess/video/gba.c
@@ -0,0 +1,1811 @@
+ /***************************************************************************
+
+ gba.c
+
+ File to handle emulation of the video hardware of the Game Boy Advance
+
+ By R. Belmont, MooglyGuy, Harmony
+
+***************************************************************************/
+
+#include "emu.h"
+#include "includes/gba.h"
+
+#define VERBOSE_LEVEL (0)
+
+INLINE void verboselog(running_machine &machine, int n_level, const char *s_fmt, ...)
+{
+ if( VERBOSE_LEVEL >= n_level )
+ {
+ va_list v;
+ char buf[ 32768 ];
+ va_start( v, s_fmt );
+ vsprintf( buf, s_fmt, v );
+ va_end( v );
+ logerror( "%08x: %s", cpu_get_pc(machine.device("maincpu")), buf );
+ }
+}
+
+static const int coeff[32] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+};
+
+/* Drawing functions */
+static void draw_roz_bitmap_scanline(gba_state *state, UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, INT32 X, INT32 Y, INT32 PA, INT32 PB, INT32 PC, INT32 PD, INT32 *currentx, INT32 *currenty, int changed, int depth);
+static void draw_roz_scanline(gba_state *state, UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, INT32 X, INT32 Y, INT32 PA, INT32 PB, INT32 PC, INT32 PD, INT32 *currentx, INT32 *currenty, int changed);
+static void draw_bg_scanline(gba_state *state, UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, UINT32 hofs, UINT32 vofs);
+static void draw_gba_oam_window(gba_state *state, running_machine &machine, UINT32 *scanline, int y);
+static void draw_gba_oam(gba_state *state, running_machine &machine, UINT32 *scanline, int y);
+static void invalid_gba_draw_function(running_machine &machine, gba_state *state, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int aux);
+
+/* Utility functions */
+INLINE int is_in_window(gba_state *state, int x, int window);
+INLINE UINT32 alpha_blend_pixel(UINT32 color0, UINT32 color1, int ca, int cb);
+INLINE UINT32 increase_brightness(UINT32 color, int coeff_);
+INLINE UINT32 decrease_brightness(UINT32 color, int coeff_);
+
+#include "gbamode0.c"
+#include "gbamode1.c"
+#include "gbamode2.c"
+#include "gbam345.c"
+
+static void (*const gba_draw_scanline_modes[8][3])(running_machine &machine, gba_state *state, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int aux) =
+{
+ /* All modes have three sub-modes: No effects, effects, and windowed effects. */
+ { /* Mode 0: 4 non-rotatable tilemaps and 1 OAM layer */
+ &draw_mode0_scanline,
+ &draw_mode0_scanline_nowindow,
+ &draw_mode0_scanline_all
+ },
+ { /* Mode 1: 2 non-rotatable tilemaps, 1 rotozoomable tilemap, and 1 OAM layer */
+ &draw_mode1_scanline,
+ &draw_mode1_scanline_nowindow,
+ &draw_mode1_scanline_all
+ },
+ { /* Mode 2: 2 rotozoomable tilemaps, and 1 OAM layer */
+ &draw_mode2_scanline,
+ &draw_mode2_scanline_nowindow,
+ &draw_mode2_scanline_all
+ },
+ { /* Mode 3: 1 rotatable 8bpp bitmap and one OAM layer */
+ &draw_roz_bitmap_mode_scanline,
+ &draw_roz_bitmap_mode_scanline_nowindow,
+ &draw_roz_bitmap_mode_scanline_all
+ },
+ { /* Mode 4: 1 rotatable 16bpp bitmap and one OAM layer */
+ &draw_roz_bitmap_mode_scanline,
+ &draw_roz_bitmap_mode_scanline_nowindow,
+ &draw_roz_bitmap_mode_scanline_all
+ },
+ { /* Mode 5: 1 rotatable 4bpp bitmap and one OAM layer */
+ &draw_roz_bitmap_mode_scanline,
+ &draw_roz_bitmap_mode_scanline_nowindow,
+ &draw_roz_bitmap_mode_scanline_all
+ },
+ {
+ &invalid_gba_draw_function,
+ &invalid_gba_draw_function,
+ &invalid_gba_draw_function,
+ },
+ {
+ &invalid_gba_draw_function,
+ &invalid_gba_draw_function,
+ &invalid_gba_draw_function,
+ },
+};
+
+static void invalid_gba_draw_function(running_machine &machine, gba_state *state, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int aux)
+{
+ fatalerror( "Invalid screen mode (6 or 7)!" );
+}
+
+static void draw_roz_bitmap_scanline(gba_state *state, UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, INT32 X, INT32 Y, INT32 PA, INT32 PB, INT32 PC, INT32 PD, INT32 *currentx, INT32 *currenty, int changed, int depth)
+{
+ UINT8 *src8 = (UINT8 *)state->m_gba_vram.target();
+ UINT16 *src16 = (UINT16 *)state->m_gba_vram.target();
+ UINT16 *palette = (UINT16 *)state->m_gba_pram.target();
+ INT32 sx = (depth == 4) ? 160 : 240;
+ INT32 sy = (depth == 4) ? 128 : 160;
+ UINT32 prio = ((ctrl & BGCNT_PRIORITY) << 25) + 0x1000000;
+ INT32 dx, dmx, dy, dmy, startx, starty;
+ INT32 rx, ry, pixx, pixy, x;
+
+ if ((depth == 8) && (state->m_DISPCNT & DISPCNT_FRAMESEL))
+ src8 += 0xa000;
+
+ if ((depth == 4) && (state->m_DISPCNT & DISPCNT_FRAMESEL))
+ src16 += 0xa000/2;
+
+ // sign extend roz parameters
+ if (X & 0x08000000) X |= 0xf0000000;
+ if (Y & 0x08000000) Y |= 0xf0000000;
+ if (PA & 0x8000) PA |= 0xffff0000;
+ if (PB & 0x8000) PB |= 0xffff0000;
+ if (PC & 0x8000) PC |= 0xffff0000;
+ if (PD & 0x8000) PD |= 0xffff0000;
+
+ // re-assign parameters for convenience's sake
+ dx = PA;
+ dmx = PB;
+ dy = PC;
+ dmy = PD;
+ startx = X;
+ starty = Y;
+
+ if(ypos == 0)
+ changed = 3;
+
+ if(changed & 1)
+ *currentx = startx;
+ else
+ *currentx += dmx;
+
+ if(changed & 2)
+ *currenty = starty;
+ else
+ *currenty += dmy;
+
+ rx = *currentx;
+ ry = *currenty;
+
+ if(ctrl & BGCNT_MOSAIC)
+ {
+ INT32 mosaic_line = ((state->m_MOSAIC & 0x00f0) >> 4) + 1;
+ INT32 tempy = (ypos / mosaic_line) * mosaic_line;
+ rx = startx + tempy*dmx;
+ ry = starty + tempy*dmy;
+ }
+
+ pixx = rx >> 8;
+ pixy = ry >> 8;
+
+ for(x = 0; x < 240; x++)
+ {
+ if(pixx < 0 || pixy < 0 || pixx >= sx || pixy >= sy)
+ {
+ scanline[x] = 0x80000000;
+ }
+ else
+ {
+ if (depth == 8)
+ {
+ UINT8 color = src8[pixy*sx + pixx];
+ scanline[x] = color ? (palette[color] | prio) : 0x80000000;
+ }
+ else
+ {
+ scanline[x] = src16[pixy*sx + pixx] | prio;
+ }
+ }
+
+ rx += dx;
+ ry += dy;
+
+ pixx = rx >> 8;
+ pixy = ry >> 8;
+ }
+
+ if(ctrl & BGCNT_MOSAIC)
+ {
+ INT32 mosaicx = (state->m_MOSAIC & 0x0f) + 1;
+ if(mosaicx > 1)
+ {
+ INT32 m = 1;
+ for(x = 0; x < 239; x++)
+ {
+ scanline[x+1] = scanline[x];
+ m++;
+ if(m == mosaicx)
+ {
+ m = 1;
+ x++;
+ }
+ }
+ }
+ }
+}
+
+static void draw_roz_scanline(gba_state *state, UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, INT32 X, INT32 Y, INT32 PA, INT32 PB, INT32 PC, INT32 PD, INT32 *currentx, INT32 *currenty, int changed)
+{
+ UINT32 base, mapbase, size;
+ static const INT32 sizes[4] = { 128, 256, 512, 1024 };
+ INT32 cx, cy, x, pixx, pixy;
+ UINT8 *mgba_vram = (UINT8 *)state->m_gba_vram.target();
+ UINT32 tile;
+ UINT16 *pgba_pram = (UINT16 *)state->m_gba_pram.target();
+ UINT16 pixel;
+ UINT32 prio = ((ctrl & BGCNT_PRIORITY) << 25) + 0x1000000;
+
+ for(x = 0; x < 240; x++)
+ {
+ scanline[x] = 0x80000000;
+ }
+
+ if (state->m_DISPCNT & enablemask)
+ {
+ base = ((ctrl & BGCNT_CHARBASE) >> BGCNT_CHARBASE_SHIFT) * 0x4000; // VRAM base of tiles
+ mapbase = ((ctrl & BGCNT_SCREENBASE) >> BGCNT_SCREENBASE_SHIFT) * 0x800; // VRAM base of map
+ size = (ctrl & BGCNT_SCREENSIZE) >> BGCNT_SCREENSIZE_SHIFT; // size of map in submaps
+
+ // sign extend roz parameters
+ if (X & 0x08000000) X |= 0xf0000000;
+ if (Y & 0x08000000) Y |= 0xf0000000;
+ if (PA & 0x8000) PA |= 0xffff0000;
+ if (PB & 0x8000) PB |= 0xffff0000;
+ if (PC & 0x8000) PC |= 0xffff0000;
+ if (PD & 0x8000) PD |= 0xffff0000;
+
+ if(ypos == 0)
+ {
+ changed = 3;
+ }
+
+ if(changed & 1)
+ {
+ *currentx = X;
+ }
+ else
+ {
+ *currentx += PB;
+ }
+
+ if(changed & 2)
+ {
+ *currenty = Y;
+ }
+ else
+ {
+ *currenty += PD;
+ }
+
+ cx = *currentx;
+ cy = *currenty;
+
+ if(ctrl & BGCNT_MOSAIC)
+ {
+ int mosaicy = ((state->m_MOSAIC & 0xf0) >> 4) + 1;
+ int y = ypos % mosaicy;
+ cx -= y*PB;
+ cy -= y*PD;
+ }
+
+ pixx = cx >> 8;
+ pixy = cy >> 8;
+
+ if(ctrl & BGCNT_PALETTESET_WRAP)
+ {
+ pixx %= sizes[size];
+ pixy %= sizes[size];
+ if(pixx < 0)
+ {
+ pixx += sizes[size];
+ }
+ if(pixy < 0)
+ {
+ pixy += sizes[size];
+ }
+ }
+
+ if(ctrl & BGCNT_PALETTE256)
+ {
+ for(x = 0; x < 240; x++)
+ {
+ if(pixx < 0 || pixy < 0 || pixx >= sizes[size] || pixy >= sizes[size])
+ {
+ scanline[x] = 0x80000000;
+ }
+ else
+ {
+ int tilex = pixx & 7;
+ int tiley = pixy & 7;
+
+ tile = mgba_vram[mapbase + (pixx >> 3) + (pixy >> 3) * (sizes[size] >> 3)];
+ pixel = mgba_vram[base + (tile << 6) + (tiley << 3) + tilex];
+
+ // plot it
+ scanline[x] = pixel ? (pgba_pram[pixel] | prio) : 0x80000000;
+ }
+
+ cx += PA;
+ cy += PC;
+
+ pixx = cx >> 8;
+ pixy = cy >> 8;
+
+ if(ctrl & BGCNT_PALETTESET_WRAP)
+ {
+ pixx %= sizes[size];
+ pixy %= sizes[size];
+ if(pixx < 0)
+ {
+ pixx += sizes[size];
+ }
+ if(pixy < 0)
+ {
+ pixy += sizes[size];
+ }
+ }
+ }
+ }
+ else
+ {
+ for(x = 0; x < 240; x++)
+ {
+ if(pixx < 0 || pixy < 0 || pixx >= sizes[size] || pixy >= sizes[size])
+ {
+ scanline[x] = 0x80000000;
+ }
+ else
+ {
+ int tilex = pixx & 7;
+ int tiley = pixy & 7;
+
+ tile = mgba_vram[mapbase + (pixx >> 3) + (pixy >> 3) * (sizes[size] >> 3)];
+ pixel = mgba_vram[base + (tile << 6) + (tiley << 3) + tilex];
+
+ // plot it
+ scanline[x] = pixel ? (pgba_pram[pixel] | prio) : 0x80000000;
+ }
+
+ cx += PA;
+ cy += PC;
+
+ pixx = cx >> 8;
+ pixy = cy >> 8;
+
+ if(ctrl & BGCNT_PALETTESET_WRAP)
+ {
+ pixx %= sizes[size];
+ pixy %= sizes[size];
+ if(pixx < 0)
+ {
+ pixx += sizes[size];
+ }
+ if(pixy < 0)
+ {
+ pixy += sizes[size];
+ }
+ }
+ }
+ }
+
+ if(ctrl & BGCNT_MOSAIC)
+ {
+ int mosaicx = (state->m_MOSAIC & 0x0f) + 1;
+ if(mosaicx > 1)
+ {
+ int m = 1;
+ for(x = 0; x < 239; x++)
+ {
+ scanline[x+1] = scanline[x];
+ m++;
+ if(m == mosaicx)
+ {
+ m = 1;
+ x++;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void draw_bg_scanline(gba_state *state, UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, UINT32 hofs, UINT32 vofs)
+{
+ UINT8 *vram = (UINT8*)state->m_gba_vram.target();
+ UINT16 *palette = (UINT16*)state->m_gba_pram.target();
+ UINT8 *chardata = &vram[((ctrl & BGCNT_CHARBASE) >> BGCNT_CHARBASE_SHIFT) * 0x4000];
+ UINT16 *screendata = (UINT16*)&vram[((ctrl & BGCNT_SCREENBASE) >> BGCNT_SCREENBASE_SHIFT) * 0x800];
+ UINT32 priority = ((ctrl & BGCNT_PRIORITY) << 25) + 0x1000000;
+ INT32 width = 256;
+ INT32 height = 256;
+ INT32 maskx, masky, pixx, pixy;
+ UINT8 use_mosaic = (ctrl & BGCNT_MOSAIC) ? 1 : 0;
+ INT32 mosaicx = (state->m_MOSAIC & 0x000f) + 1;
+ INT32 mosaicy = ((state->m_MOSAIC & 0x00f0) >> 4) + 1;
+ INT32 stride;
+ INT32 x;
+
+ if(!(state->m_DISPCNT & enablemask))
+ {
+ for(x = 0; x < 240; x++)
+ {
+ scanline[x] = 0x80000000;
+ }
+
+ return;
+ }
+
+ switch((ctrl & BGCNT_SCREENSIZE) >> BGCNT_SCREENSIZE_SHIFT)
+ {
+ case 1:
+ width = 512;
+ break;
+ case 2:
+ height = 512;
+ break;
+ case 3:
+ width = 512;
+ height = 512;
+ break;
+ }
+
+ maskx = width - 1;
+ masky = height - 1;
+
+ pixx = hofs & maskx;
+ pixy = (vofs + ypos) & masky;
+
+ if(use_mosaic)
+ {
+ if((ypos % mosaicy) != 0)
+ {
+ mosaicy = (ypos / mosaicy) * mosaicy;
+ pixy = (vofs + mosaicy) & masky;
+ }
+ }
+
+ if(pixy > 255 && height > 256)
+ {
+ pixy &= 0x000000ff;
+ screendata += 0x400;
+ if(width > 256)
+ {
+ screendata += 0x400;
+ }
+ }
+
+ stride = (pixy >> 3) << 5;
+
+ if(ctrl & BGCNT_PALETTE256)
+ {
+ UINT16 *src = screendata + 0x400 * (pixx >> 8) + ((pixx & 255) >> 3) + stride;
+ for(x = 0; x < 240; x++)
+ {
+ UINT16 data = *src;
+ INT32 tile = data & TILEOBJ_TILE;
+ INT32 tilex = pixx & 7;
+ INT32 tiley = pixy & 7;
+ UINT8 color;
+
+ if(data & TILEOBJ_HFLIP)
+ {
+ tilex = 7 - tilex;
+ }
+ if(data & TILEOBJ_VFLIP)
+ {
+ tiley = 7 - tiley;
+ }
+
+ color = chardata[(tile << 6) + (tiley << 3) + tilex];
+
+ if(color)
+ {
+ scanline[x] = palette[color] | priority;
+ }
+ else
+ {
+ scanline[x] = 0x80000000;
+ }
+
+ if(data & TILEOBJ_HFLIP)
+ {
+ if(tilex == 0)
+ {
+ src++;
+ }
+ }
+ else if(tilex == 7)
+ {
+ src++;
+ }
+
+ pixx++;
+ if(pixx == 256)
+ {
+ if(width > 256)
+ {
+ src = screendata + 0x400 + stride;
+ }
+ else
+ {
+ src = screendata + stride;
+ pixx = 0;
+ }
+ }
+ else if(pixx >= width)
+ {
+ pixx = 0;
+ src = screendata + stride;
+ }
+ }
+ }
+ else
+ {
+ UINT16 *src = screendata + 0x400 * (pixx >> 8) + ((pixx & 255) >> 3) + stride;
+ for(x = 0; x < 240; x++)
+ {
+ UINT16 data = *src;
+ INT32 tile = data & TILEOBJ_TILE;
+ INT32 tilex = pixx & 7;
+ INT32 tiley = pixy & 7;
+ UINT8 color;
+ UINT8 palindex;
+
+ if(data & TILEOBJ_HFLIP)
+ {
+ tilex = 7 - tilex;
+ }
+ if(data & TILEOBJ_VFLIP)
+ {
+ tiley = 7 - tiley;
+ }
+
+ color = chardata[(tile << 5) + (tiley << 2) + (tilex >> 1)];
+
+ if(tilex & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ palindex = (data >> 8) & 0x00f0;
+ if(color)
+ {
+ scanline[x] = palette[palindex + color] | priority;
+ }
+ else
+ {
+ scanline[x] = 0x80000000;
+ }
+
+ if(data & TILEOBJ_HFLIP)
+ {
+ if(tilex == 0)
+ {
+ src++;
+ }
+ }
+ else if(tilex == 7)
+ {
+ src++;
+ }
+
+ pixx++;
+ if(pixx == 256)
+ {
+ if(width > 256)
+ {
+ src = screendata + 0x400 + stride;
+ }
+ else
+ {
+ src = screendata + stride;
+ pixx = 0;
+ }
+ }
+ else if(pixx >= width)
+ {
+ pixx = 0;
+ src = screendata + stride;
+ }
+ }
+ }
+
+ if(use_mosaic)
+ {
+ if(mosaicx > 1)
+ {
+ INT32 m = 1;
+ for(x = 0; x < 239; x++)
+ {
+ scanline[x+1] = scanline[x];
+ m++;
+ if(m == mosaicx)
+ {
+ m = 1;
+ x++;
+ }
+ }
+ }
+ }
+}
+
+static void draw_gba_oam_window(gba_state *state, running_machine &machine, UINT32 *scanline, int y)
+{
+ INT16 gba_oamindex;
+ UINT32 tilebytebase, tileindex, tiledrawindex;
+ UINT32 width, height;
+ UINT16 *pgba_oam = (UINT16 *)state->m_gba_oam.target();
+ int x = 0;
+ UINT8 *src = (UINT8*)state->m_gba_vram.target();
+
+ for(x = 0; x < 240; x++)
+ {
+ scanline[x] = 0x80000000;
+ }
+
+ if( state->m_DISPCNT & DISPCNT_OBJWIN_EN )
+ {
+ for( gba_oamindex = 127; gba_oamindex >= 0; gba_oamindex-- )
+ {
+ INT32 sx, sy;
+ UINT16 attr0, attr1, attr2;
+ INT32 cury;
+
+ attr0 = pgba_oam[(4*gba_oamindex)+0];
+ attr1 = pgba_oam[(4*gba_oamindex)+1];
+ attr2 = pgba_oam[(4*gba_oamindex)+2];
+
+ sx = (attr1 & OBJ_X_COORD);
+ sy = (attr0 & OBJ_Y_COORD);
+
+ if(sy > 160)
+ {
+ sy -= 256;
+ }
+
+ if ((attr0 & OBJ_MODE) != OBJ_MODE_WINDOW)
+ {
+ continue;
+ }
+ else
+ {
+ width = 0;
+ height = 0;
+ switch (attr0 & OBJ_SHAPE )
+ {
+ case OBJ_SHAPE_SQR:
+ switch(attr1 & OBJ_SIZE )
+ {
+ case OBJ_SIZE_8:
+ width = 1;
+ height = 1;
+ break;
+ case OBJ_SIZE_16:
+ width = 2;
+ height = 2;
+ break;
+ case OBJ_SIZE_32:
+ width = 4;
+ height = 4;
+ break;
+ case OBJ_SIZE_64:
+ width = 8;
+ height = 8;
+ break;
+ }
+ break;
+ case OBJ_SHAPE_HORIZ:
+ switch(attr1 & OBJ_SIZE )
+ {
+ case OBJ_SIZE_8:
+ width = 2;
+ height = 1;
+ break;
+ case OBJ_SIZE_16:
+ width = 4;
+ height = 1;
+ break;
+ case OBJ_SIZE_32:
+ width = 4;
+ height = 2;
+ break;
+ case OBJ_SIZE_64:
+ width = 8;
+ height = 4;
+ break;
+ }
+ break;
+ case OBJ_SHAPE_VERT:
+ switch(attr1 & OBJ_SIZE )
+ {
+ case OBJ_SIZE_8:
+ width = 1;
+ height = 2;
+ break;
+ case OBJ_SIZE_16:
+ width = 1;
+ height = 4;
+ break;
+ case OBJ_SIZE_32:
+ width = 2;
+ height = 4;
+ break;
+ case OBJ_SIZE_64:
+ width = 4;
+ height = 8;
+ break;
+ }
+ break;
+ default:
+ width = 0;
+ height = 0;
+ verboselog(machine, 0, "OAM error: Trying to draw OBJ with OBJ_SHAPE = 3!\n" );
+ break;
+ }
+
+ tiledrawindex = tileindex = (attr2 & OBJ_TILENUM);
+ tilebytebase = 0x10000; // the index doesn't change in the higher modes, we just ignore sprites that are out of range
+
+ if (attr0 & OBJ_ROZMODE_ROZ)
+ {
+ INT32 fx, fy, ax, ay, rx, ry;
+ INT16 dx, dy, dmx, dmy;
+ UINT8 color;
+
+ width *= 8;
+ height *= 8;
+
+ if ((attr0 & OBJ_ROZMODE) == OBJ_ROZMODE_DISABLE)
+ {
+ continue;
+ }
+
+ fx = width;
+ fy = height;
+
+ if((attr0 & OBJ_ROZMODE) == OBJ_ROZMODE_DBLROZ)
+ {
+ fx *= 2;
+ fy *= 2;
+ }
+
+ cury = y - sy;
+
+ if(cury >= 0 && cury < fy)
+ {
+ if(sx < 240 || ((sx + fx) & 0x1ff) < 240)
+ {
+ int rot = (attr1 & OBJ_SCALE_PARAM) >> OBJ_SCALE_PARAM_SHIFT;
+ dx = (INT16)pgba_oam[(rot << 4)+3];
+ dmx = (INT16)pgba_oam[(rot << 4)+7];
+ dy = (INT16)pgba_oam[(rot << 4)+11];
+ dmy = (INT16)pgba_oam[(rot << 4)+15];
+
+ rx = (width << 7) - (fx >> 1)*dx - (fy >> 1)*dmx + cury * dmx;
+ ry = (height << 7) - (fx >> 1)*dy - (fy >> 1)*dmy + cury * dmy;
+
+ if((attr0 & OBJ_PALMODE) == OBJ_PALMODE_256)
+ {
+ int inc = 32;
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = sx >> 2;
+ }
+ else
+ {
+ tiledrawindex &= 0x3fe;
+ }
+ for(x = 0; x < fx; x++)
+ {
+ ax = rx >> 8;
+ ay = ry >> 8;
+
+ if(ax < 0 || ax >= sx || ay < 0 || ay >= sy)
+ {
+ }
+ else
+ {
+ color = src[tilebytebase + ((((tiledrawindex + (ay >> 3) * inc) << 5) + ((ay & 0x07) << 3) + ((ax >> 3) << 6) + (ax & 0x07)) & 0x7fff)];
+
+ if(color)
+ {
+ scanline[sx] = 1;
+ }
+ }
+
+ sx = (sx + 1) & 0x1ff;
+
+ rx += dx;
+ ry += dy;
+ }
+ }
+ else
+ {
+ int inc = 32;
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = sx >> 3;
+ }
+ for(x = 0; x < fx; x++)
+ {
+ ax = rx >> 8;
+ ay = ry >> 8;
+
+ if(ax < 0 || ax >= sx || ay < 0 || ay >= sy)
+ {
+ }
+ else
+ {
+ color = src[tilebytebase + ((((tiledrawindex + (ay >> 3) * inc) << 5) + ((ay & 0x07) << 2) + ((ax >> 3) << 5) + ((ax & 0x07) >> 1)) & 0x7fff)];
+
+ if(ax & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ if(color)
+ {
+ scanline[sx] = 1;
+ }
+ }
+
+ sx = (sx + 1) & 0x1ff;
+
+ rx += dx;
+ ry += dy;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ INT32 ax;
+ int cury_ = y - sy;
+
+ width *= 8;
+ height *= 8;
+
+ if(cury_ >= 0 && cury_ < height)
+ {
+ if( ( (sx < 240) || ( ( (sx + width) & 0x1ff ) < 240 ) ) && (attr0 & OBJ_ROZMODE_DISABLE) == 0)
+ {
+ if((attr0 & OBJ_PALMODE) == OBJ_PALMODE_256)
+ {
+ int inc = 32;
+ int address = 0;
+ if(attr1 & OBJ_VFLIP)
+ {
+ cury_ = height - cury_ - 1;
+ }
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = width >> 2;
+ }
+ else
+ {
+ tiledrawindex &= 0x3fe;
+ }
+
+ ax = 0;
+ if(attr1 & OBJ_HFLIP)
+ {
+ ax = width - 1;
+ }
+
+ address = 0x10000 + ((((tiledrawindex + (cury_ >> 3) * inc) << 5) + ((cury_ & 7) << 3) + ((ax >> 3) << 6) + (ax & 7)) & 0x7fff);
+
+ if(attr1 & OBJ_HFLIP)
+ {
+ ax = 7;
+ }
+
+ for(x = 0; x < width; x++)
+ {
+ if(sx < 240)
+ {
+ UINT8 color = src[address];
+
+ if(color)
+ {
+ scanline[sx] = 1;
+ }
+ }
+
+ sx = (sx + 1) & 0x1ff;
+
+ if(attr1 & OBJ_HFLIP)
+ {
+ ax--;
+ address--;
+ if(ax == -1)
+ {
+ address -= 56;
+ ax = 7;
+ }
+ if(address < 0x10000)
+ {
+ address += 0x8000;
+ }
+ }
+ else
+ {
+ ax++;
+ address++;
+ if(ax == 8)
+ {
+ address += 56;
+ ax = 0;
+ }
+ if(address > 0x17fff)
+ {
+ address -= 0x8000;
+ }
+ }
+ }
+ }
+ else
+ {
+ int inc = 32;
+ UINT32 address;
+ if(attr1 & OBJ_VFLIP)
+ {
+ cury_ = height - cury_ - 1;
+ }
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = width >> 3;
+ }
+
+ ax = 0;
+ if(attr1 & OBJ_HFLIP)
+ {
+ ax = width - 1;
+ }
+
+ address = 0x10000 + ((((tiledrawindex + (cury_ >> 3) * inc) << 5) + ((cury_ & 0x07) << 2) + ((ax >> 3) << 5) + ((ax & 0x07) >> 1)) & 0x7fff);
+ if(attr1 & OBJ_HFLIP)
+ {
+ ax = 7;
+ for(x = width - 1; x >= 0; x--)
+ {
+ if(sx < 240)
+ {
+ UINT8 color = src[address];
+ if(x & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ if(color)
+ {
+ scanline[sx] = 1;
+ }
+ }
+
+ sx = (sx + 1) & 0x1ff;
+ ax--;
+ if((x & 1) == 0)
+ {
+ address--;
+ }
+ if(ax == -1)
+ {
+ ax = 7;
+ address -= 28;
+ }
+ if(address < 0x10000)
+ {
+ address += 0x8000;
+ }
+ }
+ }
+ else
+ {
+ for(x = 0; x < width; x++)
+ {
+ if(sx < 240)
+ {
+ UINT8 color = src[address];
+
+ if(x & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ if(color)
+ {
+ scanline[sx] = 1;
+ }
+ }
+
+ sx = (sx + 1) & 0x1ff;
+ ax++;
+ if(x & 1)
+ {
+ address++;
+ }
+ if(ax == 8)
+ {
+ address += 28;
+ ax = 0;
+ }
+ if(address > 0x17fff)
+ {
+ address -= 0x8000;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void draw_gba_oam(gba_state *state, running_machine &machine, UINT32 *scanline, int y)
+{
+ INT16 gba_oamindex;
+ INT32 mosaiccnt = 0;
+ INT32 mosaicy = ((state->m_MOSAIC & 0xf000) >> 12) + 1;
+ INT32 mosaicx = ((state->m_MOSAIC & 0x0f00) >> 8) + 1;
+ UINT32 tileindex, tiledrawindex; //, tilebytebase
+ UINT8 width, height;
+ UINT16 *pgba_oam = (UINT16 *)state->m_gba_oam.target();
+ UINT8 *src = (UINT8 *)state->m_gba_vram.target();
+ UINT16 *palette = (UINT16*)state->m_gba_pram.target();
+ int x = 0;
+
+ for(x = 0; x < 240; x++)
+ {
+ scanline[x] = 0x80000000;
+ }
+
+ if( state->m_DISPCNT & DISPCNT_OBJ_EN )
+ {
+ for( gba_oamindex = 0; gba_oamindex < 128; gba_oamindex++ )
+ {
+ UINT16 attr0, attr1, attr2;
+ INT32 cury;
+ UINT32 prio;
+ UINT32 priority;
+
+ attr0 = pgba_oam[(4*gba_oamindex)+0];
+ attr1 = pgba_oam[(4*gba_oamindex)+1];
+ attr2 = pgba_oam[(4*gba_oamindex)+2];
+ priority = (attr2 & OBJ_PRIORITY) >> OBJ_PRIORITY_SHIFT;
+ prio = (priority << 25) | ((attr0 & OBJ_MODE) << 6);
+
+ if ((attr0 & OBJ_MODE) != OBJ_MODE_WINDOW)
+ {
+ width = 0;
+ height = 0;
+ switch (attr0 & OBJ_SHAPE)
+ {
+ case OBJ_SHAPE_SQR:
+ switch(attr1 & OBJ_SIZE )
+ {
+ case OBJ_SIZE_8:
+ width = 1;
+ height = 1;
+ break;
+ case OBJ_SIZE_16:
+ width = 2;
+ height = 2;
+ break;
+ case OBJ_SIZE_32:
+ width = 4;
+ height = 4;
+ break;
+ case OBJ_SIZE_64:
+ width = 8;
+ height = 8;
+ break;
+ }
+ break;
+ case OBJ_SHAPE_HORIZ:
+ switch(attr1 & OBJ_SIZE )
+ {
+ case OBJ_SIZE_8:
+ width = 2;
+ height = 1;
+ break;
+ case OBJ_SIZE_16:
+ width = 4;
+ height = 1;
+ break;
+ case OBJ_SIZE_32:
+ width = 4;
+ height = 2;
+ break;
+ case OBJ_SIZE_64:
+ width = 8;
+ height = 4;
+ break;
+ }
+ break;
+ case OBJ_SHAPE_VERT:
+ switch(attr1 & OBJ_SIZE )
+ {
+ case OBJ_SIZE_8:
+ width = 1;
+ height = 2;
+ break;
+ case OBJ_SIZE_16:
+ width = 1;
+ height = 4;
+ break;
+ case OBJ_SIZE_32:
+ width = 2;
+ height = 4;
+ break;
+ case OBJ_SIZE_64:
+ width = 4;
+ height = 8;
+ break;
+ }
+ break;
+ default:
+ width = 0;
+ height = 0;
+ verboselog(machine, 0, "OAM error: Trying to draw OBJ with OBJ_SHAPE = 3!\n" );
+ break;
+ }
+
+ tiledrawindex = tileindex = (attr2 & OBJ_TILENUM);
+// tilebytebase = 0x10000; // the index doesn't change in the higher modes, we just ignore sprites that are out of range
+
+ if (attr0 & OBJ_ROZMODE_ROZ)
+ {
+ INT32 sx, sy;
+ INT32 fx, fy, rx, ry;
+ INT16 dx, dy, dmx, dmy;
+
+ width *= 8;
+ height *= 8;
+
+ if ((attr0 & OBJ_ROZMODE) == OBJ_ROZMODE_DISABLE)
+ {
+ continue;
+ }
+
+ sx = (attr1 & OBJ_X_COORD);
+ sy = (attr0 & OBJ_Y_COORD);
+
+ if(sy > 160)
+ {
+ sy -= 256;
+ }
+
+ fx = width;
+ fy = height;
+
+ if((attr0 & OBJ_ROZMODE) == OBJ_ROZMODE_DBLROZ)
+ {
+ fx *= 2;
+ fy *= 2;
+ }
+
+ cury = y - sy;
+
+ if(cury >= 0 && cury < fy)
+ {
+ if(sx < 240 || ((sx + fx) & 0x1ff) < 240)
+ {
+ INT32 oamparam = (attr1 & OBJ_SCALE_PARAM) >> OBJ_SCALE_PARAM_SHIFT;
+
+ dx = (INT16)pgba_oam[(oamparam << 4)+3];
+ dmx = (INT16)pgba_oam[(oamparam << 4)+7];
+ dy = (INT16)pgba_oam[(oamparam << 4)+11];
+ dmy = (INT16)pgba_oam[(oamparam << 4)+15];
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ cury -= (cury % mosaicy);
+ }
+
+ rx = (width << 7) - (fx >> 1)*dx - (fy >> 1)*dmx + cury*dmx;
+ ry = (height << 7) - (fx >> 1)*dy - (fy >> 1)*dmy + cury*dmy;
+
+ if((attr0 & OBJ_PALMODE) == OBJ_PALMODE_256)
+ {
+ INT32 inc = 32;
+
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = width >> 2;
+ }
+ else
+ {
+ tiledrawindex &= 0x3fe;
+ }
+
+ for(x = 0; x < fx; x++)
+ {
+ INT32 pixx = rx >> 8;
+ INT32 pixy = ry >> 8;
+
+ if(!(pixx < 0 || pixx >= width || pixy < 0 || pixy >= height || sx >= 240))
+ {
+ UINT8 color = src[0x10000 + ((((tiledrawindex + (pixy >> 3) * inc) << 5) + ((pixy & 7) << 3) + ((pixx >> 3) << 6) + (pixx & 7)) & 0x7fff)];
+ if(color == 0 && priority < ((scanline[sx] >> 25) & 3))
+ {
+ scanline[sx] = (scanline[sx] & 0xf9ffffff) | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ else if(color != 0 && prio < (scanline[sx] & 0xff000000))
+ {
+ scanline[sx] = palette[256 + color] | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ mosaiccnt++;
+ if(mosaiccnt == mosaicx)
+ {
+ mosaiccnt = 0;
+ }
+ }
+ }
+
+ sx++;
+ sx &= 0x1ff;
+
+ rx += dx;
+ ry += dy;
+ }
+ }
+ else
+ {
+ INT32 inc = 32;
+ INT32 palentry = (attr2 >> 8) & 0xf0;
+
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = width >> 3;
+ }
+
+ for(x = 0; x < fx; x++)
+ {
+ INT32 pixx = rx >> 8;
+ INT32 pixy = ry >> 8;
+
+ if(!(pixx < 0 || pixx >= width || pixy < 0 || pixy >= height || sx >= 240))
+ {
+ UINT8 color = src[0x10000 + ((((tiledrawindex + (pixy >> 3) * inc) << 5) + ((pixy & 7) << 2) + ((pixx >> 3) << 5) + ((pixx & 7) >> 1)) & 0x7fff)];
+
+ if(pixx & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ if(color == 0 && priority < ((scanline[sx] >> 25) & 3))
+ {
+ scanline[sx] = (scanline[sx] & 0xf9ffffff) | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ else if(color != 0 && prio < (scanline[sx] & 0xff000000))
+ {
+ scanline[sx] = palette[256 + palentry + color] | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ }
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ mosaiccnt++;
+ if(mosaiccnt == mosaicx)
+ {
+ mosaiccnt = 0;
+ }
+ }
+
+ sx++;
+
+ sx &= 0x1ff;
+
+ rx += dx;
+ ry += dy;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ INT32 sx, sy;
+ INT32 vflip = (attr1 & OBJ_VFLIP) ? 1 : 0;
+ INT32 hflip = (attr1 & OBJ_HFLIP) ? 1 : 0;
+
+ width *= 8;
+ height *= 8;
+
+ if ((attr0 & OBJ_ROZMODE) == OBJ_ROZMODE_DISABLE)
+ {
+ continue;
+ }
+
+ sx = (attr1 & OBJ_X_COORD);
+ sy = (attr0 & OBJ_Y_COORD);
+
+ if(sy > 160)
+ {
+ sy -= 256;
+ }
+
+ cury = y - sy;
+ if(cury >= 0 && cury < height)
+ {
+ if(sx < 240 || ((sx + width) & 0x1ff) < 240)
+ {
+ if((attr0 & OBJ_PALMODE) == OBJ_PALMODE_256)
+ {
+ INT32 pixx;
+ INT32 inc = 32;
+ INT32 address = 0;
+
+ if(vflip)
+ {
+ cury = height - cury - 1;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = width >> 2;
+ }
+ else
+ {
+ tiledrawindex &= 0x3fe;
+ }
+
+ pixx = 0;
+ if(hflip)
+ {
+ pixx = width - 1;
+ }
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ cury -= (cury % mosaicy);
+ }
+
+ address = 0x10000 + ((((tiledrawindex + (cury >> 3) * inc) << 5) + ((cury & 7) << 3) + ((pixx >> 3) << 6) + (pixx & 7)) & 0x7fff);
+
+ if(hflip)
+ {
+ pixx = 7;
+ }
+
+ for(x = 0; x < width; x++)
+ {
+ if(sx < 240)
+ {
+ UINT8 color = src[address];
+ if(color == 0 && priority < ((scanline[sx] >> 25) & 3))
+ {
+ scanline[sx] = (scanline[sx] & 0xf9ffffff) | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ else if(color != 0 && prio < (scanline[sx] & 0xff000000))
+ {
+ scanline[sx] = palette[256 + color] | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ }
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ mosaiccnt++;
+ if(mosaiccnt == mosaicx)
+ {
+ mosaiccnt = 0;
+ }
+ }
+
+ sx++;
+ sx &= 0x1ff;
+
+ if(hflip)
+ {
+ pixx--;
+ address--;
+ if(pixx == -1)
+ {
+ address -= 56;
+ pixx = 7;
+ }
+ if(address < 0x10000)
+ {
+ address += 0x8000;
+ }
+ }
+ else
+ {
+ pixx++;
+ address++;
+ if(pixx == 8)
+ {
+ address += 56;
+ pixx = 0;
+ }
+ if(address > 0x17fff)
+ {
+ address -= 0x8000;
+ }
+ }
+ }
+ }
+ else
+ {
+ INT32 pixx;
+ INT32 inc = 32;
+ UINT32 address = 0;
+
+ if(vflip)
+ {
+ cury = height - cury - 1;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_MODE) > 2 && tiledrawindex < 0x200)
+ {
+ continue;
+ }
+
+ if((state->m_DISPCNT & DISPCNT_VRAM_MAP) == DISPCNT_VRAM_MAP_1D)
+ {
+ inc = width >> 3;
+ }
+
+ pixx = 0;
+ if(hflip)
+ {
+ pixx = width - 1;
+ }
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ cury -= (cury % mosaicy);
+ }
+
+ address = 0x10000 + ((((tiledrawindex + (cury >> 3) * inc) << 5) + ((cury & 7) << 2) + ((pixx >> 3) << 5) + ((pixx & 7) >> 1)) & 0x7fff);
+
+ if(hflip)
+ {
+ pixx = 7;
+ for(x = width - 1; x >= 0; x--)
+ {
+ if(sx < 240)
+ {
+ UINT8 color = src[address];
+ UINT8 palentry = (attr2 >> 8) & 0xf0;
+
+ if(x & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ if(color == 0 && priority < ((scanline[sx] >> 25) & 3))
+ {
+ scanline[sx] = (scanline[sx] & 0xf9ffffff) | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ else if(color != 0 && prio < (scanline[sx] & 0xff000000))
+ {
+ scanline[sx] = palette[256 + palentry + color] | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ }
+
+ sx++;
+ sx &= 0x1ff;
+
+ pixx--;
+ if(!(x & 1))
+ {
+ address--;
+ }
+ if(pixx == -1)
+ {
+ address -= 28;
+ pixx = 7;
+ }
+ if(address < 0x10000)
+ {
+ address += 0x8000;
+ }
+ }
+ }
+ else
+ {
+ for(x = 0; x < width; x++)
+ {
+ if(sx < 240)
+ {
+ UINT8 color = src[address];
+ UINT8 palentry = (attr2 >> 8) & 0xf0;
+
+ if(x & 1)
+ {
+ color >>= 4;
+ }
+ else
+ {
+ color &= 0x0f;
+ }
+
+ if(color == 0 && priority < ((scanline[sx] >> 25) & 3))
+ {
+ scanline[sx] = (scanline[sx] & 0xf9ffffff) | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ else if(color != 0 && prio < (scanline[sx] & 0xff000000))
+ {
+ scanline[sx] = palette[256 + palentry + color] | prio;
+ if((attr0 & OBJ_MOSAIC) != 0 && mosaiccnt != 0)
+ {
+ scanline[sx] = (scanline[sx - 1] & 0xf9ffffff) | prio;
+ }
+ }
+ }
+
+ if(attr0 & OBJ_MOSAIC)
+ {
+ mosaiccnt++;
+ if(mosaiccnt == mosaicx)
+ {
+ mosaiccnt = 0;
+ }
+ }
+
+ sx++;
+ sx &= 0x1ff;
+
+ pixx++;
+ if(x & 1)
+ {
+ address++;
+ }
+ if(pixx == 8)
+ {
+ address += 28;
+ pixx = 0;
+ }
+ if(address > 0x17fff)
+ {
+ address -= 0x8000;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+INLINE int is_in_window(gba_state *state, int x, int window)
+{
+ int x0 = state->m_WIN0H >> 8;
+ int x1 = state->m_WIN0H & 0x00ff;
+
+ if(window == 1)
+ {
+ x0 = state->m_WIN1H >> 8;
+ x1 = state->m_WIN1H & 0x00ff;
+ }
+
+ if(x0 <= x1)
+ {
+ if(x >= x0 && x < x1)
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if(x >= x0 || x < x1)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+INLINE UINT32 alpha_blend_pixel(UINT32 color0, UINT32 color1, int ca, int cb)
+{
+ if(color0 < 0x80000000)
+ {
+ int r0 = (color0 >> 0) & 0x1f;
+ int g0 = (color0 >> 5) & 0x1f;
+ int b0 = (color0 >> 10) & 0x1f;
+ int r1 = (color1 >> 0) & 0x1f;
+ int g1 = (color1 >> 5) & 0x1f;
+ int b1 = (color1 >> 10) & 0x1f;
+ int r = ((r0 * ca) >> 4) + ((r1 * cb) >> 4);
+ int g = ((g0 * ca) >> 4) + ((g1 * cb) >> 4);
+ int b = ((b0 * ca) >> 4) + ((b1 * cb) >> 4);
+
+ if(r > 0x1f) r = 0x1f;
+ if(g > 0x1f) g = 0x1f;
+ if(b > 0x1f) b = 0x1f;
+
+ return (color0 & 0xffff0000) | (b << 10) | (g << 5) | r;
+ }
+ return color0;
+}
+
+INLINE UINT32 increase_brightness(UINT32 color, int coeff_)
+{
+ int r = (color >> 0) & 0x1f;
+ int g = (color >> 5) & 0x1f;
+ int b = (color >> 10) & 0x1f;
+
+ r += ((0x1f - r) * coeff_) >> 4;
+ g += ((0x1f - g) * coeff_) >> 4;
+ b += ((0x1f - b) * coeff_) >> 4;
+
+ if(r > 0x1f) r = 0x1f;
+ if(g > 0x1f) g = 0x1f;
+ if(b > 0x1f) b = 0x1f;
+
+ return (color & 0xffff0000) | (b << 10) | (g << 5) | r;
+}
+
+INLINE UINT32 decrease_brightness(UINT32 color, int coeff_)
+{
+ int r = (color >> 0) & 0x1f;
+ int g = (color >> 5) & 0x1f;
+ int b = (color >> 10) & 0x1f;
+
+ r -= (r * coeff_) >> 4;
+ g -= (g * coeff_) >> 4;
+ b -= (b * coeff_) >> 4;
+
+ if(r < 0) r = 0;
+ if(g < 0) g = 0;
+ if(b < 0) b = 0;
+
+ return (color & 0xffff0000) | (b << 10) | (g << 5) | r;
+}
+
+void gba_draw_scanline(running_machine &machine, int y)
+{
+ gba_state *state = machine.driver_data<gba_state>();
+ bitmap_ind16 &bitmap = state->m_bitmap;
+ UINT16 *scanline = &bitmap.pix16(y);
+ int i, x;
+ UINT8 submode = 0;
+ int bpp = 0;
+
+ // forced blank
+ if (state->m_DISPCNT & DISPCNT_BLANK)
+ {
+ // forced blank is white
+ for (i = 0; i < 240; i++)
+ {
+ scanline[i] = 0x7fff;
+ }
+ return;
+ }
+
+ if(!state->m_fxOn && !state->m_windowOn && !(state->m_DISPCNT & DISPCNT_OBJWIN_EN))
+ {
+ submode = 0;
+ }
+ else if(state->m_fxOn && !state->m_windowOn && !(state->m_DISPCNT & DISPCNT_OBJWIN_EN))
+ {
+ submode = 1;
+ }
+ else
+ {
+ submode = 2;
+ }
+
+ //printf( "mode = %d, %d\n", state->m_DISPCNT & 7, submode );
+
+ switch(state->m_DISPCNT & 7)
+ {
+ case 3:
+ bpp = 16;
+ break;
+ case 4:
+ bpp = 8;
+ break;
+ case 5:
+ bpp = 4;
+ break;
+ }
+
+ gba_draw_scanline_modes[state->m_DISPCNT & 7][submode](machine, state, y, &state->m_xferscan[0][1024], &state->m_xferscan[1][1024], &state->m_xferscan[2][1024], &state->m_xferscan[3][1024], &state->m_xferscan[4][1024], &state->m_xferscan[5][1024], &state->m_xferscan[6][1024], bpp);
+
+ for(x = 0; x < 240; x++)
+ {
+ scanline[x] = state->m_xferscan[6][1024 + x] & 0x7fff;
+ }
+
+ return;
+}
+
+void gba_state::video_start()
+{
+ machine().primary_screen->register_screen_bitmap(m_bitmap);
+}
+
+UINT32 gba_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
+ return 0;
+}
+