summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author etabeta78 <etabeta78@users.noreply.github.com>2014-10-28 14:18:33 +0100
committer etabeta78 <etabeta78@users.noreply.github.com>2014-10-28 14:18:33 +0100
commite6a5e406bf00e95d4df741325d4444ab427f2fa0 (patch)
tree8f9a965adc505c3131c2528937a0c44e36e7a171
parent31fd590aa633dddcc6fa665e3226301f9f4c779e (diff)
(MESS) wswan: converted the video chip to be a device. nw.
-rw-r--r--src/mess/drivers/wswan.c28
-rw-r--r--src/mess/includes/wswan.h97
-rw-r--r--src/mess/machine/wswan.c1009
-rw-r--r--src/mess/mess.mak2
-rw-r--r--src/mess/video/wswan.c583
-rw-r--r--src/mess/video/wswan_video.c1211
-rw-r--r--src/mess/video/wswan_video.h147
7 files changed, 1656 insertions, 1421 deletions
diff --git a/src/mess/drivers/wswan.c b/src/mess/drivers/wswan.c
index a4c7c1ed4a2..23b113c7316 100644
--- a/src/mess/drivers/wswan.c
+++ b/src/mess/drivers/wswan.c
@@ -35,14 +35,14 @@
#include "wswan.lh"
static ADDRESS_MAP_START (wswan_mem, AS_PROGRAM, 8, wswan_state)
- AM_RANGE(0x00000, 0x03fff) AM_RAM // 16kb RAM / 4 colour tiles
+ AM_RANGE(0x00000, 0x03fff) AM_DEVREADWRITE("vdp", wswan_video_device, vram_r, vram_w) // 16kb RAM / 4 colour tiles
AM_RANGE(0x04000, 0x0ffff) AM_NOP // nothing
//AM_RANGE(0x10000, 0xeffff) // cart range, setup at machine_start
AM_RANGE(0xf0000, 0xfffff) AM_READ(bios_r)
ADDRESS_MAP_END
static ADDRESS_MAP_START (wscolor_mem, AS_PROGRAM, 8, wswan_state)
- AM_RANGE(0x00000, 0x0ffff) AM_RAM // 16kb RAM / 4 colour tiles, 16 colour tiles + palettes
+ AM_RANGE(0x00000, 0x0ffff) AM_DEVREADWRITE("vdp", wswan_video_device, vram_r, vram_w) // 16kb RAM / 4 colour tiles, 16 colour tiles + palettes
//AM_RANGE(0x10000, 0xeffff) // cart range, setup at machine_start
AM_RANGE(0xf0000, 0xfffff) AM_READ(bios_r)
ADDRESS_MAP_END
@@ -83,7 +83,7 @@ PALETTE_INIT_MEMBER(wswan_state, wswan)
}
}
-PALETTE_INIT_MEMBER(wswan_state,wscolor)
+PALETTE_INIT_MEMBER(wswan_state, wscolor)
{
for (int i = 0; i < 4096; i++)
{
@@ -95,9 +95,9 @@ PALETTE_INIT_MEMBER(wswan_state,wscolor)
}
static SLOT_INTERFACE_START(wswan_cart)
- SLOT_INTERFACE_INTERNAL("ws_rom", WS_ROM_STD)
- SLOT_INTERFACE_INTERNAL("ws_sram", WS_ROM_SRAM)
- SLOT_INTERFACE_INTERNAL("ws_eeprom", WS_ROM_EEPROM)
+ SLOT_INTERFACE_INTERNAL("ws_rom", WS_ROM_STD)
+ SLOT_INTERFACE_INTERNAL("ws_sram", WS_ROM_SRAM)
+ SLOT_INTERFACE_INTERNAL("ws_eeprom", WS_ROM_EEPROM)
SLOT_INTERFACE_END
static MACHINE_CONFIG_START( wswan, wswan_state )
@@ -106,11 +106,16 @@ static MACHINE_CONFIG_START( wswan, wswan_state )
MCFG_CPU_PROGRAM_MAP(wswan_mem)
MCFG_CPU_IO_MAP(wswan_io)
+ MCFG_DEVICE_ADD("vdp", WSWAN_VIDEO, 0)
+ MCFG_WSWAN_VIDEO_TYPE(VDP_TYPE_WSWAN)
+ MCFG_WSWAN_VIDEO_IRQ_CB(wswan_state, set_irq_line)
+ MCFG_WSWAN_VIDEO_DMASND_CB(wswan_state, dma_sound_cb)
+
MCFG_SCREEN_ADD("screen", LCD)
MCFG_SCREEN_REFRESH_RATE(75)
MCFG_SCREEN_VBLANK_TIME(0)
- MCFG_SCREEN_UPDATE_DRIVER(wswan_state, screen_update)
- MCFG_SCREEN_SIZE( WSWAN_X_PIXELS, WSWAN_Y_PIXELS )
+ MCFG_SCREEN_UPDATE_DEVICE("vdp", wswan_video_device, screen_update)
+ MCFG_SCREEN_SIZE(WSWAN_X_PIXELS, WSWAN_Y_PIXELS)
MCFG_SCREEN_VISIBLE_AREA(0*8, WSWAN_X_PIXELS - 1, 0, WSWAN_Y_PIXELS - 1)
MCFG_SCREEN_PALETTE("palette")
@@ -141,11 +146,14 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( wscolor, wswan )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(wscolor_mem)
- MCFG_MACHINE_START_OVERRIDE(wswan_state, wscolor )
+ MCFG_MACHINE_START_OVERRIDE(wswan_state, wscolor)
+
+ MCFG_DEVICE_MODIFY("vdp")
+ MCFG_WSWAN_VIDEO_TYPE(VDP_TYPE_WSC)
MCFG_PALETTE_MODIFY("palette")
MCFG_PALETTE_ENTRIES(4096)
- MCFG_PALETTE_INIT_OWNER(wswan_state, wscolor )
+ MCFG_PALETTE_INIT_OWNER(wswan_state, wscolor)
/* software lists */
MCFG_DEVICE_REMOVE("cart_list")
diff --git a/src/mess/includes/wswan.h b/src/mess/includes/wswan.h
index c92c9d95e31..418b44f5021 100644
--- a/src/mess/includes/wswan.h
+++ b/src/mess/includes/wswan.h
@@ -10,15 +10,13 @@
#define WSWAN_TYPE_MONO 0
#define WSWAN_TYPE_COLOR 1
-#define WSWAN_X_PIXELS (28*8)
-#define WSWAN_Y_PIXELS (18*8)
-
#define INTERNAL_EEPROM_SIZE 1024
#include "emu.h"
#include "cpu/v30mz/v30mz.h"
-#include "audio/wswan_snd.h"
#include "machine/nvram.h"
+#include "audio/wswan_snd.h"
+#include "video/wswan_video.h"
#include "bus/wswan/slot.h"
#include "bus/wswan/rom.h"
@@ -30,52 +28,6 @@ struct SoundDMA
UINT8 enable; /* Enabled */
};
-struct VDP
-{
- UINT8 layer_bg_enable; /* Background layer on/off */
- UINT8 layer_fg_enable; /* Foreground layer on/off */
- UINT8 sprites_enable; /* Sprites on/off */
- UINT8 window_sprites_enable; /* Sprite window on/off */
- UINT8 window_fg_mode; /* 0:inside/outside, 1:??, 2:inside, 3:outside */
- UINT8 current_line; /* Current scanline : 0-158 (159?) */
- UINT8 line_compare; /* Line to trigger line interrupt on */
- UINT32 sprite_table_address; /* Address of the sprite table */
- UINT8 sprite_table_buffer[512];
- UINT8 sprite_first; /* First sprite to draw */
- UINT8 sprite_count; /* Number of sprites to draw */
- UINT16 layer_bg_address; /* Address of the background screen map */
- UINT16 layer_fg_address; /* Address of the foreground screen map */
- UINT8 window_fg_left; /* Left coordinate of foreground window */
- UINT8 window_fg_top; /* Top coordinate of foreground window */
- UINT8 window_fg_right; /* Right coordinate of foreground window */
- UINT8 window_fg_bottom; /* Bottom coordinate of foreground window */
- UINT8 window_sprites_left; /* Left coordinate of sprites window */
- UINT8 window_sprites_top; /* Top coordinate of sprites window */
- UINT8 window_sprites_right; /* Right coordinate of sprites window */
- UINT8 window_sprites_bottom; /* Bottom coordinate of sprites window */
- UINT8 layer_bg_scroll_x; /* Background layer X scroll */
- UINT8 layer_bg_scroll_y; /* Background layer Y scroll */
- UINT8 layer_fg_scroll_x; /* Foreground layer X scroll */
- UINT8 layer_fg_scroll_y; /* Foreground layer Y scroll */
- UINT8 lcd_enable; /* LCD on/off */
- UINT8 icons; /* FIXME: What do we do with these? Maybe artwork? */
- UINT8 color_mode; /* monochrome/color mode */
- UINT8 colors_16; /* 4/16 colors mode */
- UINT8 tile_packed; /* layered/packed tile mode switch */
- UINT8 timer_hblank_enable; /* Horizontal blank interrupt on/off */
- UINT8 timer_hblank_mode; /* Horizontal blank timer mode */
- UINT16 timer_hblank_reload; /* Horizontal blank timer reload value */
- UINT16 timer_hblank_count; /* Horizontal blank timer counter value */
- UINT8 timer_vblank_enable; /* Vertical blank interrupt on/off */
- UINT8 timer_vblank_mode; /* Vertical blank timer mode */
- UINT16 timer_vblank_reload; /* Vertical blank timer reload value */
- UINT16 timer_vblank_count; /* Vertical blank timer counter value */
- UINT8 *vram; /* pointer to start of ram/vram (set by machine_reset) */
- UINT8 *palette_vram; /* pointer to start of palette area in ram/vram (set by machine_reset), WSC only */
- int main_palette[8];
- emu_timer *timer;
-};
-
class wswan_state : public driver_device
{
@@ -83,44 +35,39 @@ public:
wswan_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
+ m_vdp(*this, "vdp"),
m_sound(*this, "custom"),
m_cart(*this, "cartslot"),
m_cursx(*this, "CURSX"),
m_cursy(*this, "CURSY"),
- m_buttons(*this, "BUTTONS") { }
-
- virtual void video_start();
-
- UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-
+ m_buttons(*this, "BUTTONS")
+ { }
+
required_device<cpu_device> m_maincpu;
+ required_device<wswan_video_device> m_vdp;
required_device<wswan_sound_device> m_sound;
required_device<ws_cart_slot_device> m_cart;
DECLARE_READ8_MEMBER(bios_r);
DECLARE_READ8_MEMBER(port_r);
DECLARE_WRITE8_MEMBER(port_w);
-
- VDP m_vdp;
+
UINT8 m_ws_portram[256];
UINT8 m_internal_eeprom[INTERNAL_EEPROM_SIZE];
UINT8 m_system_type;
SoundDMA m_sound_dma;
- UINT8 *m_ws_ram;
UINT8 *m_ws_bios_bank;
UINT8 m_bios_disabled;
- int m_pal[16][16];
- bitmap_ind16 m_bitmap;
UINT8 m_rotate;
-
- void wswan_clear_irq_line(int irq);
+
+ void set_irq_line(int irq);
+ void dma_sound_cb();
void common_start();
virtual void machine_start();
virtual void machine_reset();
DECLARE_PALETTE_INIT(wswan);
DECLARE_MACHINE_START(wscolor);
DECLARE_PALETTE_INIT(wscolor);
- TIMER_CALLBACK_MEMBER(wswan_scanline_interrupt);
-
+
protected:
/* Interrupt flags */
static const UINT8 WSWAN_IFLAG_STX = 0x01;
@@ -131,7 +78,7 @@ protected:
static const UINT8 WSWAN_IFLAG_VBLTMR = 0x20;
static const UINT8 WSWAN_IFLAG_VBL = 0x40;
static const UINT8 WSWAN_IFLAG_HBLTMR = 0x80;
-
+
/* Interrupts */
static const UINT8 WSWAN_INT_STX = 0;
static const UINT8 WSWAN_INT_KEY = 1;
@@ -141,22 +88,14 @@ protected:
static const UINT8 WSWAN_INT_VBLTMR = 5;
static const UINT8 WSWAN_INT_VBL = 6;
static const UINT8 WSWAN_INT_HBLTMR = 7;
-
+
required_ioport m_cursx;
required_ioport m_cursy;
required_ioport m_buttons;
-
- void wswan_register_save();
- void wswan_postload();
- void wswan_handle_irqs();
- void wswan_set_irq_line(int irq);
- void wswan_setup_palettes();
- void wswan_draw_background();
- void wswan_draw_foreground_0();
- void wswan_draw_foreground_2();
- void wswan_draw_foreground_3();
- void wswan_handle_sprites( int mask );
- void wswan_refresh_scanline( );
+
+ void register_save();
+ void handle_irqs();
+ void clear_irq_line(int irq);
};
diff --git a/src/mess/machine/wswan.c b/src/mess/machine/wswan.c
index 46d213e6eba..afa8ce8077f 100644
--- a/src/mess/machine/wswan.c
+++ b/src/mess/machine/wswan.c
@@ -78,144 +78,108 @@ static const UINT8 ws_fake_bios_code[] = {
0xea, 0xc0, 0xff, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-void wswan_state::wswan_handle_irqs()
+void wswan_state::handle_irqs()
{
- if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR )
+ if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY);
}
- else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX )
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX)
{
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX );
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX);
}
else
{
- m_maincpu->set_input_line(0, CLEAR_LINE );
+ m_maincpu->set_input_line(0, CLEAR_LINE);
}
}
-void wswan_state::wswan_set_irq_line(int irq)
+void wswan_state::set_irq_line(int irq)
{
- if ( m_ws_portram[0xb2] & irq )
+ if (m_ws_portram[0xb2] & irq)
{
m_ws_portram[0xb6] |= irq;
- wswan_handle_irqs();
+ handle_irqs();
}
}
-void wswan_state::wswan_clear_irq_line(int irq)
+void wswan_state::dma_sound_cb()
+{
+ 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::clear_irq_line(int irq)
{
m_ws_portram[0xb6] &= ~irq;
- wswan_handle_irqs();
+ handle_irqs();
}
-void wswan_state::wswan_register_save()
+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_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::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<void (int irq)> wswan_video_irq_cb_delegate;
+#define WSWAN_VIDEO_IRQ_CB_MEMBER(_name) void _name(int irq)
+
+typedef device_delegate<void (void)> 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<wswan_video_device &>(device).m_set_irq_cb = callback; }
+ static void set_dmasnd_callback(device_t &device, wswan_video_dmasnd_cb_delegate callback) { downcast<wswan_video_device &>(device).m_snd_dma_cb = callback; }
+ static void set_vdp_type(device_t &device, int type) { downcast<wswan_video_device &>(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