diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 95cccd99bfe..8958c7e3852 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -876,3 +876,15 @@ if (VIDEOS["GB_LCD"]~=null) then MAME_DIR .. "src/devices/video/gb_lcd.h", } end + +-------------------------------------------------- +-- +--@src/devices/video/gba_lcd.h,VIDEOS["GBA_LCD"] = true +-------------------------------------------------- + +if (VIDEOS["GBA_LCD"]~=null) then + files { + MAME_DIR .. "src/devices/video/gba_lcd.cpp", + MAME_DIR .. "src/devices/video/gba_lcd.h", + } +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 799f3f1cb68..3146e53bbbc 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -333,6 +333,7 @@ VIDEOS["VIC4567"] = true --VIDEOS+= VOODOO"] = true VIDEOS["SCN2674"] = true VIDEOS["GB_LCD"] = true +VIDEOS["GBA_LCD"] = true -------------------------------------------------- -- specify available machine cores @@ -2313,7 +2314,6 @@ files { MAME_DIR .. "src/mame/machine/gb.cpp", MAME_DIR .. "src/mame/drivers/gba.cpp", MAME_DIR .. "src/mame/includes/gba.h", - MAME_DIR .. "src/mame/video/gba.cpp", MAME_DIR .. "src/mame/drivers/n64.cpp", MAME_DIR .. "src/mame/includes/n64.h", MAME_DIR .. "src/mame/drivers/nes.cpp", diff --git a/src/mame/video/gba.cpp b/src/devices/video/gba_lcd.cpp similarity index 70% rename from src/mame/video/gba.cpp rename to src/devices/video/gba_lcd.cpp index f8f559efc0e..4a7173a6e03 100644 --- a/src/mame/video/gba.cpp +++ b/src/devices/video/gba_lcd.cpp @@ -2,7 +2,7 @@ // copyright-holders:R. Belmont,Ryan Holtz /*************************************************************************** - gba.c + gba_lcd.c File to handle emulation of the video hardware of the Game Boy Advance @@ -11,8 +11,170 @@ ***************************************************************************/ #include "emu.h" +#include "rendlay.h" + +#include "gba_lcd.h" + #include "includes/gba.h" +#define REG_BASE 0x000 + +/* LCD I/O Registers */ +#define DISPCNT HWLO(0x000) /* 0x4000000 2 R/W LCD Control */ +#define GRNSWAP HWHI(0x000) /* 0x4000002 2 R/W Undocumented - Green Swap */ +#define DISPSTAT HWLO(0x004) /* 0x4000004 2 R/W General LCD Status (STAT,LYC) */ +#define VCOUNT HWHI(0x004) /* 0x4000006 2 R Vertical Counter (LY) */ +#define BG0CNT HWLO(0x008) /* 0x4000008 2 R/W BG0 Control */ +#define BG1CNT HWHI(0x008) /* 0x400000A 2 R/W BG1 Control */ +#define BG2CNT HWLO(0x00C) /* 0x400000C 2 R/W BG2 Control */ +#define BG3CNT HWHI(0x00C) /* 0x400000E 2 R/W BG3 Control */ +#define BG0HOFS HWLO(0x010) /* 0x4000010 2 W BG0 X-Offset */ +#define BG0VOFS HWHI(0x010) /* 0x4000012 2 W BG0 Y-Offset */ +#define BG1HOFS HWLO(0x014) /* 0x4000014 2 W BG1 X-Offset */ +#define BG1VOFS HWHI(0x014) /* 0x4000016 2 W BG1 Y-Offset */ +#define BG2HOFS HWLO(0x018) /* 0x4000018 2 W BG2 X-Offset */ +#define BG2VOFS HWHI(0x018) /* 0x400001A 2 W BG2 Y-Offset */ +#define BG3HOFS HWLO(0x01C) /* 0x400001C 2 W BG3 X-Offset */ +#define BG3VOFS HWHI(0x01C) /* 0x400001E 2 W BG3 Y-Offset */ +#define BG2PA HWLO(0x020) /* 0x4000020 2 W BG2 Rotation/Scaling Parameter A (dx) */ +#define BG2PB HWHI(0x020) /* 0x4000022 2 W BG2 Rotation/Scaling Parameter B (dmx) */ +#define BG2PC HWLO(0x024) /* 0x4000024 2 W BG2 Rotation/Scaling Parameter C (dy) */ +#define BG2PD HWHI(0x024) /* 0x4000026 2 W BG2 Rotation/Scaling Parameter D (dmy) */ +#define BG2X WORD(0x028) /* 0x4000028 4 W BG2 Reference Point X-Coordinate */ +#define BG2Y WORD(0x02C) /* 0x400002C 4 W BG2 Reference Point Y-Coordinate */ +#define BG3PA HWLO(0x030) /* 0x4000030 2 W BG3 Rotation/Scaling Parameter A (dx) */ +#define BG3PB HWHI(0x030) /* 0x4000032 2 W BG3 Rotation/Scaling Parameter B (dmx) */ +#define BG3PC HWLO(0x034) /* 0x4000034 2 W BG3 Rotation/Scaling Parameter C (dy) */ +#define BG3PD HWHI(0x034) /* 0x4000036 2 W BG3 Rotation/Scaling Parameter D (dmy) */ +#define BG3X WORD(0x038) /* 0x4000038 4 W BG3 Reference Point X-Coordinate */ +#define BG3Y WORD(0x03C) /* 0x400003C 4 W BG3 Reference Point Y-Coordinate */ +#define WIN0H HWLO(0x040) /* 0x4000040 2 W Window 0 Horizontal Dimensions */ +#define WIN1H HWHI(0x040) /* 0x4000042 2 W Window 1 Horizontal Dimensions */ +#define WIN0V HWLO(0x044) /* 0x4000044 2 W Window 0 Vertical Dimensions */ +#define WIN1V HWHI(0x044) /* 0x4000046 2 W Window 1 Vertical Dimensions */ +#define WININ HWLO(0x048) /* 0x4000048 2 R/W Inside of Window 0 and 1 */ +#define WINOUT HWHI(0x048) /* 0x400004A 2 R/W Inside of OBJ Window & Outside of Windows */ +#define MOSAIC HWLO(0x04C) /* 0x400004C 2 W Mosaic Size */ + /* 0x400004E 2 - Unused */ +#define BLDCNT HWLO(0x050) /* 0x4000050 2 R/W Color Special Effects Selection */ +#define BLDALPHA HWHI(0x050) /* 0x4000052 2 W Alpha Blending Coefficients */ +#define BLDY HWLO(0x054) /* 0x4000054 2 W Brightness (Fade-In/Out) Coefficient */ + /* 0x4000056 2 - Unused */ + +#define DISPSTAT_SET(val) HWLO_SET(0x004, val) +#define DISPSTAT_RESET(val) HWLO_RESET(0x004, val) + +#define DISPSTAT_VBL 0x0001 +#define DISPSTAT_HBL 0x0002 +#define DISPSTAT_VCNT 0x0004 +#define DISPSTAT_VBL_IRQ_EN 0x0008 +#define DISPSTAT_HBL_IRQ_EN 0x0010 +#define DISPSTAT_VCNT_IRQ_EN 0x0020 +#define DISPSTAT_VCNT_VALUE 0xff00 + +#define DISPCNT_MODE 0x0007 +#define DISPCNT_FRAMESEL 0x0010 +#define DISPCNT_HBL_FREE 0x0020 + +#define DISPCNT_VRAM_MAP 0x0040 +#define DISPCNT_VRAM_MAP_2D 0x0000 +#define DISPCNT_VRAM_MAP_1D 0x0040 + +#define DISPCNT_BLANK 0x0080 +#define DISPCNT_BG0_EN 0x0100 +#define DISPCNT_BG1_EN 0x0200 +#define DISPCNT_BG2_EN 0x0400 +#define DISPCNT_BG3_EN 0x0800 +#define DISPCNT_OBJ_EN 0x1000 +#define DISPCNT_WIN0_EN 0x2000 +#define DISPCNT_WIN1_EN 0x4000 +#define DISPCNT_OBJWIN_EN 0x8000 + +#define OBJ_Y_COORD 0x00ff +#define OBJ_ROZMODE 0x0300 +#define OBJ_ROZMODE_NONE 0x0000 +#define OBJ_ROZMODE_ROZ 0x0100 +#define OBJ_ROZMODE_DISABLE 0x0200 +#define OBJ_ROZMODE_DBLROZ 0x0300 + +#define OBJ_MODE 0x0c00 +#define OBJ_MODE_NORMAL 0x0000 +#define OBJ_MODE_ALPHA 0x0400 +#define OBJ_MODE_WINDOW 0x0800 +#define OBJ_MODE_UNDEFINED 0x0c00 + +#define OBJ_MOSAIC 0x1000 + +#define OBJ_PALMODE 0x2000 +#define OBJ_PALMODE_16 0x0000 +#define OBJ_PALMODE_256 0x2000 + +#define OBJ_SHAPE 0xc000 +#define OBJ_SHAPE_SQR 0x0000 +#define OBJ_SHAPE_HORIZ 0x4000 +#define OBJ_SHAPE_VERT 0x8000 + +#define OBJ_X_COORD 0x01ff +#define OBJ_SCALE_PARAM 0x3e00 +#define OBJ_SCALE_PARAM_SHIFT 9 +#define OBJ_HFLIP 0x1000 +#define OBJ_VFLIP 0x2000 +#define OBJ_SIZE 0xc000 +#define OBJ_SIZE_8 0x0000 +#define OBJ_SIZE_16 0x4000 +#define OBJ_SIZE_32 0x8000 +#define OBJ_SIZE_64 0xc000 + +#define OBJ_TILENUM 0x03ff +#define OBJ_PRIORITY 0x0c00 +#define OBJ_PRIORITY_SHIFT 10 +#define OBJ_PALNUM 0xf000 +#define OBJ_PALNUM_SHIFT 12 + +#define BGCNT_SCREENSIZE 0xc000 +#define BGCNT_SCREENSIZE_SHIFT 14 +#define BGCNT_PALETTESET_WRAP 0x2000 +#define BGCNT_SCREENBASE 0x1f00 +#define BGCNT_SCREENBASE_SHIFT 8 +#define BGCNT_PALETTE256 0x0080 +#define BGCNT_MOSAIC 0x0040 +#define BGCNT_CHARBASE 0x003c +#define BGCNT_CHARBASE_SHIFT 2 +#define BGCNT_PRIORITY 0x0003 + +#define BLDCNT_BG0TP1 0x0001 +#define BLDCNT_BG1TP1 0x0002 +#define BLDCNT_BG2TP1 0x0004 +#define BLDCNT_BG3TP1 0x0008 +#define BLDCNT_OBJTP1 0x0010 +#define BLDCNT_BDTP1 0x0020 +#define BLDCNT_SFX 0x00c0 +#define BLDCNT_SFX_NONE 0x0000 +#define BLDCNT_SFX_ALPHA 0x0040 +#define BLDCNT_SFX_LIGHTEN 0x0080 +#define BLDCNT_SFX_DARKEN 0x00c0 +#define BLDCNT_BG0TP2 0x0100 +#define BLDCNT_BG1TP2 0x0200 +#define BLDCNT_BG2TP2 0x0400 +#define BLDCNT_BG3TP2 0x0800 +#define BLDCNT_OBJTP2 0x1000 +#define BLDCNT_BDTP2 0x2000 +#define BLDCNT_TP2_SHIFT 8 + +#define TILEOBJ_TILE 0x03ff +#define TILEOBJ_HFLIP 0x0400 +#define TILEOBJ_VFLIP 0x0800 +#define TILEOBJ_PALETTE 0xf000 + +#define GBA_MODE0 0 +#define GBA_MODE1 1 +#define GBA_MODE2 2 +#define GBA_MODE345 3 + +#define GBA_SUBMODE0 0 +#define GBA_SUBMODE1 1 +#define GBA_SUBMODE2 2 + #define VERBOSE_LEVEL (0) static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, const char *s_fmt, ...) @@ -24,7 +186,7 @@ static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, co va_start( v, s_fmt ); vsprintf( buf, s_fmt, v ); va_end( v ); - device.logerror( "%08x: %s", device.machine().driver_data()->m_maincpu->pc(), buf ); + device.logerror( "%08x: %s", device.machine().describe_context(), buf ); } } @@ -33,21 +195,72 @@ static const int coeff[32] = { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; -/* Utility functions */ -static inline UINT32 alpha_blend_pixel(UINT32 color0, UINT32 color1, int ca, int cb); -static inline UINT32 increase_brightness(UINT32 color, int coeff_); -static inline UINT32 decrease_brightness(UINT32 color, int coeff_); +static 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); -#define GBA_MODE0 0 -#define GBA_MODE1 1 -#define GBA_MODE2 2 -#define GBA_MODE345 3 + if(r > 0x1f) r = 0x1f; + if(g > 0x1f) g = 0x1f; + if(b > 0x1f) b = 0x1f; -#define GBA_SUBMODE0 0 -#define GBA_SUBMODE1 1 -#define GBA_SUBMODE2 2 + return (color0 & 0xffff0000) | (b << 10) | (g << 5) | r; + } + return color0; +} -inline void gba_state::update_mask(UINT8* mask, int mode, int submode, UINT32* obj_win, UINT8 inwin0, UINT8 inwin1, UINT8 in0_mask, UINT8 in1_mask, UINT8 out_mask) +static 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; +} + +static 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; +} + +const device_type GBA_LCD = &device_creator; + +gba_lcd_device::gba_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, GBA_LCD, "GBA LCD", tag, owner, clock, "gba_lcd", __FILE__), + device_video_interface(mconfig, *this) +{ +} + +inline void gba_lcd_device::update_mask(UINT8* mask, int mode, int submode, UINT32* obj_win, UINT8 inwin0, UINT8 inwin1, UINT8 in0_mask, UINT8 in1_mask, UINT8 out_mask) { UINT8 mode_mask = 0; if (submode == GBA_SUBMODE2) @@ -97,9 +310,9 @@ inline void gba_state::update_mask(UINT8* mask, int mode, int submode, UINT32* o } } -void gba_state::draw_modes(int mode, int submode, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int bpp) +void gba_lcd_device::draw_modes(int mode, int submode, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int bpp) { - UINT32 backdrop = ((UINT16*)m_gba_pram.target())[0] | 0x30000000; + UINT32 backdrop = ((UINT16*)m_pram.get())[0] | 0x30000000; int inWindow0 = 0; int inWindow1 = 0; UINT8 inWin0Mask = WININ & 0x00ff; @@ -329,11 +542,11 @@ void gba_state::draw_modes(int mode, int submode, int y, UINT32* line0, UINT32* m_gfxBG3Changed = 0; } -void gba_state::draw_roz_bitmap_scanline(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) +void gba_lcd_device::draw_roz_bitmap_scanline(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 *)m_gba_vram.target(); - UINT16 *src16 = (UINT16 *)m_gba_vram.target(); - UINT16 *palette = (UINT16 *)m_gba_pram.target(); + UINT8 *src8 = (UINT8 *)m_vram.get(); + UINT16 *src16 = (UINT16 *)m_vram.get(); + UINT16 *palette = (UINT16 *)m_pram.get(); INT32 sx = (depth == 4) ? 160 : 240; INT32 sy = (depth == 4) ? 128 : 160; UINT32 prio = ((ctrl & BGCNT_PRIORITY) << 25) + 0x1000000; @@ -426,14 +639,14 @@ void gba_state::draw_roz_bitmap_scanline(UINT32 *scanline, int ypos, UINT32 enab } } -void gba_state::draw_roz_scanline(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) +void gba_lcd_device::draw_roz_scanline(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, pixx, pixy; - UINT8 *mgba_vram = (UINT8 *)m_gba_vram.target(); + UINT8 *mgba_vram = (UINT8 *)m_vram.get(); UINT32 tile; - UINT16 *pgba_pram = (UINT16 *)m_gba_pram.target(); + UINT16 *pgba_pram = (UINT16 *)m_pram.get(); UINT16 pixel; UINT32 prio = ((ctrl & BGCNT_PRIORITY) << 25) + 0x1000000; int x = 0; @@ -557,10 +770,10 @@ void gba_state::draw_roz_scanline(UINT32 *scanline, int ypos, UINT32 enablemask, } } -void gba_state::draw_bg_scanline(UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, UINT32 hofs, UINT32 vofs) +void gba_lcd_device::draw_bg_scanline(UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, UINT32 hofs, UINT32 vofs) { - UINT8 *vram = (UINT8*)m_gba_vram.target(); - UINT16 *palette = (UINT16*)m_gba_pram.target(); + UINT8 *vram = (UINT8*)m_vram.get(); + UINT16 *palette = (UINT16*)m_pram.get(); 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; @@ -712,13 +925,13 @@ void gba_state::draw_bg_scanline(UINT32 *scanline, int ypos, UINT32 enablemask, } } -void gba_state::draw_gba_oam_window(UINT32 *scanline, int y) +void gba_lcd_device::draw_gba_oam_window(UINT32 *scanline, int y) { INT16 gba_oamindex; UINT32 tilebytebase, tileindex, tiledrawindex; UINT32 width, height; - UINT16 *pgba_oam = (UINT16 *)m_gba_oam.target(); - UINT8 *src = (UINT8*)m_gba_vram.target(); + UINT16 *pgba_oam = (UINT16 *)m_oam.get(); + UINT8 *src = (UINT8*)m_vram.get(); int x = 0; for (x = 0; x < 240; x++) @@ -1156,7 +1369,7 @@ void gba_state::draw_gba_oam_window(UINT32 *scanline, int y) } } -void gba_state::draw_gba_oam(UINT32 *scanline, int y) +void gba_lcd_device::draw_gba_oam(UINT32 *scanline, int y) { INT16 gba_oamindex; INT32 mosaiccnt = 0; @@ -1164,9 +1377,9 @@ void gba_state::draw_gba_oam(UINT32 *scanline, int y) INT32 mosaicx = ((MOSAIC & 0x0f00) >> 8) + 1; UINT32 tileindex, tiledrawindex; //, tilebytebase UINT8 width, height; - UINT16 *pgba_oam = (UINT16 *)m_gba_oam.target(); - UINT8 *src = (UINT8 *)m_gba_vram.target(); - UINT16 *palette = (UINT16*)m_gba_pram.target(); + UINT16 *pgba_oam = (UINT16 *)m_oam.get(); + UINT8 *src = (UINT8 *)m_vram.get(); + UINT16 *palette = (UINT16*)m_pram.get(); int x = 0; for (x = 0; x < 240; x++) @@ -1747,7 +1960,7 @@ void gba_state::draw_gba_oam(UINT32 *scanline, int y) } } -inline int gba_state::is_in_window(int x, int window) +inline int gba_lcd_device::is_in_window(int x, int window) { int x0 = WIN0H >> 8; int x1 = WIN0H & 0x00ff; @@ -1776,64 +1989,7 @@ inline int gba_state::is_in_window(int x, int window) return 0; } -static 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; -} - -static 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; -} - -static 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_state::draw_scanline(int y) +void gba_lcd_device::draw_scanline(int y) { bitmap_ind16 &bitmap = m_bitmap; UINT16 *scanline = &bitmap.pix16(y); @@ -1885,17 +2041,316 @@ void gba_state::draw_scanline(int y) { scanline[x] = m_xferscan[6][1024 + x] & 0x7fff; } - - return; } -void gba_state::video_start() +static const char *reg_names[] = { + /* LCD I/O Registers */ + "DISPCNT", "GRNSWAP", "DISPSTAT", "VCOUNT", + "BG0CNT", "BG1CNT", "BG2CNT", "BG3CNT", + "BG0HOFS", "BG0VOFS", "BG1HOFS", "BG1VOFS", + "BG2HOFS", "BG2VOFS", "BG3HOFS", "BG3VOFS", + "BG2PA", "BG2PB", "BG2PC", "BG2PD", + "BG2X_L", "BG2X_H", "BG2Y_L", "BG2Y_H", + "BG3PA", "BG3PB", "BG3PC", "BG3PD", + "BG3X_L", "BG3X_H", "BG3Y_L", "BG3Y_H", + "WIN0H", "WIN1H", "WIN0V", "WIN1V", + "WININ", "WINOUT", "MOSAIC", "Unused", + "BLDCNT", "BLDALPHA", "BLDY", "Unused", + "Unused", "Unused", "Unused", "Unused", +}; + +READ32_MEMBER(gba_lcd_device::video_r) { - machine().first_screen()->register_screen_bitmap(m_bitmap); + UINT32 retval = 0; + + switch( offset ) + { + case 0x0004/4: + retval = (DISPSTAT & 0xffff) | (machine().first_screen()->vpos()<<16); + break; + default: + if( ACCESSING_BITS_0_15 ) + { + retval |= m_regs[offset] & 0x0000ffff; + } + if( ACCESSING_BITS_16_31 ) + { + retval |= m_regs[offset] & 0xffff0000; + } + break; + } + + assert_always(offset < ARRAY_LENGTH(reg_names) / 2, "Not enough register names in gba_lcd_device"); + + if (ACCESSING_BITS_0_15) + { + verboselog(*this, 2, "GBA I/O Read: %s = %04x\n", reg_names[offset * 2], retval & 0x0000ffff); + } + if (ACCESSING_BITS_16_31) + { + verboselog(*this, 2, "GBA I/O Read: %s = %04x\n", reg_names[offset * 2 + 1], (retval & 0xffff0000) >> 16); + } + + return retval; } -UINT32 gba_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +WRITE32_MEMBER(gba_lcd_device::video_w) +{ + COMBINE_DATA(&m_regs[offset]); + + assert_always(offset < ARRAY_LENGTH(reg_names) / 2, "Not enough register names in gba_lcd_device"); + + if (ACCESSING_BITS_0_15) + { + verboselog(*this, 2, "GBA I/O Write: %s = %04x\n", reg_names[offset * 2], data & 0x0000ffff); + } + if (ACCESSING_BITS_16_31) + { + verboselog(*this, 2, "GBA I/O Write: %s = %04x\n", reg_names[offset * 2 + 1], (data & 0xffff0000) >> 16); + } + + switch( offset ) + { + case 0x0000/4: + if( ACCESSING_BITS_0_15 ) + { + if(DISPCNT & (DISPCNT_WIN0_EN | DISPCNT_WIN1_EN)) + { + m_windowOn = 1; + } + else + { + m_windowOn = 0; + } + } + break; + case 0x0028/4: + m_gfxBG2Changed |= 1; + break; + case 0x002c/4: + m_gfxBG2Changed |= 2; + break; + case 0x0038/4: + m_gfxBG3Changed |= 1; + break; + case 0x003c/4: + m_gfxBG3Changed |= 2; + break; + case 0x0050/4: + if( ACCESSING_BITS_0_15 ) + { + if(BLDCNT & BLDCNT_SFX) + { + m_fxOn = 1; + } + else + { + m_fxOn = 0; + } + } + break; + } +} + +static inline UINT32 combine_data_32_16(UINT32 prev, UINT32 data, UINT32 mem_mask) +{ + COMBINE_DATA(&prev); + switch(mem_mask) + { + case 0x000000ff: + prev &= 0xffff00ff; + prev |= data << 8; + break; + case 0x0000ff00: + prev &= 0xffffff00; + prev |= data >> 8; + break; + case 0x00ff0000: + prev &= 0x00ffffff; + prev |= data << 8; + break; + case 0xff000000: + prev &= 0xff00ffff; + prev |= data >> 8; + break; + default: + break; + } + return prev; +} + +READ32_MEMBER(gba_lcd_device::gba_pram_r) +{ + return m_pram[offset]; +} + +WRITE32_MEMBER(gba_lcd_device::gba_pram_w) +{ + m_pram[offset] = combine_data_32_16(m_pram[offset], data, mem_mask); +} + +READ32_MEMBER(gba_lcd_device::gba_vram_r) +{ + return m_vram[offset]; +} + +WRITE32_MEMBER(gba_lcd_device::gba_vram_w) +{ + m_vram[offset] = combine_data_32_16(m_vram[offset], data, mem_mask); +} + +READ32_MEMBER(gba_lcd_device::gba_oam_r) +{ + return m_oam[offset]; +} + +WRITE32_MEMBER(gba_lcd_device::gba_oam_w) +{ + m_oam[offset] = combine_data_32_16(m_oam[offset], data, mem_mask); +} + +TIMER_CALLBACK_MEMBER(gba_lcd_device::perform_hbl) +{ + int scanline = machine().first_screen()->vpos(); + + // draw only visible scanlines + if (scanline < 160) + { + draw_scanline(scanline); + + machine().driver_data()->request_dma(gba_state::dma_start_timing::hblank); + } + + if ((DISPSTAT & DISPSTAT_HBL_IRQ_EN ) != 0) + { + machine().driver_data()->request_irq(INT_HBL); + } + + DISPSTAT_SET(DISPSTAT_HBL); + + m_hbl_timer->adjust(attotime::never); +} + +TIMER_CALLBACK_MEMBER(gba_lcd_device::perform_scan) +{ + // clear hblank and raster IRQ flags + DISPSTAT_RESET(DISPSTAT_HBL|DISPSTAT_VCNT); + + int scanline = machine().first_screen()->vpos(); + + // VBL is set for scanlines 160 through 226 (but not 227, which is the last line) + if (scanline >= 160 && scanline < 227) + { + DISPSTAT_SET(DISPSTAT_VBL); + + // VBL IRQ and DMA on line 160 + if (scanline == 160) + { + if (DISPSTAT & DISPSTAT_VBL_IRQ_EN) + { + machine().driver_data()->request_irq(INT_VBL); + } + + machine().driver_data()->request_dma(gba_state::dma_start_timing::vblank); + } + } + else + { + DISPSTAT_RESET(DISPSTAT_VBL); + } + + // handle VCNT match interrupt/flag + if (scanline == ((DISPSTAT >> 8) & 0xff)) + { + DISPSTAT_SET(DISPSTAT_VCNT); + + if (DISPSTAT & DISPSTAT_VCNT_IRQ_EN) + { + machine().driver_data()->request_irq(INT_VCNT); + } + } + + m_hbl_timer->adjust(machine().first_screen()->time_until_pos(scanline, 240)); + m_scan_timer->adjust(machine().first_screen()->time_until_pos(( scanline + 1 ) % 228, 0)); +} + +PALETTE_INIT_MEMBER(gba_lcd_device, gba) +{ + for( UINT8 b = 0; b < 32; b++ ) + { + for( UINT8 g = 0; g < 32; g++ ) + { + for( UINT8 r = 0; r < 32; r++ ) + { + palette.set_pen_color( ( b << 10 ) | ( g << 5 ) | r, pal5bit(r), pal5bit(g), pal5bit(b) ); + } + } + } +} + +UINT32 gba_lcd_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); return 0; } + +void gba_lcd_device::device_start() +{ + m_pram = make_unique_clear(0x400 / 4); + m_vram = make_unique_clear(0x18000 / 4); + m_oam = make_unique_clear(0x400 / 4); + + save_pointer(NAME(m_pram.get()), 0x400 / 4); + save_pointer(NAME(m_vram.get()), 0x18000 / 4); + save_pointer(NAME(m_oam.get()), 0x400 / 4); + + m_screen->register_screen_bitmap(m_bitmap); + + /* create a timer to fire scanline functions */ + m_scan_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gba_lcd_device::perform_scan),this)); + m_hbl_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gba_lcd_device::perform_hbl),this)); + m_scan_timer->adjust(machine().first_screen()->time_until_pos(0, 0)); + + save_item(NAME(m_windowOn)); + save_item(NAME(m_fxOn)); + save_item(NAME(m_gfxBG2Changed)); + save_item(NAME(m_gfxBG3Changed)); + save_item(NAME(m_gfxBG2X)); + save_item(NAME(m_gfxBG2Y)); + save_item(NAME(m_gfxBG3X)); + save_item(NAME(m_gfxBG3Y)); + save_item(NAME(m_xferscan)); +} + +void gba_lcd_device::device_reset() +{ + memset(m_regs, 0, sizeof(m_regs)); + + m_gfxBG2Changed = 0; + m_gfxBG3Changed = 0; + m_gfxBG2X = 0; + m_gfxBG2Y = 0; + m_gfxBG3X = 0; + m_gfxBG3Y = 0; + m_windowOn = 0; + m_fxOn = 0; + + m_scan_timer->adjust(machine().first_screen()->time_until_pos(0, 0)); + m_hbl_timer->adjust(attotime::never); +} + +static MACHINE_CONFIG_FRAGMENT( gba_lcd ) + MCFG_SCREEN_ADD("screen", LCD) + MCFG_SCREEN_RAW_PARAMS(XTAL_16_777216MHz/4, 308, 0, 240, 228, 0, 160) + MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, gba_lcd_device, screen_update) + MCFG_SCREEN_PALETTE("palette") + + MCFG_DEFAULT_LAYOUT(layout_lcd) + MCFG_PALETTE_ADD("palette", 32768) + MCFG_PALETTE_INIT_OWNER(gba_lcd_device, gba) +MACHINE_CONFIG_END + +machine_config_constructor gba_lcd_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( gba_lcd ); +} diff --git a/src/devices/video/gba_lcd.h b/src/devices/video/gba_lcd.h new file mode 100644 index 00000000000..38a315af251 --- /dev/null +++ b/src/devices/video/gba_lcd.h @@ -0,0 +1,100 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont,Ryan Holtz +/*************************************************************************** + + gba_lcd.h + + File to handle emulation of the video hardware of the Game Boy Advance + + By R. Belmont, Ryan Holtz + +***************************************************************************/ + +#pragma once + +#ifndef __GBA_LCD_H__ +#define __GBA_LCD_H__ + +#include "emu.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +extern const device_type GBA_LCD; + + +//************************************************************************** +// DEVICE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_GBA_LCD_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, GBA_LCD, 0) + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class gba_lcd_device : public device_t, + public device_video_interface +{ +public: + gba_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + DECLARE_READ32_MEMBER(video_r); + DECLARE_WRITE32_MEMBER(video_w); + DECLARE_READ32_MEMBER(gba_pram_r); + DECLARE_WRITE32_MEMBER(gba_pram_w); + DECLARE_READ32_MEMBER(gba_vram_r); + DECLARE_WRITE32_MEMBER(gba_vram_w); + DECLARE_READ32_MEMBER(gba_oam_r); + DECLARE_WRITE32_MEMBER(gba_oam_w); + DECLARE_PALETTE_INIT(gba); + TIMER_CALLBACK_MEMBER(perform_hbl); + TIMER_CALLBACK_MEMBER(perform_scan); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual machine_config_constructor device_mconfig_additions() const override; + +private: + inline void update_mask(UINT8* mask, int mode, int submode, UINT32* obj_win, UINT8 inwin0, UINT8 inwin1, UINT8 in0_mask, UINT8 in1_mask, UINT8 out_mask); + void draw_modes(int mode, int submode, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int bpp); + void draw_roz_bitmap_scanline(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); + void draw_roz_scanline(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); + void draw_bg_scanline(UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, UINT32 hofs, UINT32 vofs); + void draw_gba_oam_window(UINT32 *scanline, int y); + void draw_gba_oam(UINT32 *scanline, int y); + inline int is_in_window(int x, int window); + void draw_scanline(int y); + + std::unique_ptr m_pram; + std::unique_ptr m_vram; + std::unique_ptr m_oam; + + emu_timer *m_scan_timer, *m_hbl_timer; + + bitmap_ind16 m_bitmap; + + UINT32 m_regs[0x60 / 4]; + + UINT8 m_windowOn; + UINT8 m_fxOn; + UINT8 m_gfxBG2Changed; + UINT8 m_gfxBG3Changed; + INT32 m_gfxBG2X; + INT32 m_gfxBG2Y; + INT32 m_gfxBG3X; + INT32 m_gfxBG3Y; + + UINT32 m_xferscan[7][240+2048]; +}; + +#endif /* GBA_LCD_H_ */ diff --git a/src/mame/drivers/gba.cpp b/src/mame/drivers/gba.cpp index 923d5beb2d4..daaaf72a3be 100644 --- a/src/mame/drivers/gba.cpp +++ b/src/mame/drivers/gba.cpp @@ -17,9 +17,90 @@ #include "sound/gb.h" #include "includes/gba.h" #include "bus/gba/rom.h" -#include "rendlay.h" #include "softlist.h" +#define REG_BASE 0x060 + +/* Sound Registers */ +#define SOUNDCNT_L HWLO(0x080) /* 0x4000080 2 R/W Control Stereo/Volume/Enable */ +#define SOUNDCNT_H HWHI(0x080) /* 0x4000082 2 R/W Control Mixing/DMA Control */ +#define SOUNDCNT_X HWLO(0x084) /* 0x4000084 2 R/W Control Sound on/off */ + /* 0x4000086 2 - Unused */ +#define SOUNDBIAS HWLO(0x088) /* 0x4000088 2 BIOS Sound PWM Control */ + /* 0x400008A 2 - Unused */ + +/* DMA Registers (4 Transfer Channels) */ +#define DMASAD(c) WORD(0x0B0 + c * 0xC) /* 0x40000B0 4 W DMA 0 Source Address */ +#define DMADAD(c) WORD(0x0B4 + c * 0xC) /* 0x40000B4 4 W DMA 0 Destination Address */ +#define DMACNT_L(c) HWLO(0x0B8 + c * 0xC) /* 0x40000B8 2 W DMA 0 Word Count */ +#define DMACNT_H(c) HWHI(0x0B8 + c * 0xC) /* 0x40000BA 2 R/W DMA 0 Control */ + +/* Serial Communication (1) Registers */ +#define SIODATA32 WORD(0x120) /* 0x4000120 4 R/W SIO Data (Normal-32bit Mode; shared with below) */ +#define SIOMULTI0 HWLO(0x120) /* 0x4000120 2 R/W SIO Data 0 (Parent) (Multi-Player Mode) */ +#define SIOMULTI1 HWHI(0x120) /* 0x4000122 2 R/W SIO Data 1 (1st Child) (Multi-Player Mode) */ +#define SIOMULTI2 HWLO(0x124) /* 0x4000124 2 R/W SIO Data 2 (2nd Child) (Multi-Player Mode) */ +#define SIOMULTI3 HWHI(0x124) /* 0x4000126 2 R/W SIO Data 3 (3rd Child) (Multi-Player Mode) */ +#define SIOCNT HWLO(0x128) /* 0x4000128 2 R/W SIO Control Register */ +#define SIOMLT_SEND HWHI(0x128) /* 0x400012A 2 R/W SIO Data (Local of MultiPlayer; shared below) */ +#define SIODATA8 HWHI(0x128) /* 0x400012A 2 R/W SIO Data (Normal-8bit and UART Mode) */ + /* 0x400012C 2 - Unused */ + +/* Keypad Input Registers */ +#define KEYINPUT HWLO(0x130) /* 0x4000130 2 R Key Status */ +#define KEYCNT HWHI(0x130) /* 0x4000132 2 R/W Key Interrupt Control */ + +/* Serial Communication (2) Registers */ +#define RCNT HWLO(0x134) /* 0x4000134 2 R/W SIO Mode Select/General Purpose Data */ +#define IR HWHI(0x134) /* 0x4000136 2 R/W Ancient - Infrared Register (Prototypes only) */ + /* 0x4000138 8 - Unused */ +#define JOYCNT HWLO(0x140) /* 0x4000140 2 R/W SIO JOY Bus Control */ + /* 0x4000142 2 - Unused */ +#define JOY_RECV WORD(0x150) /* 0x4000150 4 R/W SIO JOY Bus Receive Data */ +#define JOY_TRANS WORD(0x154) /* 0x4000154 4 R/W SIO JOY Bus Transmit Data */ +#define JOYSTAT HWLO(0x158) /* 0x4000158 2 R/? SIO JOY Bus Receive Status */ + /* 0x400015A 2 - Unused */ + +/* Interrupt, Waitstate, and Power-Down Control Registers */ +#define IE HWLO(0x200) /* 0x4000200 2 R/W Interrupt Enable Register */ +#define IF HWHI(0x200) /* 0x4000202 2 R/W Interrupt Request Flags / IRQ Acknowledge */ +#define WAITCNT HWLO(0x204) /* 0x4000204 2 R/W Game Pak Waitstate Control */ + /* 0x4000206 - Unused */ +#define IME HWLO(0x208) /* 0x4000208 2 R/W Interrupt Master Enable Register */ + /* 0x400020A - Unused */ + /* 0x4000300 1 R/W Undocumented - Post Boot Flag */ + /* 0x4000301 1 W Undocumented - Power Down Control */ + /* 0x4000302 - Unused */ + /* 0x4000410 ? ? Undocumented - Purpose Unknown / Bug ??? 0FFh */ + /* 0x4000411 - Unused */ + /* 0x4000800 4 R/W Undocumented - Internal Memory Control (R/W) */ + /* 0x4000804 - Unused */ + /* 0x4xx0800 4 R/W Mirrors of 4000800h (repeated each 64K) */ + +#define SOUNDBIAS_SET(val) HWLO_SET(0x088, val) + +#define DMASAD_SET(c, val) WORD_SET(0x0B0 + (c * 0xC), val) +#define DMADAD_SET(c, val) WORD_SET(0x0B4 + (c * 0xC), val) +#define DMACNT_L_SET(c, val) HWLO_SET(0x0B8 + (c * 0xC), val) +#define DMACNT_H_SET(c, val) HWHI_SET(0x0B8 + (c * 0xC), val) +#define DMACNT_H_RESET(c, val) HWHI_RESET(0x0B8 + (c * 0xC), val) + +#define SIOMULTI0_SET(val) HWLO_SET(0x120, val) +#define SIOMULTI1_SET(val) HWHI_SET(0x120, val) +#define SIOMULTI2_SET(val) HWLO_SET(0x124, val) +#define SIOMULTI3_SET(val) HWHI_SET(0x124, val) + +#define SIOCNT_RESET(val) HWLO_RESET(0x128, val) + +#define KEYCNT_SET(val) HWHI_SET(0x130, val) + +#define RCNT_SET(val) HWLO_SET(0x134, val) + +#define JOYSTAT_SET(val) HWLO_SET(0x158, val) + +#define IF_SET(val) HWHI_SET(0x200, val) +#define IF_RESET(val) HWHI_RESET(0x200, val) + #define VERBOSE_LEVEL (0) static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, const char *s_fmt, ...) @@ -38,21 +119,6 @@ static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, co static const UINT32 timer_clks[4] = { XTAL_16_777216MHz, XTAL_16_777216MHz / 64, XTAL_16_777216MHz / 256, XTAL_16_777216MHz / 1024 }; -PALETTE_INIT_MEMBER(gba_state, gba) -{ - UINT8 r, g, b; - for( b = 0; b < 32; b++ ) - { - for( g = 0; g < 32; g++ ) - { - for( r = 0; r < 32; r++ ) - { - palette.set_pen_color( ( b << 10 ) | ( g << 5 ) | r, pal5bit(r), pal5bit(g), pal5bit(b) ); - } - } - } -} - void gba_state::request_irq(UINT32 int_type) { // set flag for later recovery @@ -71,6 +137,34 @@ void gba_state::request_irq(UINT32 int_type) } } +void gba_state::request_dma(dma_start_timing start) +{ + UINT16 mask = 0x0000; + switch (start) + { + case immediately: + mask = 0x0000; + break; + case vblank: + mask = 0x1000; + break; + case hblank: + mask = 0x2000; + break; + case special: + mask = 0x3000; + break; + } + + for (int ch = 0; ch < 4; ch++) + { + int ctrl = DMACNT_H(ch); + + if ((ctrl & 0x8000) && ((ctrl & 0x3000) == mask)) + dma_exec(ch); + } +} + TIMER_CALLBACK_MEMBER(gba_state::dma_complete) { static const UINT32 ch_int[4] = { INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3 }; @@ -450,20 +544,6 @@ TIMER_CALLBACK_MEMBER(gba_state::handle_irq) } static const char *reg_names[] = { - /* LCD I/O Registers */ - "DISPCNT", "GRNSWAP", "DISPSTAT", "VCOUNT", - "BG0CNT", "BG1CNT", "BG2CNT", "BG3CNT", - "BG0HOFS", "BG0VOFS", "BG1HOFS", "BG1VOFS", - "BG2HOFS", "BG2VOFS", "BG3HOFS", "BG3VOFS", - "BG2PA", "BG2PB", "BG2PC", "BG2PD", - "BG2X_L", "BG2X_H", "BG2Y_L", "BG2Y_H", - "BG3PA", "BG3PB", "BG3PC", "BG3PD", - "BG3X_L", "BG3X_H", "BG3Y_L", "BG3Y_H", - "WIN0H", "WIN1H", "WIN0V", "WIN1V", - "WININ", "WINOUT", "MOSAIC", "Unused", - "BLDCNT", "BLDALPHA", "BLDY", "Unused", - "Unused", "Unused", "Unused", "Unused", - /* Sound Registers */ "SOUND1CNT_L", "SOUND1CNT_H", "SOUND1CNT_X", "Unused", "SOUND2CNT_L", "Unused", "SOUND2CNT_H", "Unused", @@ -482,11 +562,8 @@ READ32_MEMBER(gba_state::gba_io_r) { UINT32 retval = 0; - switch( offset ) + switch( offset + 0x60/4 ) { - case 0x0004/4: - retval = (DISPSTAT & 0xffff) | (machine().first_screen()->vpos()<<16); - break; case 0x0060/4: retval = m_gbsound->sound_r(space, 0) | m_gbsound->sound_r(space, 1)<<16 | m_gbsound->sound_r(space, 2)<<24; break; @@ -602,7 +679,7 @@ READ32_MEMBER(gba_state::gba_io_r) { UINT32 elapsed; double time, ticks; - int timer = offset-(0x100/4); + int timer = offset + 0x60/4 - 0x100/4; // printf("Read timer reg %x (PC=%x)\n", timer, space.device().safe_pc()); @@ -654,25 +731,24 @@ READ32_MEMBER(gba_state::gba_io_r) default: if( ACCESSING_BITS_0_15 ) { - retval |= m_io_regs[offset] & 0x0000ffff; + retval |= m_regs[offset] & 0x0000ffff; } if( ACCESSING_BITS_16_31 ) { - retval |= m_io_regs[offset] & 0xffff0000; + retval |= m_regs[offset] & 0xffff0000; } break; } - if (offset < ARRAY_LENGTH(reg_names) / 2) +// assert_always(offset < ARRAY_LENGTH(reg_names) / 2, "Not enough register names in gba_state"); + + if (ACCESSING_BITS_0_15) { - if (ACCESSING_BITS_0_15) - { - verboselog(*this, 2, "GBA I/O Read: %s (%08x) = %04x (%08x)\n", reg_names[offset * 2], 0x04000000 + ( offset << 2 ), retval & 0x0000ffff, ~mem_mask); - } - if (ACCESSING_BITS_16_31) - { - verboselog(*this, 2, "GBA I/O Read: %s (%08x) = %04x (%08x)\n", reg_names[offset * 2 + 1], 0x04000000 + ( offset << 2 ) + 2, (retval & 0xffff0000) >> 16, ~mem_mask); - } + verboselog(*this, 2, "GBA I/O Read: %s = %04x\n", reg_names[offset * 2], retval & 0x0000ffff); + } + if (ACCESSING_BITS_16_31) + { + verboselog(*this, 2, "GBA I/O Read: %s = %04x\n", reg_names[offset * 2 + 1], (retval & 0xffff0000) >> 16); } return retval; @@ -684,7 +760,7 @@ WRITE32_MEMBER(gba_state::gba_io_w) UINT16 siocnt = SIOCNT; UINT16 dmachcnt[4] = { DMACNT_H(0), DMACNT_H(1), DMACNT_H(2), DMACNT_H(3) }; - COMBINE_DATA(&m_io_regs[offset]); + COMBINE_DATA(&m_regs[offset]); // assert_always(offset < ARRAY_LENGTH(reg_names) / 2, "Not enough register names in gba_state"); @@ -697,46 +773,8 @@ WRITE32_MEMBER(gba_state::gba_io_w) verboselog(*this, 2, "GBA I/O Write: %s = %04x\n", reg_names[offset * 2 + 1], (data & 0xffff0000) >> 16); } - switch( offset ) + switch( offset + 0x60/4 ) { - case 0x0000/4: - if( ACCESSING_BITS_0_15 ) - { - if(DISPCNT & (DISPCNT_WIN0_EN | DISPCNT_WIN1_EN)) - { - m_windowOn = 1; - } - else - { - m_windowOn = 0; - } - } - break; - case 0x0028/4: - m_gfxBG2Changed |= 1; - break; - case 0x002c/4: - m_gfxBG2Changed |= 2; - break; - case 0x0038/4: - m_gfxBG3Changed |= 1; - break; - case 0x003c/4: - m_gfxBG3Changed |= 2; - break; - case 0x0050/4: - if( ACCESSING_BITS_0_15 ) - { - if(BLDCNT & BLDCNT_SFX) - { - m_fxOn = 1; - } - else - { - m_fxOn = 0; - } - } - break; case 0x0060/4: if( ACCESSING_BITS_0_7 ) // SOUNDCNTL { @@ -969,7 +1007,7 @@ WRITE32_MEMBER(gba_state::gba_io_w) case 0x00dc/4: if( ACCESSING_BITS_16_31 ) { - int ch = (offset - (0xb0/4)) / 3; + int ch = (offset + 0x60/4 - 0xb0/4) / 3; int ctrl = data>>16; @@ -1003,7 +1041,7 @@ WRITE32_MEMBER(gba_state::gba_io_w) double rate, clocksel; UINT32 old_timer_regs; - int timer = offset - 0x100/4; + int timer = offset + 0x60/4 - 0x100/4; old_timer_regs = m_timer_regs[timer]; @@ -1104,54 +1142,9 @@ WRITE32_MEMBER(gba_state::gba_io_w) m_maincpu->spin_until_interrupt(); } break; - default: -// verboselog(machine, 0, "Unknown GBA I/O register write: %08x = %08x (%08x)\n", 0x04000000 + ( offset << 2 ), data, ~mem_mask ); - break; } } -static inline UINT32 COMBINE_DATA32_16(UINT32 prev, UINT32 data, UINT32 mem_mask) -{ - COMBINE_DATA(&prev); - switch(mem_mask) - { - case 0x000000ff: - prev &= 0xffff00ff; - prev |= data << 8; - break; - case 0x0000ff00: - prev &= 0xffffff00; - prev |= data >> 8; - break; - case 0x00ff0000: - prev &= 0x00ffffff; - prev |= data << 8; - break; - case 0xff000000: - prev &= 0xff00ffff; - prev |= data >> 8; - break; - default: - break; - } - return prev; -} - -WRITE32_MEMBER(gba_state::gba_pram_w) -{ - m_gba_pram[offset] = COMBINE_DATA32_16(m_gba_pram[offset], data, mem_mask); -} - -WRITE32_MEMBER(gba_state::gba_vram_w) -{ - m_gba_vram[offset] = COMBINE_DATA32_16(m_gba_vram[offset], data, mem_mask); -} - -WRITE32_MEMBER(gba_state::gba_oam_w) -{ - m_gba_oam[offset] = COMBINE_DATA32_16(m_gba_oam[offset], data, mem_mask); -} - READ32_MEMBER(gba_state::gba_bios_r) { UINT32 *rom = m_region_maincpu; @@ -1192,11 +1185,12 @@ static ADDRESS_MAP_START( gba_map, AS_PROGRAM, 32, gba_state ) AM_RANGE(0x00000000, 0x00003fff) AM_ROM AM_READ(gba_bios_r) AM_RANGE(0x02000000, 0x0203ffff) AM_RAM AM_MIRROR(0xfc0000) AM_RANGE(0x03000000, 0x03007fff) AM_RAM AM_MIRROR(0xff8000) - AM_RANGE(0x04000000, 0x040003ff) AM_READWRITE(gba_io_r, gba_io_w) + AM_RANGE(0x04000000, 0x0400005f) AM_DEVREADWRITE("lcd", gba_lcd_device, video_r, video_w) + AM_RANGE(0x04000060, 0x040003ff) AM_READWRITE(gba_io_r, gba_io_w) AM_RANGE(0x04000400, 0x04ffffff) AM_NOP // Not used - AM_RANGE(0x05000000, 0x050003ff) AM_RAM_WRITE(gba_pram_w) AM_SHARE("gba_pram") // Palette RAM - AM_RANGE(0x06000000, 0x06017fff) AM_RAM_WRITE(gba_vram_w) AM_SHARE("gba_vram") // VRAM - AM_RANGE(0x07000000, 0x070003ff) AM_RAM_WRITE(gba_oam_w) AM_SHARE("gba_oam") // OAM + AM_RANGE(0x05000000, 0x050003ff) AM_DEVREADWRITE("lcd", gba_lcd_device, gba_pram_r, gba_pram_w) // Palette RAM + AM_RANGE(0x06000000, 0x06017fff) AM_DEVREADWRITE("lcd", gba_lcd_device, gba_vram_r, gba_vram_w) // VRAM + AM_RANGE(0x07000000, 0x070003ff) AM_DEVREADWRITE("lcd", gba_lcd_device, gba_oam_r, gba_oam_w) // OAM AM_RANGE(0x07000400, 0x07ffffff) AM_NOP // Not used //AM_RANGE(0x08000000, 0x0cffffff) // cart ROM + mirrors, mapped here at machine_start if a cart is present AM_RANGE(0x10000000, 0xffffffff) AM_READ(gba_10000000_r) // for "Justice League Chronicles" (game bug) @@ -1223,97 +1217,10 @@ static INPUT_PORTS_START( gbadv ) INPUT_PORTS_END -TIMER_CALLBACK_MEMBER(gba_state::perform_hbl) -{ - int ch, ctrl; - int scanline = machine().first_screen()->vpos(); - - // draw only visible scanlines - if (scanline < 160) - { - draw_scanline(scanline); - - for (ch = 0; ch < 4; ch++) - { - ctrl = DMACNT_H(ch); - - // HBL-triggered DMA? - if ((ctrl & 0x8000) && ((ctrl & 0x3000) == 0x2000)) - { - dma_exec(ch); - } - } - } - - if ((DISPSTAT & DISPSTAT_HBL_IRQ_EN ) != 0) - { - request_irq(INT_HBL); - } - - DISPSTAT_SET(DISPSTAT_HBL); - - m_hbl_timer->adjust(attotime::never); -} - -TIMER_CALLBACK_MEMBER(gba_state::perform_scan) -{ - int scanline; - - // clear hblank and raster IRQ flags - DISPSTAT_RESET(DISPSTAT_HBL|DISPSTAT_VCNT); - - scanline = machine().first_screen()->vpos(); - - // VBL is set for scanlines 160 through 226 (but not 227, which is the last line) - if (scanline >= 160 && scanline < 227) - { - DISPSTAT_SET(DISPSTAT_VBL); - - // VBL IRQ and DMA on line 160 - if (scanline == 160) - { - int ch, ctrl; - - if (DISPSTAT & DISPSTAT_VBL_IRQ_EN) - { - request_irq(INT_VBL); - } - - for (ch = 0; ch < 4; ch++) - { - ctrl = DMACNT_H(ch); - - // VBL-triggered DMA? - if ((ctrl & 0x8000) && ((ctrl & 0x3000) == 0x1000)) - { - dma_exec(ch); - } - } - } - } - else - { - DISPSTAT_RESET(DISPSTAT_VBL); - } - - // handle VCNT match interrupt/flag - if (scanline == ((DISPSTAT >> 8) & 0xff)) - { - DISPSTAT_SET(DISPSTAT_VCNT); - - if (DISPSTAT & DISPSTAT_VCNT_IRQ_EN) - { - request_irq(INT_VCNT); - } - } - - m_hbl_timer->adjust(machine().first_screen()->time_until_pos(scanline, 240)); - m_scan_timer->adjust(machine().first_screen()->time_until_pos(( scanline + 1 ) % 228, 0)); -} - void gba_state::machine_reset() { - memset(m_io_regs, 0, sizeof(m_io_regs)); + memset(m_regs, 0, sizeof(m_regs)); + SOUNDBIAS_SET(0x0200); SIOMULTI0_SET(0xffff); SIOMULTI1_SET(0xffff); @@ -1322,20 +1229,9 @@ void gba_state::machine_reset() KEYCNT_SET(0x03ff); RCNT_SET(0x8000); JOYSTAT_SET(0x0002); - m_gfxBG2Changed = 0; - m_gfxBG3Changed = 0; - m_gfxBG2X = 0; - m_gfxBG2Y = 0; - m_gfxBG3X = 0; - m_gfxBG3Y = 0; - - m_windowOn = 0; - m_fxOn = 0; m_bios_protected = 0; - m_scan_timer->adjust(machine().first_screen()->time_until_pos(0, 0)); - m_hbl_timer->adjust(attotime::never); m_dma_timer[0]->adjust(attotime::never); m_dma_timer[1]->adjust(attotime::never, 1); m_dma_timer[2]->adjust(attotime::never, 2); @@ -1353,11 +1249,6 @@ void gba_state::machine_reset() void gba_state::machine_start() { - /* create a timer to fire scanline functions */ - m_scan_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gba_state::perform_scan),this)); - m_hbl_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gba_state::perform_hbl),this)); - m_scan_timer->adjust(machine().first_screen()->time_until_pos(0, 0)); - /* and one for each DMA channel */ m_dma_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gba_state::dma_complete),this)); m_dma_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gba_state::dma_complete),this)); @@ -1444,15 +1335,7 @@ void gba_state::machine_start() } - save_pointer(NAME(m_io_regs), sizeof(m_io_regs)); - save_item(NAME(m_windowOn)); - save_item(NAME(m_fxOn)); - save_item(NAME(m_gfxBG2Changed)); - save_item(NAME(m_gfxBG3Changed)); - save_item(NAME(m_gfxBG2X)); - save_item(NAME(m_gfxBG2Y)); - save_item(NAME(m_gfxBG3X)); - save_item(NAME(m_gfxBG3Y)); + save_pointer(NAME(m_regs), sizeof(m_regs)); save_item(NAME(m_dma_src)); save_item(NAME(m_dma_dst)); save_item(NAME(m_dma_cnt)); @@ -1466,7 +1349,6 @@ void gba_state::machine_start() save_item(NAME(m_fifo_b_in)); save_item(NAME(m_fifo_a)); save_item(NAME(m_fifo_b)); - save_item(NAME(m_xferscan)); save_item(NAME(m_bios_last_address)); save_item(NAME(m_bios_protected)); } @@ -1496,14 +1378,7 @@ static MACHINE_CONFIG_START( gbadv, gba_state ) MCFG_CPU_ADD("maincpu", ARM7, XTAL_16_777216MHz) MCFG_CPU_PROGRAM_MAP(gba_map) - MCFG_SCREEN_ADD("screen", LCD) - MCFG_SCREEN_RAW_PARAMS(XTAL_16_777216MHz/4, 308, 0, 240, 228, 0, 160) - MCFG_SCREEN_UPDATE_DRIVER(gba_state, screen_update) - MCFG_SCREEN_PALETTE("palette") - - MCFG_DEFAULT_LAYOUT(layout_lcd) - MCFG_PALETTE_ADD("palette", 32768) - MCFG_PALETTE_INIT_OWNER(gba_state, gba) + MCFG_GBA_LCD_ADD("lcd") MCFG_SPEAKER_STANDARD_STEREO("spkleft", "spkright") MCFG_SOUND_ADD("custom", GAMEBOY, 0) diff --git a/src/mame/includes/gba.h b/src/mame/includes/gba.h index 6e78eeb3abc..1e2344e1018 100644 --- a/src/mame/includes/gba.h +++ b/src/mame/includes/gba.h @@ -7,168 +7,19 @@ #include "machine/intelfsh.h" #include "bus/gba/gba_slot.h" #include "sound/dac.h" +#include "video/gba_lcd.h" -#define WORD(x) (m_io_regs[(x) / 4]) /* 32-bit Register */ -#define HWHI(x) (m_io_regs[(x) / 4] >> 16) /* 16-bit Register, Upper Half-Word */ -#define HWLO(x) (m_io_regs[(x) / 4] & 0x0000ffff) /* 16-bit Register, Lower Half-Word */ +#define WORD(x) (m_regs[(x - REG_BASE) / 4]) /* 32-bit Register */ +#define HWHI(x) (m_regs[(x - REG_BASE) / 4] >> 16) /* 16-bit Register, Upper Half-Word */ +#define HWLO(x) (m_regs[(x - REG_BASE) / 4] & 0x0000ffff) /* 16-bit Register, Lower Half-Word */ -#define WORD_SET(x, y) (m_io_regs[(x) / 4] |= (y)) -#define HWHI_SET(x, y) ((m_io_regs[(x) / 4] |= (y << 16))) -#define HWLO_SET(x, y) (m_io_regs[(x) / 4] |= (y)) +#define WORD_SET(x, y) (m_regs[(x - REG_BASE) / 4] |= (y)) +#define HWHI_SET(x, y) ((m_regs[(x - REG_BASE) / 4] |= (y << 16))) +#define HWLO_SET(x, y) (m_regs[(x - REG_BASE) / 4] |= (y)) -#define WORD_RESET(x, y) (m_io_regs[(x) / 4] &= ~(y)) -#define HWHI_RESET(x, y) ((m_io_regs[(x) / 4] &= ~(y << 16))) -#define HWLO_RESET(x, y) (m_io_regs[(x) / 4] &= ~(y)) - -/* LCD I/O Registers */ -#define DISPCNT HWLO(0x000) /* 0x4000000 2 R/W LCD Control */ -#define GRNSWAP HWHI(0x000) /* 0x4000002 2 R/W Undocumented - Green Swap */ -#define DISPSTAT HWLO(0x004) /* 0x4000004 2 R/W General LCD Status (STAT,LYC) */ -#define VCOUNT HWHI(0x004) /* 0x4000006 2 R Vertical Counter (LY) */ -#define BG0CNT HWLO(0x008) /* 0x4000008 2 R/W BG0 Control */ -#define BG1CNT HWHI(0x008) /* 0x400000A 2 R/W BG1 Control */ -#define BG2CNT HWLO(0x00C) /* 0x400000C 2 R/W BG2 Control */ -#define BG3CNT HWHI(0x00C) /* 0x400000E 2 R/W BG3 Control */ -#define BG0HOFS HWLO(0x010) /* 0x4000010 2 W BG0 X-Offset */ -#define BG0VOFS HWHI(0x010) /* 0x4000012 2 W BG0 Y-Offset */ -#define BG1HOFS HWLO(0x014) /* 0x4000014 2 W BG1 X-Offset */ -#define BG1VOFS HWHI(0x014) /* 0x4000016 2 W BG1 Y-Offset */ -#define BG2HOFS HWLO(0x018) /* 0x4000018 2 W BG2 X-Offset */ -#define BG2VOFS HWHI(0x018) /* 0x400001A 2 W BG2 Y-Offset */ -#define BG3HOFS HWLO(0x01C) /* 0x400001C 2 W BG3 X-Offset */ -#define BG3VOFS HWHI(0x01C) /* 0x400001E 2 W BG3 Y-Offset */ -#define BG2PA HWLO(0x020) /* 0x4000020 2 W BG2 Rotation/Scaling Parameter A (dx) */ -#define BG2PB HWHI(0x020) /* 0x4000022 2 W BG2 Rotation/Scaling Parameter B (dmx) */ -#define BG2PC HWLO(0x024) /* 0x4000024 2 W BG2 Rotation/Scaling Parameter C (dy) */ -#define BG2PD HWHI(0x024) /* 0x4000026 2 W BG2 Rotation/Scaling Parameter D (dmy) */ -#define BG2X WORD(0x028) /* 0x4000028 4 W BG2 Reference Point X-Coordinate */ -#define BG2Y WORD(0x02C) /* 0x400002C 4 W BG2 Reference Point Y-Coordinate */ -#define BG3PA HWLO(0x030) /* 0x4000030 2 W BG3 Rotation/Scaling Parameter A (dx) */ -#define BG3PB HWHI(0x030) /* 0x4000032 2 W BG3 Rotation/Scaling Parameter B (dmx) */ -#define BG3PC HWLO(0x034) /* 0x4000034 2 W BG3 Rotation/Scaling Parameter C (dy) */ -#define BG3PD HWHI(0x034) /* 0x4000036 2 W BG3 Rotation/Scaling Parameter D (dmy) */ -#define BG3X WORD(0x038) /* 0x4000038 4 W BG3 Reference Point X-Coordinate */ -#define BG3Y WORD(0x03C) /* 0x400003C 4 W BG3 Reference Point Y-Coordinate */ -#define WIN0H HWLO(0x040) /* 0x4000040 2 W Window 0 Horizontal Dimensions */ -#define WIN1H HWHI(0x040) /* 0x4000042 2 W Window 1 Horizontal Dimensions */ -#define WIN0V HWLO(0x044) /* 0x4000044 2 W Window 0 Vertical Dimensions */ -#define WIN1V HWHI(0x044) /* 0x4000046 2 W Window 1 Vertical Dimensions */ -#define WININ HWLO(0x048) /* 0x4000048 2 R/W Inside of Window 0 and 1 */ -#define WINOUT HWHI(0x048) /* 0x400004A 2 R/W Inside of OBJ Window & Outside of Windows */ -#define MOSAIC HWLO(0x04C) /* 0x400004C 2 W Mosaic Size */ - /* 0x400004E 2 - Unused */ -#define BLDCNT HWLO(0x050) /* 0x4000050 2 R/W Color Special Effects Selection */ -#define BLDALPHA HWHI(0x050) /* 0x4000052 2 W Alpha Blending Coefficients */ -#define BLDY HWLO(0x054) /* 0x4000054 2 W Brightness (Fade-In/Out) Coefficient */ - /* 0x4000056 2 - Unused */ - -/* Sound Registers */ -#define SOUNDCNT_L HWLO(0x080) /* 0x4000080 2 R/W Control Stereo/Volume/Enable */ -#define SOUNDCNT_H HWHI(0x080) /* 0x4000082 2 R/W Control Mixing/DMA Control */ -#define SOUNDCNT_X HWLO(0x084) /* 0x4000084 2 R/W Control Sound on/off */ - /* 0x4000086 2 - Unused */ -#define SOUNDBIAS HWLO(0x088) /* 0x4000088 2 BIOS Sound PWM Control */ - /* 0x400008A 2 - Unused */ - -/* DMA Transfer Channels Registers */ -#define DMA0SAD WORD(0x0B0) /* 0x40000B0 4 W DMA 0 Source Address */ -#define DMA0DAD WORD(0x0B4) /* 0x40000B4 4 W DMA 0 Destination Address */ -#define DMA0CNT_L HWLO(0x0B8) /* 0x40000B8 2 W DMA 0 Word Count */ -#define DMA0CNT_H HWHI(0x0B8) /* 0x40000BA 2 R/W DMA 0 Control */ -#define DMA1SAD WORD(0x0BC) /* 0x40000BC 4 W DMA 1 Source Address */ -#define DMA1DAD WORD(0x0C0) /* 0x40000C0 4 W DMA 1 Destination Address */ -#define DMA1CNT_L HWLO(0x0C4) /* 0x40000C4 2 W DMA 1 Word Count */ -#define DMA1CNT_H HWHI(0x0C4) /* 0x40000C6 2 R/W DMA 1 Control */ -#define DMA2SAD WORD(0x0C8) /* 0x40000C8 4 W DMA 2 Source Address */ -#define DMA2DAD WORD(0x0CC) /* 0x40000CC 4 W DMA 2 Destination Address */ -#define DMA2CNT_L HWLO(0x0D0) /* 0x40000D0 2 W DMA 2 Word Count */ -#define DMA2CNT_H HWHI(0x0D0) /* 0x40000D2 2 R/W DMA 2 Control */ -#define DMA3SAD WORD(0x0D4) /* 0x40000D4 4 W DMA 3 Source Address */ -#define DMA3DAD WORD(0x0D8) /* 0x40000D8 4 W DMA 3 Destination Address */ -#define DMA3CNT_L HWLO(0x0DC) /* 0x40000DC 2 W DMA 3 Word Count */ -#define DMA3CNT_H HWHI(0x0DC) /* 0x40000DE 2 R/W DMA 3 Control */ - -#define DMASAD(c) WORD(0x0B0 + (c * 0xC)) -#define DMADAD(c) WORD(0x0B4 + (c * 0xC)) -#define DMACNT_L(c) HWLO(0x0B8 + (c * 0xC)) -#define DMACNT_H(c) HWHI(0x0B8 + (c * 0xC)) - -/* Serial Communication (1) Registers */ -#define SIODATA32 WORD(0x120) /* 0x4000120 4 R/W SIO Data (Normal-32bit Mode; shared with below) */ -#define SIOMULTI0 HWLO(0x120) /* 0x4000120 2 R/W SIO Data 0 (Parent) (Multi-Player Mode) */ -#define SIOMULTI1 HWHI(0x120) /* 0x4000122 2 R/W SIO Data 1 (1st Child) (Multi-Player Mode) */ -#define SIOMULTI2 HWLO(0x124) /* 0x4000124 2 R/W SIO Data 2 (2nd Child) (Multi-Player Mode) */ -#define SIOMULTI3 HWHI(0x124) /* 0x4000126 2 R/W SIO Data 3 (3rd Child) (Multi-Player Mode) */ -#define SIOCNT HWLO(0x128) /* 0x4000128 2 R/W SIO Control Register */ -#define SIOMLT_SEND HWHI(0x128) /* 0x400012A 2 R/W SIO Data (Local of MultiPlayer; shared below) */ -#define SIODATA8 HWHI(0x128) /* 0x400012A 2 R/W SIO Data (Normal-8bit and UART Mode) */ - /* 0x400012C 2 - Unused */ - -/* Keypad Input Registers */ -#define KEYINPUT HWLO(0x130) /* 0x4000130 2 R Key Status */ -#define KEYCNT HWHI(0x130) /* 0x4000132 2 R/W Key Interrupt Control */ - -/* Serial Communication (2) Registers */ -#define RCNT HWLO(0x134) /* 0x4000134 2 R/W SIO Mode Select/General Purpose Data */ -#define IR HWHI(0x134) /* 0x4000136 2 R/W Ancient - Infrared Register (Prototypes only) */ - /* 0x4000138 8 - Unused */ -#define JOYCNT HWLO(0x140) /* 0x4000140 2 R/W SIO JOY Bus Control */ - /* 0x4000142 2 - Unused */ -#define JOY_RECV WORD(0x150) /* 0x4000150 4 R/W SIO JOY Bus Receive Data */ -#define JOY_TRANS WORD(0x154) /* 0x4000154 4 R/W SIO JOY Bus Transmit Data */ -#define JOYSTAT HWLO(0x158) /* 0x4000158 2 R/? SIO JOY Bus Receive Status */ - /* 0x400015A 2 - Unused */ - -/* Interrupt, Waitstate, and Power-Down Control Registers */ -#define IE HWLO(0x200) /* 0x4000200 2 R/W Interrupt Enable Register */ -#define IF HWHI(0x200) /* 0x4000202 2 R/W Interrupt Request Flags / IRQ Acknowledge */ -#define WAITCNT HWLO(0x204) /* 0x4000204 2 R/W Game Pak Waitstate Control */ - /* 0x4000206 - Unused */ -#define IME HWLO(0x208) /* 0x4000208 2 R/W Interrupt Master Enable Register */ - /* 0x400020A - Unused */ - /* 0x4000300 1 R/W Undocumented - Post Boot Flag */ - /* 0x4000301 1 W Undocumented - Power Down Control */ - /* 0x4000302 - Unused */ - /* 0x4000410 ? ? Undocumented - Purpose Unknown / Bug ??? 0FFh */ - /* 0x4000411 - Unused */ - /* 0x4000800 4 R/W Undocumented - Internal Memory Control (R/W) */ - /* 0x4000804 - Unused */ - /* 0x4xx0800 4 R/W Mirrors of 4000800h (repeated each 64K) */ - -#define DISPSTAT_SET(val) HWLO_SET(0x004, val) -#define DISPSTAT_RESET(val) HWLO_RESET(0x004, val) - -#define SOUNDBIAS_SET(val) HWLO_SET(0x088, val) - -#define DMASAD_SET(c, val) WORD_SET(0x0B0 + (c * 0xC), val) -#define DMADAD_SET(c, val) WORD_SET(0x0B4 + (c * 0xC), val) -#define DMACNT_L_SET(c, val) HWLO_SET(0x0B8 + (c * 0xC), val) -#define DMACNT_H_SET(c, val) HWHI_SET(0x0B8 + (c * 0xC), val) -#define DMACNT_H_RESET(c, val) HWHI_RESET(0x0B8 + (c * 0xC), val) - -#define SIOMULTI0_SET(val) HWLO_SET(0x120, val) -#define SIOMULTI1_SET(val) HWHI_SET(0x120, val) -#define SIOMULTI2_SET(val) HWLO_SET(0x124, val) -#define SIOMULTI3_SET(val) HWHI_SET(0x124, val) - -#define SIOCNT_RESET(val) HWLO_RESET(0x128, val) - -#define KEYCNT_SET(val) HWHI_SET(0x130, val) - -#define RCNT_SET(val) HWLO_SET(0x134, val) - -#define JOYSTAT_SET(val) HWLO_SET(0x158, val) - -#define IF_SET(val) HWHI_SET(0x200, val) -#define IF_RESET(val) HWHI_RESET(0x200, val) - -#define DISPSTAT_VBL 0x0001 -#define DISPSTAT_HBL 0x0002 -#define DISPSTAT_VCNT 0x0004 -#define DISPSTAT_VBL_IRQ_EN 0x0008 -#define DISPSTAT_HBL_IRQ_EN 0x0010 -#define DISPSTAT_VCNT_IRQ_EN 0x0020 -#define DISPSTAT_VCNT_VALUE 0xff00 +#define WORD_RESET(x, y) (m_regs[(x - REG_BASE) / 4] &= ~(y)) +#define HWHI_RESET(x, y) ((m_regs[(x - REG_BASE) / 4] &= ~(y << 16))) +#define HWLO_RESET(x, y) (m_regs[(x - REG_BASE) / 4] &= ~(y)) #define INT_VBL 0x0001 #define INT_HBL 0x0002 @@ -185,100 +36,6 @@ #define INT_KEYPAD 0x1000 #define INT_GAMEPAK 0x2000 -#define DISPCNT_MODE 0x0007 -#define DISPCNT_FRAMESEL 0x0010 -#define DISPCNT_HBL_FREE 0x0020 - -#define DISPCNT_VRAM_MAP 0x0040 -#define DISPCNT_VRAM_MAP_2D 0x0000 -#define DISPCNT_VRAM_MAP_1D 0x0040 - -#define DISPCNT_BLANK 0x0080 -#define DISPCNT_BG0_EN 0x0100 -#define DISPCNT_BG1_EN 0x0200 -#define DISPCNT_BG2_EN 0x0400 -#define DISPCNT_BG3_EN 0x0800 -#define DISPCNT_OBJ_EN 0x1000 -#define DISPCNT_WIN0_EN 0x2000 -#define DISPCNT_WIN1_EN 0x4000 -#define DISPCNT_OBJWIN_EN 0x8000 - -#define OBJ_Y_COORD 0x00ff -#define OBJ_ROZMODE 0x0300 -#define OBJ_ROZMODE_NONE 0x0000 -#define OBJ_ROZMODE_ROZ 0x0100 -#define OBJ_ROZMODE_DISABLE 0x0200 -#define OBJ_ROZMODE_DBLROZ 0x0300 - -#define OBJ_MODE 0x0c00 -#define OBJ_MODE_NORMAL 0x0000 -#define OBJ_MODE_ALPHA 0x0400 -#define OBJ_MODE_WINDOW 0x0800 -#define OBJ_MODE_UNDEFINED 0x0c00 - -#define OBJ_MOSAIC 0x1000 - -#define OBJ_PALMODE 0x2000 -#define OBJ_PALMODE_16 0x0000 -#define OBJ_PALMODE_256 0x2000 - -#define OBJ_SHAPE 0xc000 -#define OBJ_SHAPE_SQR 0x0000 -#define OBJ_SHAPE_HORIZ 0x4000 -#define OBJ_SHAPE_VERT 0x8000 - -#define OBJ_X_COORD 0x01ff -#define OBJ_SCALE_PARAM 0x3e00 -#define OBJ_SCALE_PARAM_SHIFT 9 -#define OBJ_HFLIP 0x1000 -#define OBJ_VFLIP 0x2000 -#define OBJ_SIZE 0xc000 -#define OBJ_SIZE_8 0x0000 -#define OBJ_SIZE_16 0x4000 -#define OBJ_SIZE_32 0x8000 -#define OBJ_SIZE_64 0xc000 - -#define OBJ_TILENUM 0x03ff -#define OBJ_PRIORITY 0x0c00 -#define OBJ_PRIORITY_SHIFT 10 -#define OBJ_PALNUM 0xf000 -#define OBJ_PALNUM_SHIFT 12 - -#define BGCNT_SCREENSIZE 0xc000 -#define BGCNT_SCREENSIZE_SHIFT 14 -#define BGCNT_PALETTESET_WRAP 0x2000 -#define BGCNT_SCREENBASE 0x1f00 -#define BGCNT_SCREENBASE_SHIFT 8 -#define BGCNT_PALETTE256 0x0080 -#define BGCNT_MOSAIC 0x0040 -#define BGCNT_CHARBASE 0x003c -#define BGCNT_CHARBASE_SHIFT 2 -#define BGCNT_PRIORITY 0x0003 - -#define BLDCNT_BG0TP1 0x0001 -#define BLDCNT_BG1TP1 0x0002 -#define BLDCNT_BG2TP1 0x0004 -#define BLDCNT_BG3TP1 0x0008 -#define BLDCNT_OBJTP1 0x0010 -#define BLDCNT_BDTP1 0x0020 -#define BLDCNT_SFX 0x00c0 -#define BLDCNT_SFX_NONE 0x0000 -#define BLDCNT_SFX_ALPHA 0x0040 -#define BLDCNT_SFX_LIGHTEN 0x0080 -#define BLDCNT_SFX_DARKEN 0x00c0 -#define BLDCNT_BG0TP2 0x0100 -#define BLDCNT_BG1TP2 0x0200 -#define BLDCNT_BG2TP2 0x0400 -#define BLDCNT_BG3TP2 0x0800 -#define BLDCNT_OBJTP2 0x1000 -#define BLDCNT_BDTP2 0x2000 -#define BLDCNT_TP2_SHIFT 8 - -#define TILEOBJ_TILE 0x03ff -#define TILEOBJ_HFLIP 0x0400 -#define TILEOBJ_VFLIP 0x0800 -#define TILEOBJ_PALETTE 0xf000 - /* driver state */ class gba_state : public driver_device { @@ -286,9 +43,6 @@ public: gba_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), - m_gba_pram(*this, "gba_pram"), - m_gba_vram(*this, "gba_vram"), - m_gba_oam(*this, "gba_oam"), m_ladac(*this, "direct_a_left"), m_radac(*this, "direct_a_right"), m_lbdac(*this, "direct_b_left"), @@ -301,9 +55,6 @@ public: { } required_device m_maincpu; - required_shared_ptr m_gba_pram; - required_shared_ptr m_gba_vram; - required_shared_ptr m_gba_oam; required_device m_ladac; required_device m_radac; required_device m_lbdac; @@ -312,24 +63,19 @@ public: required_device m_cart; void request_irq(UINT32 int_type); + + enum dma_start_timing { + immediately = 0, + vblank, + hblank, + special + }; + + void request_dma(dma_start_timing start); void dma_exec(int ch); void audio_tick(int ref); - // video-related - virtual void video_start() override; - UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - bitmap_ind16 m_bitmap; - - UINT32 m_io_regs[0x400 / 4]; - - UINT8 m_windowOn; - UINT8 m_fxOn; - UINT8 m_gfxBG2Changed; - UINT8 m_gfxBG3Changed; - INT32 m_gfxBG2X; - INT32 m_gfxBG2Y; - INT32 m_gfxBG3X; - INT32 m_gfxBG3Y; + UINT32 m_regs[(0x400 - 0x60) / 4]; // DMA emu_timer *m_dma_timer[4]; @@ -343,7 +89,6 @@ public: int m_timer_recalc[4]; emu_timer *m_tmr_timer[4], *m_irq_timer; - emu_timer *m_scan_timer, *m_hbl_timer; double m_timer_hz[4]; @@ -353,7 +98,6 @@ public: int m_fifo_b_in; UINT8 m_fifo_a[20]; UINT8 m_fifo_b[20]; - UINT32 m_xferscan[7][240+2048]; UINT32 m_bios_last_address; int m_bios_protected; @@ -361,34 +105,14 @@ public: DIRECT_UPDATE_MEMBER(gba_direct); DECLARE_READ32_MEMBER(gba_io_r); DECLARE_WRITE32_MEMBER(gba_io_w); - DECLARE_WRITE32_MEMBER(gba_pram_w); - DECLARE_WRITE32_MEMBER(gba_vram_w); - DECLARE_WRITE32_MEMBER(gba_oam_w); DECLARE_READ32_MEMBER(gba_bios_r); DECLARE_READ32_MEMBER(gba_10000000_r); DECLARE_DRIVER_INIT(gbadv); virtual void machine_start() override; virtual void machine_reset() override; - DECLARE_PALETTE_INIT(gba); TIMER_CALLBACK_MEMBER(dma_complete); TIMER_CALLBACK_MEMBER(timer_expire); TIMER_CALLBACK_MEMBER(handle_irq); - TIMER_CALLBACK_MEMBER(perform_hbl); - TIMER_CALLBACK_MEMBER(perform_scan); - - // video related - void draw_scanline(int y); - - void draw_roz_bitmap_scanline(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); - void draw_roz_scanline(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); - void draw_bg_scanline(UINT32 *scanline, int ypos, UINT32 enablemask, UINT32 ctrl, UINT32 hofs, UINT32 vofs); - void draw_gba_oam_window(UINT32 *scanline, int y); - void draw_gba_oam(UINT32 *scanline, int y); - - inline int is_in_window(int x, int window); - - inline void update_mask(UINT8* mask, int mode, int submode, UINT32* obj_win, UINT8 inwin0, UINT8 inwin1, UINT8 in0_mask, UINT8 in1_mask, UINT8 out_mask); - void draw_modes(int mode, int submode, int y, UINT32* line0, UINT32* line1, UINT32* line2, UINT32* line3, UINT32* lineOBJ, UINT32* lineOBJWin, UINT32* lineMix, int bpp); protected: required_region_ptr m_region_maincpu;