mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
(MESS) gameboy/gbcolor: simplified video code by reducing the number of memory pointers used,
and added support for save state registration. [Fabio Priuli] I haven't added the support_save flag yet because I'd like to receive some feedback from users (I have only tested 2 dozen of games, without issues, but there are thousands...)
This commit is contained in:
parent
342b2024f2
commit
78b2889737
@ -736,6 +736,7 @@ static MACHINE_CONFIG_DERIVED( gbpocket, gameboy )
|
||||
MCFG_LR35902_HALT_BUG
|
||||
MCFG_LR35902_RESET_VALUES(mgb_cpu_regs)
|
||||
|
||||
MCFG_MACHINE_START_OVERRIDE(gb_state, gbpocket)
|
||||
MCFG_MACHINE_RESET_OVERRIDE(gb_state, gbpocket)
|
||||
MCFG_PALETTE_INIT_OVERRIDE(gb_state,gbp)
|
||||
MACHINE_CONFIG_END
|
||||
|
@ -92,16 +92,16 @@ struct gb_lcd_t {
|
||||
emu_timer *lcd_timer;
|
||||
int gbc_mode;
|
||||
|
||||
memory_region *gb_vram; /* Pointer to VRAM */
|
||||
memory_region *gb_oam; /* Pointer to OAM memory */
|
||||
UINT8 *gb_vram_ptr;
|
||||
UINT8 *gb_chrgen; /* Character generator */
|
||||
UINT8 *gb_bgdtab; /* Background character table */
|
||||
UINT8 *gb_wndtab; /* Window character table */
|
||||
UINT8 *gb_vram; // Pointer to VRAM
|
||||
UINT8 *gb_oam; // Pointer to OAM memory
|
||||
UINT8 gb_tile_no_mod;
|
||||
UINT8 *gbc_chrgen; /* CGB Character generator */
|
||||
UINT8 *gbc_bgdtab; /* CGB Background character table */
|
||||
UINT8 *gbc_wndtab; /* CGB Window character table */
|
||||
UINT32 gb_chrgen_offs; // GB Character generator
|
||||
UINT32 gb_bgdtab_offs; // GB Background character table
|
||||
UINT32 gb_wndtab_offs; // GB Window character table
|
||||
UINT32 gbc_chrgen_offs; // CGB Character generator
|
||||
UINT32 gbc_bgdtab_offs; // CGB Background character table
|
||||
UINT32 gbc_wndtab_offs; // CGB Window character table
|
||||
int gb_vram_bank;
|
||||
};
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ public:
|
||||
UINT8 m_reloading;
|
||||
|
||||
/* Serial I/O related */
|
||||
UINT32 m_SIOCount; /* Serial I/O counter */
|
||||
UINT32 m_sio_count; /* Serial I/O counter */
|
||||
emu_timer *m_gb_serial_timer;
|
||||
|
||||
/* SGB variables */
|
||||
@ -154,13 +154,13 @@ public:
|
||||
UINT32 m_sgb_atf;
|
||||
|
||||
/* CGB variables */
|
||||
UINT8 *m_GBC_RAMMap[8]; /* (CGB) Addresses of internal RAM banks */
|
||||
UINT8 m_GBC_RAMBank; /* (CGB) Current CGB RAM bank */
|
||||
UINT8 *m_gbc_rammap[8]; /* (CGB) Addresses of internal RAM banks */
|
||||
UINT8 m_gbc_rambank; /* (CGB) Current CGB RAM bank */
|
||||
|
||||
|
||||
gb_lcd_t m_lcd;
|
||||
void (gb_state::*update_scanline) ();
|
||||
bool m_bios_disable;
|
||||
int m_bios_disable;
|
||||
|
||||
bitmap_ind16 m_bitmap;
|
||||
DECLARE_WRITE8_MEMBER(gb_io_w);
|
||||
@ -185,13 +185,12 @@ public:
|
||||
DECLARE_MACHINE_START(sgb);
|
||||
DECLARE_MACHINE_RESET(sgb);
|
||||
DECLARE_PALETTE_INIT(sgb);
|
||||
DECLARE_MACHINE_START(gbpocket);
|
||||
DECLARE_MACHINE_RESET(gbpocket);
|
||||
DECLARE_PALETTE_INIT(gbp);
|
||||
DECLARE_MACHINE_START(gbc);
|
||||
DECLARE_MACHINE_RESET(gbc);
|
||||
DECLARE_PALETTE_INIT(gbc);
|
||||
DECLARE_MACHINE_START(gb_video);
|
||||
DECLARE_MACHINE_START(gbc_video);
|
||||
INTERRUPT_GEN_MEMBER(gb_scanline_interrupt);
|
||||
TIMER_CALLBACK_MEMBER(gb_serial_timer_proc);
|
||||
TIMER_CALLBACK_MEMBER(gb_video_init_vbl);
|
||||
@ -228,11 +227,19 @@ protected:
|
||||
void sgb_update_scanline();
|
||||
void cgb_update_sprites();
|
||||
void cgb_update_scanline();
|
||||
void gb_video_reset( int mode );
|
||||
void gb_video_reset(int mode);
|
||||
void gb_video_start(int mode);
|
||||
void gbc_hdma(UINT16 length);
|
||||
void gb_increment_scanline();
|
||||
void gb_lcd_switch_on();
|
||||
inline void gb_plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);
|
||||
|
||||
void save_gb_base();
|
||||
void save_gb_video();
|
||||
void save_gbc_only();
|
||||
void save_sgb_only();
|
||||
void gb_videoptr_restore();
|
||||
void gbc_videoptr_restore();
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,28 +87,6 @@ TODO:
|
||||
#include "audio/gb.h"
|
||||
#include "includes/gb.h"
|
||||
|
||||
/* Memory bank controller types */
|
||||
enum {
|
||||
MBC_NONE=0, /* 32KB ROM - No memory bank controller */
|
||||
MBC_MBC1, /* ~2MB ROM, 8KB RAM -or- 512KB ROM, 32KB RAM */
|
||||
MBC_MBC2, /* 256KB ROM, 32KB RAM */
|
||||
MBC_MMM01, /* ?? ROM, ?? RAM */
|
||||
MBC_MBC3, /* 2MB ROM, 32KB RAM, RTC */
|
||||
MBC_MBC4, /* ?? ROM, ?? RAM */
|
||||
MBC_MBC5, /* 8MB ROM, 128KB RAM (32KB w/ Rumble) */
|
||||
MBC_TAMA5, /* ?? ROM ?? RAM - What is this? */
|
||||
MBC_HUC1, /* ?? ROM, ?? RAM - Hudson Soft Controller */
|
||||
MBC_HUC3, /* ?? ROM, ?? RAM - Hudson Soft Controller */
|
||||
MBC_MBC6, /* ?? ROM, 32KB SRAM */
|
||||
MBC_MBC7, /* ?? ROM, ?? RAM */
|
||||
MBC_WISDOM, /* ?? ROM, ?? RAM - Wisdom tree controller */
|
||||
MBC_MBC1_KOR, /* 1MB ROM, ?? RAM - Korean MBC1 variant */
|
||||
MBC_YONGYONG, /* ?? ROM, ?? RAM - Appears in Sonic 3D Blast 5 pirate */
|
||||
MBC_LASAMA, /* ?? ROM, ?? RAM - Appears in La Sa Ma */
|
||||
MBC_ATVRACIN,
|
||||
MBC_MEGADUCK, /* MEGADUCK style banking */
|
||||
MBC_UNKNOWN, /* Unknown mapper */
|
||||
};
|
||||
|
||||
/* RAM layout defines */
|
||||
#define CGB_START_VRAM_BANKS 0x0000
|
||||
@ -134,6 +112,51 @@ enum {
|
||||
/* #define V_BANK*/ /* Display bank switching debug information */
|
||||
#endif
|
||||
|
||||
//-------------------------
|
||||
// handle save state
|
||||
//-------------------------
|
||||
|
||||
void gb_state::save_gb_base()
|
||||
{
|
||||
save_item(NAME(m_gb_io));
|
||||
save_item(NAME(m_divcount));
|
||||
save_item(NAME(m_shift));
|
||||
save_item(NAME(m_shift_cycles));
|
||||
save_item(NAME(m_triggering_irq));
|
||||
save_item(NAME(m_reloading));
|
||||
save_item(NAME(m_sio_count));
|
||||
save_item(NAME(m_bios_disable));
|
||||
}
|
||||
|
||||
void gb_state::save_gbc_only()
|
||||
{
|
||||
save_item(NAME(m_gbc_rambank));
|
||||
}
|
||||
|
||||
void gb_state::save_sgb_only()
|
||||
{
|
||||
save_item(NAME(m_sgb_pal_data));
|
||||
save_item(NAME(m_sgb_pal));
|
||||
save_item(NAME(m_sgb_tile_map));
|
||||
save_item(NAME(m_sgb_window_mask));
|
||||
save_item(NAME(m_sgb_pal_data));
|
||||
save_item(NAME(m_sgb_atf_data));
|
||||
save_item(NAME(m_sgb_packets));
|
||||
save_item(NAME(m_sgb_bitcount));
|
||||
save_item(NAME(m_sgb_bytecount));
|
||||
save_item(NAME(m_sgb_start));
|
||||
save_item(NAME(m_sgb_rest));
|
||||
save_item(NAME(m_sgb_controller_no));
|
||||
save_item(NAME(m_sgb_controller_mode));
|
||||
save_item(NAME(m_sgb_data));
|
||||
save_item(NAME(m_sgb_atf));
|
||||
|
||||
save_pointer(NAME(m_sgb_tile_data), 0x2000);
|
||||
for (int i = 0; i < 20; i++)
|
||||
save_item(NAME(m_sgb_pal_map[i]));
|
||||
}
|
||||
|
||||
|
||||
void gb_state::gb_init_regs()
|
||||
{
|
||||
/* Initialize the registers */
|
||||
@ -163,7 +186,18 @@ MACHINE_START_MEMBER(gb_state,gb)
|
||||
m_gb_serial_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_serial_timer_proc),this));
|
||||
m_gb_serial_timer->enable( 0 );
|
||||
|
||||
MACHINE_START_CALL_MEMBER( gb_video );
|
||||
save_gb_base();
|
||||
gb_video_start(GB_VIDEO_DMG);
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(gb_state,gbpocket)
|
||||
{
|
||||
/* Allocate the serial timer, and disable it */
|
||||
m_gb_serial_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_serial_timer_proc),this));
|
||||
m_gb_serial_timer->enable( 0 );
|
||||
|
||||
save_gb_base();
|
||||
gb_video_start(GB_VIDEO_MGB);
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(gb_state,gbc)
|
||||
@ -172,52 +206,38 @@ MACHINE_START_MEMBER(gb_state,gbc)
|
||||
m_gb_serial_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_serial_timer_proc),this));
|
||||
m_gb_serial_timer->enable( 0 );
|
||||
|
||||
MACHINE_START_CALL_MEMBER( gbc_video );
|
||||
}
|
||||
for (int i = 0; i < 8; i++)
|
||||
m_gbc_rammap[i] = m_ram->pointer() + CGB_START_RAM_BANKS + i * 0x1000;
|
||||
|
||||
MACHINE_RESET_MEMBER(gb_state,gb)
|
||||
{
|
||||
gb_init();
|
||||
|
||||
gb_video_reset(GB_VIDEO_DMG);
|
||||
|
||||
/* Enable BIOS rom */
|
||||
m_bios_disable = FALSE;
|
||||
|
||||
m_divcount = 0x0004;
|
||||
save_gb_base();
|
||||
save_gbc_only();
|
||||
gb_video_start(GB_VIDEO_CGB);
|
||||
}
|
||||
|
||||
|
||||
MACHINE_START_MEMBER(gb_state,sgb)
|
||||
{
|
||||
m_sgb_packets = -1;
|
||||
m_sgb_tile_data = auto_alloc_array_clear(machine(), UINT8, 0x2000 );
|
||||
m_sgb_tile_data = auto_alloc_array_clear(machine(), UINT8, 0x2000);
|
||||
|
||||
/* Allocate the serial timer, and disable it */
|
||||
m_gb_serial_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_serial_timer_proc),this));
|
||||
m_gb_serial_timer->enable( 0 );
|
||||
|
||||
MACHINE_START_CALL_MEMBER( gb_video );
|
||||
save_gb_base();
|
||||
save_sgb_only();
|
||||
gb_video_start(GB_VIDEO_SGB);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER(gb_state,sgb)
|
||||
MACHINE_RESET_MEMBER(gb_state,gb)
|
||||
{
|
||||
gb_init();
|
||||
|
||||
gb_video_reset(GB_VIDEO_SGB);
|
||||
|
||||
gb_init_regs();
|
||||
|
||||
|
||||
|
||||
gb_video_reset(GB_VIDEO_DMG);
|
||||
|
||||
/* Enable BIOS rom */
|
||||
m_bios_disable = FALSE;
|
||||
|
||||
memset(m_sgb_tile_data, 0, 0x2000);
|
||||
|
||||
m_sgb_window_mask = 0;
|
||||
memset(m_sgb_pal_map, 0, sizeof(m_sgb_pal_map));
|
||||
memset(m_sgb_atf_data, 0, sizeof(m_sgb_atf_data));
|
||||
|
||||
m_bios_disable = 0;
|
||||
|
||||
m_divcount = 0x0004;
|
||||
}
|
||||
|
||||
@ -229,7 +249,7 @@ MACHINE_RESET_MEMBER(gb_state,gbpocket)
|
||||
|
||||
gb_init_regs();
|
||||
|
||||
m_bios_disable = TRUE;
|
||||
m_bios_disable = 0;
|
||||
|
||||
/* Initialize the Sound registers */
|
||||
gb_sound_w(m_custom, generic_space(), 0x16,0x80);
|
||||
@ -241,8 +261,6 @@ MACHINE_RESET_MEMBER(gb_state,gbpocket)
|
||||
|
||||
MACHINE_RESET_MEMBER(gb_state,gbc)
|
||||
{
|
||||
int ii;
|
||||
|
||||
gb_init();
|
||||
|
||||
gb_video_reset( GB_VIDEO_CGB );
|
||||
@ -250,16 +268,34 @@ MACHINE_RESET_MEMBER(gb_state,gbc)
|
||||
gb_init_regs();
|
||||
|
||||
/* Enable BIOS rom */
|
||||
m_bios_disable = FALSE;
|
||||
m_bios_disable = 0;
|
||||
|
||||
/* Allocate memory for internal ram */
|
||||
for (ii = 0; ii < 8; ii++)
|
||||
{
|
||||
m_GBC_RAMMap[ii] = m_ram->pointer() + CGB_START_RAM_BANKS + ii * 0x1000;
|
||||
memset(m_GBC_RAMMap[ii], 0, 0x1000);
|
||||
}
|
||||
for (int i = 0; i < 8; i++)
|
||||
memset(m_gbc_rammap[i], 0, 0x1000);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER(gb_state,sgb)
|
||||
{
|
||||
gb_init();
|
||||
|
||||
gb_video_reset(GB_VIDEO_SGB);
|
||||
|
||||
gb_init_regs();
|
||||
|
||||
|
||||
/* Enable BIOS rom */
|
||||
m_bios_disable = 0;
|
||||
|
||||
memset(m_sgb_tile_data, 0, 0x2000);
|
||||
|
||||
m_sgb_window_mask = 0;
|
||||
memset(m_sgb_pal_map, 0, sizeof(m_sgb_pal_map));
|
||||
memset(m_sgb_atf_data, 0, sizeof(m_sgb_atf_data));
|
||||
|
||||
m_divcount = 0x0004;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(gb_state::gb_io_w)
|
||||
{
|
||||
static const UINT8 timer_shifts[4] = {10, 4, 6, 8};
|
||||
@ -281,11 +317,11 @@ WRITE8_MEMBER(gb_state::gb_io_w)
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x80: /* enabled & external clock */
|
||||
m_SIOCount = 0;
|
||||
m_sio_count = 0;
|
||||
break;
|
||||
case 0x81: /* enabled & internal clock */
|
||||
SIODATA = 0xFF;
|
||||
m_SIOCount = 8;
|
||||
m_sio_count = 8;
|
||||
m_gb_serial_timer->adjust(m_maincpu->cycles_to_attotime(512), 0, m_maincpu->cycles_to_attotime(512));
|
||||
m_gb_serial_timer->enable( 1 );
|
||||
break;
|
||||
@ -339,7 +375,7 @@ WRITE8_MEMBER(gb_state::gb_io2_w)
|
||||
if (offset == 0x10)
|
||||
{
|
||||
/* disable BIOS ROM */
|
||||
m_bios_disable = TRUE;
|
||||
m_bios_disable = 1;
|
||||
//printf("here again?\n");
|
||||
}
|
||||
else
|
||||
@ -731,7 +767,7 @@ WRITE8_MEMBER(gb_state::sgb_io_w)
|
||||
|
||||
for( I = 0; I < 2048; I++ )
|
||||
{
|
||||
col = ( m_lcd.gb_vram_ptr[ 0x0800 + (I*2) + 1 ] << 8 ) | m_lcd.gb_vram_ptr[ 0x0800 + (I*2) ];
|
||||
col = (m_lcd.gb_vram[0x0800 + (I*2) + 1] << 8) | m_lcd.gb_vram[0x0800 + (I*2)];
|
||||
m_sgb_pal_data[I] = col;
|
||||
}
|
||||
}
|
||||
@ -761,10 +797,10 @@ WRITE8_MEMBER(gb_state::sgb_io_w)
|
||||
/* Not Implemented */
|
||||
break;
|
||||
case 0x13: /* CHR_TRN */
|
||||
if( sgb_data[1] & 0x1 )
|
||||
memcpy( m_sgb_tile_data + 4096, m_lcd.gb_vram_ptr + 0x0800, 4096 );
|
||||
if (sgb_data[1] & 0x1)
|
||||
memcpy(m_sgb_tile_data + 4096, m_lcd.gb_vram + 0x0800, 4096);
|
||||
else
|
||||
memcpy( m_sgb_tile_data, m_lcd.gb_vram_ptr + 0x0800, 4096 );
|
||||
memcpy(m_sgb_tile_data, m_lcd.gb_vram + 0x0800, 4096);
|
||||
break;
|
||||
case 0x14: /* PCT_TRN */
|
||||
{
|
||||
@ -772,26 +808,26 @@ WRITE8_MEMBER(gb_state::sgb_io_w)
|
||||
UINT16 col;
|
||||
if (m_cartslot && m_cartslot->get_sgb_hack())
|
||||
{
|
||||
memcpy( m_sgb_tile_map, m_lcd.gb_vram_ptr + 0x1000, 2048 );
|
||||
memcpy(m_sgb_tile_map, m_lcd.gb_vram + 0x1000, 2048);
|
||||
for( I = 0; I < 64; I++ )
|
||||
{
|
||||
col = ( m_lcd.gb_vram_ptr[ 0x0800 + (I*2) + 1 ] << 8 ) | m_lcd.gb_vram_ptr[ 0x0800 + (I*2) ];
|
||||
col = (m_lcd.gb_vram[0x0800 + (I*2) + 1 ] << 8) | m_lcd.gb_vram[0x0800 + (I*2)];
|
||||
m_sgb_pal[SGB_BORDER_PAL_OFFSET + I] = col;
|
||||
}
|
||||
}
|
||||
else /* Do things normally */
|
||||
{
|
||||
memcpy( m_sgb_tile_map, m_lcd.gb_vram_ptr + 0x0800, 2048 );
|
||||
memcpy(m_sgb_tile_map, m_lcd.gb_vram + 0x0800, 2048);
|
||||
for( I = 0; I < 64; I++ )
|
||||
{
|
||||
col = ( m_lcd.gb_vram_ptr[ 0x1000 + (I*2) + 1 ] << 8 ) | m_lcd.gb_vram_ptr[ 0x1000 + (I*2) ];
|
||||
col = (m_lcd.gb_vram[0x1000 + (I*2) + 1] << 8) | m_lcd.gb_vram[0x1000 + (I*2)];
|
||||
m_sgb_pal[SGB_BORDER_PAL_OFFSET + I] = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x15: /* ATTR_TRN */
|
||||
memcpy( m_sgb_atf_data, m_lcd.gb_vram_ptr + 0x0800, 4050 );
|
||||
memcpy( m_sgb_atf_data, m_lcd.gb_vram + 0x0800, 4050 );
|
||||
break;
|
||||
case 0x16: /* ATTR_SET */
|
||||
{
|
||||
@ -923,9 +959,9 @@ TIMER_CALLBACK_MEMBER(gb_state::gb_serial_timer_proc)
|
||||
/* Shift in a received bit */
|
||||
SIODATA = (SIODATA << 1) | 0x01;
|
||||
/* Decrement number of handled bits */
|
||||
m_SIOCount--;
|
||||
m_sio_count--;
|
||||
/* If all bits done, stop timer and trigger interrupt */
|
||||
if ( ! m_SIOCount )
|
||||
if ( ! m_sio_count )
|
||||
{
|
||||
SIOCONT &= 0x7F;
|
||||
m_gb_serial_timer->enable( 0 );
|
||||
@ -994,15 +1030,15 @@ WRITE8_MEMBER(gb_state::gbc_io2_w)
|
||||
m_maincpu->set_speed(data);
|
||||
return;
|
||||
case 0x10: /* BFF - Bios disable */
|
||||
m_bios_disable = TRUE;
|
||||
m_bios_disable = 1;
|
||||
return;
|
||||
case 0x16: /* RP - Infrared port */
|
||||
break;
|
||||
case 0x30: /* SVBK - RAM bank select */
|
||||
m_GBC_RAMBank = data & 0x7;
|
||||
if (!m_GBC_RAMBank)
|
||||
m_GBC_RAMBank = 1;
|
||||
m_rambank->set_base(m_GBC_RAMMap[m_GBC_RAMBank]);
|
||||
m_gbc_rambank = data & 0x7;
|
||||
if (!m_gbc_rambank)
|
||||
m_gbc_rambank = 1;
|
||||
m_rambank->set_base(m_gbc_rammap[m_gbc_rambank]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1019,7 +1055,7 @@ READ8_MEMBER(gb_state::gbc_io2_r)
|
||||
case 0x16: /* RP - Infrared port */
|
||||
break;
|
||||
case 0x30: /* SVBK - RAM bank select */
|
||||
return m_GBC_RAMBank;
|
||||
return m_gbc_rambank;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1037,8 +1073,9 @@ MACHINE_START_MEMBER(megaduck_state,megaduck)
|
||||
/* Allocate the serial timer, and disable it */
|
||||
m_gb_serial_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_serial_timer_proc),this));
|
||||
m_gb_serial_timer->enable( 0 );
|
||||
|
||||
MACHINE_START_CALL_MEMBER( gb_video );
|
||||
|
||||
save_gb_base();
|
||||
gb_video_start(GB_VIDEO_DMG);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER(megaduck_state,megaduck)
|
||||
@ -1046,7 +1083,7 @@ MACHINE_RESET_MEMBER(megaduck_state,megaduck)
|
||||
/* We may have to add some more stuff here, if not then it can be merged back into gb */
|
||||
gb_init();
|
||||
|
||||
m_bios_disable = TRUE;
|
||||
m_bios_disable = 1;
|
||||
|
||||
gb_video_reset( GB_VIDEO_DMG );
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ inline void gb_state::gb_plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 c
|
||||
void gb_state::gb_select_sprites()
|
||||
{
|
||||
int i, /*yindex,*/ line, height;
|
||||
UINT8 *oam = m_lcd.gb_oam->base() + 39 * 4;
|
||||
UINT8 *oam = m_lcd.gb_oam + 39 * 4;
|
||||
|
||||
m_lcd.sprCount = 0;
|
||||
|
||||
@ -211,8 +211,8 @@ void gb_state::gb_update_sprites()
|
||||
yindex = m_lcd.current_line;
|
||||
line = m_lcd.current_line + 16;
|
||||
|
||||
oam = m_lcd.gb_oam->base() + 39 * 4;
|
||||
vram = m_lcd.gb_vram->base();
|
||||
oam = m_lcd.gb_oam + 39 * 4;
|
||||
vram = m_lcd.gb_vram;
|
||||
for (i = 39; i >= 0; i--)
|
||||
{
|
||||
/* if sprite is on current line && x-coordinate && x-coordinate is < 168 */
|
||||
@ -304,8 +304,8 @@ void gb_state::gb_update_scanline()
|
||||
if ( m_lcd.layer[0].enabled )
|
||||
{
|
||||
m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_bgdtab;
|
||||
m_lcd.layer[0].bg_tiles = m_lcd.gb_chrgen;
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
|
||||
m_lcd.layer[0].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
|
||||
m_lcd.layer[0].xindex = SCROLLX >> 3;
|
||||
m_lcd.layer[0].xshift = SCROLLX & 7;
|
||||
m_lcd.layer[0].xstart = 0;
|
||||
@ -321,8 +321,8 @@ void gb_state::gb_update_scanline()
|
||||
xpos = 0;
|
||||
|
||||
m_lcd.layer[1].bgline = m_lcd.window_lines_drawn;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_wndtab;
|
||||
m_lcd.layer[1].bg_tiles = m_lcd.gb_chrgen;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
|
||||
m_lcd.layer[1].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
|
||||
m_lcd.layer[1].xindex = 0;
|
||||
m_lcd.layer[1].xshift = 0;
|
||||
m_lcd.layer[1].xstart = xpos;
|
||||
@ -448,8 +448,8 @@ void gb_state::sgb_update_sprites()
|
||||
yindex = m_lcd.current_line + SGB_YOFFSET;
|
||||
line = m_lcd.current_line + 16;
|
||||
|
||||
oam = m_lcd.gb_oam->base() + 39 * 4;
|
||||
vram = m_lcd.gb_vram->base();
|
||||
oam = m_lcd.gb_oam + 39 * 4;
|
||||
vram = m_lcd.gb_vram;
|
||||
for (i = 39; i >= 0; i--)
|
||||
{
|
||||
/* if sprite is on current line && x-coordinate && x-coordinate is < 168 */
|
||||
@ -617,8 +617,8 @@ void gb_state::sgb_update_scanline()
|
||||
if ( m_lcd.layer[0].enabled )
|
||||
{
|
||||
m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_bgdtab;
|
||||
m_lcd.layer[0].bg_tiles = m_lcd.gb_chrgen;
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
|
||||
m_lcd.layer[0].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
|
||||
m_lcd.layer[0].xindex = SCROLLX >> 3;
|
||||
m_lcd.layer[0].xshift = SCROLLX & 7;
|
||||
m_lcd.layer[0].xstart = 0;
|
||||
@ -635,8 +635,8 @@ void gb_state::sgb_update_scanline()
|
||||
xpos = 0;
|
||||
|
||||
m_lcd.layer[1].bgline = m_lcd.window_lines_drawn;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_wndtab;
|
||||
m_lcd.layer[1].bg_tiles = m_lcd.gb_chrgen;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
|
||||
m_lcd.layer[1].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
|
||||
m_lcd.layer[1].xindex = 0;
|
||||
m_lcd.layer[1].xshift = 0;
|
||||
m_lcd.layer[1].xstart = xpos;
|
||||
@ -791,7 +791,7 @@ void gb_state::cgb_update_sprites()
|
||||
yindex = m_lcd.current_line;
|
||||
line = m_lcd.current_line + 16;
|
||||
|
||||
oam = m_lcd.gb_oam->base() + 39 * 4;
|
||||
oam = m_lcd.gb_oam + 39 * 4;
|
||||
for (i = 39; i >= 0; i--)
|
||||
{
|
||||
/* if sprite is on current line && x-coordinate && x-coordinate is < 168 */
|
||||
@ -809,11 +809,11 @@ void gb_state::cgb_update_sprites()
|
||||
xindex = oam[1] - 8;
|
||||
if (oam[3] & 0x40) /* flip y ? */
|
||||
{
|
||||
data = *((UINT16 *) &m_lcd.gb_vram->base()[ ((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (height - 1 - line + oam[0]) * 2]);
|
||||
data = *((UINT16 *) &m_lcd.gb_vram[((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (height - 1 - line + oam[0]) * 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = *((UINT16 *) &m_lcd.gb_vram->base()[ ((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (line - oam[0]) * 2]);
|
||||
data = *((UINT16 *) &m_lcd.gb_vram[((oam[3] & 0x8)<<10) + (oam[2] & tilemask) * 16 + (line - oam[0]) * 2]);
|
||||
}
|
||||
#ifndef LSB_FIRST
|
||||
data = (data << 8) | (data >> 8);
|
||||
@ -908,8 +908,8 @@ void gb_state::cgb_update_scanline()
|
||||
if ( m_lcd.layer[0].enabled )
|
||||
{
|
||||
m_lcd.layer[0].bgline = ( SCROLLY + m_lcd.current_line ) & 0xFF;
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_bgdtab;
|
||||
m_lcd.layer[0].gbc_map = m_lcd.gbc_bgdtab;
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
|
||||
m_lcd.layer[0].gbc_map = m_lcd.gb_vram + m_lcd.gbc_bgdtab_offs;
|
||||
m_lcd.layer[0].xindex = SCROLLX >> 3;
|
||||
m_lcd.layer[0].xshift = SCROLLX & 7;
|
||||
m_lcd.layer[0].xstart = 0;
|
||||
@ -926,8 +926,8 @@ void gb_state::cgb_update_scanline()
|
||||
xpos = 0;
|
||||
|
||||
m_lcd.layer[1].bgline = m_lcd.window_lines_drawn;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_wndtab;
|
||||
m_lcd.layer[1].gbc_map = m_lcd.gbc_wndtab;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
|
||||
m_lcd.layer[1].gbc_map = m_lcd.gb_vram + m_lcd.gbc_wndtab_offs;
|
||||
m_lcd.layer[1].xindex = 0;
|
||||
m_lcd.layer[1].xshift = 0;
|
||||
m_lcd.layer[1].xstart = xpos;
|
||||
@ -959,7 +959,7 @@ void gb_state::cgb_update_scanline()
|
||||
}
|
||||
map = m_lcd.layer[l].bg_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
|
||||
gbcmap = m_lcd.layer[l].gbc_map + ( ( m_lcd.layer[l].bgline << 2 ) & 0x3E0 );
|
||||
tiles = ( gbcmap[ m_lcd.layer[l].xindex ] & 0x08 ) ? m_lcd.gbc_chrgen : m_lcd.gb_chrgen;
|
||||
tiles = (gbcmap[m_lcd.layer[l].xindex] & 0x08) ? (m_lcd.gb_vram + m_lcd.gbc_chrgen_offs) : (m_lcd.gb_vram + m_lcd.gb_chrgen_offs);
|
||||
|
||||
/* Check for vertical flip */
|
||||
if ( gbcmap[ m_lcd.layer[l].xindex ] & 0x40 )
|
||||
@ -1024,7 +1024,7 @@ void gb_state::cgb_update_scanline()
|
||||
|
||||
m_lcd.layer[l].xindex = ( m_lcd.layer[l].xindex + 1 ) & 31;
|
||||
m_lcd.layer[l].xshift = 0;
|
||||
tiles = ( gbcmap[ m_lcd.layer[l].xindex ] & 0x08 ) ? m_lcd.gbc_chrgen : m_lcd.gb_chrgen;
|
||||
tiles = (gbcmap[m_lcd.layer[l].xindex] & 0x08) ? (m_lcd.gb_vram + m_lcd.gbc_chrgen_offs) : (m_lcd.gb_vram + m_lcd.gb_chrgen_offs);
|
||||
|
||||
/* Check for vertical flip */
|
||||
if ( gbcmap[ m_lcd.layer[l].xindex ] & 0x40 )
|
||||
@ -1183,18 +1183,129 @@ TIMER_CALLBACK_MEMBER(gb_state::gb_video_init_vbl)
|
||||
m_maincpu->set_input_line(VBL_INT, ASSERT_LINE );
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(gb_state,gb_video)
|
||||
void gb_state::gb_videoptr_restore()
|
||||
{
|
||||
m_lcd.lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_lcd_timer_proc),this));
|
||||
machine().primary_screen->register_screen_bitmap(m_bitmap);
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
|
||||
m_lcd.layer[0].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
|
||||
m_lcd.layer[1].bg_tiles = m_lcd.gb_vram + m_lcd.gb_chrgen_offs;
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(gb_state,gbc_video)
|
||||
void gb_state::gbc_videoptr_restore()
|
||||
{
|
||||
m_lcd.lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gbc_lcd_timer_proc),this));
|
||||
machine().primary_screen->register_screen_bitmap(m_bitmap);
|
||||
m_lcd.layer[0].bg_map = m_lcd.gb_vram + m_lcd.gb_bgdtab_offs;
|
||||
m_lcd.layer[0].gbc_map = m_lcd.gb_vram + m_lcd.gbc_bgdtab_offs;
|
||||
m_lcd.layer[1].bg_map = m_lcd.gb_vram + m_lcd.gb_wndtab_offs;
|
||||
m_lcd.layer[1].gbc_map = m_lcd.gb_vram + m_lcd.gbc_wndtab_offs;
|
||||
}
|
||||
|
||||
void gb_state::save_gb_video()
|
||||
{
|
||||
save_item(NAME(m_lcd.window_lines_drawn));
|
||||
save_item(NAME(m_lcd.gb_vid_regs));
|
||||
save_item(NAME(m_lcd.bg_zbuf));
|
||||
|
||||
save_item(NAME(m_lcd.cgb_bpal));
|
||||
save_item(NAME(m_lcd.cgb_spal));
|
||||
|
||||
save_item(NAME(m_lcd.gb_bpal));
|
||||
save_item(NAME(m_lcd.gb_spal0));
|
||||
save_item(NAME(m_lcd.gb_spal1));
|
||||
|
||||
save_item(NAME(m_lcd.current_line));
|
||||
save_item(NAME(m_lcd.cmp_line));
|
||||
save_item(NAME(m_lcd.sprCount));
|
||||
save_item(NAME(m_lcd.sprite));
|
||||
save_item(NAME(m_lcd.previous_line));
|
||||
save_item(NAME(m_lcd.start_x));
|
||||
save_item(NAME(m_lcd.end_x));
|
||||
save_item(NAME(m_lcd.mode));
|
||||
save_item(NAME(m_lcd.state));
|
||||
save_item(NAME(m_lcd.lcd_irq_line));
|
||||
save_item(NAME(m_lcd.triggering_line_irq));
|
||||
save_item(NAME(m_lcd.line_irq));
|
||||
save_item(NAME(m_lcd.triggering_mode_irq));
|
||||
save_item(NAME(m_lcd.mode_irq));
|
||||
save_item(NAME(m_lcd.delayed_line_irq));
|
||||
save_item(NAME(m_lcd.sprite_cycles));
|
||||
save_item(NAME(m_lcd.scrollx_adjust));
|
||||
save_item(NAME(m_lcd.oam_locked));
|
||||
save_item(NAME(m_lcd.vram_locked));
|
||||
save_item(NAME(m_lcd.pal_locked));
|
||||
save_item(NAME(m_lcd.hdma_enabled));
|
||||
save_item(NAME(m_lcd.hdma_possible));
|
||||
save_item(NAME(m_lcd.gbc_mode));
|
||||
save_item(NAME(m_lcd.gb_tile_no_mod));
|
||||
save_item(NAME(m_lcd.gb_vram_bank));
|
||||
|
||||
save_item(NAME(m_lcd.gb_chrgen_offs));
|
||||
save_item(NAME(m_lcd.gb_bgdtab_offs));
|
||||
save_item(NAME(m_lcd.gb_wndtab_offs));
|
||||
save_item(NAME(m_lcd.gbc_chrgen_offs));
|
||||
save_item(NAME(m_lcd.gbc_bgdtab_offs));
|
||||
save_item(NAME(m_lcd.gbc_wndtab_offs));
|
||||
|
||||
save_item(NAME(m_lcd.layer[0].enabled));
|
||||
save_item(NAME(m_lcd.layer[0].xindex));
|
||||
save_item(NAME(m_lcd.layer[0].xshift));
|
||||
save_item(NAME(m_lcd.layer[0].xstart));
|
||||
save_item(NAME(m_lcd.layer[0].xend));
|
||||
save_item(NAME(m_lcd.layer[0].bgline));
|
||||
save_item(NAME(m_lcd.layer[1].enabled));
|
||||
save_item(NAME(m_lcd.layer[1].xindex));
|
||||
save_item(NAME(m_lcd.layer[1].xshift));
|
||||
save_item(NAME(m_lcd.layer[1].xstart));
|
||||
save_item(NAME(m_lcd.layer[1].xend));
|
||||
save_item(NAME(m_lcd.layer[1].bgline));
|
||||
}
|
||||
|
||||
void gb_state::gb_video_start( int mode )
|
||||
{
|
||||
int vram_size = (mode == GB_VIDEO_CGB) ? 0x4000 : 0x2000;
|
||||
|
||||
machine().primary_screen->register_screen_bitmap(m_bitmap);
|
||||
m_lcd.gb_vram = auto_alloc_array_clear(machine(), UINT8, vram_size);
|
||||
m_lcd.gb_oam = auto_alloc_array_clear(machine(), UINT8, 0x100);
|
||||
|
||||
save_pointer(NAME(m_lcd.gb_vram), vram_size);
|
||||
save_pointer(NAME(m_lcd.gb_oam), 0x100);
|
||||
save_gb_video();
|
||||
|
||||
if (mode == GB_VIDEO_CGB)
|
||||
{
|
||||
m_lcd.lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gbc_lcd_timer_proc),this));
|
||||
machine().save().register_postload(save_prepost_delegate(FUNC(gb_state::gbc_videoptr_restore), this));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lcd.lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_state::gb_lcd_timer_proc),this));
|
||||
machine().save().register_postload(save_prepost_delegate(FUNC(gb_state::gb_videoptr_restore), this));
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GB_VIDEO_DMG:
|
||||
memcpy(m_lcd.gb_oam, dmg_oam_fingerprint, 0x100);
|
||||
break;
|
||||
case GB_VIDEO_MGB:
|
||||
/* Initialize part of VRAM. This code must be deleted when we have added the bios dump */
|
||||
for (int i = 1; i < 0x0d; i++)
|
||||
{
|
||||
m_lcd.gb_vram[0x1903 + i] = i;
|
||||
m_lcd.gb_vram[0x1923 + i] = i + 0x0C;
|
||||
}
|
||||
m_lcd.gb_vram[0x1910] = 0x19;
|
||||
memcpy(m_lcd.gb_oam, mgb_oam_fingerprint, 0x100);
|
||||
break;
|
||||
case GB_VIDEO_SGB:
|
||||
break;
|
||||
case GB_VIDEO_CGB:
|
||||
memcpy(m_lcd.gb_oam, cgb_oam_fingerprint, 0x100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT32 gb_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
@ -1203,34 +1314,50 @@ UINT32 gb_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, cons
|
||||
|
||||
void gb_state::gb_video_reset( int mode )
|
||||
{
|
||||
int i;
|
||||
int vram_size = 0x2000;
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
emu_timer *old_timer = m_lcd.lcd_timer;
|
||||
|
||||
memset( &m_lcd, 0, sizeof(m_lcd) );
|
||||
m_lcd.lcd_timer = old_timer;
|
||||
m_lcd.window_lines_drawn = 0;
|
||||
|
||||
m_lcd.current_line = 0;
|
||||
m_lcd.cmp_line = 0;
|
||||
m_lcd.sprCount = 0;
|
||||
m_lcd.previous_line = 0;
|
||||
m_lcd.start_x = 0;
|
||||
m_lcd.end_x = 0;
|
||||
m_lcd.mode = 0;
|
||||
m_lcd.state = 0;
|
||||
m_lcd.lcd_irq_line = 0;
|
||||
m_lcd.triggering_line_irq = 0;
|
||||
m_lcd.line_irq = 0;
|
||||
m_lcd.triggering_mode_irq = 0;
|
||||
m_lcd.mode_irq = 0;
|
||||
m_lcd.delayed_line_irq = 0;
|
||||
m_lcd.sprite_cycles = 0;
|
||||
m_lcd.scrollx_adjust = 0;
|
||||
m_lcd.oam_locked = 0;
|
||||
m_lcd.vram_locked = 0;
|
||||
m_lcd.pal_locked = 0;
|
||||
m_lcd.gbc_mode = 0;
|
||||
m_lcd.gb_tile_no_mod = 0;
|
||||
m_lcd.gb_vram_bank = 0;
|
||||
|
||||
m_lcd.gb_chrgen_offs = 0;
|
||||
m_lcd.gb_bgdtab_offs = 0x1c00;
|
||||
m_lcd.gb_wndtab_offs = 0x1c00;
|
||||
|
||||
memset(&m_lcd.gb_vid_regs, 0, sizeof(m_lcd.gb_vid_regs));
|
||||
memset(&m_lcd.bg_zbuf, 0, sizeof(m_lcd.bg_zbuf));
|
||||
memset(&m_lcd.cgb_bpal, 0, sizeof(m_lcd.cgb_bpal));
|
||||
memset(&m_lcd.cgb_spal, 0, sizeof(m_lcd.cgb_spal));
|
||||
memset(&m_lcd.sprite, 0, sizeof(m_lcd.sprite));
|
||||
memset(&m_lcd.layer[0], 0, sizeof(m_lcd.layer[0]));
|
||||
memset(&m_lcd.layer[1], 0, sizeof(m_lcd.layer[1]));
|
||||
|
||||
if (mode == GB_VIDEO_CGB) vram_size = 0x4000;
|
||||
// specific reg initialization
|
||||
m_lcd.gb_vid_regs[0x06] = 0xff;
|
||||
|
||||
/* free regions if already allocated */
|
||||
if (memregion("gfx1")->base()) machine().memory().region_free(":gfx1");
|
||||
if (memregion("gfx2")->base()) machine().memory().region_free(":gfx2");
|
||||
|
||||
m_lcd.gb_vram = machine().memory().region_alloc(":gfx1", vram_size, 1, ENDIANNESS_LITTLE );
|
||||
m_lcd.gb_oam = machine().memory().region_alloc(":gfx2", 0x100, 1, ENDIANNESS_LITTLE );
|
||||
memset( m_lcd.gb_vram->base(), 0, vram_size );
|
||||
|
||||
m_lcd.gb_vram_ptr = m_lcd.gb_vram->base();
|
||||
m_lcd.gb_chrgen = m_lcd.gb_vram->base();
|
||||
m_lcd.gb_bgdtab = m_lcd.gb_vram->base() + 0x1C00;
|
||||
m_lcd.gb_wndtab = m_lcd.gb_vram->base() + 0x1C00;
|
||||
|
||||
m_lcd.gb_vid_regs[0x06] = 0xFF;
|
||||
for( i = 0x0c; i < _NR_GB_VID_REGS; i++ )
|
||||
{
|
||||
m_lcd.gb_vid_regs[i] = 0xFF;
|
||||
}
|
||||
for (int i = 0x0c; i < _NR_GB_VID_REGS; i++)
|
||||
m_lcd.gb_vid_regs[i] = 0xff;
|
||||
|
||||
LCDSTAT = 0x80;
|
||||
LCDCONT = 0x00; /* Video hardware is turned off at boot time */
|
||||
@ -1239,11 +1366,9 @@ void gb_state::gb_video_reset( int mode )
|
||||
SPR0PAL = SPR1PAL = 0xFF;
|
||||
WNDPOSX = WNDPOSY = 0x00;
|
||||
|
||||
/* Initialize palette arrays */
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
// Initialize palette arrays
|
||||
for (int i = 0; i < 4; i++)
|
||||
m_lcd.gb_bpal[i] = m_lcd.gb_spal0[i] = m_lcd.gb_spal1[i] = i;
|
||||
}
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
@ -1252,55 +1377,38 @@ void gb_state::gb_video_reset( int mode )
|
||||
|
||||
/* set the scanline update function */
|
||||
update_scanline = &gb_state::gb_update_scanline;
|
||||
|
||||
memcpy( m_lcd.gb_oam->base(), dmg_oam_fingerprint, 0x100 );
|
||||
|
||||
break;
|
||||
|
||||
case GB_VIDEO_MGB:
|
||||
/* set the scanline update function */
|
||||
update_scanline = &gb_state::gb_update_scanline;
|
||||
/* Initialize part of VRAM. This code must be deleted when we have added the bios dump */
|
||||
for( i = 1; i < 0x0D; i++ )
|
||||
{
|
||||
m_lcd.gb_vram->base()[ 0x1903 + i ] = i;
|
||||
m_lcd.gb_vram->base()[ 0x1923 + i ] = i + 0x0C;
|
||||
}
|
||||
m_lcd.gb_vram->base()[ 0x1910 ] = 0x19;
|
||||
|
||||
|
||||
memcpy( m_lcd.gb_oam->base(), mgb_oam_fingerprint, 0x100 );
|
||||
|
||||
/* Make sure the VBlank interrupt is set when the first instruction gets executed */
|
||||
machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(1), timer_expired_delegate(FUNC(gb_state::gb_video_init_vbl),this));
|
||||
|
||||
/* Initialize some video registers */
|
||||
gb_video_w( space, 0x0, 0x91 ); /* LCDCONT */
|
||||
gb_video_w( space, 0x7, 0xFC ); /* BGRDPAL */
|
||||
gb_video_w( space, 0x8, 0xFC ); /* SPR0PAL */
|
||||
gb_video_w( space, 0x9, 0xFC ); /* SPR1PAL */
|
||||
gb_video_w(space, 0x0, 0x91); /* LCDCONT */
|
||||
gb_video_w(space, 0x7, 0xFC); /* BGRDPAL */
|
||||
gb_video_w(space, 0x8, 0xFC); /* SPR0PAL */
|
||||
gb_video_w(space, 0x9, 0xFC); /* SPR1PAL */
|
||||
|
||||
CURLINE = m_lcd.current_line = 0;
|
||||
LCDSTAT = ( LCDSTAT & 0xF8 ) | 0x05;
|
||||
m_lcd.mode = 1;
|
||||
m_lcd.lcd_timer->adjust(m_maincpu->cycles_to_attotime(60), GB_LCD_STATE_LY00_M0);
|
||||
|
||||
break;
|
||||
|
||||
case GB_VIDEO_SGB:
|
||||
/* set the scanline update function */
|
||||
update_scanline = &gb_state::sgb_update_scanline;
|
||||
|
||||
break;
|
||||
|
||||
case GB_VIDEO_CGB:
|
||||
/* set the scanline update function */
|
||||
update_scanline = &gb_state::cgb_update_scanline;
|
||||
|
||||
memcpy( m_lcd.gb_oam->base(), cgb_oam_fingerprint, 0x100 );
|
||||
|
||||
m_lcd.gb_chrgen = m_lcd.gb_vram->base();
|
||||
m_lcd.gbc_chrgen = m_lcd.gb_vram->base() + 0x2000;
|
||||
m_lcd.gb_bgdtab = m_lcd.gb_wndtab = m_lcd.gb_vram->base() + 0x1C00;
|
||||
m_lcd.gbc_bgdtab = m_lcd.gbc_wndtab = m_lcd.gb_vram->base() + 0x3C00;
|
||||
m_lcd.gbc_chrgen_offs = 0x2000;
|
||||
m_lcd.gbc_bgdtab_offs = 0x3c00;
|
||||
m_lcd.gbc_wndtab_offs = 0x3c00;
|
||||
|
||||
/* HDMA disabled */
|
||||
m_lcd.hdma_enabled = 0;
|
||||
@ -1958,30 +2066,28 @@ READ8_MEMBER(gb_state::gb_video_r)
|
||||
|
||||
READ8_MEMBER(gb_state::gb_vram_r)
|
||||
{
|
||||
return ( m_lcd.vram_locked == LOCKED ) ? 0xFF : m_lcd.gb_vram_ptr[offset];
|
||||
return (m_lcd.vram_locked == LOCKED) ? 0xff : m_lcd.gb_vram[offset + (m_lcd.gb_vram_bank * 0x2000)];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(gb_state::gb_vram_w)
|
||||
{
|
||||
if ( m_lcd.vram_locked == LOCKED )
|
||||
{
|
||||
if (m_lcd.vram_locked == LOCKED)
|
||||
return;
|
||||
}
|
||||
m_lcd.gb_vram_ptr[offset] = data;
|
||||
|
||||
m_lcd.gb_vram[offset + (m_lcd.gb_vram_bank * 0x2000)] = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(gb_state::gb_oam_r)
|
||||
{
|
||||
return ( m_lcd.oam_locked == LOCKED ) ? 0xFF : m_lcd.gb_oam->base()[offset];
|
||||
return (m_lcd.oam_locked == LOCKED) ? 0xff : m_lcd.gb_oam[offset];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(gb_state::gb_oam_w)
|
||||
{
|
||||
if ( m_lcd.oam_locked == LOCKED || offset >= 0xa0 )
|
||||
{
|
||||
if (m_lcd.oam_locked == LOCKED || offset >= 0xa0)
|
||||
return;
|
||||
}
|
||||
m_lcd.gb_oam->base()[offset] = data;
|
||||
|
||||
m_lcd.gb_oam[offset] = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(gb_state::gb_video_w)
|
||||
@ -1989,12 +2095,12 @@ WRITE8_MEMBER(gb_state::gb_video_w)
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: /* LCDC - LCD Control */
|
||||
m_lcd.gb_chrgen = m_lcd.gb_vram->base() + ((data & 0x10) ? 0x0000 : 0x0800);
|
||||
m_lcd.gb_chrgen_offs = (data & 0x10) ? 0x0000 : 0x0800;
|
||||
m_lcd.gb_tile_no_mod = (data & 0x10) ? 0x00 : 0x80;
|
||||
m_lcd.gb_bgdtab = m_lcd.gb_vram->base() + ((data & 0x08) ? 0x1C00 : 0x1800 );
|
||||
m_lcd.gb_wndtab = m_lcd.gb_vram->base() + ((data & 0x40) ? 0x1C00 : 0x1800 );
|
||||
m_lcd.gb_bgdtab_offs = (data & 0x08) ? 0x1c00 : 0x1800;
|
||||
m_lcd.gb_wndtab_offs = (data & 0x40) ? 0x1c00 : 0x1800;
|
||||
/* if LCD controller is switched off, set STAT and LY to 00 */
|
||||
if ( ! ( data & 0x80 ) )
|
||||
if (!(data & 0x80))
|
||||
{
|
||||
LCDSTAT &= ~0x03;
|
||||
CURLINE = 0;
|
||||
@ -2002,7 +2108,7 @@ WRITE8_MEMBER(gb_state::gb_video_w)
|
||||
m_lcd.vram_locked = UNLOCKED;
|
||||
}
|
||||
/* If LCD is being switched on */
|
||||
if ( !( LCDCONT & 0x80 ) && ( data & 0x80 ) )
|
||||
if (!(LCDCONT & 0x80) && (data & 0x80))
|
||||
{
|
||||
gb_lcd_switch_on();
|
||||
}
|
||||
@ -2077,7 +2183,7 @@ WRITE8_MEMBER(gb_state::gb_video_w)
|
||||
break;
|
||||
case 0x06: /* DMA - DMA Transfer and Start Address */
|
||||
{
|
||||
UINT8 *P = m_lcd.gb_oam->base();
|
||||
UINT8 *P = m_lcd.gb_oam;
|
||||
offset = (UINT16) data << 8;
|
||||
for (data = 0; data < 0xA0; data++)
|
||||
*P++ = space.read_byte(offset++);
|
||||
@ -2113,7 +2219,7 @@ WRITE8_MEMBER(gb_state::gb_video_w)
|
||||
default: /* Unknown register, no change */
|
||||
return;
|
||||
}
|
||||
m_lcd.gb_vid_regs[ offset ] = data;
|
||||
m_lcd.gb_vid_regs[offset] = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(gb_state::gbc_video_r)
|
||||
@ -2141,13 +2247,13 @@ WRITE8_MEMBER(gb_state::gbc_video_w)
|
||||
switch( offset )
|
||||
{
|
||||
case 0x00: /* LCDC - LCD Control */
|
||||
m_lcd.gb_chrgen = m_lcd.gb_vram->base() + ((data & 0x10) ? 0x0000 : 0x0800);
|
||||
m_lcd.gbc_chrgen = m_lcd.gb_vram->base() + ((data & 0x10) ? 0x2000 : 0x2800);
|
||||
m_lcd.gb_chrgen_offs = (data & 0x10) ? 0x0000 : 0x0800;
|
||||
m_lcd.gbc_chrgen_offs = (data & 0x10) ? 0x2000 : 0x2800;
|
||||
m_lcd.gb_tile_no_mod = (data & 0x10) ? 0x00 : 0x80;
|
||||
m_lcd.gb_bgdtab = m_lcd.gb_vram->base() + ((data & 0x08) ? 0x1C00 : 0x1800);
|
||||
m_lcd.gbc_bgdtab = m_lcd.gb_vram->base() + ((data & 0x08) ? 0x3C00 : 0x3800);
|
||||
m_lcd.gb_wndtab = m_lcd.gb_vram->base() + ((data & 0x40) ? 0x1C00 : 0x1800);
|
||||
m_lcd.gbc_wndtab = m_lcd.gb_vram->base() + ((data & 0x40) ? 0x3C00 : 0x3800);
|
||||
m_lcd.gb_bgdtab_offs = (data & 0x08) ? 0x1c00 : 0x1800;
|
||||
m_lcd.gbc_bgdtab_offs = (data & 0x08) ? 0x3c00 : 0x3800;
|
||||
m_lcd.gb_wndtab_offs = (data & 0x40) ? 0x1c00 : 0x1800;
|
||||
m_lcd.gbc_wndtab_offs = (data & 0x40) ? 0x3c00 : 0x3800;
|
||||
/* if LCD controller is switched off, set STAT to 00 */
|
||||
if ( ! ( data & 0x80 ) )
|
||||
{
|
||||
@ -2234,7 +2340,7 @@ WRITE8_MEMBER(gb_state::gbc_video_w)
|
||||
logerror( "Write to undocumented register: %X = %X\n", offset, data );
|
||||
break;
|
||||
case 0x0F: /* VBK - VRAM bank select */
|
||||
m_lcd.gb_vram_ptr = m_lcd.gb_vram->base() + ( data & 0x01 ) * 0x2000;
|
||||
m_lcd.gb_vram_bank = data & 0x01;
|
||||
data |= 0xFE;
|
||||
break;
|
||||
case 0x11: /* HDMA1 - HBL General DMA - Source High */
|
||||
|
Loading…
Reference in New Issue
Block a user