From 6f99dba4254cedc1cfe4e29cdcaf0a4194d3023e Mon Sep 17 00:00:00 2001 From: Jon Sturm Date: Mon, 27 Oct 2014 18:50:42 -0500 Subject: [PATCH 1/5] ti85: use direct update handler to remove boot memory mapping hacks This allows the flash calculators to properly reset pc to 0x0000 instead of 0x8000 and properly reset all memory banks to page 0x00. --- src/mess/includes/ti85.h | 3 ++- src/mess/machine/ti85.c | 51 ++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/mess/includes/ti85.h b/src/mess/includes/ti85.h index 40c98d9ea52..e967101f034 100755 --- a/src/mess/includes/ti85.h +++ b/src/mess/includes/ti85.h @@ -86,10 +86,10 @@ public: UINT8 m_ON_interrupt_status; UINT8 m_ON_pressed; UINT8 m_flash_unlocked; - UINT8 m_ti8x_memory_page_0; UINT8 m_ti8x_memory_page_1; UINT8 m_ti8x_memory_page_2; UINT8 m_ti8x_memory_page_3; + bool m_booting; UINT8 m_LCD_mask; UINT8 m_power_mode; UINT8 m_cpu_speed; @@ -217,6 +217,7 @@ public: void ti85_setup_snapshot (UINT8 * data); void ti86_setup_snapshot (UINT8 * data); DECLARE_SNAPSHOT_LOAD_MEMBER( ti8x ); + DECLARE_DIRECT_UPDATE_MEMBER( ti83p_direct_update_handler ); ti83pse_timer m_ctimer[3]; diff --git a/src/mess/machine/ti85.c b/src/mess/machine/ti85.c index 44fc0d0ae9f..90c8577394d 100755 --- a/src/mess/machine/ti85.c +++ b/src/mess/machine/ti85.c @@ -154,7 +154,7 @@ void ti85_state::update_ti83p_memory () { //address_space &space = m_maincpu->space(AS_PROGRAM); - m_membank1->set_bank(0); //Always flash page 0, well allmost + m_membank1->set_bank(m_booting ? 0x1f : 0); //Always flash page 0, well allmost if (m_ti83p_port4 & 1) { @@ -182,7 +182,7 @@ void ti85_state::update_ti83pse_memory () { //address_space &space = m_maincpu->space(AS_PROGRAM); - m_membank1->set_bank(m_ti8x_memory_page_0); + m_membank1->set_bank(m_booting ? (m_model==TI84P ? 0x3f : 0x7f) : 0); if (m_ti83p_port4 & 1) { @@ -273,30 +273,32 @@ MACHINE_RESET_MEMBER(ti85_state,ti85) m_PCR = 0xc0; } +DIRECT_UPDATE_MEMBER(ti85_state::ti83p_direct_update_handler) +{ + if (m_booting) + { + if (((m_ti83p_port4 & 1) && (address >= 0x4000 && address < 0xc000)) || (address >= 0x4000 && address < 0x8000)) + { + m_booting = false; + update_ti83p_memory(); + } + } + return address; +} + + MACHINE_RESET_MEMBER(ti85_state,ti83p) { m_red_out = 0x00; m_white_out = 0x00; m_PCR = 0xc0; - m_ti8x_memory_page_0 = 0;//0x1f; - - if (m_model == TI83P) - { - m_ti8x_memory_page_1 = 0x1f; - } - else if (m_model == TI84P) - { - m_ti8x_memory_page_1 = 0x3f; - } - else - { - m_ti8x_memory_page_1 = 0x7f; - } + m_ti8x_memory_page_1 = 0; m_ti8x_memory_page_2 = 0; m_ti8x_memory_page_3 = 0; m_ti83p_port4 = 1; + m_booting = true; if (m_model == TI83P) { update_ti83p_memory(); @@ -305,8 +307,6 @@ MACHINE_RESET_MEMBER(ti85_state,ti83p) { update_ti83pse_memory(); } - - m_maincpu->set_pc(0x8000); } MACHINE_START_MEMBER(ti85_state,ti83p) @@ -314,14 +314,14 @@ MACHINE_START_MEMBER(ti85_state,ti83p) m_model = TI83P; //address_space &space = m_maincpu->space(AS_PROGRAM); //m_bios = memregion("flash")->base(); + m_maincpu->space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(ti85_state::ti83p_direct_update_handler), this)); m_timer_interrupt_mask = 0; m_timer_interrupt_status = 0; m_ON_interrupt_mask = 0; m_ON_interrupt_status = 0; m_ON_pressed = 0; - m_ti8x_memory_page_0 = 0;//0x1f; - m_ti8x_memory_page_1 = 0x1f; + m_ti8x_memory_page_1 = 0; m_ti8x_memory_page_2 = 0; m_ti8x_memory_page_3 = 0; m_LCD_memory_base = 0; @@ -334,8 +334,9 @@ MACHINE_START_MEMBER(ti85_state,ti83p) m_ti83p_port4 = 1; m_flash_unlocked = 0; + m_booting = true; + ti85_state::update_ti83p_memory(); - m_maincpu->set_pc(0x8000); //this is a hack due to incomplete memory mapping emulation machine().scheduler().timer_pulse(attotime::from_hz(256), timer_expired_delegate(FUNC(ti85_state::ti83_timer1_callback),this)); @@ -345,11 +346,11 @@ MACHINE_START_MEMBER(ti85_state,ti83p) /* save states and debugging */ save_item(NAME(m_timer_interrupt_status)); save_item(NAME(m_timer_interrupt_mask)); - save_item(NAME(m_ti8x_memory_page_0)); save_item(NAME(m_ti8x_memory_page_1)); save_item(NAME(m_ti8x_memory_page_2)); save_item(NAME(m_ti8x_memory_page_3)); save_item(NAME(m_ti83p_port4)); + save_item(NAME(m_booting)); } void ti85_state::ti8xpse_init_common() @@ -363,8 +364,7 @@ void ti85_state::ti8xpse_init_common() m_ON_interrupt_mask = 0; m_ON_interrupt_status = 0; m_ON_pressed = 0; - m_ti8x_memory_page_0 = 00;//0x7f; - m_ti8x_memory_page_1 = (m_model != TI84P ) ? 0x7f : 0x3f ; + m_ti8x_memory_page_1 = 0; m_ti8x_memory_page_2 = 0; m_ti8x_memory_page_3 = 0; m_LCD_memory_base = 0; @@ -378,7 +378,7 @@ void ti85_state::ti8xpse_init_common() m_flash_unlocked = 0; ti85_state::update_ti83pse_memory(); - m_maincpu->set_pc(0x8000);//same as above, hack to work around incomplete memory mapping emulation + m_maincpu->space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(ti85_state::ti83p_direct_update_handler), this)); machine().scheduler().timer_pulse(attotime::from_hz(256), timer_expired_delegate(FUNC(ti85_state::ti83_timer1_callback),this)); @@ -391,7 +391,6 @@ void ti85_state::ti8xpse_init_common() /* save states and debugging */ save_item(NAME(m_ctimer_interrupt_status)); save_item(NAME(m_timer_interrupt_status)); - save_item(NAME(m_ti8x_memory_page_0)); save_item(NAME(m_ti8x_memory_page_1)); save_item(NAME(m_ti8x_memory_page_2)); save_item(NAME(m_ti8x_memory_page_3)); From e27079c36ef7e4d8d32b6ea88fa7cf4f5ab37091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Tue, 28 Oct 2014 09:46:52 +0100 Subject: [PATCH 2/5] fixed usage of uninitialized member in grip_device (nw) happened with prof80 --- src/emu/bus/ecbbus/grip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/emu/bus/ecbbus/grip.c b/src/emu/bus/ecbbus/grip.c index 397c985aa1e..744ac847b96 100644 --- a/src/emu/bus/ecbbus/grip.c +++ b/src/emu/bus/ecbbus/grip.c @@ -681,6 +681,7 @@ void grip_device::device_reset() { m_base = m_j7->read(); m_page = 0; + m_lps = 0; } From 6be505ac9e93f0294370611ae3319e7329822d8d Mon Sep 17 00:00:00 2001 From: Curt Coder Date: Tue, 28 Oct 2014 10:54:05 +0200 Subject: [PATCH 3/5] vreader.xml: Make it valid xml. (nw) --- hash/vreader.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/hash/vreader.xml b/hash/vreader.xml index c429d65e3e8..aa324ff2e4d 100644 --- a/hash/vreader.xml +++ b/hash/vreader.xml @@ -47,3 +47,4 @@ Language: --> + \ No newline at end of file From 31fd590aa633dddcc6fa665e3226301f9f4c779e Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Tue, 28 Oct 2014 12:17:24 +0100 Subject: [PATCH 4/5] Some corrections to the Amiga Workbench softlist --- hash/amiga_workbench.xml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hash/amiga_workbench.xml b/hash/amiga_workbench.xml index f6585cef478..cdb5539f2eb 100644 --- a/hash/amiga_workbench.xml +++ b/hash/amiga_workbench.xml @@ -212,20 +212,21 @@ - - Workbench 1.3.3 (Rev. 34.34) + + + + + Workbench 1.3.3 (US) 1990 Commodore - - + - + - - + From e6a5e406bf00e95d4df741325d4444ab427f2fa0 Mon Sep 17 00:00:00 2001 From: etabeta78 Date: Tue, 28 Oct 2014 14:18:33 +0100 Subject: [PATCH 5/5] (MESS) wswan: converted the video chip to be a device. nw. --- src/mess/drivers/wswan.c | 28 +- src/mess/includes/wswan.h | 97 +-- src/mess/machine/wswan.c | 1011 ++++++++-------------------- src/mess/mess.mak | 2 +- src/mess/video/wswan.c | 583 ---------------- src/mess/video/wswan_video.c | 1211 ++++++++++++++++++++++++++++++++++ src/mess/video/wswan_video.h | 147 +++++ 7 files changed, 1657 insertions(+), 1422 deletions(-) delete mode 100644 src/mess/video/wswan.c create mode 100644 src/mess/video/wswan_video.c create mode 100644 src/mess/video/wswan_video.h diff --git a/src/mess/drivers/wswan.c b/src/mess/drivers/wswan.c index a4c7c1ed4a2..23b113c7316 100644 --- a/src/mess/drivers/wswan.c +++ b/src/mess/drivers/wswan.c @@ -35,14 +35,14 @@ #include "wswan.lh" static ADDRESS_MAP_START (wswan_mem, AS_PROGRAM, 8, wswan_state) - AM_RANGE(0x00000, 0x03fff) AM_RAM // 16kb RAM / 4 colour tiles + AM_RANGE(0x00000, 0x03fff) AM_DEVREADWRITE("vdp", wswan_video_device, vram_r, vram_w) // 16kb RAM / 4 colour tiles AM_RANGE(0x04000, 0x0ffff) AM_NOP // nothing //AM_RANGE(0x10000, 0xeffff) // cart range, setup at machine_start AM_RANGE(0xf0000, 0xfffff) AM_READ(bios_r) ADDRESS_MAP_END static ADDRESS_MAP_START (wscolor_mem, AS_PROGRAM, 8, wswan_state) - AM_RANGE(0x00000, 0x0ffff) AM_RAM // 16kb RAM / 4 colour tiles, 16 colour tiles + palettes + AM_RANGE(0x00000, 0x0ffff) AM_DEVREADWRITE("vdp", wswan_video_device, vram_r, vram_w) // 16kb RAM / 4 colour tiles, 16 colour tiles + palettes //AM_RANGE(0x10000, 0xeffff) // cart range, setup at machine_start AM_RANGE(0xf0000, 0xfffff) AM_READ(bios_r) ADDRESS_MAP_END @@ -83,7 +83,7 @@ PALETTE_INIT_MEMBER(wswan_state, wswan) } } -PALETTE_INIT_MEMBER(wswan_state,wscolor) +PALETTE_INIT_MEMBER(wswan_state, wscolor) { for (int i = 0; i < 4096; i++) { @@ -95,9 +95,9 @@ PALETTE_INIT_MEMBER(wswan_state,wscolor) } static SLOT_INTERFACE_START(wswan_cart) - SLOT_INTERFACE_INTERNAL("ws_rom", WS_ROM_STD) - SLOT_INTERFACE_INTERNAL("ws_sram", WS_ROM_SRAM) - SLOT_INTERFACE_INTERNAL("ws_eeprom", WS_ROM_EEPROM) + SLOT_INTERFACE_INTERNAL("ws_rom", WS_ROM_STD) + SLOT_INTERFACE_INTERNAL("ws_sram", WS_ROM_SRAM) + SLOT_INTERFACE_INTERNAL("ws_eeprom", WS_ROM_EEPROM) SLOT_INTERFACE_END static MACHINE_CONFIG_START( wswan, wswan_state ) @@ -106,11 +106,16 @@ static MACHINE_CONFIG_START( wswan, wswan_state ) MCFG_CPU_PROGRAM_MAP(wswan_mem) MCFG_CPU_IO_MAP(wswan_io) + MCFG_DEVICE_ADD("vdp", WSWAN_VIDEO, 0) + MCFG_WSWAN_VIDEO_TYPE(VDP_TYPE_WSWAN) + MCFG_WSWAN_VIDEO_IRQ_CB(wswan_state, set_irq_line) + MCFG_WSWAN_VIDEO_DMASND_CB(wswan_state, dma_sound_cb) + MCFG_SCREEN_ADD("screen", LCD) MCFG_SCREEN_REFRESH_RATE(75) MCFG_SCREEN_VBLANK_TIME(0) - MCFG_SCREEN_UPDATE_DRIVER(wswan_state, screen_update) - MCFG_SCREEN_SIZE( WSWAN_X_PIXELS, WSWAN_Y_PIXELS ) + MCFG_SCREEN_UPDATE_DEVICE("vdp", wswan_video_device, screen_update) + MCFG_SCREEN_SIZE(WSWAN_X_PIXELS, WSWAN_Y_PIXELS) MCFG_SCREEN_VISIBLE_AREA(0*8, WSWAN_X_PIXELS - 1, 0, WSWAN_Y_PIXELS - 1) MCFG_SCREEN_PALETTE("palette") @@ -141,11 +146,14 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( wscolor, wswan ) MCFG_CPU_MODIFY("maincpu") MCFG_CPU_PROGRAM_MAP(wscolor_mem) - MCFG_MACHINE_START_OVERRIDE(wswan_state, wscolor ) + MCFG_MACHINE_START_OVERRIDE(wswan_state, wscolor) + + MCFG_DEVICE_MODIFY("vdp") + MCFG_WSWAN_VIDEO_TYPE(VDP_TYPE_WSC) MCFG_PALETTE_MODIFY("palette") MCFG_PALETTE_ENTRIES(4096) - MCFG_PALETTE_INIT_OWNER(wswan_state, wscolor ) + MCFG_PALETTE_INIT_OWNER(wswan_state, wscolor) /* software lists */ MCFG_DEVICE_REMOVE("cart_list") diff --git a/src/mess/includes/wswan.h b/src/mess/includes/wswan.h index c92c9d95e31..418b44f5021 100644 --- a/src/mess/includes/wswan.h +++ b/src/mess/includes/wswan.h @@ -10,15 +10,13 @@ #define WSWAN_TYPE_MONO 0 #define WSWAN_TYPE_COLOR 1 -#define WSWAN_X_PIXELS (28*8) -#define WSWAN_Y_PIXELS (18*8) - #define INTERNAL_EEPROM_SIZE 1024 #include "emu.h" #include "cpu/v30mz/v30mz.h" -#include "audio/wswan_snd.h" #include "machine/nvram.h" +#include "audio/wswan_snd.h" +#include "video/wswan_video.h" #include "bus/wswan/slot.h" #include "bus/wswan/rom.h" @@ -30,52 +28,6 @@ struct SoundDMA UINT8 enable; /* Enabled */ }; -struct VDP -{ - UINT8 layer_bg_enable; /* Background layer on/off */ - UINT8 layer_fg_enable; /* Foreground layer on/off */ - UINT8 sprites_enable; /* Sprites on/off */ - UINT8 window_sprites_enable; /* Sprite window on/off */ - UINT8 window_fg_mode; /* 0:inside/outside, 1:??, 2:inside, 3:outside */ - UINT8 current_line; /* Current scanline : 0-158 (159?) */ - UINT8 line_compare; /* Line to trigger line interrupt on */ - UINT32 sprite_table_address; /* Address of the sprite table */ - UINT8 sprite_table_buffer[512]; - UINT8 sprite_first; /* First sprite to draw */ - UINT8 sprite_count; /* Number of sprites to draw */ - UINT16 layer_bg_address; /* Address of the background screen map */ - UINT16 layer_fg_address; /* Address of the foreground screen map */ - UINT8 window_fg_left; /* Left coordinate of foreground window */ - UINT8 window_fg_top; /* Top coordinate of foreground window */ - UINT8 window_fg_right; /* Right coordinate of foreground window */ - UINT8 window_fg_bottom; /* Bottom coordinate of foreground window */ - UINT8 window_sprites_left; /* Left coordinate of sprites window */ - UINT8 window_sprites_top; /* Top coordinate of sprites window */ - UINT8 window_sprites_right; /* Right coordinate of sprites window */ - UINT8 window_sprites_bottom; /* Bottom coordinate of sprites window */ - UINT8 layer_bg_scroll_x; /* Background layer X scroll */ - UINT8 layer_bg_scroll_y; /* Background layer Y scroll */ - UINT8 layer_fg_scroll_x; /* Foreground layer X scroll */ - UINT8 layer_fg_scroll_y; /* Foreground layer Y scroll */ - UINT8 lcd_enable; /* LCD on/off */ - UINT8 icons; /* FIXME: What do we do with these? Maybe artwork? */ - UINT8 color_mode; /* monochrome/color mode */ - UINT8 colors_16; /* 4/16 colors mode */ - UINT8 tile_packed; /* layered/packed tile mode switch */ - UINT8 timer_hblank_enable; /* Horizontal blank interrupt on/off */ - UINT8 timer_hblank_mode; /* Horizontal blank timer mode */ - UINT16 timer_hblank_reload; /* Horizontal blank timer reload value */ - UINT16 timer_hblank_count; /* Horizontal blank timer counter value */ - UINT8 timer_vblank_enable; /* Vertical blank interrupt on/off */ - UINT8 timer_vblank_mode; /* Vertical blank timer mode */ - UINT16 timer_vblank_reload; /* Vertical blank timer reload value */ - UINT16 timer_vblank_count; /* Vertical blank timer counter value */ - UINT8 *vram; /* pointer to start of ram/vram (set by machine_reset) */ - UINT8 *palette_vram; /* pointer to start of palette area in ram/vram (set by machine_reset), WSC only */ - int main_palette[8]; - emu_timer *timer; -}; - class wswan_state : public driver_device { @@ -83,44 +35,39 @@ public: wswan_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), + m_vdp(*this, "vdp"), m_sound(*this, "custom"), m_cart(*this, "cartslot"), m_cursx(*this, "CURSX"), m_cursy(*this, "CURSY"), - m_buttons(*this, "BUTTONS") { } - - virtual void video_start(); - - UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - + m_buttons(*this, "BUTTONS") + { } + required_device m_maincpu; + required_device m_vdp; required_device m_sound; required_device m_cart; DECLARE_READ8_MEMBER(bios_r); DECLARE_READ8_MEMBER(port_r); DECLARE_WRITE8_MEMBER(port_w); - - VDP m_vdp; + UINT8 m_ws_portram[256]; UINT8 m_internal_eeprom[INTERNAL_EEPROM_SIZE]; UINT8 m_system_type; SoundDMA m_sound_dma; - UINT8 *m_ws_ram; UINT8 *m_ws_bios_bank; UINT8 m_bios_disabled; - int m_pal[16][16]; - bitmap_ind16 m_bitmap; UINT8 m_rotate; - - void wswan_clear_irq_line(int irq); + + void set_irq_line(int irq); + void dma_sound_cb(); void common_start(); virtual void machine_start(); virtual void machine_reset(); DECLARE_PALETTE_INIT(wswan); DECLARE_MACHINE_START(wscolor); DECLARE_PALETTE_INIT(wscolor); - TIMER_CALLBACK_MEMBER(wswan_scanline_interrupt); - + protected: /* Interrupt flags */ static const UINT8 WSWAN_IFLAG_STX = 0x01; @@ -131,7 +78,7 @@ protected: static const UINT8 WSWAN_IFLAG_VBLTMR = 0x20; static const UINT8 WSWAN_IFLAG_VBL = 0x40; static const UINT8 WSWAN_IFLAG_HBLTMR = 0x80; - + /* Interrupts */ static const UINT8 WSWAN_INT_STX = 0; static const UINT8 WSWAN_INT_KEY = 1; @@ -141,22 +88,14 @@ protected: static const UINT8 WSWAN_INT_VBLTMR = 5; static const UINT8 WSWAN_INT_VBL = 6; static const UINT8 WSWAN_INT_HBLTMR = 7; - + required_ioport m_cursx; required_ioport m_cursy; required_ioport m_buttons; - - void wswan_register_save(); - void wswan_postload(); - void wswan_handle_irqs(); - void wswan_set_irq_line(int irq); - void wswan_setup_palettes(); - void wswan_draw_background(); - void wswan_draw_foreground_0(); - void wswan_draw_foreground_2(); - void wswan_draw_foreground_3(); - void wswan_handle_sprites( int mask ); - void wswan_refresh_scanline( ); + + void register_save(); + void handle_irqs(); + void clear_irq_line(int irq); }; diff --git a/src/mess/machine/wswan.c b/src/mess/machine/wswan.c index 46d213e6eba..afa8ce8077f 100644 --- a/src/mess/machine/wswan.c +++ b/src/mess/machine/wswan.c @@ -78,144 +78,108 @@ static const UINT8 ws_fake_bios_code[] = { 0xea, 0xc0, 0xff, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -void wswan_state::wswan_handle_irqs() +void wswan_state::handle_irqs() { - if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR ) + if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY); } - else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX ) + else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX ); + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX); } else { - m_maincpu->set_input_line(0, CLEAR_LINE ); + m_maincpu->set_input_line(0, CLEAR_LINE); } } -void wswan_state::wswan_set_irq_line(int irq) +void wswan_state::set_irq_line(int irq) { - if ( m_ws_portram[0xb2] & irq ) + if (m_ws_portram[0xb2] & irq) { m_ws_portram[0xb6] |= irq; - wswan_handle_irqs(); + handle_irqs(); } } -void wswan_state::wswan_clear_irq_line(int irq) +void wswan_state::dma_sound_cb() { - m_ws_portram[0xb6] &= ~irq; - wswan_handle_irqs(); + if ((m_sound_dma.enable & 0x88) == 0x80) + { + address_space &space = m_maincpu->space(AS_PROGRAM); + /* TODO: Output sound DMA byte */ + port_w(space, 0x89, space.read_byte(m_sound_dma.source)); + m_sound_dma.size--; + m_sound_dma.source = (m_sound_dma.source + 1) & 0x0fffff; + if (m_sound_dma.size == 0) + { + m_sound_dma.enable &= 0x7F; + } + } } -void wswan_state::wswan_register_save() +void wswan_state::clear_irq_line(int irq) +{ + m_ws_portram[0xb6] &= ~irq; + handle_irqs(); +} + +void wswan_state::register_save() { save_item(NAME(m_ws_portram)); save_item(NAME(m_internal_eeprom)); save_item(NAME(m_bios_disabled)); save_item(NAME(m_rotate)); - - save_item(NAME(m_vdp.layer_bg_enable)); - save_item(NAME(m_vdp.layer_fg_enable)); - save_item(NAME(m_vdp.sprites_enable)); - save_item(NAME(m_vdp.window_sprites_enable)); - save_item(NAME(m_vdp.window_fg_mode)); - save_item(NAME(m_vdp.current_line)); - save_item(NAME(m_vdp.line_compare)); - save_item(NAME(m_vdp.sprite_table_address)); - save_item(NAME(m_vdp.sprite_table_buffer)); - save_item(NAME(m_vdp.sprite_first)); - save_item(NAME(m_vdp.sprite_count)); - save_item(NAME(m_vdp.layer_bg_address)); - save_item(NAME(m_vdp.layer_fg_address)); - save_item(NAME(m_vdp.window_fg_left)); - save_item(NAME(m_vdp.window_fg_top)); - save_item(NAME(m_vdp.window_fg_right)); - save_item(NAME(m_vdp.window_fg_bottom)); - save_item(NAME(m_vdp.window_sprites_left)); - save_item(NAME(m_vdp.window_sprites_top)); - save_item(NAME(m_vdp.window_sprites_right)); - save_item(NAME(m_vdp.window_sprites_bottom)); - save_item(NAME(m_vdp.layer_bg_scroll_x)); - save_item(NAME(m_vdp.layer_bg_scroll_y)); - save_item(NAME(m_vdp.layer_fg_scroll_x)); - save_item(NAME(m_vdp.layer_fg_scroll_y)); - save_item(NAME(m_vdp.lcd_enable)); - save_item(NAME(m_vdp.icons)); - save_item(NAME(m_vdp.color_mode)); - save_item(NAME(m_vdp.colors_16)); - save_item(NAME(m_vdp.tile_packed)); - save_item(NAME(m_vdp.timer_hblank_enable)); - save_item(NAME(m_vdp.timer_hblank_mode)); - save_item(NAME(m_vdp.timer_hblank_reload)); - save_item(NAME(m_vdp.timer_vblank_enable)); - save_item(NAME(m_vdp.timer_vblank_mode)); - save_item(NAME(m_vdp.timer_vblank_reload)); - save_item(NAME(m_vdp.timer_vblank_count)); - save_item(NAME(m_vdp.main_palette)); - + save_item(NAME(m_sound_dma.source)); save_item(NAME(m_sound_dma.size)); save_item(NAME(m_sound_dma.enable)); - + if (m_cart->exists()) m_cart->save_nvram(); - - machine().save().register_postload(save_prepost_delegate(FUNC(wswan_state::wswan_postload), this)); -} - -void wswan_state::wswan_postload() -{ - address_space &space = m_maincpu->space(AS_PROGRAM); - // restore the vdp pointers - m_vdp.vram = (UINT8*)space.get_read_ptr(0); - m_vdp.palette_vram = (UINT8*)space.get_read_ptr((m_system_type == TYPE_WSC) ? 0xfe00 : 0); } void wswan_state::common_start() { m_ws_bios_bank = auto_alloc_array(machine(), UINT8, 0x10000); memcpy(m_ws_bios_bank + 0xffc0, ws_fake_bios_code, 0x40); - - m_vdp.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(wswan_state::wswan_scanline_interrupt),this), &m_vdp); - m_vdp.timer->adjust(attotime::from_ticks(256, 3072000), 0, attotime::from_ticks(256, 3072000)); - - wswan_register_save(); - + + register_save(); + machine().device("nvram")->set_base(m_internal_eeprom, INTERNAL_EEPROM_SIZE); - + if (m_cart->exists()) { // ROM m_maincpu->space(AS_PROGRAM).install_read_handler(0x20000, 0x2ffff, read8_delegate(FUNC(ws_cart_slot_device::read_rom20),(ws_cart_slot_device*)m_cart)); m_maincpu->space(AS_PROGRAM).install_read_handler(0x30000, 0x3ffff, read8_delegate(FUNC(ws_cart_slot_device::read_rom30),(ws_cart_slot_device*)m_cart)); m_maincpu->space(AS_PROGRAM).install_read_handler(0x40000, 0xeffff, read8_delegate(FUNC(ws_cart_slot_device::read_rom40),(ws_cart_slot_device*)m_cart)); - + // SRAM if (m_cart->get_type() == WS_SRAM) { @@ -231,7 +195,7 @@ void wswan_state::machine_start() m_system_type = TYPE_WSWAN; } -MACHINE_START_MEMBER(wswan_state,wscolor) +MACHINE_START_MEMBER(wswan_state, wscolor) { common_start(); m_system_type = TYPE_WSC; @@ -239,34 +203,19 @@ MACHINE_START_MEMBER(wswan_state,wscolor) void wswan_state::machine_reset() { - address_space &space = m_maincpu->space(AS_PROGRAM); - m_bios_disabled = 0; - - m_ws_ram = (UINT8*) m_maincpu->space(AS_PROGRAM).get_read_ptr(0); - memset(m_ws_ram, 0, 0xffff); - + if (m_cart->exists()) m_rotate = m_cart->get_is_rotated(); else m_rotate = 0; - + /* Intialize ports */ memcpy(m_ws_portram, ws_portram_init, 256); - - /* Initialize VDP */ - memset(&m_vdp, 0, sizeof(m_vdp)); - - m_vdp.vram = (UINT8*)space.get_read_ptr(0); - m_vdp.palette_vram = (UINT8*)space.get_read_ptr(( m_system_type == TYPE_WSC ) ? 0xFE00 : 0 ); - m_vdp.current_line = 145; /* Randomly chosen, beginning of VBlank period to give cart some time to boot up */ - m_vdp.color_mode = 0; - m_vdp.colors_16 = 0; - m_vdp.tile_packed = 0; - + render_target *target = machine().render().first_target(); target->set_view(m_rotate); - + /* Initialize sound DMA */ memset(&m_sound_dma, 0, sizeof(m_sound_dma)); } @@ -282,14 +231,15 @@ READ8_MEMBER( wswan_state::bios_r ) READ8_MEMBER( wswan_state::port_r ) { UINT8 value = m_ws_portram[offset]; - + if (offset != 2) logerror("PC=%X: port read %02X\n", m_maincpu->pc(), offset); + + if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0)) + return m_vdp->reg_r(space, offset); + switch (offset) { - case 0x02: // Current line - value = m_vdp.current_line; - break; case 0x4a: // Sound DMA source address (low) value = m_sound_dma.source & 0xff; break; @@ -308,26 +258,17 @@ READ8_MEMBER( wswan_state::port_r ) case 0x52: // Sound DMA start/stop value = m_sound_dma.enable; break; + case 0x60: + value = m_vdp->reg_r(space, offset); + break; case 0xa0: // Hardware type - // Bit 0 - Disable/enable Bios - // Bit 1 - Determine mono/color - // Bit 2 - Determine color/crystal + // Bit 0 - Disable/enable Bios + // Bit 1 - Determine mono/color + // Bit 2 - Determine color/crystal value = value & ~ 0x02; if (m_system_type == TYPE_WSC) value |= 2; break; - case 0xa8: - value = m_vdp.timer_hblank_count & 0xff; - break; - case 0xa9: - value = m_vdp.timer_hblank_count >> 8; - break; - case 0xaa: - value = m_vdp.timer_vblank_count & 0xff; - break; - case 0xab: - value = m_vdp.timer_vblank_count >> 8; - break; case 0xc0: case 0xc1: case 0xc2: @@ -347,7 +288,7 @@ READ8_MEMBER( wswan_state::port_r ) value = m_cart->read_io(space, offset & 0x0f); break; } - + return value; } @@ -356,319 +297,49 @@ WRITE8_MEMBER( wswan_state::port_w ) address_space &mem = m_maincpu->space(AS_PROGRAM); UINT8 input; logerror("PC=%X: port write %02X <- %02X\n", m_maincpu->pc(), offset, data); + + if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0)) + { + m_vdp->reg_w(space, offset, data); + return; + } + switch (offset) { - case 0x00: /* Display control - Bit 0 - Background layer enable - Bit 1 - Foreground layer enable - Bit 2 - Sprites enable - Bit 3 - Sprite window enable - Bit 4-5 - Foreground window configuration - 00 - Foreground layer is displayed inside and outside foreground window area - 01 - Unknown - 10 - Foreground layer is displayed only inside foreground window area - 11 - Foreground layer is displayed outside foreground window area - Bit 6-7 - Unknown - */ - m_vdp.layer_bg_enable = data & 0x1; - m_vdp.layer_fg_enable = (data & 0x2) >> 1; - m_vdp.sprites_enable = (data & 0x4) >> 2; - m_vdp.window_sprites_enable = (data & 0x8) >> 3; - m_vdp.window_fg_mode = (data & 0x30) >> 4; - break; - case 0x01: /* Background colour - In 16 colour mode: - Bit 0-3 - Palette index - Bit 4-7 - Palette number - Otherwise: - Bit 0-2 - Main palette index - Bit 3-7 - Unknown - */ - break; - case 0x02: /* Current scanline - Bit 0-7 - Current scanline (Most likely read-only) - */ - logerror( "Write to current scanline! Current value: %d Data to write: %d\n", m_vdp.current_line, data ); - /* Returning so we don't overwrite the value here, not that it - * really matters */ - return; - case 0x03: /* Line compare - Bit 0-7 - Line compare - */ - m_vdp.line_compare = data; - logerror( "Write to line compare: %d\n", data ); - break; - case 0x04: /* Sprite table base address - Bit 0-5 - Determine sprite table base address 0 0xxxxxx0 00000000 - Bit 6-7 - Unknown - */ - m_vdp.sprite_table_address = ( data & 0x3F ) << 9; - break; - case 0x05: /* Number of sprite to start drawing with - Bit 0-7 - First sprite number - */ - //m_vdp.sprite_first = data; - if (data) logerror("non-zero first sprite %d\n", m_vdp.sprite_first); - break; - case 0x06: /* Number of sprites to draw - Bit 0-7 - Number of sprites to draw - */ - //m_vdp.sprite_count = data; - break; - case 0x07: /* Background/Foreground table base addresses - Bit 0-2 - Determine background table base address 00xxx000 00000000 - Bit 3 - Unknown - Bit 4-6 - Determine foreground table base address 00xxx000 00000000 - Bit 7 - Unknown - */ - m_vdp.layer_bg_address = (data & 0x7) << 11; - m_vdp.layer_fg_address = (data & 0x70) << 7; - break; - case 0x08: /* Left coordinate of foreground window - Bit 0-7 - Left coordinate of foreground window area - */ - m_vdp.window_fg_left = data; - break; - case 0x09: /* Top coordinate of foreground window - Bit 0-7 - Top coordinatte of foreground window area - */ - m_vdp.window_fg_top = data; - break; - case 0x0a: /* Right coordinate of foreground window - Bit 0-7 - Right coordinate of foreground window area - */ - m_vdp.window_fg_right = data; - break; - case 0x0b: /* Bottom coordinate of foreground window - Bit 0-7 - Bottom coordinate of foreground window area - */ - m_vdp.window_fg_bottom = data; - break; - case 0x0c: /* Left coordinate of sprite window - Bit 0-7 - Left coordinate of sprite window area - */ - m_vdp.window_sprites_left = data; - break; - case 0x0d: /* Top coordinate of sprite window - Bit 0-7 - Top coordinate of sprite window area - */ - m_vdp.window_sprites_top = data; - break; - case 0x0e: /* Right coordinate of sprite window - Bit 0-7 - Right coordinate of sprite window area - */ - m_vdp.window_sprites_right = data; - break; - case 0x0f: /* Bottom coordinate of sprite window - Bit 0-7 - Bottom coordiante of sprite window area - */ - m_vdp.window_sprites_bottom = data; - break; - case 0x10: /* Background layer X scroll - Bit 0-7 - Background layer X scroll - */ - m_vdp.layer_bg_scroll_x = data; - break; - case 0x11: /* Background layer Y scroll - Bit 0-7 - Background layer Y scroll - */ - m_vdp.layer_bg_scroll_y = data; - break; - case 0x12: /* Foreground layer X scroll - Bit 0-7 - Foreground layer X scroll - */ - m_vdp.layer_fg_scroll_x = data; - break; - case 0x13: /* Foreground layer Y scroll - Bit 0-7 - Foreground layer Y scroll - */ - m_vdp.layer_fg_scroll_y = data; - break; - case 0x14: /* LCD control - Bit 0 - LCD enable - Bit 1-7 - Unknown - */ - m_vdp.lcd_enable = data & 0x1; - break; - case 0x15: /* LCD icons - Bit 0 - LCD sleep icon enable - Bit 1 - Vertical position icon enable - Bit 2 - Horizontal position icon enable - Bit 3 - Dot 1 icon enable - Bit 4 - Dot 2 icon enable - Bit 5 - Dot 3 icon enable - Bit 6-7 - Unknown - */ - m_vdp.icons = data; /* ummmmm */ - break; - case 0x1c: /* Palette colors 0 and 1 - Bit 0-3 - Gray tone setting for main palette index 0 - Bit 4-7 - Gray tone setting for main palette index 1 - */ - if (m_system_type == TYPE_WSC) - { - int i = 15 - ( data & 0x0F ); - int j = 15 - ( ( data & 0xF0 ) >> 4 ); - m_vdp.main_palette[0] = ( i << 8 ) | ( i << 4 ) | i; - m_vdp.main_palette[1] = ( j << 8 ) | ( j << 4 ) | j; - } - else - { - m_vdp.main_palette[0] = data & 0x0F; - m_vdp.main_palette[1] = ( data & 0xF0 ) >> 4; - } - break; - case 0x1d: /* Palette colors 2 and 3 - Bit 0-3 - Gray tone setting for main palette index 2 - Bit 4-7 - Gray tone setting for main palette index 3 - */ - if (m_system_type == TYPE_WSC) - { - int i = 15 - ( data & 0x0F ); - int j = 15 - ( ( data & 0xF0 ) >> 4 ); - m_vdp.main_palette[2] = ( i << 8 ) | ( i << 4 ) | i; - m_vdp.main_palette[3] = ( j << 8 ) | ( j << 4 ) | j; - } - else - { - m_vdp.main_palette[2] = data & 0x0F; - m_vdp.main_palette[3] = ( data & 0xF0 ) >> 4; - } - break; - case 0x1e: /* Palette colors 4 and 5 - Bit 0-3 - Gray tone setting for main palette index 4 - Bit 4-7 - Gray tone setting for main paeltte index 5 - */ - if (m_system_type == TYPE_WSC) - { - int i = 15 - ( data & 0x0F ); - int j = 15 - ( ( data & 0xF0 ) >> 4 ); - m_vdp.main_palette[4] = ( i << 8 ) | ( i << 4 ) | i; - m_vdp.main_palette[5] = ( j << 8 ) | ( j << 4 ) | j; - } - else - { - m_vdp.main_palette[4] = data & 0x0F; - m_vdp.main_palette[5] = ( data & 0xF0 ) >> 4; - } - break; - case 0x1f: /* Palette colors 6 and 7 - Bit 0-3 - Gray tone setting for main palette index 6 - Bit 4-7 - Gray tone setting for main palette index 7 - */ - if (m_system_type == TYPE_WSC) - { - int i = 15 - ( data & 0x0F ); - int j = 15 - ( ( data & 0xF0 ) >> 4 ); - m_vdp.main_palette[6] = ( i << 8 ) | ( i << 4 ) | i; - m_vdp.main_palette[7] = ( j << 8 ) | ( j << 4 ) | j; - } - else - { - m_vdp.main_palette[6] = data & 0x0F; - m_vdp.main_palette[7] = ( data & 0xF0 ) >> 4; - } - break; - case 0x20: /* tile/sprite palette settings - Bit 0-3 - Palette 0 index 0 - Bit 4-7 - Palette 0 index 1 */ - case 0x21: /* Bit 0-3 - Palette 0 index 2 - Bit 4-7 - Palette 0 index 3 */ - case 0x22: /* Bit 0-3 - Palette 1 index 0 - Bit 4-7 - Palette 1 index 1 */ - case 0x23: /* Bit 0-3 - Palette 1 index 2 - Bit 4-7 - Palette 1 index 3 */ - case 0x24: /* Bit 0-3 - Palette 2 index 0 - Bit 4-7 - Palette 2 index 1 */ - case 0x25: /* Bit 0-3 - Palette 2 index 2 - Bit 4-7 - Palette 2 index 3 */ - case 0x26: /* Bit 0-3 - Palette 3 index 0 - Bit 4-7 - Palette 3 index 1 */ - case 0x27: /* Bit 0-3 - Palette 3 index 2 - Bit 4-7 - Palette 3 index 3 */ - case 0x28: /* Bit 0-3 - Palette 4 index 0 - Bit 4-7 - Palette 4 index 1 */ - case 0x29: /* Bit 0-3 - Palette 4 index 2 - Bit 4-7 - Palette 4 index 3 */ - case 0x2a: /* Bit 0-3 - Palette 5 index 0 - Bit 4-7 - Palette 5 index 1 */ - case 0x2b: /* Bit 0-3 - Palette 5 index 2 - Bit 4-7 - Palette 5 index 3 */ - case 0x2c: /* Bit 0-3 - Palette 6 index 0 - Bit 4-7 - Palette 6 index 1 */ - case 0x2d: /* Bit 0-3 - Palette 6 index 2 - Bit 4-7 - Palette 6 index 3 */ - case 0x2e: /* Bit 0-3 - Palette 7 index 0 - Bit 4-7 - Palette 7 index 1 */ - case 0x2f: /* Bit 0-3 - Palette 7 index 2 - Bit 4-7 - Palette 7 index 3 */ - case 0x30: /* Bit 0-3 - Palette 8 / Sprite Palette 0 index 0 - Bit 4-7 - Palette 8 / Sprite Palette 0 index 1 */ - case 0x31: /* Bit 0-3 - Palette 8 / Sprite Palette 0 index 2 - Bit 4-7 - Palette 8 / Sprite Palette 0 index 3 */ - case 0x32: /* Bit 0-3 - Palette 9 / Sprite Palette 1 index 0 - Bit 4-7 - Palette 9 / Sprite Palette 1 index 1 */ - case 0x33: /* Bit 0-3 - Palette 9 / Sprite Palette 1 index 2 - Bit 4-7 - Palette 9 / Sprite Palette 1 index 3 */ - case 0x34: /* Bit 0-3 - Palette 10 / Sprite Palette 2 index 0 - Bit 4-7 - Palette 10 / Sprite Palette 2 index 1 */ - case 0x35: /* Bit 0-3 - Palette 10 / Sprite Palette 2 index 2 - Bit 4-7 - Palette 10 / Sprite Palette 2 index 3 */ - case 0x36: /* Bit 0-3 - Palette 11 / Sprite Palette 3 index 0 - Bit 4-7 - Palette 11 / Sprite Palette 3 index 1 */ - case 0x37: /* Bit 0-3 - Palette 11 / Sprite Palette 3 index 2 - Bit 4-7 - Palette 11 / Sprite Palette 3 index 3 */ - case 0x38: /* Bit 0-3 - Palette 12 / Sprite Palette 4 index 0 - Bit 4-7 - Palette 12 / Sprite Palette 4 index 1 */ - case 0x39: /* Bit 0-3 - Palette 12 / Sprite Palette 4 index 2 - Bit 4-7 - Palette 12 / Sprite Palette 4 index 3 */ - case 0x3a: /* Bit 0-3 - Palette 13 / Sprite Palette 5 index 0 - Bit 4-7 - Palette 13 / Sprite Palette 5 index 1 */ - case 0x3b: /* Bit 0-3 - Palette 13 / Sprite Palette 5 index 2 - Bit 4-7 - Palette 13 / Sprite Palette 5 index 3 */ - case 0x3c: /* Bit 0-3 - Palette 14 / Sprite Palette 6 index 0 - Bit 4-7 - Palette 14 / Sprite Palette 6 index 1 */ - case 0x3d: /* Bit 0-3 - Palette 14 / Sprite Palette 6 index 2 - Bit 4-7 - Palette 14 / Sprite Palette 6 index 3 */ - case 0x3e: /* Bit 0-3 - Palette 15 / Sprite Palette 7 index 0 - Bit 4-7 - Palette 15 / Sprite Palette 7 index 1 */ - case 0x3f: /* Bit 0-3 - Palette 15 / Sprite Palette 7 index 2 - Bit 4-7 - Palette 15 / Sprite Palette 7 index 3 */ - break; case 0x40: /* DMA source address (low) - Bit 0-7 - DMA source address bit 0-7 - */ + Bit 0-7 - DMA source address bit 0-7 + */ case 0x41: /* DMA source address (high) - Bit 0-7 - DMA source address bit 8-15 - */ + Bit 0-7 - DMA source address bit 8-15 + */ case 0x42: /* DMA source bank - Bit 0-7 - DMA source bank number - */ + Bit 0-7 - DMA source bank number + */ case 0x43: /* DMA destination bank - Bit 0-7 - DMA destination bank number - */ + Bit 0-7 - DMA destination bank number + */ case 0x44: /* DMA destination address (low) - Bit 0-7 - DMA destination address bit 0-7 - */ + Bit 0-7 - DMA destination address bit 0-7 + */ case 0x45: /* DMA destination address (high) - Bit 0-7 - DMA destination address bit 8-15 - */ + Bit 0-7 - DMA destination address bit 8-15 + */ case 0x46: /* Size of copied data (low) - Bit 0-7 - DMA size bit 0-7 - */ + Bit 0-7 - DMA size bit 0-7 + */ case 0x47: /* Size of copied data (high) - Bit 0-7 - DMA size bit 8-15 - */ + Bit 0-7 - DMA size bit 8-15 + */ break; case 0x48: /* DMA control - Bit 0-6 - Unknown - Bit 7 - DMA stop/start - */ + Bit 0-6 - Unknown + Bit 7 - DMA stop/start + */ if (data & 0x80) { UINT32 src, dst; UINT16 length; - + src = m_ws_portram[0x40] + (m_ws_portram[0x41] << 8) + (m_ws_portram[0x42] << 16); dst = m_ws_portram[0x44] + (m_ws_portram[0x45] << 8) + (m_ws_portram[0x43] << 16); length = m_ws_portram[0x46] + (m_ws_portram[0x47] << 8); @@ -679,7 +350,7 @@ WRITE8_MEMBER( wswan_state::port_w ) dst++; } #ifdef MAME_DEBUG - logerror("DMA src:%X dst:%X length:%d\n", src, dst, length); + logerror("DMA src:%X dst:%X length:%d\n", src, dst, length); #endif m_ws_portram[0x40] = src & 0xff; m_ws_portram[0x41] = (src >> 8) & 0xff; @@ -691,330 +362,257 @@ WRITE8_MEMBER( wswan_state::port_w ) } break; case 0x4a: /* Sound DMA source address (low) - Bit 0-7 - Sound DMA source address bit 0-7 - */ + Bit 0-7 - Sound DMA source address bit 0-7 + */ m_sound_dma.source = (m_sound_dma.source & 0x0fff00) | data; break; case 0x4b: /* Sound DMA source address (high) - Bit 0-7 - Sound DMA source address bit 8-15 - */ + Bit 0-7 - Sound DMA source address bit 8-15 + */ m_sound_dma.source = (m_sound_dma.source & 0x0f00ff) | (data << 8); break; case 0x4c: /* Sound DMA source memory segment - Bit 0-3 - Sound DMA source address segment - Bit 4-7 - Unknown - */ + Bit 0-3 - Sound DMA source address segment + Bit 4-7 - Unknown + */ m_sound_dma.source = (m_sound_dma.source & 0xffff) | ((data & 0x0f) << 16); break; case 0x4d: /* Unknown */ break; case 0x4e: /* Sound DMA transfer size (low) - Bit 0-7 - Sound DMA transfer size bit 0-7 - */ + Bit 0-7 - Sound DMA transfer size bit 0-7 + */ m_sound_dma.size = (m_sound_dma.size & 0xff00) | data; break; case 0x4f: /* Sound DMA transfer size (high) - Bit 0-7 - Sound DMA transfer size bit 8-15 - */ + Bit 0-7 - Sound DMA transfer size bit 8-15 + */ m_sound_dma.size = (m_sound_dma.size & 0xff) | (data << 8); break; case 0x50: /* Unknown */ case 0x51: /* Unknown */ break; case 0x52: /* Sound DMA start/stop - Bit 0-6 - Unknown - Bit 7 - Sound DMA stop/start - */ + Bit 0-6 - Unknown + Bit 7 - Sound DMA stop/start + */ m_sound_dma.enable = data; break; - case 0x60: /* Video mode - Bit 0-4 - Unknown - Bit 5 - Packed mode 0 = not packed mode, 1 = packed mode - Bit 6 - 4/16 colour mode select: 0 = 4 colour mode, 1 = 16 colour mode - Bit 7 - monochrome/colour mode select: 0 = monochrome mode, 1 = colour mode - */ - /* - * 111 - packed, 16 color, use 4000/8000, color - * 110 - not packed, 16 color, use 4000/8000, color - * 101 - packed, 4 color, use 2000, color - * 100 - not packed, 4 color, use 2000, color - * 011 - packed, 16 color, use 4000/8000, monochrome - * 010 - not packed, 16 color , use 4000/8000, monochrome - * 001 - packed, 4 color, use 2000, monochrome - * 000 - not packed, 4 color, use 2000, monochrome - Regular WS monochrome - */ - if (m_system_type == TYPE_WSC) - { - m_vdp.color_mode = data & 0x80; - m_vdp.colors_16 = data & 0x40; - m_vdp.tile_packed = data & 0x20; - } + case 0x60: + m_vdp->reg_w(space, offset, data); break; case 0x80: /* Audio 1 freq (lo) - Bit 0-7 - Audio channel 1 frequency bit 0-7 - */ + Bit 0-7 - Audio channel 1 frequency bit 0-7 + */ case 0x81: /* Audio 1 freq (hi) - Bit 0-7 - Audio channel 1 frequency bit 8-15 - */ + Bit 0-7 - Audio channel 1 frequency bit 8-15 + */ case 0x82: /* Audio 2 freq (lo) - Bit 0-7 - Audio channel 2 frequency bit 0-7 - */ + Bit 0-7 - Audio channel 2 frequency bit 0-7 + */ case 0x83: /* Audio 2 freq (hi) - Bit 0-7 - Audio channel 2 frequency bit 8-15 - */ + Bit 0-7 - Audio channel 2 frequency bit 8-15 + */ case 0x84: /* Audio 3 freq (lo) - Bit 0-7 - Audio channel 3 frequency bit 0-7 - */ + Bit 0-7 - Audio channel 3 frequency bit 0-7 + */ case 0x85: /* Audio 3 freq (hi) - Bit 0-7 - Audio channel 3 frequency bit 8-15 - */ + Bit 0-7 - Audio channel 3 frequency bit 8-15 + */ case 0x86: /* Audio 4 freq (lo) - Bit 0-7 - Audio channel 4 frequency bit 0-7 - */ + Bit 0-7 - Audio channel 4 frequency bit 0-7 + */ case 0x87: /* Audio 4 freq (hi) - Bit 0-7 - Audio channel 4 frequency bit 8-15 - */ + Bit 0-7 - Audio channel 4 frequency bit 8-15 + */ case 0x88: /* Audio 1 volume - Bit 0-3 - Right volume audio channel 1 - Bit 4-7 - Left volume audio channel 1 - */ + Bit 0-3 - Right volume audio channel 1 + Bit 4-7 - Left volume audio channel 1 + */ case 0x89: /* Audio 2 volume - Bit 0-3 - Right volume audio channel 2 - Bit 4-7 - Left volume audio channel 2 - */ + Bit 0-3 - Right volume audio channel 2 + Bit 4-7 - Left volume audio channel 2 + */ case 0x8a: /* Audio 3 volume - Bit 0-3 - Right volume audio channel 3 - Bit 4-7 - Left volume audio channel 3 - */ + Bit 0-3 - Right volume audio channel 3 + Bit 4-7 - Left volume audio channel 3 + */ case 0x8b: /* Audio 4 volume - Bit 0-3 - Right volume audio channel 4 - Bit 4-7 - Left volume audio channel 4 - */ + Bit 0-3 - Right volume audio channel 4 + Bit 4-7 - Left volume audio channel 4 + */ case 0x8c: /* Sweep step - Bit 0-7 - Sweep step - */ + Bit 0-7 - Sweep step + */ case 0x8d: /* Sweep time - Bit 0-7 - Sweep time - */ + Bit 0-7 - Sweep time + */ case 0x8e: /* Noise control - Bit 0-2 - Noise generator type - Bit 3 - Reset - Bit 4 - Enable - Bit 5-7 - Unknown - */ + Bit 0-2 - Noise generator type + Bit 3 - Reset + Bit 4 - Enable + Bit 5-7 - Unknown + */ case 0x8f: /* Sample location - Bit 0-7 - Sample address location 0 00xxxxxx xx000000 - */ + Bit 0-7 - Sample address location 0 00xxxxxx xx000000 + */ case 0x90: /* Audio control - Bit 0 - Audio 1 enable - Bit 1 - Audio 2 enable - Bit 2 - Audio 3 enable - Bit 3 - Audio 4 enable - Bit 4 - Unknown - Bit 5 - Audio 2 voice mode enable - Bit 6 - Audio 3 sweep mode enable - Bit 7 - Audio 4 noise mode enable - */ + Bit 0 - Audio 1 enable + Bit 1 - Audio 2 enable + Bit 2 - Audio 3 enable + Bit 3 - Audio 4 enable + Bit 4 - Unknown + Bit 5 - Audio 2 voice mode enable + Bit 6 - Audio 3 sweep mode enable + Bit 7 - Audio 4 noise mode enable + */ case 0x91: /* Audio output - Bit 0 - Mono select - Bit 1-2 - Output volume - Bit 3 - External stereo - Bit 4-6 - Unknown - Bit 7 - External speaker (Read-only, set by hardware) - */ + Bit 0 - Mono select + Bit 1-2 - Output volume + Bit 3 - External stereo + Bit 4-6 - Unknown + Bit 7 - External speaker (Read-only, set by hardware) + */ case 0x92: /* Noise counter shift register (lo) - Bit 0-7 - Noise counter shift register bit 0-7 - */ + Bit 0-7 - Noise counter shift register bit 0-7 + */ case 0x93: /* Noise counter shift register (hi) - Bit 0-6 - Noise counter shift register bit 8-14 - bit 7 - Unknown - */ + Bit 0-6 - Noise counter shift register bit 8-14 + bit 7 - Unknown + */ case 0x94: /* Master volume - Bit 0-3 - Master volume - Bit 4-7 - Unknown - */ + Bit 0-3 - Master volume + Bit 4-7 - Unknown + */ m_sound->port_w(space, offset, data); break; case 0xa0: /* Hardware type - this is probably read only - Bit 0 - Enable cartridge slot and/or disable bios - Bit 1 - Hardware type: 0 = WS, 1 = WSC - Bit 2-7 - Unknown - */ + Bit 0 - Enable cartridge slot and/or disable bios + Bit 1 - Hardware type: 0 = WS, 1 = WSC + Bit 2-7 - Unknown + */ if ((data & 0x01) && !m_bios_disabled) m_bios_disabled = 1; break; - case 0xa2: /* Timer control - Bit 0 - HBlank Timer enable - Bit 1 - HBlank Timer mode: 0 = one shot, 1 = auto reset - Bit 2 - VBlank Timer(1/75s) enable - Bit 3 - VBlank Timer mode: 0 = one shot, 1 = auto reset - Bit 4-7 - Unknown - */ - m_vdp.timer_hblank_enable = BIT(data, 0); - m_vdp.timer_hblank_mode = BIT(data, 1); - m_vdp.timer_vblank_enable = BIT(data, 2); - m_vdp.timer_vblank_mode = BIT(data, 3); - break; - case 0xa4: /* HBlank timer frequency (low) - reload value - Bit 0-7 - HBlank timer reload value bit 0-7 - */ - m_vdp.timer_hblank_reload &= 0xff00; - m_vdp.timer_hblank_reload += data; - m_vdp.timer_hblank_count = m_vdp.timer_hblank_reload; - break; - case 0xa5: /* HBlank timer frequency (high) - reload value - Bit 8-15 - HBlank timer reload value bit 8-15 - */ - m_vdp.timer_hblank_reload &= 0xff; - m_vdp.timer_hblank_reload += data << 8; - m_vdp.timer_hblank_count = m_vdp.timer_hblank_reload; - break; - case 0xa6: /* VBlank timer frequency (low) - reload value - Bit 0-7 - VBlank timer reload value bit 0-7 - */ - m_vdp.timer_vblank_reload &= 0xff00; - m_vdp.timer_vblank_reload += data; - m_vdp.timer_vblank_count = m_vdp.timer_vblank_reload; - break; - case 0xa7: /* VBlank timer frequency (high) - reload value - Bit 0-7 - VBlank timer reload value bit 8-15 - */ - m_vdp.timer_vblank_reload &= 0xff; - m_vdp.timer_vblank_reload += data << 8; - m_vdp.timer_vblank_count = m_vdp.timer_vblank_reload; - break; - case 0xa8: /* HBlank counter (low) - Bit 0-7 - HBlank counter bit 0-7 - */ - case 0xa9: /* HBlank counter (high) - Bit 0-7 - HBlank counter bit 8-15 - */ - case 0xaa: /* VBlank counter (low) - Bit 0-7 - VBlank counter bit 0-7 - */ - case 0xab: /* VBlank counter (high) - Bit 0-7 - VBlank counter bit 8-15 - */ - break; - + case 0xb0: /* Interrupt base vector - Bit 0-7 - Interrupt base vector - */ + Bit 0-7 - Interrupt base vector + */ break; case 0xb1: /* Communication byte - Bit 0-7 - Communication byte - */ + Bit 0-7 - Communication byte + */ break; case 0xb2: /* Interrupt enable - Bit 0 - Serial transmit interrupt enable - Bit 1 - Key press interrupt enable - Bit 2 - RTC alarm interrupt enable - Bit 3 - Serial receive interrupt enable - Bit 4 - Drawing line detection interrupt enable - Bit 5 - VBlank timer interrupt enable - Bit 6 - VBlank interrupt enable - Bit 7 - HBlank timer interrupt enable - */ + Bit 0 - Serial transmit interrupt enable + Bit 1 - Key press interrupt enable + Bit 2 - RTC alarm interrupt enable + Bit 3 - Serial receive interrupt enable + Bit 4 - Drawing line detection interrupt enable + Bit 5 - VBlank timer interrupt enable + Bit 6 - VBlank interrupt enable + Bit 7 - HBlank timer interrupt enable + */ break; case 0xb3: /* serial communication control - Bit 0 - Receive complete - Bit 1 - Error - Bit 2 - Send complete - Bit 3-4 - Unknown - Bit 5 - Send data interrupt generation - Bit 6 - Connection speed: 0 = 9600 bps, 1 = 38400 bps - bit 7 - Receive data interrupt generation - */ -// data |= 0x02; + Bit 0 - Receive complete + Bit 1 - Error + Bit 2 - Send complete + Bit 3-4 - Unknown + Bit 5 - Send data interrupt generation + Bit 6 - Connection speed: 0 = 9600 bps, 1 = 38400 bps + bit 7 - Receive data interrupt generation + */ + // data |= 0x02; m_ws_portram[0xb1] = 0xff; if (data & 0x80) { -// m_ws_portram[0xb1] = 0x00; + // m_ws_portram[0xb1] = 0x00; data |= 0x04; } if (data & 0x20) { -// data |= 0x01; + // data |= 0x01; } break; case 0xb5: /* Read controls - Bit 0-3 - Current state of input lines (read-only) - Bit 4-6 - Select line of inputs to read - 001 - Read Y cursors - 010 - Read X cursors - 100 - Read START,A,B buttons - Bit 7 - Unknown - */ + Bit 0-3 - Current state of input lines (read-only) + Bit 4-6 - Select line of inputs to read + 001 - Read Y cursors + 010 - Read X cursors + 100 - Read START,A,B buttons + Bit 7 - Unknown + */ data = data & 0xf0; switch (data) - { - case 0x10: /* Read Y cursors: Y1 - Y2 - Y3 - Y4 */ - input = m_cursy->read(); - if (m_rotate) // reorient controls if the console is rotated - { - if (input & 0x01) data |= 0x02; - if (input & 0x02) data |= 0x04; - if (input & 0x04) data |= 0x08; - if (input & 0x08) data |= 0x01; - } - else - data = data | input; + { + case 0x10: /* Read Y cursors: Y1 - Y2 - Y3 - Y4 */ + input = m_cursy->read(); + if (m_rotate) // reorient controls if the console is rotated + { + if (input & 0x01) data |= 0x02; + if (input & 0x02) data |= 0x04; + if (input & 0x04) data |= 0x08; + if (input & 0x08) data |= 0x01; + } + else + data = data | input; break; - case 0x20: /* Read X cursors: X1 - X2 - X3 - X4 */ - input = m_cursx->read(); - if (m_rotate) // reorient controls if the console is rotated - { - if (input & 0x01) data |= 0x02; - if (input & 0x02) data |= 0x04; - if (input & 0x04) data |= 0x08; - if (input & 0x08) data |= 0x01; - } - else - data = data | input; + case 0x20: /* Read X cursors: X1 - X2 - X3 - X4 */ + input = m_cursx->read(); + if (m_rotate) // reorient controls if the console is rotated + { + if (input & 0x01) data |= 0x02; + if (input & 0x02) data |= 0x04; + if (input & 0x04) data |= 0x08; + if (input & 0x08) data |= 0x01; + } + else + data = data | input; break; - case 0x40: /* Read buttons: START - A - B */ - data = data | m_buttons->read(); + case 0x40: /* Read buttons: START - A - B */ + data = data | m_buttons->read(); break; - } + } break; case 0xb6: /* Interrupt acknowledge - Bit 0 - Serial transmit interrupt acknowledge - Bit 1 - Key press interrupt acknowledge - Bit 2 - RTC alarm interrupt acknowledge - Bit 3 - Serial receive interrupt acknowledge - Bit 4 - Drawing line detection interrupt acknowledge - Bit 5 - VBlank timer interrupt acknowledge - Bit 6 - VBlank interrupt acknowledge - Bit 7 - HBlank timer interrupt acknowledge - */ - wswan_clear_irq_line(data); + Bit 0 - Serial transmit interrupt acknowledge + Bit 1 - Key press interrupt acknowledge + Bit 2 - RTC alarm interrupt acknowledge + Bit 3 - Serial receive interrupt acknowledge + Bit 4 - Drawing line detection interrupt acknowledge + Bit 5 - VBlank timer interrupt acknowledge + Bit 6 - VBlank interrupt acknowledge + Bit 7 - HBlank timer interrupt acknowledge + */ + clear_irq_line(data); data = m_ws_portram[0xb6]; break; case 0xba: /* Internal EEPROM data (low) - Bit 0-7 - Internal EEPROM data transfer bit 0-7 - */ + Bit 0-7 - Internal EEPROM data transfer bit 0-7 + */ case 0xbb: /* Internal EEPROM data (high) - Bit 0-7 - Internal EEPROM data transfer bit 8-15 - */ + Bit 0-7 - Internal EEPROM data transfer bit 8-15 + */ break; case 0xbc: /* Internal EEPROM address (low) - Bit 0-7 - Internal EEPROM address bit 1-8 - */ + Bit 0-7 - Internal EEPROM address bit 1-8 + */ case 0xbd: /* Internal EEPROM address (high) - Bit 0 - Internal EEPROM address bit 9(?) - Bit 1-7 - Unknown - Only 1KByte internal EEPROM?? - */ + Bit 0 - Internal EEPROM address bit 9(?) + Bit 1-7 - Unknown + Only 1KByte internal EEPROM?? + */ break; case 0xbe: /* Internal EEPROM command - Bit 0 - Read complete (read only) - Bit 1 - Write complete (read only) - Bit 2-3 - Unknown - Bit 4 - Read - Bit 5 - Write - Bit 6 - Protect - Bit 7 - Initialize - */ + Bit 0 - Read complete (read only) + Bit 1 - Write complete (read only) + Bit 2-3 - Unknown + Bit 4 - Read + Bit 5 - Write + Bit 6 - Protect + Bit 7 - Initialize + */ if (data & 0x20) { UINT16 addr = ( ( ( m_ws_portram[0xbd] << 8 ) | m_ws_portram[0xbc] ) << 1 ) & 0x1FF; @@ -1056,92 +654,7 @@ WRITE8_MEMBER( wswan_state::port_w ) logerror( "Write to unsupported port: %X - %X\n", offset, data ); break; } - + /* Update the port value */ m_ws_portram[offset] = data; } - - -TIMER_CALLBACK_MEMBER(wswan_state::wswan_scanline_interrupt) -{ - if( m_vdp.current_line < 144 ) - { - wswan_refresh_scanline(); - } - - /* Decrement 12kHz (HBlank) counter */ - if ( m_vdp.timer_hblank_enable && m_vdp.timer_hblank_reload != 0 ) - { - m_vdp.timer_hblank_count--; - logerror( "timer_hblank_count: %X\n", m_vdp.timer_hblank_count ); - if ( m_vdp.timer_hblank_count == 0 ) - { - if ( m_vdp.timer_hblank_mode ) - { - m_vdp.timer_hblank_count = m_vdp.timer_hblank_reload; - } - else - { - m_vdp.timer_hblank_reload = 0; - } - logerror( "trigerring hbltmr interrupt\n" ); - wswan_set_irq_line( WSWAN_IFLAG_HBLTMR ); - } - } - - /* Handle Sound DMA */ - if ( ( m_sound_dma.enable & 0x88 ) == 0x80 ) - { - address_space &space = m_maincpu->space(AS_PROGRAM ); - /* TODO: Output sound DMA byte */ - port_w( space, 0x89, space.read_byte(m_sound_dma.source ) ); - m_sound_dma.size--; - m_sound_dma.source = ( m_sound_dma.source + 1 ) & 0x0FFFFF; - if ( m_sound_dma.size == 0 ) - { - m_sound_dma.enable &= 0x7F; - } - } - -// m_vdp.current_line = (m_vdp.current_line + 1) % 159; - - if( m_vdp.current_line == 144 ) // buffer sprite table - { - memcpy(m_vdp.sprite_table_buffer, &m_vdp.vram[m_vdp.sprite_table_address], 512); - m_vdp.sprite_count = m_ws_portram[0x06]; - m_vdp.sprite_first = m_ws_portram[0x05]; // always zero? - } - - if( m_vdp.current_line == 144 ) - { - wswan_set_irq_line( WSWAN_IFLAG_VBL ); - /* Decrement 75Hz (VBlank) counter */ - if ( m_vdp.timer_vblank_enable && m_vdp.timer_vblank_reload != 0 ) - { - m_vdp.timer_vblank_count--; - logerror( "timer_vblank_count: %X\n", m_vdp.timer_vblank_count ); - if ( m_vdp.timer_vblank_count == 0 ) - { - if ( m_vdp.timer_vblank_mode ) - { - m_vdp.timer_vblank_count = m_vdp.timer_vblank_reload; - } - else - { - m_vdp.timer_vblank_reload = 0; - } - logerror( "triggering vbltmr interrupt\n" ); - wswan_set_irq_line( WSWAN_IFLAG_VBLTMR ); - } - } - } - -// m_vdp.current_line = (m_vdp.current_line + 1) % 159; - - if ( m_vdp.current_line == m_vdp.line_compare ) - { - wswan_set_irq_line( WSWAN_IFLAG_LCMP ); - } - - m_vdp.current_line = (m_vdp.current_line + 1) % 159; -} diff --git a/src/mess/mess.mak b/src/mess/mess.mak index a0d06ec1e98..f14e966a98b 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -1029,7 +1029,7 @@ $(MESSOBJ)/bally.a: \ $(MESSOBJ)/bandai.a: \ $(MESS_DRIVERS)/sv8000.o \ $(MESS_DRIVERS)/rx78.o \ - $(MESS_DRIVERS)/wswan.o $(MESS_AUDIO)/wswan_snd.o $(MESS_MACHINE)/wswan.o $(MESS_VIDEO)/wswan.o \ + $(MESS_DRIVERS)/wswan.o $(MESS_AUDIO)/wswan_snd.o $(MESS_MACHINE)/wswan.o $(MESS_VIDEO)/wswan_video.o \ $(MESSOBJ)/be.a: \ $(MESS_DRIVERS)/bebox.o $(MESS_MACHINE)/bebox.o \ diff --git a/src/mess/video/wswan.c b/src/mess/video/wswan.c deleted file mode 100644 index da649d76779..00000000000 --- a/src/mess/video/wswan.c +++ /dev/null @@ -1,583 +0,0 @@ -/*************************************************************************** - - wswan.c - - File to handle video emulation of the Bandai WonderSwan. - - Anthony Kruize - Wilbert Pol - -***************************************************************************/ - -#include "includes/wswan.h" - -void wswan_state::wswan_setup_palettes() -{ - int i,j; - - if ( m_vdp.color_mode ) { - for( i = 0; i < 16; i++ ) { - for( j = 0; j < 16; j++ ) { - m_pal[i][j] = ( ( m_vdp.palette_vram[ ( i << 5 ) + j*2 + 1 ] << 8 ) | m_vdp.palette_vram[ ( i << 5 ) + j*2 ] ) & 0x0FFF; - } - } - } else { - for( i = 0; i < 16; i++ ) { - m_pal[i][0] = m_ws_portram[ 0x20 + ( i << 1 ) ] & 0x07; - m_pal[i][1] = ( m_ws_portram[ 0x20 + ( i << 1 ) ] >> 4 ) & 0x07; - m_pal[i][2] = m_ws_portram[ 0x21 + ( i << 1 ) ] & 0x07; - m_pal[i][3] = ( m_ws_portram[ 0x21 + ( i << 1 ) ] >> 4 ) & 0x07; - } - } -} - -void wswan_state::wswan_draw_background() -{ - UINT16 map_addr; - UINT8 start_column; - int column; - - map_addr = m_vdp.layer_bg_address + ( ( ( m_vdp.current_line + m_vdp.layer_bg_scroll_y ) & 0xF8 ) << 3 ); - start_column = ( m_vdp.layer_bg_scroll_x >> 3 ); - for( column = 0; column < 29; column++ ) { - int tile_data, tile_number, tile_palette, tile_line, tile_address; - UINT32 plane0=0, plane1=0, plane2=0, plane3=0; - int x, x_offset; - - tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) - | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; - tile_number = tile_data & 0x01FF; - tile_palette = ( tile_data >> 9 ) & 0x0F; - - tile_line = ( m_vdp.current_line + m_vdp.layer_bg_scroll_y ) & 0x07; - if ( tile_data & 0x8000 ) { - tile_line = 7 - tile_line; - } - - if ( m_vdp.colors_16 ) { - tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 24 ) | ( m_vdp.vram[ tile_address + 1 ] << 16 ) | ( m_vdp.vram[ tile_address + 2 ] << 8 ) | m_vdp.vram[ tile_address + 3 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = m_vdp.vram[ tile_address + 2 ] << 2; - plane3 = m_vdp.vram[ tile_address + 3 ] << 3; - } - } else { - tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = 0; - plane3 = 0; - } - } - - for( x = 0; x < 8; x++ ) { - int col; - if ( m_vdp.tile_packed ) { - if ( m_vdp.colors_16 ) { - col = plane0 & 0x0F; - plane0 = plane0 >> 4; - } else { - col = plane0 & 0x03; - plane0 = plane0 >> 2; - } - } else { - col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); - plane3 = plane3 >> 1; - plane2 = plane2 >> 1; - plane1 = plane1 >> 1; - plane0 = plane0 >> 1; - } - if ( tile_data & 0x4000 ) { - x_offset = x + ( column << 3 ) - ( m_vdp.layer_bg_scroll_x & 0x07 ); - } else { - x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_bg_scroll_x & 0x07 ); - } - if ( x_offset >= 0 && x_offset < WSWAN_X_PIXELS ) { - if ( m_vdp.colors_16 ) { - if ( col ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - /* Hmmmm, what should we do here... Is this correct?? */ - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } - } - } else { - if ( col || !(tile_palette & 4 ) ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; - } - } - } - } - } - } -} - -void wswan_state::wswan_draw_foreground_0() -{ - UINT16 map_addr; - UINT8 start_column; - int column; - map_addr = m_vdp.layer_fg_address + ( ( ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0xF8 ) << 3 ); - start_column = ( m_vdp.layer_fg_scroll_x >> 3 ); - for( column = 0; column < 29; column++ ) { - UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; - int x, x_offset, tile_line, tile_address; - int tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) - | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; - int tile_number = tile_data & 0x01FF; - int tile_palette = ( tile_data >> 9 ) & 0x0F; - - tile_line = ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0x07; - if ( tile_data & 0x8000 ) { - tile_line = 7 - tile_line; - } - - if ( m_vdp.colors_16 ) { - tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 24 ) | ( m_vdp.vram[ tile_address + 1 ] << 16 ) | ( m_vdp.vram[ tile_address + 2 ] << 8 ) | m_vdp.vram[ tile_address + 3 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = m_vdp.vram[ tile_address + 2 ] << 2; - plane3 = m_vdp.vram[ tile_address + 3 ] << 3; - } - } else { - tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = 0; - plane3 = 0; - } - } - - for( x = 0; x < 8; x++ ) { - int col; - if ( m_vdp.tile_packed ) { - if ( m_vdp.colors_16 ) { - col = plane0 & 0x0F; - plane0 = plane0 >> 4; - } else { - col = plane0 & 0x03; - plane0 = plane0 >> 2; - } - } else { - col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); - plane3 = plane3 >> 1; - plane2 = plane2 >> 1; - plane1 = plane1 >> 1; - plane0 = plane0 >> 1; - } - if ( tile_data & 0x4000 ) { - x_offset = x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); - } else { - x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); - } - if ( x_offset >= 0 && x_offset < WSWAN_X_PIXELS ) { - if ( m_vdp.colors_16 ) { - if ( col ) { -// if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; -// } else { -// /* Hmmmm, what should we do here... Is this correct?? */ -// m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; -// } - } - } else { - if ( col || !(tile_palette & 4 ) ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; - } - } - } - } - } - } -} - -void wswan_state::wswan_draw_foreground_2() -{ - UINT16 map_addr; - UINT8 start_column; - int column; - map_addr = m_vdp.layer_fg_address + ( ( ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0xF8 ) << 3 ); - start_column = ( m_vdp.layer_fg_scroll_x >> 3 ); - for( column = 0; column < 29; column++ ) { - UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; - int x, x_offset, tile_line, tile_address; - int tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) - | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; - int tile_number = tile_data & 0x01FF; - int tile_palette = ( tile_data >> 9 ) & 0x0F; - - tile_line = ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0x07; - if ( tile_data & 0x8000 ) { - tile_line = 7 - tile_line; - } - - if ( m_vdp.colors_16 ) { - tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 24 ) | ( m_vdp.vram[ tile_address + 1 ] << 16 ) | ( m_vdp.vram[ tile_address + 2 ] << 8 ) | m_vdp.vram[ tile_address + 3 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = m_vdp.vram[ tile_address + 2 ] << 2; - plane3 = m_vdp.vram[ tile_address + 3 ] << 3; - } - } else { - tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = 0; - plane3 = 0; - } - } - - for( x = 0; x < 8; x++ ) { - int col; - if ( m_vdp.tile_packed ) { - if ( m_vdp.colors_16 ) { - col = plane0 & 0x0F; - plane0 = plane0 >> 4; - } else { - col = plane0 & 0x03; - plane0 = plane0 >> 2; - } - } else { - col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); - plane3 = plane3 >> 1; - plane2 = plane2 >> 1; - plane1 = plane1 >> 1; - plane0 = plane0 >> 1; - } - if ( tile_data & 0x4000 ) { - x_offset = x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); - } else { - x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); - } - if ( x_offset >= 0 && x_offset >= m_vdp.window_fg_left && x_offset < m_vdp.window_fg_right && x_offset < WSWAN_X_PIXELS ) { - if ( m_vdp.colors_16 ) { - if ( col ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - /* Hmmmm, what should we do here... Is this correct?? */ - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } - } - } else { - if ( col || !(tile_palette & 4 ) ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; - } - } - } - } - } - } -} - -void wswan_state::wswan_draw_foreground_3() -{ - UINT16 map_addr; - UINT8 start_column; - int column; - map_addr = m_vdp.layer_fg_address + ( ( ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0xF8 ) << 3 ); - start_column = ( m_vdp.layer_fg_scroll_x >> 3 ); - for( column = 0; column < 29; column++ ) { - UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; - int x, x_offset, tile_line, tile_address; - int tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) - | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; - int tile_number = tile_data & 0x01FF; - int tile_palette = ( tile_data >> 9 ) & 0x0F; - - tile_line = ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0x07; - if ( tile_data & 0x8000 ) { // vflip - tile_line = 7 - tile_line; - } - - if ( m_vdp.colors_16 ) { - tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 24 ) | ( m_vdp.vram[ tile_address + 1 ] << 16 ) | ( m_vdp.vram[ tile_address + 2 ] << 8 ) | m_vdp.vram[ tile_address + 3 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = m_vdp.vram[ tile_address + 2 ] << 2; - plane3 = m_vdp.vram[ tile_address + 3 ] << 3; - } - } else { - tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = 0; - plane3 = 0; - } - } - - for( x = 0; x < 8; x++ ) { - int col; - if ( m_vdp.tile_packed ) { - if ( m_vdp.colors_16 ) { - col = plane0 & 0x0F; - plane0 = plane0 >> 4; - } else { - col = plane0 & 0x03; - plane0 = plane0 >> 2; - } - } else { - col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); - plane3 = plane3 >> 1; - plane2 = plane2 >> 1; - plane1 = plane1 >> 1; - plane0 = plane0 >> 1; - } - if ( tile_data & 0x4000 ) { - x_offset = x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); - } else { - x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); - } - if ( ( x_offset >= 0 && x_offset < m_vdp.window_fg_left ) || ( x_offset >= m_vdp.window_fg_right && x_offset < WSWAN_X_PIXELS ) ) { - if ( m_vdp.colors_16 ) { - if ( col ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - /* Hmmmm, what should we do here... Is this correct?? */ - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } - } - } else { - if ( col || !(tile_palette & 4 ) ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; - } - } - } - } - } - } -} - -void wswan_state::wswan_handle_sprites(int mask ) -{ - int i; - if ( m_vdp.sprite_count == 0 ) - return; - for( i = m_vdp.sprite_first + m_vdp.sprite_count - 1; i >= m_vdp.sprite_first; i-- ) { - UINT8 x, y; - UINT16 tile_data; - int tile_line; - - tile_data = ( m_vdp.sprite_table_buffer[ i * 4 + 1 ] << 8 ) | m_vdp.sprite_table_buffer[ i * 4 ]; - y = m_vdp.sprite_table_buffer[ i * 4 + 2 ]; - x = m_vdp.sprite_table_buffer[ i * 4 + 3 ]; - tile_line = m_vdp.current_line - y; - tile_line = tile_line & 0xFF; - if ( ( tile_line >= 0 ) && ( tile_line < 8 ) && ( ( tile_data & 0x2000 ) == mask ) ) { - UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; - int j, x_offset, tile_address; - int tile_number = tile_data & 0x01FF; - int tile_palette = 8 + ( ( tile_data >> 9 ) & 0x07 ); - int check_clip = 0; - if ( tile_data & 0x8000 ) { - tile_line = 7 - tile_line; - } - - if ( m_vdp.colors_16 ) { - tile_address = 0x4000 + ( tile_number * 32 ) + ( tile_line << 2 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 24 ) | ( m_vdp.vram[ tile_address + 1 ] << 16 ) | ( m_vdp.vram[ tile_address + 2 ] << 8 ) | m_vdp.vram[ tile_address + 3 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = m_vdp.vram[ tile_address + 2 ] << 2; - plane3 = m_vdp.vram[ tile_address + 3 ] << 3; - } - } else { - tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); - if ( m_vdp.tile_packed ) { - plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; - } else { - plane0 = m_vdp.vram[ tile_address + 0 ]; - plane1 = m_vdp.vram[ tile_address + 1 ] << 1; - plane2 = 0; - plane3 = 0; - } - } - - if ( m_vdp.window_sprites_enable ) { - if ( tile_data & 0x1000 ) { - if ( m_vdp.current_line >= m_vdp.window_sprites_top && m_vdp.current_line <= m_vdp.window_sprites_bottom ) { - check_clip = 1; - } - } else { - if ( m_vdp.current_line < m_vdp.window_sprites_top || m_vdp.current_line > m_vdp.window_sprites_bottom ) { - continue; - } - } - } - - for ( j = 0; j < 8; j++ ) { - int col; - if ( m_vdp.tile_packed ) { - if ( m_vdp.colors_16 ) { - col = plane0 & 0x0F; - plane0 = plane0 >> 4; - } else { - col = plane0 & 0x03; - plane0 = plane0 >> 2; - } - } else { - col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); - plane3 = plane3 >> 1; - plane2 = plane2 >> 1; - plane1 = plane1 >> 1; - plane0 = plane0 >> 1; - } - if ( tile_data & 0x4000 ) { - x_offset = x + j; - } else { - x_offset = x + 7 - j; - } - x_offset = x_offset & 0xFF; - if ( m_vdp.window_sprites_enable ) { - if ( tile_data & 0x1000 && check_clip ) { - if ( x_offset >= m_vdp.window_sprites_left && x_offset <= m_vdp.window_sprites_right ) { - continue; - } - } else { - if ( x_offset < m_vdp.window_sprites_left || x_offset > m_vdp.window_sprites_right ) { -// continue; - } - } - } - if ( x_offset >= 0 && x_offset < WSWAN_X_PIXELS ) { - if ( m_vdp.colors_16 ) { - if ( col ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - /* Hmmmm, what should we do here... Is this correct?? */ - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } - } - } else { - if ( col || !(tile_palette & 4 ) ) { - if ( m_vdp.color_mode ) { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; - } else { - m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; - } - } - } - } - } - } - } -} - -void wswan_state::wswan_refresh_scanline() -{ - wswan_setup_palettes(); - - rectangle rec(0, WSWAN_X_PIXELS, m_vdp.current_line, m_vdp.current_line); - if ( m_ws_portram[0x14] ) { - /* Not sure if these background color checks and settings are correct */ - if ( m_vdp.color_mode && m_vdp.colors_16 ) { - m_bitmap.fill( m_pal[m_ws_portram[0x01]>>4][m_ws_portram[0x01]&0x0F], rec ); - } else { - m_bitmap.fill( m_vdp.main_palette[m_ws_portram[0x01]&0x07], rec ); - } - } else { - m_bitmap.fill( 0, rec ); - return; - } - - /* - * Draw background layer - */ - if ( m_vdp.layer_bg_enable ) { - wswan_draw_background(); - } - - /* - * Draw sprites between background and foreground layers - */ - if ( m_vdp.sprites_enable ) { - wswan_handle_sprites(0); - } - - /* - * Draw foreground layer, taking window settings into account - */ - if ( m_vdp.layer_fg_enable ) { - switch( m_vdp.window_fg_mode ) { - case 0: /* FG inside & outside window area */ - wswan_draw_foreground_0(); - break; - case 1: /* ??? */ - logerror( "Unknown foreground mode 1 set\n" ); - break; - case 2: /* FG only inside window area */ - if ( m_vdp.current_line >= m_vdp.window_fg_top && m_vdp.current_line <= m_vdp.window_fg_bottom ) { - wswan_draw_foreground_2(); - } - break; - case 3: /* FG only outside window area */ - if ( m_vdp.current_line < m_vdp.window_fg_top || m_vdp.current_line > m_vdp.window_fg_bottom ) { - wswan_draw_foreground_0(); - } else { - wswan_draw_foreground_3(); - } - break; - } - } - - /* - * Draw sprites in front of foreground layer - */ - if ( m_vdp.sprites_enable ) { - wswan_handle_sprites(0x2000); - } -} - - -void wswan_state::video_start() -{ - machine().first_screen()->register_screen_bitmap(m_bitmap); - save_item(NAME(m_bitmap)); -} - -UINT32 wswan_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); - return 0; -} diff --git a/src/mess/video/wswan_video.c b/src/mess/video/wswan_video.c new file mode 100644 index 00000000000..c4f6c72c8c5 --- /dev/null +++ b/src/mess/video/wswan_video.c @@ -0,0 +1,1211 @@ +/*************************************************************************** + + wswan_video.c + + File to handle video emulation of the Bandai WonderSwan VDP. + + Anthony Kruize + Wilbert Pol + + TODO: + - remove the redundant parts of m_regs + - split the Color VDP from the Mono VDP? + + ***************************************************************************/ + +#include "wswan_video.h" + +const device_type WSWAN_VIDEO = &device_creator; + + +wswan_video_device::wswan_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, WSWAN_VIDEO, "Bandai WonderSwan VDP", tag, owner, clock, "wswan_video", __FILE__), + m_vdp_type(VDP_TYPE_WSWAN) +{ +} + + +void wswan_video_device::common_save() +{ + save_item(NAME(m_bitmap)); + save_item(NAME(m_vram)); + save_item(NAME(m_palette_port)); + save_item(NAME(m_pal)); + save_item(NAME(m_regs)); + + save_item(NAME(m_layer_bg_enable)); + save_item(NAME(m_layer_fg_enable)); + save_item(NAME(m_sprites_enable)); + save_item(NAME(m_window_sprites_enable)); + save_item(NAME(m_window_fg_mode)); + save_item(NAME(m_bg_control)); + save_item(NAME(m_current_line)); + save_item(NAME(m_line_compare)); + save_item(NAME(m_sprite_table_address)); + save_item(NAME(m_sprite_table_buffer)); + save_item(NAME(m_sprite_first)); + save_item(NAME(m_sprite_count)); + save_item(NAME(m_sprite_first_latch)); + save_item(NAME(m_sprite_count_latch)); + save_item(NAME(m_layer_bg_address)); + save_item(NAME(m_layer_fg_address)); + save_item(NAME(m_window_fg_left)); + save_item(NAME(m_window_fg_top)); + save_item(NAME(m_window_fg_right)); + save_item(NAME(m_window_fg_bottom)); + save_item(NAME(m_window_sprites_left)); + save_item(NAME(m_window_sprites_top)); + save_item(NAME(m_window_sprites_right)); + save_item(NAME(m_window_sprites_bottom)); + save_item(NAME(m_layer_bg_scroll_x)); + save_item(NAME(m_layer_bg_scroll_y)); + save_item(NAME(m_layer_fg_scroll_x)); + save_item(NAME(m_layer_fg_scroll_y)); + save_item(NAME(m_lcd_control)); + save_item(NAME(m_icons)); + save_item(NAME(m_color_mode)); + save_item(NAME(m_colors_16)); + save_item(NAME(m_tile_packed)); + save_item(NAME(m_timer_hblank_enable)); + save_item(NAME(m_timer_hblank_mode)); + save_item(NAME(m_timer_hblank_reload)); + save_item(NAME(m_timer_vblank_enable)); + save_item(NAME(m_timer_vblank_mode)); + save_item(NAME(m_timer_vblank_reload)); + save_item(NAME(m_timer_vblank_count)); + save_item(NAME(m_main_palette)); +} + +void wswan_video_device::device_start() +{ + machine().first_screen()->register_screen_bitmap(m_bitmap); + + m_timer = timer_alloc(TIMER_SCANLINE); + m_timer->adjust(attotime::from_ticks(256, 3072000), 0, attotime::from_ticks(256, 3072000)); + + // bind callbacks + m_set_irq_cb.bind_relative_to(*owner()); + m_snd_dma_cb.bind_relative_to(*owner()); + + if (m_vdp_type == VDP_TYPE_WSC) + { + m_vram.resize_and_clear(0x10000); + m_palette_vram = m_vram + 0xfe00; + } + else + { + m_vram.resize_and_clear(0x4000); + m_palette_vram = m_vram; + } + + common_save(); +} + +// This is a copy of ws_portram_init +// TODO: remove unneeded parts! +static const UINT8 vdp_regs_init[256] = +{ + 0x00, 0x00, 0x00/*?*/, 0xbb, 0x00, 0x00, 0x00, 0x26, 0xfe, 0xde, 0xf9, 0xfb, 0xdb, 0xd7, 0x7f, 0xf5, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x99, 0xfd, 0xb7, 0xdf, + 0x30, 0x57, 0x75, 0x76, 0x15, 0x73, 0x70/*77?*/, 0x77, 0x20, 0x75, 0x50, 0x36, 0x70, 0x67, 0x50, 0x77, + 0x57, 0x54, 0x75, 0x77, 0x75, 0x17, 0x37, 0x73, 0x50, 0x57, 0x60, 0x77, 0x70, 0x77, 0x10, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x87, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdb, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x83, 0x00, + 0x2f, 0x3f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, + 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, + 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, + 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 +}; + + +void wswan_video_device::device_reset() +{ + m_layer_bg_enable = 0; + m_layer_fg_enable = 0; + m_sprites_enable = 0; + m_window_sprites_enable = 0; + m_window_fg_mode = 0; + m_bg_control = 0; + m_current_line = 145; // Randomly chosen, beginning of VBlank period to give cart some time to boot up + m_line_compare = 0; + m_sprite_table_address = 0; + m_sprite_first = 0; + m_sprite_count = 0; + m_sprite_first_latch = 0; + m_sprite_count_latch = 0; + m_layer_bg_address = 0; + m_layer_fg_address = 0; + m_window_fg_left = 0; + m_window_fg_top = 0; + m_window_fg_right = 0; + m_window_fg_bottom = 0; + m_window_sprites_left = 0; + m_window_sprites_top = 0; + m_window_sprites_right = 0; + m_window_sprites_bottom = 0; + m_layer_bg_scroll_x = 0; + m_layer_bg_scroll_y = 0; + m_layer_fg_scroll_x = 0; + m_layer_fg_scroll_y = 0; + m_lcd_control = 0x01; + m_icons = 0; + m_color_mode = 0; + m_colors_16 = 0; + m_tile_packed = 0; + m_timer_hblank_enable = 0; + m_timer_hblank_mode = 0; + m_timer_hblank_reload = 0; + m_timer_hblank_count = 0; + m_timer_vblank_enable = 0; + m_timer_vblank_mode = 0; + m_timer_vblank_reload = 0; + m_timer_vblank_count = 0; /* Vertical blank timer counter value */ + + memset(m_sprite_table_buffer, 0, sizeof(m_sprite_table_buffer)); + memset(m_main_palette, 0, sizeof(m_main_palette)); + memcpy(m_regs, vdp_regs_init, 256); + for (int i = 0; i < 0x20; i++) + m_palette_port[i] = m_regs[i + 0x20]; + + setup_palettes(); +} + + +void wswan_video_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_SCANLINE: + scanline_interrupt(); + break; + } +} + + +void wswan_video_device::setup_palettes() +{ + if (m_color_mode) + { + for (int i = 0; i < 16; i++) + for (int j = 0; j < 16; j++) + m_pal[i][j] = ((m_palette_vram[(i << 5) + j * 2 + 1] << 8) | m_palette_vram[(i << 5) + j * 2]) & 0x0fff; + } + else + { + for (int i = 0; i < 16; i++) + { + m_pal[i][0] = (m_palette_port[(i << 1)] >> 0) & 0x07; + m_pal[i][1] = (m_palette_port[(i << 1)] >> 4) & 0x07; + m_pal[i][2] = (m_palette_port[(i << 1) + 1] >> 0) & 0x07; + m_pal[i][3] = (m_palette_port[(i << 1) + 1] >> 4) & 0x07; + } + } +} + +void wswan_video_device::draw_background() +{ + UINT16 map_addr = m_layer_bg_address + (((m_current_line + m_layer_bg_scroll_y) & 0xf8) << 3); + UINT8 start_column = (m_layer_bg_scroll_x >> 3); + + for (int column = 0; column < 29; column++) + { + UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; + int x_offset, tile_line, tile_address; + int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) + | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; + int tile_number = tile_data & 0x01ff; + int tile_palette = (tile_data >> 9) & 0x0f; + + tile_line = (m_current_line + m_layer_bg_scroll_y) & 0x07; + if (tile_data & 0x8000) // vflip + tile_line = 7 - tile_line; + + if (m_colors_16) + { + tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = m_vram[tile_address + 2] << 2; + plane3 = m_vram[tile_address + 3] << 3; + } + } + else + { + tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = 0; + plane3 = 0; + } + } + + for (int x = 0; x < 8; x++) + { + int col; + if (m_tile_packed) + { + if (m_colors_16) + { + col = plane0 & 0x0f; + plane0 = plane0 >> 4; + } + else + { + col = plane0 & 0x03; + plane0 = plane0 >> 2; + } + } + else + { + col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); + plane3 = plane3 >> 1; + plane2 = plane2 >> 1; + plane1 = plane1 >> 1; + plane0 = plane0 >> 1; + } + + if (tile_data & 0x4000) + x_offset = x + (column << 3) - (m_layer_bg_scroll_x & 0x07); + else + x_offset = 7 - x + (column << 3) - (m_layer_bg_scroll_x & 0x07); + + if (x_offset >= 0 && x_offset < WSWAN_X_PIXELS) + { + if (m_colors_16) + { + if (col) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + { + /* Hmmmm, what should we do here... Is this correct?? */ + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + } + } + } + else + { + if (col || !(tile_palette & 4)) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; + } + } + } + } + } +} + +void wswan_video_device::draw_foreground_0() +{ + UINT16 map_addr = m_layer_fg_address + (((m_current_line + m_layer_fg_scroll_y) & 0xf8) << 3); + UINT8 start_column = (m_layer_fg_scroll_x >> 3); + + for (int column = 0; column < 29; column++) + { + UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; + int x_offset, tile_line, tile_address; + int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) + | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; + int tile_number = tile_data & 0x01ff; + int tile_palette = (tile_data >> 9) & 0x0f; + + tile_line = (m_current_line + m_layer_fg_scroll_y) & 0x07; + if (tile_data & 0x8000) // vflip + tile_line = 7 - tile_line; + + if (m_colors_16) + { + tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = m_vram[tile_address + 2] << 2; + plane3 = m_vram[tile_address + 3] << 3; + } + } + else + { + tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = 0; + plane3 = 0; + } + } + + for (int x = 0; x < 8; x++ ) + { + int col; + if (m_tile_packed) + { + if (m_colors_16) + { + col = plane0 & 0x0f; + plane0 = plane0 >> 4; + } + else + { + col = plane0 & 0x03; + plane0 = plane0 >> 2; + } + } + else + { + col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); + plane3 = plane3 >> 1; + plane2 = plane2 >> 1; + plane1 = plane1 >> 1; + plane0 = plane0 >> 1; + } + + if (tile_data & 0x4000) + x_offset = x + (column << 3) - (m_layer_fg_scroll_x & 0x07); + else + x_offset = 7 - x + (column << 3) - (m_layer_fg_scroll_x & 0x07); + + if (x_offset >= 0 && x_offset < WSWAN_X_PIXELS) + { + if (m_colors_16) + { + if (col) + { +// if (m_color_mode) { + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; +// } else { +// /* Hmmmm, what should we do here... Is this correct?? */ +// m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; +// } + } + } + else + { + if (col || !(tile_palette & 4)) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; + } + } + } + } + } +} + +void wswan_video_device::draw_foreground_2() +{ + UINT16 map_addr = m_layer_fg_address + (((m_current_line + m_layer_fg_scroll_y) & 0xf8) << 3); + UINT8 start_column = (m_layer_fg_scroll_x >> 3); + + for (int column = 0; column < 29; column++) + { + UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; + int x_offset, tile_line, tile_address; + int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) + | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; + int tile_number = tile_data & 0x01ff; + int tile_palette = (tile_data >> 9) & 0x0f; + + tile_line = (m_current_line + m_layer_fg_scroll_y) & 0x07; + if (tile_data & 0x8000) // vflip + tile_line = 7 - tile_line; + + + if (m_colors_16) + { + tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = m_vram[tile_address + 2] << 2; + plane3 = m_vram[tile_address + 3] << 3; + } + } + else + { + tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = 0; + plane3 = 0; + } + } + + for (int x = 0; x < 8; x++) + { + int col; + if (m_tile_packed) + { + if (m_colors_16) + { + col = plane0 & 0x0f; + plane0 = plane0 >> 4; + } + else + { + col = plane0 & 0x03; + plane0 = plane0 >> 2; + } + } + else + { + col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); + plane3 = plane3 >> 1; + plane2 = plane2 >> 1; + plane1 = plane1 >> 1; + plane0 = plane0 >> 1; + } + + if (tile_data & 0x4000) + x_offset = x + (column << 3) - (m_layer_fg_scroll_x & 0x07); + else + x_offset = 7 - x + (column << 3) - (m_layer_fg_scroll_x & 0x07); + + if (x_offset >= 0 && x_offset >= m_window_fg_left && x_offset < m_window_fg_right && x_offset < WSWAN_X_PIXELS) + { + if (m_colors_16) + { + if (col) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + /* Hmmmm, what should we do here... Is this correct?? */ + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + } + } + else + { + if (col || !(tile_palette & 4)) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; + } + } + } + } + } +} + +void wswan_video_device::draw_foreground_3() +{ + UINT16 map_addr = m_layer_fg_address + (((m_current_line + m_layer_fg_scroll_y) & 0xf8) << 3); + UINT8 start_column = (m_layer_fg_scroll_x >> 3); + + for (int column = 0; column < 29; column++) + { + UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; + int x_offset, tile_line, tile_address; + int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) + | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; + int tile_number = tile_data & 0x01ff; + int tile_palette = (tile_data >> 9) & 0x0f; + + tile_line = (m_current_line + m_layer_fg_scroll_y) & 0x07; + if (tile_data & 0x8000) // vflip + tile_line = 7 - tile_line; + + if (m_colors_16) + { + tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = m_vram[tile_address + 2] << 2; + plane3 = m_vram[tile_address + 3] << 3; + } + } + else + { + tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = 0; + plane3 = 0; + } + } + + for (int x = 0; x < 8; x++) + { + int col; + if (m_tile_packed) + { + if (m_colors_16) + { + col = plane0 & 0x0f; + plane0 = plane0 >> 4; + } + else + { + col = plane0 & 0x03; + plane0 = plane0 >> 2; + } + } + else + { + col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); + plane3 = plane3 >> 1; + plane2 = plane2 >> 1; + plane1 = plane1 >> 1; + plane0 = plane0 >> 1; + } + + if (tile_data & 0x4000) + x_offset = x + (column << 3) - (m_layer_fg_scroll_x & 0x07); + else + x_offset = 7 - x + (column << 3) - (m_layer_fg_scroll_x & 0x07); + + if ((x_offset >= 0 && x_offset < m_window_fg_left) || (x_offset >= m_window_fg_right && x_offset < WSWAN_X_PIXELS)) + { + if (m_colors_16) + { + if (col) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + /* Hmmmm, what should we do here... Is this correct?? */ + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + } + } + else + { + if (col || !(tile_palette & 4)) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; + } + } + } + } + } +} + +void wswan_video_device::handle_sprites(int mask) +{ + if (m_sprite_count == 0) + return; + + for (int i = m_sprite_first + m_sprite_count - 1; i >= m_sprite_first; i--) + { + UINT16 tile_data = (m_sprite_table_buffer[i * 4 + 1] << 8) | m_sprite_table_buffer[i * 4]; + UINT8 y = m_sprite_table_buffer[ i * 4 + 2 ]; + UINT8 x = m_sprite_table_buffer[ i * 4 + 3 ]; + int tile_line = (m_current_line - y) & 0xff; + + if ((tile_line >= 0) && (tile_line < 8) && ((tile_data & 0x2000) == mask)) + { + UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; + int x_offset, tile_address; + int tile_number = tile_data & 0x01ff; + int tile_palette = 8 + ((tile_data >> 9) & 0x07); + int check_clip = 0; + + if (tile_data & 0x8000) + tile_line = 7 - tile_line; + + if (m_colors_16) + { + tile_address = 0x4000 + (tile_number * 32) + (tile_line << 2); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = m_vram[tile_address + 2] << 2; + plane3 = m_vram[tile_address + 3] << 3; + } + } + else + { + tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); + if (m_tile_packed) + { + plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; + } + else + { + plane0 = m_vram[tile_address + 0]; + plane1 = m_vram[tile_address + 1] << 1; + plane2 = 0; + plane3 = 0; + } + } + + if (m_window_sprites_enable) + { + if (tile_data & 0x1000) + { + if (m_current_line >= m_window_sprites_top && m_current_line <= m_window_sprites_bottom) + check_clip = 1; + } + else + { + if (m_current_line < m_window_sprites_top || m_current_line > m_window_sprites_bottom) + continue; + } + } + + for (int j = 0; j < 8; j++) + { + int col; + if (m_tile_packed) + { + if (m_colors_16) + { + col = plane0 & 0x0f; + plane0 = plane0 >> 4; + } + else + { + col = plane0 & 0x03; + plane0 = plane0 >> 2; + } + } + else + { + col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); + plane3 = plane3 >> 1; + plane2 = plane2 >> 1; + plane1 = plane1 >> 1; + plane0 = plane0 >> 1; + } + + if (tile_data & 0x4000) + x_offset = x + j; + else + x_offset = x + 7 - j; + + x_offset = x_offset & 0xff; + + if (m_window_sprites_enable) + { + if (tile_data & 0x1000 && check_clip) + { + if (x_offset >= m_window_sprites_left && x_offset <= m_window_sprites_right) + continue; + } + else + { + if (x_offset < m_window_sprites_left || x_offset > m_window_sprites_right) + { +// continue; + } + } + } + if (x_offset >= 0 && x_offset < WSWAN_X_PIXELS) + { + if (m_colors_16) + { + if (col) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + /* Hmmmm, what should we do here... Is this correct?? */ + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + } + } + else + { + if (col || !(tile_palette & 4)) + { + if (m_color_mode) + m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; + else + m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; + } + } + } + } + } + } +} + + +void wswan_video_device::refresh_scanline() +{ + setup_palettes(); + + rectangle rec(0, WSWAN_X_PIXELS, m_current_line, m_current_line); + if (m_lcd_control) + { + /* Not sure if these background color checks and settings are correct */ + if (m_color_mode && m_colors_16) + m_bitmap.fill(m_pal[m_bg_control >> 4][m_bg_control & 0x0f], rec); + else + m_bitmap.fill(m_main_palette[m_bg_control & 0x07], rec); + } + else + { + m_bitmap.fill(0, rec); + return; + } + + // Draw background layer + if (m_layer_bg_enable) + draw_background(); + + // Draw sprites between background and foreground layers + if (m_sprites_enable) + handle_sprites(0); + + // Draw foreground layer, taking window settings into account + if (m_layer_fg_enable) + { + switch (m_window_fg_mode) + { + case 0: // FG inside & outside window area + draw_foreground_0(); + break; + case 1: // ??? + logerror("Unknown foreground mode 1 set\n"); + break; + case 2: // FG only inside window area + if (m_current_line >= m_window_fg_top && m_current_line <= m_window_fg_bottom) + draw_foreground_2(); + break; + case 3: // FG only outside window area + if (m_current_line < m_window_fg_top || m_current_line > m_window_fg_bottom) + draw_foreground_0(); + else + draw_foreground_3(); + break; + } + } + + // Draw sprites in front of foreground layer + if (m_sprites_enable) + handle_sprites(0x2000); +} + + + +UINT32 wswan_video_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); + return 0; +} + + +READ8_MEMBER(wswan_video_device::reg_r) +{ + UINT8 value = m_regs[offset]; + + if (offset >= 0x20 && offset < 0x40) + return m_palette_port[offset & 0x1f]; + + switch (offset) + { + case 0x01: + value = m_bg_control; + break; + case 0x02: + value = m_current_line; + break; + case 0x14: + value = m_lcd_control; + break; + case 0xa8: + value = m_timer_hblank_count & 0xff; + break; + case 0xa9: + value = m_timer_hblank_count >> 8; + break; + case 0xaa: + value = m_timer_vblank_count & 0xff; + break; + case 0xab: + value = m_timer_vblank_count >> 8; + break; + } + + return value; +} + + +WRITE8_MEMBER(wswan_video_device::reg_w) +{ + if (offset >= 0x20 && offset < 0x40) + { + // 0x20-0x3f tile/sprite palette settings + // even offs + // Bit 0-3 - Palette (offs & 0x1f)/2 index 0 + // Bit 4-7 - Palette (offs & 0x1f)/2 index 1 + // odd offs + // Bit 0-3 - Palette (offs & 0x1f)/2 index 2 + // Bit 4-7 - Palette (offs & 0x1f)/2 index 3 + m_palette_port[offset & 0x1f] = data; + return; + } + + switch (offset) + { + case 0x00: // Display control + // Bit 0 - Background layer enable + // Bit 1 - Foreground layer enable + // Bit 2 - Sprites enable + // Bit 3 - Sprite window enable + // Bit 4-5 - Foreground window configuration + // 00 - Foreground layer is displayed inside and outside foreground window area + // 01 - Unknown + // 10 - Foreground layer is displayed only inside foreground window area + // 11 - Foreground layer is displayed outside foreground window area + // Bit 6-7 - Unknown + m_layer_bg_enable = data & 0x1; + m_layer_fg_enable = (data & 0x2) >> 1; + m_sprites_enable = (data & 0x4) >> 2; + m_window_sprites_enable = (data & 0x8) >> 3; + m_window_fg_mode = (data & 0x30) >> 4; + break; + case 0x01: // Background colour + // In 16 colour mode: + // Bit 0-3 - Palette index + // Bit 4-7 - Palette number + // Otherwise: + // Bit 0-2 - Main palette index + // Bit 3-7 - Unknown + m_bg_control = data; + break; + case 0x02: // Current scanline (Most likely read-only) + logerror("Write to current scanline! Current value: %d Data to write: %d\n", m_current_line, data); + // Returning so we don't overwrite the value here, not that it really matters + return; + case 0x03: // Line compare + m_line_compare = data; + logerror("Write to line compare: %d\n", data); + break; + case 0x04: // Sprite table base address + // Bit 0-5 - Determine sprite table base address 0 0xxxxxx0 00000000 + // Bit 6-7 - Unknown + m_sprite_table_address = (data & 0x3f) << 9; + break; + case 0x05: // First sprite number (the one we start drawing with) + m_sprite_first_latch = data; + if (data) logerror("non-zero first sprite %d\n", data); + break; + case 0x06: // Number of sprites to draw + m_sprite_count_latch = data; + break; + case 0x07: // Background/Foreground table base addresses + // Bit 0-2 - Determine background table base address 00xxx000 00000000 + // Bit 3 - Unknown + // Bit 4-6 - Determine foreground table base address 00xxx000 00000000 + // Bit 7 - Unknown + m_layer_bg_address = (data & 0x7) << 11; + m_layer_fg_address = (data & 0x70) << 7; + break; + case 0x08: // Left coordinate of foreground window + m_window_fg_left = data; + break; + case 0x09: // Top coordinate of foreground window + m_window_fg_top = data; + break; + case 0x0a: // Right coordinate of foreground window + m_window_fg_right = data; + break; + case 0x0b: // Bottom coordinate of foreground window + m_window_fg_bottom = data; + break; + case 0x0c: // Left coordinate of sprite window + m_window_sprites_left = data; + break; + case 0x0d: // Top coordinate of sprite window + m_window_sprites_top = data; + break; + case 0x0e: // Right coordinate of sprite window + m_window_sprites_right = data; + break; + case 0x0f: // Bottom coordinate of sprite window + m_window_sprites_bottom = data; + break; + case 0x10: // Background layer X scroll + m_layer_bg_scroll_x = data; + break; + case 0x11: // Background layer Y scroll + m_layer_bg_scroll_y = data; + break; + case 0x12: // Foreground layer X scroll + m_layer_fg_scroll_x = data; + break; + case 0x13: // Foreground layer Y scroll + m_layer_fg_scroll_y = data; + break; + case 0x14: // LCD control + // Bit 0 - LCD enable + // Bit 1-7 - Unknown + m_lcd_control = data; + break; + case 0x15: // LCD icons + // Bit 0 - LCD sleep icon enable + // Bit 1 - Vertical position icon enable + // Bit 2 - Horizontal position icon enable + // Bit 3 - Dot 1 icon enable + // Bit 4 - Dot 2 icon enable + // Bit 5 - Dot 3 icon enable + // Bit 6-7 - Unknown + m_icons = data; /* ummmmm */ + break; + case 0x1c: // Palette colors 0 and 1 + // Bit 0-3 - Gray tone setting for main palette index 0 + // Bit 4-7 - Gray tone setting for main palette index 1 + if (m_vdp_type == VDP_TYPE_WSC) + { + int i = 15 - (data & 0x0f); + int j = 15 - ((data & 0xf0) >> 4); + m_main_palette[0] = (i << 8) | (i << 4) | i; + m_main_palette[1] = (j << 8) | (j << 4) | j; + } + else + { + m_main_palette[0] = data & 0x0f; + m_main_palette[1] = (data & 0xf0) >> 4; + } + break; + case 0x1d: // Palette colors 2 and 3 + // Bit 0-3 - Gray tone setting for main palette index 2 + // Bit 4-7 - Gray tone setting for main palette index 3 + if (m_vdp_type == VDP_TYPE_WSC) + { + int i = 15 - (data & 0x0f); + int j = 15 - ((data & 0xf0) >> 4); + m_main_palette[2] = (i << 8) | (i << 4) | i; + m_main_palette[3] = (j << 8) | (j << 4) | j; + } + else + { + m_main_palette[2] = data & 0x0f; + m_main_palette[3] = (data & 0xf0) >> 4; + } + break; + case 0x1e: // Palette colors 4 and 5 + // Bit 0-3 - Gray tone setting for main palette index 4 + // Bit 4-7 - Gray tone setting for main palette index 5 + if (m_vdp_type == VDP_TYPE_WSC) + { + int i = 15 - (data & 0x0f); + int j = 15 - ((data & 0xf0) >> 4); + m_main_palette[4] = (i << 8) | (i << 4) | i; + m_main_palette[5] = (j << 8) | (j << 4) | j; + } + else + { + m_main_palette[4] = data & 0x0f; + m_main_palette[5] = (data & 0xf0) >> 4; + } + break; + case 0x1f: // Palette colors 6 and 7 + // Bit 0-3 - Gray tone setting for main palette index 6 + // Bit 4-7 - Gray tone setting for main palette index 7 + if (m_vdp_type == VDP_TYPE_WSC) + { + int i = 15 - (data & 0x0f); + int j = 15 - ((data & 0xf0) >> 4); + m_main_palette[6] = (i << 8) | (i << 4) | i; + m_main_palette[7] = (j << 8) | (j << 4) | j; + } + else + { + m_main_palette[6] = data & 0x0f; + m_main_palette[7] = (data & 0xf0) >> 4; + } + break; + case 0x60: // Video mode + // Bit 0-4 - Unknown + // Bit 5 - Packed mode 0 = not packed mode, 1 = packed mode + // Bit 6 - 4/16 colour mode select: 0 = 4 colour mode, 1 = 16 colour mode + // Bit 7 - monochrome/colour mode select: 0 = monochrome mode, 1 = colour mode + /* + * 111 - packed, 16 color, use 4000/8000, color + * 110 - not packed, 16 color, use 4000/8000, color + * 101 - packed, 4 color, use 2000, color + * 100 - not packed, 4 color, use 2000, color + * 011 - packed, 16 color, use 4000/8000, monochrome + * 010 - not packed, 16 color , use 4000/8000, monochrome + * 001 - packed, 4 color, use 2000, monochrome + * 000 - not packed, 4 color, use 2000, monochrome - Regular WS monochrome + */ + if (m_vdp_type == VDP_TYPE_WSC) + { + m_color_mode = data & 0x80; + m_colors_16 = data & 0x40; + m_tile_packed = data & 0x20; + } + break; + case 0xa2: // Timer control + // Bit 0 - HBlank Timer enable + // Bit 1 - HBlank Timer mode: 0 = one shot, 1 = auto reset + // Bit 2 - VBlank Timer(1/75s) enable + // Bit 3 - VBlank Timer mode: 0 = one shot, 1 = auto reset + // Bit 4-7 - Unknown + m_timer_hblank_enable = BIT(data, 0); + m_timer_hblank_mode = BIT(data, 1); + m_timer_vblank_enable = BIT(data, 2); + m_timer_vblank_mode = BIT(data, 3); + break; + case 0xa4: // HBlank timer frequency reload value (bits 0-7) + m_timer_hblank_reload &= 0xff00; + m_timer_hblank_reload += data; + m_timer_hblank_count = m_timer_hblank_reload; + break; + case 0xa5: // HBlank timer frequency reload value (bits 8-15) + m_timer_hblank_reload &= 0xff; + m_timer_hblank_reload += data << 8; + m_timer_hblank_count = m_timer_hblank_reload; + break; + case 0xa6: // VBlank timer frequency reload value (bits 0-7) + m_timer_vblank_reload &= 0xff00; + m_timer_vblank_reload += data; + m_timer_vblank_count = m_timer_vblank_reload; + break; + case 0xa7: // VBlank timer frequency reload value (bits 8-15) + m_timer_vblank_reload &= 0xff; + m_timer_vblank_reload += data << 8; + m_timer_vblank_count = m_timer_vblank_reload; + break; + case 0xa8: // HBlank counter (bits 0-7) + case 0xa9: // HBlank counter (bits 8-15) + case 0xaa: // VBlank counter (bits 0-7) + case 0xab: // VBlank counter (bits 8-15) + break; + } + + m_regs[offset] = data; +} + + +void wswan_video_device::scanline_interrupt() +{ + if (m_current_line < 144) + refresh_scanline(); + + // Decrement 12kHz (HBlank) counter + if (m_timer_hblank_enable && m_timer_hblank_reload != 0) + { + m_timer_hblank_count--; + logerror("timer_hblank_count: %X\n", m_timer_hblank_count); + if (m_timer_hblank_count == 0) + { + if (m_timer_hblank_mode) + m_timer_hblank_count = m_timer_hblank_reload; + else + m_timer_hblank_reload = 0; + + logerror( "trigerring hbltmr interrupt\n" ); + m_set_irq_cb(WSWAN_VIDEO_IFLAG_HBLTMR); + } + } + + // Handle Sound DMA + m_snd_dma_cb(); + +// m_current_line = (m_current_line + 1) % 159; + + if (m_current_line == 144) // buffer sprite table + { + memcpy(m_sprite_table_buffer, &m_vram[m_sprite_table_address], 512); + m_sprite_first = m_sprite_first_latch; // always zero? + m_sprite_count = m_sprite_count_latch; + } + + if (m_current_line == 144) + { + m_set_irq_cb(WSWAN_VIDEO_IFLAG_VBL); + /* Decrement 75Hz (VBlank) counter */ + if (m_timer_vblank_enable && m_timer_vblank_reload != 0) + { + m_timer_vblank_count--; + logerror("timer_vblank_count: %X\n", m_timer_vblank_count); + if (m_timer_vblank_count == 0) + { + if (m_timer_vblank_mode) + m_timer_vblank_count = m_timer_vblank_reload; + else + m_timer_vblank_reload = 0; + + logerror("triggering vbltmr interrupt\n"); + m_set_irq_cb(WSWAN_VIDEO_IFLAG_VBLTMR); + } + } + } + +// m_current_line = (m_current_line + 1) % 159; + + if (m_current_line == m_line_compare) + m_set_irq_cb(WSWAN_VIDEO_IFLAG_LCMP); + + m_current_line = (m_current_line + 1) % 159; +} + + +READ8_MEMBER(wswan_video_device::vram_r) +{ + return m_vram[offset]; +} + +WRITE8_MEMBER(wswan_video_device::vram_w) +{ + m_vram[offset] = data; +} diff --git a/src/mess/video/wswan_video.h b/src/mess/video/wswan_video.h new file mode 100644 index 00000000000..0ac0914f06a --- /dev/null +++ b/src/mess/video/wswan_video.h @@ -0,0 +1,147 @@ +/********************************************************************** + + wswan.h + + File to handle video emulation of the Bandai WonderSwan. + + Anthony Kruize + Wilbert Pol + +**********************************************************************/ + +#ifndef __WSWAN_VIDEO__ +#define __WSWAN_VIDEO__ + +#include "emu.h" + +enum +{ + VDP_TYPE_WSWAN = 0, + VDP_TYPE_WSC +}; + +#define WSWAN_X_PIXELS (28*8) +#define WSWAN_Y_PIXELS (18*8) + + + +typedef device_delegate wswan_video_irq_cb_delegate; +#define WSWAN_VIDEO_IRQ_CB_MEMBER(_name) void _name(int irq) + +typedef device_delegate wswan_video_dmasnd_cb_delegate; +#define WSWAN_VIDEO_DMASND_CB_MEMBER(_name) void _name(void) + +#define MCFG_WSWAN_VIDEO_IRQ_CB(_class, _method) \ + wswan_video_device::set_irq_callback(*device, wswan_video_irq_cb_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + +#define MCFG_WSWAN_VIDEO_DMASND_CB(_class, _method) \ + wswan_video_device::set_dmasnd_callback(*device, wswan_video_dmasnd_cb_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + +#define MCFG_WSWAN_VIDEO_TYPE( _type) \ + wswan_video_device::set_vdp_type(*device, _type); + + +class wswan_video_device : public device_t +{ +public: + wswan_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + ~wswan_video_device() {} + + // static configuration + static void set_irq_callback(device_t &device, wswan_video_irq_cb_delegate callback) { downcast(device).m_set_irq_cb = callback; } + static void set_dmasnd_callback(device_t &device, wswan_video_dmasnd_cb_delegate callback) { downcast(device).m_snd_dma_cb = callback; } + static void set_vdp_type(device_t &device, int type) { downcast(device).m_vdp_type = type; } + + UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + virtual DECLARE_READ8_MEMBER(vram_r); + virtual DECLARE_WRITE8_MEMBER(vram_w); + virtual DECLARE_READ8_MEMBER(reg_r); + virtual DECLARE_WRITE8_MEMBER(reg_w); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + void setup_palettes(); + void draw_background(); + void draw_foreground_0(); + void draw_foreground_2(); + void draw_foreground_3(); + void handle_sprites(int mask); + void refresh_scanline(); + void scanline_interrupt(); + void common_save(); + + bitmap_ind16 m_bitmap; + UINT8 m_layer_bg_enable; /* Background layer on/off */ + UINT8 m_layer_fg_enable; /* Foreground layer on/off */ + UINT8 m_sprites_enable; /* Sprites on/off */ + UINT8 m_window_sprites_enable; /* Sprite window on/off */ + UINT8 m_window_fg_mode; /* 0:inside/outside, 1:??, 2:inside, 3:outside */ + UINT8 m_bg_control; + UINT8 m_current_line; /* Current scanline : 0-158 (159?) */ + UINT8 m_line_compare; /* Line to trigger line interrupt on */ + UINT32 m_sprite_table_address; /* Address of the sprite table */ + UINT8 m_sprite_table_buffer[512]; + UINT8 m_sprite_first; /* First sprite to draw */ + UINT8 m_sprite_count; /* Number of sprites to draw */ + UINT8 m_sprite_first_latch; + UINT8 m_sprite_count_latch; + UINT16 m_layer_bg_address; /* Address of the background screen map */ + UINT16 m_layer_fg_address; /* Address of the foreground screen map */ + UINT8 m_window_fg_left; /* Left coordinate of foreground window */ + UINT8 m_window_fg_top; /* Top coordinate of foreground window */ + UINT8 m_window_fg_right; /* Right coordinate of foreground window */ + UINT8 m_window_fg_bottom; /* Bottom coordinate of foreground window */ + UINT8 m_window_sprites_left; /* Left coordinate of sprites window */ + UINT8 m_window_sprites_top; /* Top coordinate of sprites window */ + UINT8 m_window_sprites_right; /* Right coordinate of sprites window */ + UINT8 m_window_sprites_bottom; /* Bottom coordinate of sprites window */ + UINT8 m_layer_bg_scroll_x; /* Background layer X scroll */ + UINT8 m_layer_bg_scroll_y; /* Background layer Y scroll */ + UINT8 m_layer_fg_scroll_x; /* Foreground layer X scroll */ + UINT8 m_layer_fg_scroll_y; /* Foreground layer Y scroll */ + UINT8 m_lcd_control; /* LCD on/off */ + UINT8 m_icons; /* FIXME: What do we do with these? Maybe artwork? */ + UINT8 m_color_mode; /* monochrome/color mode */ + UINT8 m_colors_16; /* 4/16 colors mode */ + UINT8 m_tile_packed; /* layered/packed tile mode switch */ + UINT8 m_timer_hblank_enable; /* Horizontal blank interrupt on/off */ + UINT8 m_timer_hblank_mode; /* Horizontal blank timer mode */ + UINT16 m_timer_hblank_reload; /* Horizontal blank timer reload value */ + UINT16 m_timer_hblank_count; /* Horizontal blank timer counter value */ + UINT8 m_timer_vblank_enable; /* Vertical blank interrupt on/off */ + UINT8 m_timer_vblank_mode; /* Vertical blank timer mode */ + UINT16 m_timer_vblank_reload; /* Vertical blank timer reload value */ + UINT16 m_timer_vblank_count; /* Vertical blank timer counter value */ + int m_main_palette[8]; + emu_timer *m_timer; + + dynamic_buffer m_vram; + UINT8 *m_palette_vram; + UINT8 m_palette_port[0x20]; + int m_pal[16][16]; + UINT8 m_regs[256]; + + wswan_video_irq_cb_delegate m_set_irq_cb; + wswan_video_dmasnd_cb_delegate m_snd_dma_cb; + int m_vdp_type; + + // timer IDs + static const device_timer_id TIMER_SCANLINE = 0; + + // interrupt flags + // these are the same as the wswan.h ones + static const UINT8 WSWAN_VIDEO_IFLAG_LCMP = 0x10; + static const UINT8 WSWAN_VIDEO_IFLAG_VBLTMR = 0x20; + static const UINT8 WSWAN_VIDEO_IFLAG_VBL = 0x40; + static const UINT8 WSWAN_VIDEO_IFLAG_HBLTMR = 0x80; +}; + +extern const device_type WSWAN_VIDEO; + + +#endif