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 - - + - + - - + 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 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; } 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/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/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/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)); 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