mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +03:00
gba: make video subsystem into a device
Additional info taken from http://problemkaputt.de/gbatek.htm by Martin Korth
This commit is contained in:
parent
01f273d283
commit
318952746f
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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<gba_state>()->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::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<gba_state>()->request_dma(gba_state::dma_start_timing::hblank);
|
||||
}
|
||||
|
||||
if ((DISPSTAT & DISPSTAT_HBL_IRQ_EN ) != 0)
|
||||
{
|
||||
machine().driver_data<gba_state>()->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<gba_state>()->request_irq(INT_VBL);
|
||||
}
|
||||
|
||||
machine().driver_data<gba_state>()->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<gba_state>()->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<UINT32[]>(0x400 / 4);
|
||||
m_vram = make_unique_clear<UINT32[]>(0x18000 / 4);
|
||||
m_oam = make_unique_clear<UINT32[]>(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 );
|
||||
}
|
100
src/devices/video/gba_lcd.h
Normal file
100
src/devices/video/gba_lcd.h
Normal file
@ -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<UINT32[]> m_pram;
|
||||
std::unique_ptr<UINT32[]> m_vram;
|
||||
std::unique_ptr<UINT32[]> 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_ */
|
@ -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)
|
||||
|
@ -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<cpu_device> m_maincpu;
|
||||
required_shared_ptr<UINT32> m_gba_pram;
|
||||
required_shared_ptr<UINT32> m_gba_vram;
|
||||
required_shared_ptr<UINT32> m_gba_oam;
|
||||
required_device<dac_device> m_ladac;
|
||||
required_device<dac_device> m_radac;
|
||||
required_device<dac_device> m_lbdac;
|
||||
@ -312,24 +63,19 @@ public:
|
||||
required_device<gba_cart_slot_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<UINT32> m_region_maincpu;
|
||||
|
Loading…
Reference in New Issue
Block a user