trunk/src/emu/bus/astrocde/ram.c
r241553 | r241554 | |
1 | | // license:BSD-3-Clause |
2 | | // copyright-holders:etabeta |
3 | | /*********************************************************************************************************** |
4 | | |
5 | | |
6 | | Bally Astrocade RAM expansion emulation |
7 | | |
8 | | RAM Expansions (info below courtesy of Paul Thacker) |
9 | | |
10 | | Several third party RAM expansions have been made for the Astrocade. These |
11 | | allow access to various ranges of the expansion memory ($5000 to $FFFF). |
12 | | A RAM expansion is required to use extended BASIC programs like Blue RAM BASIC |
13 | | and VIPERSoft BASIC. All of the expansions also have a RAM protect switch, which |
14 | | can be flipped at any time to make the RAM act like ROM. Extended BASIC |
15 | | programs need access to the RAM and won't work with RAM protect enabled, but |
16 | | this can be useful with Bally and Astrocade BASIC. They also have a range switch |
17 | | (not implemented). The default position is 6K, but it can be switched to |
18 | | 2K. This means that the expanded memory starting at $6000 will instead be |
19 | | mapped to the cartridge memory starting at $2000. So it would be possible to |
20 | | load a cartridge program from tape into the expansion memory, then flip the range |
21 | | switch and run it as a cartridge. This is useful for cartridge development. |
22 | | |
23 | | Blue RAM -- available in 4K, 16K, and 32K. These also use an INS8154 chip, |
24 | | (not yet implemented) which has an additional $80 bytes of RAM mapped |
25 | | immediately after the end of the expansion address space. This memory |
26 | | can't be write protected. The INS8154 has I/O features needed for loading |
27 | | tape programs into Blue RAM BASIC, as well as running the Blue RAM Utility cart. |
28 | | 4K: $6000 to $6FFF (can't run VIPERSoft BASIC, because this program needs memory |
29 | | past this range) |
30 | | 16K: $6000 to $9FFF |
31 | | 32K: $6000 to $DFFF |
32 | | |
33 | | VIPER System 1 -- This is available in 16K only. It also includes a keyboard (not implemented). |
34 | | 16K: $6000 to $9FFF |
35 | | |
36 | | Lil' WHITE RAM -- This is available in 32K only. Attempts to read and write |
37 | | to memory outside of its address range ($D000 to $FFFF) are mapped to the expansion |
38 | | memory $5000 to $7FFF. The current implementation won't allow the shadow RAM area |
39 | | to be accessed when RAM protect is on, but there is no known software that will |
40 | | access the upper range of the expansion RAM when RAM protect is enabled. |
41 | | 32K: $5000 to $CFFF |
42 | | |
43 | | R&L 64K RAM Board -- This is a highly configurable kit. RAM can be installed in |
44 | | 2K increments. So, the entire 44K expansion memory can be filled. It is also |
45 | | possible to override the rest of the memory map with RAM (not implemented). |
46 | | There are 32 switches allowing users to activate and deactivate each 2K block (not implemented). |
47 | | RAM write protection can be implemented in three ranges through jumpers or by |
48 | | installing switches. The ranges are $0000 to $0FFF (first 4K), $0000 to $3FFF (first 16K), |
49 | | and $0000 to $FFFF (all 64K). The current implementation is for 44K expansion memory mapped from |
50 | | $5000 to $FFFF, with only a single write protect covering this entire range. |
51 | | |
52 | | ***********************************************************************************************************/ |
53 | | |
54 | | |
55 | | #include "emu.h" |
56 | | #include "ram.h" |
57 | | |
58 | | |
59 | | //------------------------------------------------- |
60 | | // astrocade_rom_device - constructor |
61 | | //------------------------------------------------- |
62 | | |
63 | | const device_type ASTROCADE_BLUERAM_4K = &device_creator<astrocade_blueram_4k_device>; |
64 | | const device_type ASTROCADE_BLUERAM_16K = &device_creator<astrocade_blueram_16k_device>; |
65 | | const device_type ASTROCADE_BLUERAM_32K = &device_creator<astrocade_blueram_32k_device>; |
66 | | const device_type ASTROCADE_VIPER_SYS1 = &device_creator<astrocade_viper_sys1_device>; |
67 | | const device_type ASTROCADE_WHITERAM = &device_creator<astrocade_whiteram_device>; |
68 | | const device_type ASTROCADE_RL64RAM = &device_creator<astrocade_rl64ram_device>; |
69 | | |
70 | | |
71 | | astrocade_blueram_4k_device::astrocade_blueram_4k_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) |
72 | | : device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
73 | | device_astrocade_card_interface(mconfig, *this), |
74 | | m_write_prot(*this, "RAM_PROTECT") |
75 | | { |
76 | | } |
77 | | |
78 | | astrocade_blueram_4k_device::astrocade_blueram_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
79 | | : device_t(mconfig, ASTROCADE_BLUERAM_4K, "Bally Astrocade Blue RAM 4K", tag, owner, clock, "astrocade_br4", __FILE__), |
80 | | device_astrocade_card_interface(mconfig, *this), |
81 | | m_write_prot(*this, "RAM_PROTECT") |
82 | | { |
83 | | } |
84 | | |
85 | | astrocade_blueram_16k_device::astrocade_blueram_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
86 | | : astrocade_blueram_4k_device(mconfig, ASTROCADE_BLUERAM_16K, "Bally Astrocade Blue RAM 16K", tag, owner, clock, "astrocade_br16", __FILE__) |
87 | | { |
88 | | } |
89 | | |
90 | | astrocade_blueram_32k_device::astrocade_blueram_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
91 | | : astrocade_blueram_4k_device(mconfig, ASTROCADE_BLUERAM_32K, "Bally Astrocade Blue RAM 32K", tag, owner, clock, "astrocade_br32", __FILE__) |
92 | | { |
93 | | } |
94 | | |
95 | | astrocade_viper_sys1_device::astrocade_viper_sys1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
96 | | : device_t(mconfig, ASTROCADE_VIPER_SYS1, "Bally Astrocade Viper System 1", tag, owner, clock, "astrocade_vs1", __FILE__), |
97 | | device_astrocade_card_interface(mconfig, *this), |
98 | | m_write_prot(*this, "RAM_PROTECT") |
99 | | { |
100 | | } |
101 | | |
102 | | astrocade_whiteram_device::astrocade_whiteram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
103 | | : device_t(mconfig, ASTROCADE_WHITERAM, "Bally Astrocade Lil' White RAM 32K", tag, owner, clock, "astrocade_lwr", __FILE__), |
104 | | device_astrocade_card_interface(mconfig, *this), |
105 | | m_write_prot(*this, "RAM_PROTECT") |
106 | | { |
107 | | } |
108 | | |
109 | | astrocade_rl64ram_device::astrocade_rl64ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
110 | | : device_t(mconfig, ASTROCADE_RL64RAM, "Bally Astrocade R&L RAM 64K", tag, owner, clock, "astrocade_rl64", __FILE__), |
111 | | device_astrocade_card_interface(mconfig, *this), |
112 | | m_write_prot(*this, "RAM_PROTECT") |
113 | | { |
114 | | } |
115 | | |
116 | | |
117 | | //------------------------------------------------- |
118 | | // RAM Write protect switch |
119 | | //------------------------------------------------- |
120 | | |
121 | | static INPUT_PORTS_START( exp_switches ) |
122 | | PORT_START("RAM_PROTECT") |
123 | | PORT_CONFNAME( 0x01, 0x00, "Write Protect RAM") |
124 | | PORT_CONFSETTING( 0x00, DEF_STR(Off)) |
125 | | PORT_CONFSETTING( 0x01, DEF_STR(On)) |
126 | | INPUT_PORTS_END |
127 | | |
128 | | |
129 | | ioport_constructor astrocade_blueram_4k_device::device_input_ports() const |
130 | | { |
131 | | return INPUT_PORTS_NAME( exp_switches ); |
132 | | } |
133 | | |
134 | | ioport_constructor astrocade_viper_sys1_device::device_input_ports() const |
135 | | { |
136 | | return INPUT_PORTS_NAME( exp_switches ); |
137 | | } |
138 | | |
139 | | ioport_constructor astrocade_whiteram_device::device_input_ports() const |
140 | | { |
141 | | return INPUT_PORTS_NAME( exp_switches ); |
142 | | } |
143 | | |
144 | | ioport_constructor astrocade_rl64ram_device::device_input_ports() const |
145 | | { |
146 | | return INPUT_PORTS_NAME( exp_switches ); |
147 | | } |
148 | | |
149 | | /*------------------------------------------------- |
150 | | specific handlers |
151 | | -------------------------------------------------*/ |
152 | | |
153 | | // Blue RAM expansions have RAM starting at 0x6000, up to the RAM size |
154 | | READ8_MEMBER(astrocade_blueram_4k_device::read) |
155 | | { |
156 | | if (offset >= 0x1000 && offset < 0x1000 + m_ram.bytes()) |
157 | | return m_ram[offset - 0x1000]; |
158 | | else |
159 | | return 0; |
160 | | } |
161 | | |
162 | | WRITE8_MEMBER(astrocade_blueram_4k_device::write) |
163 | | { |
164 | | if (offset >= 0x1000 && offset < 0x1000 + m_ram.bytes() && !m_write_prot->read()) |
165 | | m_ram[offset - 0x1000] = data; |
166 | | } |
167 | | |
168 | | |
169 | | |
170 | | // Viper System 1 expansion has RAM in 0x6000-0x9fff |
171 | | READ8_MEMBER(astrocade_viper_sys1_device::read) |
172 | | { |
173 | | if (offset >= 0x1000 && offset < 0xa000) |
174 | | return m_ram[offset - 0x1000]; |
175 | | else |
176 | | return 0; |
177 | | } |
178 | | |
179 | | WRITE8_MEMBER(astrocade_viper_sys1_device::write) |
180 | | { |
181 | | if (offset >= 0x1000 && offset < 0xa000 && !m_write_prot->read()) |
182 | | m_ram[offset - 0x1000] = data; |
183 | | } |
184 | | |
185 | | |
186 | | |
187 | | // Lil' WHITE RAM expansion has RAM in 0x5000-0xcfff + a mirror of the first 0x3000 bytes up to 0xffff |
188 | | READ8_MEMBER(astrocade_whiteram_device::read) |
189 | | { |
190 | | return m_ram[offset % 0x8000]; |
191 | | } |
192 | | |
193 | | WRITE8_MEMBER(astrocade_whiteram_device::write) |
194 | | { |
195 | | if (!m_write_prot->read()) |
196 | | m_ram[offset % 0x8000] = data; |
197 | | } |
198 | | |
199 | | |
200 | | |
201 | | // R&L 64K RAM Board (44KB installed) has RAM in 0x5000-0xffff |
202 | | READ8_MEMBER(astrocade_rl64ram_device::read) |
203 | | { |
204 | | return m_ram[offset]; |
205 | | } |
206 | | |
207 | | WRITE8_MEMBER(astrocade_rl64ram_device::write) |
208 | | { |
209 | | if (!m_write_prot->read()) |
210 | | m_ram[offset] = data; |
211 | | } |
212 | | |
213 | | |
trunk/src/mame/video/psychic5.c
r241553 | r241554 | |
10 | 10 | #include "video/jalblend.h" |
11 | 11 | #include "includes/psychic5.h" |
12 | 12 | |
13 | | |
| 13 | #define BG_SCROLLX_LSB 0x308 |
| 14 | #define BG_SCROLLX_MSB 0x309 |
| 15 | #define BG_SCROLLY_LSB 0x30a |
| 16 | #define BG_SCROLLY_MSB 0x30b |
| 17 | #define BG_SCREEN_MODE 0x30c |
14 | 18 | #define BG_PAL_INTENSITY_RG 0x1fe |
15 | 19 | #define BG_PAL_INTENSITY_BU 0x1ff |
16 | 20 | |
r241553 | r241554 | |
19 | 23 | Palette color |
20 | 24 | ***************************************************************************/ |
21 | 25 | |
22 | | void psychic5_state::psychic5_change_palette(int offset, UINT8* palram, int palbase) |
| 26 | void psychic5_state::psychic5_change_palette(int color, int offset) |
23 | 27 | { |
24 | | UINT8 lo = palram[(offset) & ~1]; |
25 | | UINT8 hi = palram[(offset) | 1]; |
26 | | |
27 | | int color = offset >> 1; |
28 | | |
29 | | jal_blend_set(palbase + color, hi & 0x0f); |
30 | | m_palette->set_pen_color(palbase + color, pal4bit(lo >> 4), pal4bit(lo), pal4bit(hi >> 4)); |
| 28 | UINT8 lo = m_ps5_palette_ram[offset & ~1]; |
| 29 | UINT8 hi = m_ps5_palette_ram[offset | 1]; |
| 30 | jal_blend_set(color, hi & 0x0f); |
| 31 | m_palette->set_pen_color(color, pal4bit(lo >> 4), pal4bit(lo), pal4bit(hi >> 4)); |
31 | 32 | } |
32 | 33 | |
33 | 34 | void psychic5_state::psychic5_change_bg_palette(int color, int lo_offs, int hi_offs) |
r241553 | r241554 | |
43 | 44 | |
44 | 45 | irgb = rgb_t(ir,ig,ib); |
45 | 46 | |
46 | | lo = m_ps5_palette_ram_bg[lo_offs]; |
47 | | hi = m_ps5_palette_ram_bg[hi_offs]; |
| 47 | lo = m_ps5_palette_ram[lo_offs]; |
| 48 | hi = m_ps5_palette_ram[hi_offs]; |
48 | 49 | |
49 | 50 | /* red,green,blue component */ |
50 | 51 | r = pal4bit(lo >> 4); |
r241553 | r241554 | |
52 | 53 | b = pal4bit(hi >> 4); |
53 | 54 | |
54 | 55 | /* Grey background enable */ |
55 | | if (m_bg_control[4] & 2) |
| 56 | if (m_bg_status & 2) |
56 | 57 | { |
57 | 58 | UINT8 val = (r + g + b) / 3; /* Grey */ |
58 | 59 | /* Just leave plain grey */ |
r241553 | r241554 | |
72 | 73 | void psychic5_state::set_background_palette_intensity() |
73 | 74 | { |
74 | 75 | int i; |
75 | | m_palette_intensity = m_ps5_palette_ram_sp[BG_PAL_INTENSITY_BU] | |
76 | | (m_ps5_palette_ram_sp[BG_PAL_INTENSITY_RG]<<8); |
| 76 | m_palette_intensity = m_ps5_palette_ram[BG_PAL_INTENSITY_BU] | |
| 77 | (m_ps5_palette_ram[BG_PAL_INTENSITY_RG]<<8); |
77 | 78 | |
78 | 79 | /* for all of the background palette */ |
79 | 80 | for (i = 0; i < 0x100; i++) |
80 | | psychic5_change_bg_palette(i+0x100,i*2,i*2+1); |
| 81 | psychic5_change_bg_palette(m_bg_palette_base+i,m_bg_palette_ram_base+i*2,m_bg_palette_ram_base+i*2+1); |
81 | 82 | } |
82 | 83 | |
83 | 84 | |
r241553 | r241554 | |
93 | 94 | WRITE8_MEMBER(psychic5_state::psychic5_vram_page_select_w) |
94 | 95 | { |
95 | 96 | m_ps5_vram_page = data & 1; |
96 | | m_vrambank->set_bank(data); |
97 | 97 | } |
98 | 98 | |
99 | 99 | WRITE8_MEMBER(psychic5_state::psychic5_title_screen_w) |
r241553 | r241554 | |
101 | 101 | m_title_screen = data; |
102 | 102 | } |
103 | 103 | |
| 104 | READ8_MEMBER(psychic5_state::psychic5_paged_ram_r) |
| 105 | { |
| 106 | if (m_ps5_vram_page == 1) |
| 107 | { |
| 108 | switch (offset) |
| 109 | { |
| 110 | case 0x00: return ioport("SYSTEM")->read(); |
| 111 | case 0x01: return ioport("P1")->read(); |
| 112 | case 0x02: return ioport("P2")->read(); |
| 113 | case 0x03: return ioport("DSW1")->read(); |
| 114 | case 0x04: return ioport("DSW2")->read(); |
| 115 | } |
| 116 | } |
104 | 117 | |
105 | | |
106 | | WRITE8_MEMBER(psychic5_state::sprite_col_w) |
107 | | { |
108 | | m_ps5_palette_ram_sp[offset] = data; |
109 | | psychic5_change_palette(offset,m_ps5_palette_ram_sp, 0x000); |
| 118 | return m_ps5_pagedram[m_ps5_vram_page][offset]; |
110 | 119 | } |
111 | 120 | |
112 | | WRITE8_MEMBER(psychic5_state::bg_col_w) |
| 121 | WRITE8_MEMBER(psychic5_state::psychic5_paged_ram_w) |
113 | 122 | { |
114 | | m_ps5_palette_ram_bg[offset] = data; |
115 | | psychic5_change_palette(offset,m_ps5_palette_ram_bg, 0x100); |
116 | | } |
| 123 | m_ps5_pagedram[m_ps5_vram_page][offset] = data; |
117 | 124 | |
118 | | WRITE8_MEMBER(psychic5_state::tx_col_w) |
119 | | { |
120 | | m_ps5_palette_ram_tx[offset] = data; |
121 | | psychic5_change_palette(offset,m_ps5_palette_ram_tx, 0x200); |
| 125 | if (m_ps5_vram_page == 0) |
| 126 | { |
| 127 | if (offset <= 0xfff) |
| 128 | m_bg_tilemap->mark_tile_dirty(offset >> 1); |
| 129 | } |
| 130 | else |
| 131 | { |
| 132 | if (offset == BG_SCROLLX_LSB || offset == BG_SCROLLX_MSB) |
| 133 | { |
| 134 | UINT16 bg_scrollx = m_ps5_io_ram[BG_SCROLLX_LSB] | (m_ps5_io_ram[BG_SCROLLX_MSB] << 8); |
| 135 | m_bg_tilemap->set_scrollx(0, bg_scrollx); |
| 136 | } |
| 137 | else if (offset == BG_SCROLLY_LSB || offset == BG_SCROLLY_MSB) |
| 138 | { |
| 139 | UINT16 bg_scrolly = m_ps5_io_ram[BG_SCROLLY_LSB] | (m_ps5_io_ram[BG_SCROLLY_MSB] << 8); |
| 140 | m_bg_tilemap->set_scrolly(0, bg_scrolly); |
| 141 | } |
| 142 | else if (offset == BG_SCREEN_MODE) |
| 143 | { |
| 144 | m_bg_status = m_ps5_io_ram[BG_SCREEN_MODE]; |
| 145 | } |
| 146 | else if (offset >= 0x400 && offset <= 0x5ff) /* Sprite color */ |
| 147 | psychic5_change_palette(((offset >> 1) & 0xff)+0x000,offset-0x400); |
| 148 | else if (offset >= 0x800 && offset <= 0x9ff) /* BG color */ |
| 149 | psychic5_change_palette(((offset >> 1) & 0xff)+0x100,offset-0x400); |
| 150 | else if (offset >= 0xa00 && offset <= 0xbff) /* Text color */ |
| 151 | psychic5_change_palette(((offset >> 1) & 0xff)+0x200,offset-0x400); |
| 152 | else if (offset >= 0x1000) |
| 153 | m_fg_tilemap->mark_tile_dirty((offset-0x1000) >> 1); |
| 154 | } |
122 | 155 | } |
123 | 156 | |
124 | | |
125 | | WRITE8_MEMBER(psychic5_state::fg_videoram_w) |
| 157 | WRITE8_MEMBER(psychic5_state::bombsa_paged_ram_w) |
126 | 158 | { |
127 | | m_fg_videoram[offset] = data; |
128 | | m_fg_tilemap->mark_tile_dirty(offset >> 1); |
129 | | } |
| 159 | m_ps5_pagedram[m_ps5_vram_page][offset] = data; |
130 | 160 | |
131 | | WRITE8_MEMBER( psychic5_state::bg_videoram_w ) |
132 | | { |
133 | | m_bg_videoram[offset] = data; |
134 | | m_bg_tilemap->mark_tile_dirty(offset >> 1); |
| 161 | if (m_ps5_vram_page == 0) |
| 162 | { |
| 163 | m_bg_tilemap->mark_tile_dirty(offset >> 1); |
| 164 | } |
| 165 | else |
| 166 | { |
| 167 | if (offset == BG_SCROLLX_LSB || offset == BG_SCROLLX_MSB) |
| 168 | { |
| 169 | UINT16 bg_scrollx = m_ps5_io_ram[BG_SCROLLX_LSB] | (m_ps5_io_ram[BG_SCROLLX_MSB] << 8); |
| 170 | m_bg_tilemap->set_scrollx(0, bg_scrollx); |
| 171 | } |
| 172 | else if (offset == BG_SCROLLY_LSB || offset == BG_SCROLLY_MSB) |
| 173 | { |
| 174 | UINT16 bg_scrolly = m_ps5_io_ram[BG_SCROLLY_LSB] | (m_ps5_io_ram[BG_SCROLLY_MSB] << 8); |
| 175 | m_bg_tilemap->set_scrolly(0, bg_scrolly); |
| 176 | } |
| 177 | else if (offset == BG_SCREEN_MODE) |
| 178 | { |
| 179 | m_bg_status = m_ps5_io_ram[BG_SCREEN_MODE]; |
| 180 | } |
| 181 | else if (offset >= 0x0800 && offset <= 0x0fff) |
| 182 | m_fg_tilemap->mark_tile_dirty((offset & 0x7ff) >> 1); |
| 183 | else if (offset >= 0x1000 && offset <= 0x15ff) |
| 184 | psychic5_change_palette((offset >> 1) & 0x3ff, offset-0x1000); |
| 185 | } |
135 | 186 | } |
136 | 187 | |
137 | | |
138 | | |
139 | 188 | WRITE8_MEMBER(psychic5_state::bombsa_unknown_w) |
140 | 189 | { |
141 | 190 | m_bombsa_unknown = data; |
r241553 | r241554 | |
175 | 224 | |
176 | 225 | VIDEO_START_MEMBER(psychic5_state,psychic5) |
177 | 226 | { |
| 227 | /* info offset w h col row */ |
178 | 228 | m_bg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(psychic5_state::get_bg_tile_info),this), TILEMAP_SCAN_COLS, 16, 16, 64, 32); |
179 | 229 | m_fg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(psychic5_state::get_fg_tile_info),this), TILEMAP_SCAN_COLS, 8, 8, 32, 32); |
| 230 | |
180 | 231 | m_fg_tilemap->set_transparent_pen(15); |
| 232 | |
| 233 | m_ps5_pagedram[0] = auto_alloc_array(machine(), UINT8, 0x2000); |
| 234 | m_ps5_pagedram[1] = auto_alloc_array(machine(), UINT8, 0x2000); |
| 235 | |
| 236 | m_bg_videoram = &m_ps5_pagedram[0][0x0000]; |
| 237 | m_ps5_dummy_bg_ram = &m_ps5_pagedram[0][0x1000]; |
| 238 | m_ps5_io_ram = &m_ps5_pagedram[1][0x0000]; |
| 239 | m_ps5_palette_ram = &m_ps5_pagedram[1][0x0400]; |
| 240 | m_fg_videoram = &m_ps5_pagedram[1][0x1000]; |
| 241 | |
181 | 242 | jal_blend_init(machine(), 1); |
182 | 243 | |
| 244 | m_bg_palette_ram_base = 0x400; |
| 245 | m_bg_palette_base = 0x100; |
183 | 246 | } |
184 | 247 | |
185 | 248 | VIDEO_START_MEMBER(psychic5_state,bombsa) |
186 | 249 | { |
| 250 | /* info offset w h col row */ |
187 | 251 | m_bg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(psychic5_state::get_bg_tile_info),this), TILEMAP_SCAN_COLS, 16, 16, 128, 32); |
188 | 252 | m_fg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(psychic5_state::get_fg_tile_info),this), TILEMAP_SCAN_COLS, 8, 8, 32, 32); |
| 253 | |
189 | 254 | m_fg_tilemap->set_transparent_pen(15); |
| 255 | |
| 256 | m_ps5_pagedram[0] = auto_alloc_array(machine(), UINT8, 0x2000); |
| 257 | m_ps5_pagedram[1] = auto_alloc_array(machine(), UINT8, 0x2000); |
| 258 | |
| 259 | m_bg_videoram = &m_ps5_pagedram[0][0x0000]; |
| 260 | m_ps5_dummy_bg_ram = &m_ps5_pagedram[0][0x1000]; |
| 261 | m_ps5_io_ram = &m_ps5_pagedram[1][0x0000]; |
| 262 | m_fg_videoram = &m_ps5_pagedram[1][0x0800]; |
| 263 | m_ps5_palette_ram = &m_ps5_pagedram[1][0x1000]; |
| 264 | |
190 | 265 | jal_blend_init(machine(), 0); |
| 266 | |
| 267 | m_bg_palette_ram_base = 0x000; |
| 268 | m_bg_palette_base = 0x000; |
191 | 269 | } |
192 | 270 | |
193 | 271 | VIDEO_RESET_MEMBER(psychic5_state,psychic5) |
194 | 272 | { |
195 | 273 | m_bg_clip_mode = 0; |
196 | 274 | m_ps5_vram_page = 0; |
| 275 | m_bg_status = 0; |
| 276 | memset(m_ps5_pagedram[0],0,0x2000); |
| 277 | memset(m_ps5_pagedram[1],0,0x2000); |
| 278 | m_palette_intensity = 0; |
| 279 | } |
| 280 | |
| 281 | VIDEO_RESET_MEMBER(psychic5_state,bombsa) |
| 282 | { |
| 283 | m_ps5_vram_page = 0; |
| 284 | m_bg_status = 0; |
197 | 285 | m_title_screen = 0; |
| 286 | memset(m_ps5_pagedram[0],0,0x2000); |
| 287 | memset(m_ps5_pagedram[1],0,0x2000); |
198 | 288 | m_palette_intensity = 0; |
199 | 289 | } |
200 | 290 | |
201 | 291 | |
202 | | |
203 | 292 | /*************************************************************************** |
204 | 293 | Screen refresh |
205 | 294 | ***************************************************************************/ |
r241553 | r241554 | |
317 | 406 | |
318 | 407 | UINT32 psychic5_state::screen_update_psychic5(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
319 | 408 | { |
320 | | UINT16 bg_scrollx = m_bg_control[0] | (m_bg_control[1] << 8); |
321 | | m_bg_tilemap->set_scrollx(0, bg_scrollx); |
322 | | UINT16 bg_scrolly = m_bg_control[2] | (m_bg_control[3] << 8); |
323 | | m_bg_tilemap->set_scrolly(0, bg_scrolly); |
324 | | |
325 | 409 | bitmap.fill(m_palette->black_pen(), cliprect); |
326 | | if (m_bg_control[4] & 1) /* Backgound enable */ |
| 410 | if (m_bg_status & 1) /* Backgound enable */ |
327 | 411 | draw_background(screen, bitmap, cliprect); |
328 | 412 | if (!(m_title_screen & 1)) |
329 | 413 | draw_sprites(bitmap, cliprect); |
r241553 | r241554 | |
333 | 417 | |
334 | 418 | UINT32 psychic5_state::screen_update_bombsa(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
335 | 419 | { |
336 | | UINT16 bg_scrollx = m_bg_control[0] | (m_bg_control[1] << 8); |
337 | | m_bg_tilemap->set_scrollx(0, bg_scrollx); |
338 | | UINT16 bg_scrolly = m_bg_control[2] | (m_bg_control[3] << 8); |
339 | | m_bg_tilemap->set_scrolly(0, bg_scrolly); |
340 | | bitmap.fill(m_palette->black_pen(), cliprect); |
341 | | |
342 | | if (m_bg_control[4] & 1) /* Backgound enable */ |
| 420 | if (m_bg_status & 1) /* Backgound enable */ |
343 | 421 | m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); |
344 | 422 | else |
345 | 423 | bitmap.fill(m_palette->pen(0x0ff), cliprect); |
trunk/src/mess/drivers/astrocde.c
r241553 | r241554 | |
14 | 14 | #include "sound/astrocde.h" |
15 | 15 | #include "bus/astrocde/slot.h" |
16 | 16 | #include "bus/astrocde/rom.h" |
17 | | #include "bus/astrocde/exp.h" |
18 | | #include "bus/astrocde/ram.h" |
19 | 17 | |
20 | 18 | class astrocde_mess_state : public astrocde_state |
21 | 19 | { |
r241553 | r241554 | |
26 | 24 | { } |
27 | 25 | |
28 | 26 | required_device<astrocade_cart_slot_device> m_cart; |
| 27 | void get_ram_expansion_settings(int &ram_expansion_installed, int &write_protect_on, int &expansion_ram_start, int &expansion_ram_end, int &shadow_ram_end); |
29 | 28 | DECLARE_MACHINE_START(astrocde); |
| 29 | DECLARE_MACHINE_RESET(astrocde); |
| 30 | DECLARE_INPUT_CHANGED_MEMBER(set_write_protect); |
30 | 31 | }; |
31 | 32 | |
32 | | /********************************************************************************* |
| 33 | /************************************* |
33 | 34 | * |
34 | 35 | * Memory maps |
35 | 36 | * |
r241553 | r241554 | |
41 | 42 | * by an extended BASIC program. Bally and Astrocade BASIC can access from |
42 | 43 | * $5000 to $7FFF if available. |
43 | 44 | * |
44 | | *********************************************************************************/ |
| 45 | * RAM Expansions |
| 46 | * |
| 47 | * Several third party RAM expansions have been made for the Astrocade. These |
| 48 | * allow access to various ranges of the expansion memory ($5000 to $FFFF). |
| 49 | * A RAM expansion is required to use extended BASIC programs like Blue RAM BASIC |
| 50 | * and VIPERSoft BASIC. All of the expansions also have a RAM protect switch, which |
| 51 | * can be flipped at any time to make the RAM act like ROM. Extended BASIC |
| 52 | * programs need access to the RAM and won't work with RAM protect enabled, but |
| 53 | * this can be useful with Bally and Astrocade BASIC. They also have a range switch |
| 54 | * (not implemented). The default position is 6K, but it can be switched to |
| 55 | * 2K. This means that the expanded memory starting at $6000 will instead be |
| 56 | * mapped to the cartridge memory starting at $2000. So it would be possible to |
| 57 | * load a cartridge program from tape into the expansion memory, then flip the range |
| 58 | * switch and run it as a cartridge. This is useful for cartridge development. |
| 59 | * |
| 60 | * NOTE: If you have any trouble running cartridges with a RAM expansion installed, hit reset. |
| 61 | * |
| 62 | * Blue RAM -- available in 4K, 16K, and 32K. These also use an INS8154 chip, |
| 63 | * (not yet implemented) which has an additional $80 bytes of RAM mapped |
| 64 | * immediately after the end of the expansion address space. This memory |
| 65 | * can't be write protected. The INS8154 has I/O features needed for loading |
| 66 | * tape programs into Blue RAM BASIC, as well as running the Blue RAM Utility cart. |
| 67 | * 4K: $6000 to $6FFF (can't run VIPERSoft BASIC, because this program needs memory |
| 68 | * past this range) |
| 69 | * 16K: $6000 to $9FFF |
| 70 | * 32K: $6000 to $DFFF |
| 71 | * |
| 72 | * VIPER System 1 -- This is available in 16K only. It also includes a keyboard (not implemented). |
| 73 | * 16K: $6000 to $9FFF |
| 74 | * |
| 75 | * Lil' WHITE RAM -- This is available in 32K only. Attempts to read and write |
| 76 | * to memory outside of its address range ($D000 to $FFFF) are mapped to the expansion |
| 77 | * memory $5000 to $7FFF. The current implementation won't allow the shadow RAM area |
| 78 | * to be accessed when RAM protect is on, but there is no known software that will |
| 79 | * access the upper range of the expansion RAM when RAM protect is enabled. |
| 80 | * 32K: $5000 to $CFFF |
| 81 | * |
| 82 | * R&L 64K RAM Board -- This is a highly configurable kit. RAM can be installed in |
| 83 | * 2K increments. So, the entire 44K expansion memory can be filled. It is also |
| 84 | * possible to override the rest of the memory map with RAM (not implemented). |
| 85 | * There are 32 switches allowing users to activate and deactivate each 2K block (not implemented). |
| 86 | * RAM write protection can be implemented in three ranges through jumpers or by |
| 87 | * installing switches. The ranges are $0000 to $0FFF (first 4K), $0000 to $3FFF (first 16K), |
| 88 | * and $0000 to $FFFF (all 64K). The current implementation is for 44K expansion memory mapped from |
| 89 | * $5000 to $FFFF, with only a single write protect covering this entire range. |
| 90 | * |
| 91 | *************************************/ |
45 | 92 | |
46 | 93 | static ADDRESS_MAP_START( astrocade_mem, AS_PROGRAM, 8, astrocde_mess_state ) |
47 | 94 | AM_RANGE(0x0000, 0x0fff) AM_ROM AM_WRITE(astrocade_funcgen_w) |
48 | 95 | AM_RANGE(0x1000, 0x3fff) AM_ROM /* Star Fortress writes in here?? */ |
49 | 96 | AM_RANGE(0x4000, 0x4fff) AM_RAM AM_SHARE("videoram") /* ASG */ |
50 | | AM_RANGE(0x5000, 0xffff) AM_DEVREADWRITE("exp", astrocade_exp_device, read, write) |
51 | 97 | ADDRESS_MAP_END |
52 | 98 | |
53 | 99 | |
r241553 | r241554 | |
55 | 101 | AM_RANGE(0x00, 0x1f) AM_MIRROR(0xff00) AM_MASK(0xffff) AM_READWRITE(astrocade_data_chip_register_r, astrocade_data_chip_register_w) |
56 | 102 | ADDRESS_MAP_END |
57 | 103 | |
| 104 | INPUT_CHANGED_MEMBER(astrocde_mess_state::set_write_protect) // run when RAM expansion write protect switch is changed |
| 105 | { |
| 106 | int ram_expansion_installed = 0, write_protect_on = 0, expansion_ram_start = 0, expansion_ram_end = 0, shadow_ram_end = 0; |
| 107 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 108 | UINT8 *expram = machine().device<ram_device>("ram_tag")->pointer(); |
| 109 | |
| 110 | get_ram_expansion_settings(ram_expansion_installed, write_protect_on, expansion_ram_start, expansion_ram_end, shadow_ram_end); // passing by reference |
| 111 | |
| 112 | if (ram_expansion_installed == 1) |
| 113 | { |
| 114 | if (write_protect_on == 0) // write protect off, so install memory normally |
| 115 | { |
| 116 | space.install_ram(expansion_ram_start, expansion_ram_end, expram); |
| 117 | if (shadow_ram_end > expansion_ram_end) |
| 118 | space.install_ram(expansion_ram_end + 1, shadow_ram_end, expram); |
| 119 | } |
| 120 | else // write protect on, so make memory read only |
| 121 | { |
| 122 | space.nop_write(expansion_ram_start, expansion_ram_end); |
| 123 | } |
| 124 | } |
| 125 | } |
| 126 | |
58 | 127 | /************************************* |
59 | 128 | * |
60 | 129 | * Input ports |
r241553 | r241554 | |
158 | 227 | |
159 | 228 | PORT_START("P4_KNOB") |
160 | 229 | PORT_BIT(0xff, 0x00, IPT_PADDLE) PORT_INVERT PORT_SENSITIVITY(85) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) PORT_CODE_DEC(KEYCODE_Y) PORT_CODE_INC(KEYCODE_U) PORT_PLAYER(4) |
| 230 | |
| 231 | PORT_START("CFG") /* machine config */ |
| 232 | PORT_DIPNAME( 0x3f, 0x00, "RAM Expansion") |
| 233 | PORT_DIPSETTING( 0x00, "No RAM Expansion") |
| 234 | PORT_DIPSETTING( 0x01, "16KB Viper System 1 RAM Expansion") |
| 235 | PORT_DIPSETTING( 0x02, "32KB Lil' WHITE RAM Expansion") |
| 236 | PORT_DIPSETTING( 0x04, "R&L 64K RAM Board (44K installed)") |
| 237 | PORT_DIPSETTING( 0x08, "4KB Blue RAM Expansion") |
| 238 | PORT_DIPSETTING( 0x10, "16KB Blue RAM Expansion") |
| 239 | PORT_DIPSETTING( 0x20, "32KB Blue RAM Expansion") |
| 240 | |
| 241 | PORT_START("PROTECT") /* Write protect RAM */ |
| 242 | PORT_DIPNAME( 0x01, 0x00, "Write Protect RAM") PORT_CHANGED_MEMBER(DEVICE_SELF, astrocde_mess_state, set_write_protect, 0) |
| 243 | PORT_DIPSETTING( 0x00, "Write Protect Off") |
| 244 | PORT_DIPSETTING( 0x01, "Write Protect On") |
161 | 245 | INPUT_PORTS_END |
162 | 246 | |
163 | 247 | |
r241553 | r241554 | |
173 | 257 | SLOT_INTERFACE_INTERNAL("rom_512k", ASTROCADE_ROM_512K) |
174 | 258 | SLOT_INTERFACE_END |
175 | 259 | |
176 | | static SLOT_INTERFACE_START(astrocade_exp) |
177 | | SLOT_INTERFACE("blue_ram_4k", ASTROCADE_BLUERAM_4K) |
178 | | SLOT_INTERFACE("blue_ram_16k", ASTROCADE_BLUERAM_16K) |
179 | | SLOT_INTERFACE("blue_ram_32k", ASTROCADE_BLUERAM_32K) |
180 | | SLOT_INTERFACE("viper_sys1", ASTROCADE_VIPER_SYS1) |
181 | | SLOT_INTERFACE("lil_white_ram", ASTROCADE_WHITERAM) |
182 | | SLOT_INTERFACE("rl64_ram", ASTROCADE_RL64RAM) |
183 | | SLOT_INTERFACE_END |
184 | 260 | |
185 | | |
186 | 261 | static MACHINE_CONFIG_START( astrocde, astrocde_mess_state ) |
187 | 262 | /* basic machine hardware */ |
188 | 263 | MCFG_CPU_ADD("maincpu", Z80, ASTROCADE_CLOCK/4) /* 1.789 MHz */ |
r241553 | r241554 | |
190 | 265 | MCFG_CPU_IO_MAP(astrocade_io) |
191 | 266 | |
192 | 267 | MCFG_MACHINE_START_OVERRIDE(astrocde_mess_state, astrocde) |
| 268 | MCFG_MACHINE_RESET_OVERRIDE(astrocde_mess_state, astrocde) |
193 | 269 | |
194 | 270 | /* video hardware */ |
195 | 271 | MCFG_SCREEN_ADD("screen", RASTER) |
r241553 | r241554 | |
205 | 281 | MCFG_SOUND_ADD("astrocade1", ASTROCADE, ASTROCADE_CLOCK/4) |
206 | 282 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) |
207 | 283 | |
208 | | /* expansion port */ |
209 | | MCFG_ASTROCADE_EXPANSION_SLOT_ADD("exp", astrocade_exp, NULL) |
| 284 | /* optional expansion ram (installed in machine_reset)*/ |
| 285 | MCFG_RAM_ADD("ram_tag") |
| 286 | MCFG_RAM_DEFAULT_SIZE("32k") |
210 | 287 | |
211 | 288 | /* cartridge */ |
212 | 289 | MCFG_ASTROCADE_CARTRIDGE_ADD("cartslot", astrocade_cart, NULL) |
r241553 | r241554 | |
254 | 331 | m_maincpu->space(AS_PROGRAM).install_read_handler(0x2000, 0x3fff, read8_delegate(FUNC(astrocade_cart_slot_device::read_rom),(astrocade_cart_slot_device*)m_cart)); |
255 | 332 | } |
256 | 333 | |
| 334 | MACHINE_RESET_MEMBER(astrocde_mess_state, astrocde) |
| 335 | { |
| 336 | int ram_expansion_installed = 0, write_protect_on = 0, expansion_ram_start = 0, expansion_ram_end = 0, shadow_ram_end = 0; |
| 337 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 338 | UINT8 *expram = machine().device<ram_device>("ram_tag")->pointer(); |
| 339 | space.unmap_readwrite(0x5000, 0xffff); // unmap any previously installed expansion RAM |
| 340 | |
| 341 | get_ram_expansion_settings(ram_expansion_installed, write_protect_on, expansion_ram_start, expansion_ram_end, shadow_ram_end); // passing by reference |
| 342 | |
| 343 | if (ram_expansion_installed == 1) |
| 344 | { |
| 345 | if (write_protect_on == 0) // write protect off, so install memory normally |
| 346 | { |
| 347 | space.install_ram(expansion_ram_start, expansion_ram_end, expram); |
| 348 | if (shadow_ram_end > expansion_ram_end) |
| 349 | space.install_ram(expansion_ram_end + 1, shadow_ram_end, expram); |
| 350 | } |
| 351 | else // write protect on, so make memory read only |
| 352 | { |
| 353 | space.nop_write(expansion_ram_start, expansion_ram_end); |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | void astrocde_mess_state::get_ram_expansion_settings(int &ram_expansion_installed, int &write_protect_on, int &expansion_ram_start, int &expansion_ram_end, int &shadow_ram_end) |
| 359 | { |
| 360 | if (ioport("PROTECT")->read() == 0x01) |
| 361 | write_protect_on = 1; |
| 362 | else |
| 363 | write_protect_on = 0; |
| 364 | |
| 365 | ram_expansion_installed = 1; |
| 366 | |
| 367 | switch(ioport("CFG")->read()) // check RAM expansion configuration and set address ranges |
| 368 | { |
| 369 | case 0x00: // No RAM Expansion |
| 370 | ram_expansion_installed = 0; |
| 371 | break; |
| 372 | case 0x01: // 16KB Viper System 1 RAM Expansion |
| 373 | expansion_ram_start = 0x6000; |
| 374 | expansion_ram_end = 0x9fff; |
| 375 | shadow_ram_end = 0; |
| 376 | break; |
| 377 | case 0x02: // "32KB Lil' WHITE RAM Expansion |
| 378 | expansion_ram_start = 0x5000; |
| 379 | expansion_ram_end = 0xcfff; |
| 380 | shadow_ram_end = 0xffff; |
| 381 | break; |
| 382 | case 0x04: // R&L 64K RAM Board (44KB installed) |
| 383 | expansion_ram_start = 0x5000; |
| 384 | expansion_ram_end = 0xffff; |
| 385 | shadow_ram_end = 0; |
| 386 | break; |
| 387 | case 0x08: // 4KB Blue RAM Expansion |
| 388 | expansion_ram_start = 0x6000; |
| 389 | expansion_ram_end = 0x6fff; |
| 390 | shadow_ram_end = 0; |
| 391 | break; |
| 392 | case 0x10: // 16KB Blue RAM Expansion |
| 393 | expansion_ram_start = 0x6000; |
| 394 | expansion_ram_end = 0x9fff; |
| 395 | shadow_ram_end = 0; |
| 396 | break; |
| 397 | case 0x20: // 32KB Blue RAM Expansion |
| 398 | expansion_ram_start = 0x6000; |
| 399 | expansion_ram_end = 0xdfff; |
| 400 | shadow_ram_end = 0; |
| 401 | break; |
| 402 | default: |
| 403 | break; |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | |
257 | 408 | /************************************* |
258 | 409 | * |
259 | 410 | * Driver definitions |
trunk/src/mess/machine/wswan.c
r241553 | r241554 | |
78 | 78 | 0xea, 0xc0, 0xff, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
79 | 79 | }; |
80 | 80 | |
81 | | void wswan_state::handle_irqs() |
| 81 | void wswan_state::wswan_handle_irqs() |
82 | 82 | { |
83 | | if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR) |
| 83 | if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR ) |
84 | 84 | { |
85 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR); |
| 85 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR ); |
86 | 86 | } |
87 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL) |
| 87 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL ) |
88 | 88 | { |
89 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL); |
| 89 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL ); |
90 | 90 | } |
91 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR) |
| 91 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR ) |
92 | 92 | { |
93 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR); |
| 93 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR ); |
94 | 94 | } |
95 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP) |
| 95 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP ) |
96 | 96 | { |
97 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP); |
| 97 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP ); |
98 | 98 | } |
99 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX) |
| 99 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX ) |
100 | 100 | { |
101 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX); |
| 101 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX ); |
102 | 102 | } |
103 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC) |
| 103 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC ) |
104 | 104 | { |
105 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC); |
| 105 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC ); |
106 | 106 | } |
107 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY) |
| 107 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY ) |
108 | 108 | { |
109 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY); |
| 109 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY ); |
110 | 110 | } |
111 | | else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX) |
| 111 | else if ( m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX ) |
112 | 112 | { |
113 | | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX); |
| 113 | m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX ); |
114 | 114 | } |
115 | 115 | else |
116 | 116 | { |
117 | | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 117 | m_maincpu->set_input_line(0, CLEAR_LINE ); |
118 | 118 | } |
119 | 119 | } |
120 | 120 | |
121 | | void wswan_state::set_irq_line(int irq) |
| 121 | void wswan_state::wswan_set_irq_line(int irq) |
122 | 122 | { |
123 | | if (m_ws_portram[0xb2] & irq) |
| 123 | if ( m_ws_portram[0xb2] & irq ) |
124 | 124 | { |
125 | 125 | m_ws_portram[0xb6] |= irq; |
126 | | handle_irqs(); |
| 126 | wswan_handle_irqs(); |
127 | 127 | } |
128 | 128 | } |
129 | 129 | |
130 | | void wswan_state::dma_sound_cb() |
| 130 | void wswan_state::wswan_clear_irq_line(int irq) |
131 | 131 | { |
132 | | if ((m_sound_dma.enable & 0x88) == 0x80) |
133 | | { |
134 | | address_space &space = m_maincpu->space(AS_PROGRAM); |
135 | | /* TODO: Output sound DMA byte */ |
136 | | port_w(space, 0x89, space.read_byte(m_sound_dma.source)); |
137 | | m_sound_dma.size--; |
138 | | m_sound_dma.source = (m_sound_dma.source + 1) & 0x0fffff; |
139 | | if (m_sound_dma.size == 0) |
140 | | { |
141 | | m_sound_dma.enable &= 0x7F; |
142 | | } |
143 | | } |
144 | | } |
145 | | |
146 | | void wswan_state::clear_irq_line(int irq) |
147 | | { |
148 | 132 | m_ws_portram[0xb6] &= ~irq; |
149 | | handle_irqs(); |
| 133 | wswan_handle_irqs(); |
150 | 134 | } |
151 | 135 | |
152 | | void wswan_state::register_save() |
| 136 | void wswan_state::wswan_register_save() |
153 | 137 | { |
154 | 138 | save_item(NAME(m_ws_portram)); |
155 | 139 | save_item(NAME(m_internal_eeprom)); |
156 | 140 | save_item(NAME(m_bios_disabled)); |
157 | 141 | save_item(NAME(m_rotate)); |
158 | | |
| 142 | |
| 143 | save_item(NAME(m_vdp.layer_bg_enable)); |
| 144 | save_item(NAME(m_vdp.layer_fg_enable)); |
| 145 | save_item(NAME(m_vdp.sprites_enable)); |
| 146 | save_item(NAME(m_vdp.window_sprites_enable)); |
| 147 | save_item(NAME(m_vdp.window_fg_mode)); |
| 148 | save_item(NAME(m_vdp.current_line)); |
| 149 | save_item(NAME(m_vdp.line_compare)); |
| 150 | save_item(NAME(m_vdp.sprite_table_address)); |
| 151 | save_item(NAME(m_vdp.sprite_table_buffer)); |
| 152 | save_item(NAME(m_vdp.sprite_first)); |
| 153 | save_item(NAME(m_vdp.sprite_count)); |
| 154 | save_item(NAME(m_vdp.layer_bg_address)); |
| 155 | save_item(NAME(m_vdp.layer_fg_address)); |
| 156 | save_item(NAME(m_vdp.window_fg_left)); |
| 157 | save_item(NAME(m_vdp.window_fg_top)); |
| 158 | save_item(NAME(m_vdp.window_fg_right)); |
| 159 | save_item(NAME(m_vdp.window_fg_bottom)); |
| 160 | save_item(NAME(m_vdp.window_sprites_left)); |
| 161 | save_item(NAME(m_vdp.window_sprites_top)); |
| 162 | save_item(NAME(m_vdp.window_sprites_right)); |
| 163 | save_item(NAME(m_vdp.window_sprites_bottom)); |
| 164 | save_item(NAME(m_vdp.layer_bg_scroll_x)); |
| 165 | save_item(NAME(m_vdp.layer_bg_scroll_y)); |
| 166 | save_item(NAME(m_vdp.layer_fg_scroll_x)); |
| 167 | save_item(NAME(m_vdp.layer_fg_scroll_y)); |
| 168 | save_item(NAME(m_vdp.lcd_enable)); |
| 169 | save_item(NAME(m_vdp.icons)); |
| 170 | save_item(NAME(m_vdp.color_mode)); |
| 171 | save_item(NAME(m_vdp.colors_16)); |
| 172 | save_item(NAME(m_vdp.tile_packed)); |
| 173 | save_item(NAME(m_vdp.timer_hblank_enable)); |
| 174 | save_item(NAME(m_vdp.timer_hblank_mode)); |
| 175 | save_item(NAME(m_vdp.timer_hblank_reload)); |
| 176 | save_item(NAME(m_vdp.timer_vblank_enable)); |
| 177 | save_item(NAME(m_vdp.timer_vblank_mode)); |
| 178 | save_item(NAME(m_vdp.timer_vblank_reload)); |
| 179 | save_item(NAME(m_vdp.timer_vblank_count)); |
| 180 | save_item(NAME(m_vdp.main_palette)); |
| 181 | |
159 | 182 | save_item(NAME(m_sound_dma.source)); |
160 | 183 | save_item(NAME(m_sound_dma.size)); |
161 | 184 | save_item(NAME(m_sound_dma.enable)); |
162 | | |
| 185 | |
163 | 186 | if (m_cart->exists()) |
164 | 187 | m_cart->save_nvram(); |
| 188 | |
| 189 | machine().save().register_postload(save_prepost_delegate(FUNC(wswan_state::wswan_postload), this)); |
165 | 190 | } |
166 | 191 | |
| 192 | void wswan_state::wswan_postload() |
| 193 | { |
| 194 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 195 | // restore the vdp pointers |
| 196 | m_vdp.vram = (UINT8*)space.get_read_ptr(0); |
| 197 | m_vdp.palette_vram = (UINT8*)space.get_read_ptr((m_system_type == TYPE_WSC) ? 0xfe00 : 0); |
| 198 | } |
| 199 | |
167 | 200 | void wswan_state::common_start() |
168 | 201 | { |
169 | 202 | m_ws_bios_bank = auto_alloc_array(machine(), UINT8, 0x10000); |
170 | 203 | memcpy(m_ws_bios_bank + 0xffc0, ws_fake_bios_code, 0x40); |
171 | | |
172 | | register_save(); |
173 | | |
| 204 | |
| 205 | m_vdp.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(wswan_state::wswan_scanline_interrupt),this), &m_vdp); |
| 206 | m_vdp.timer->adjust(attotime::from_ticks(256, 3072000), 0, attotime::from_ticks(256, 3072000)); |
| 207 | |
| 208 | wswan_register_save(); |
| 209 | |
174 | 210 | machine().device<nvram_device>("nvram")->set_base(m_internal_eeprom, INTERNAL_EEPROM_SIZE); |
175 | | |
| 211 | |
176 | 212 | if (m_cart->exists()) |
177 | 213 | { |
178 | 214 | // ROM |
179 | 215 | 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)); |
180 | 216 | 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)); |
181 | 217 | 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)); |
182 | | |
| 218 | |
183 | 219 | // SRAM |
184 | 220 | if (m_cart->get_type() == WS_SRAM) |
185 | 221 | { |
r241553 | r241554 | |
195 | 231 | m_system_type = TYPE_WSWAN; |
196 | 232 | } |
197 | 233 | |
198 | | MACHINE_START_MEMBER(wswan_state, wscolor) |
| 234 | MACHINE_START_MEMBER(wswan_state,wscolor) |
199 | 235 | { |
200 | 236 | common_start(); |
201 | 237 | m_system_type = TYPE_WSC; |
r241553 | r241554 | |
203 | 239 | |
204 | 240 | void wswan_state::machine_reset() |
205 | 241 | { |
| 242 | address_space &space = m_maincpu->space(AS_PROGRAM); |
| 243 | |
206 | 244 | m_bios_disabled = 0; |
207 | | |
| 245 | |
| 246 | m_ws_ram = (UINT8*) m_maincpu->space(AS_PROGRAM).get_read_ptr(0); |
| 247 | memset(m_ws_ram, 0, 0xffff); |
| 248 | |
208 | 249 | if (m_cart->exists()) |
209 | 250 | m_rotate = m_cart->get_is_rotated(); |
210 | 251 | else |
211 | 252 | m_rotate = 0; |
212 | | |
| 253 | |
213 | 254 | /* Intialize ports */ |
214 | 255 | memcpy(m_ws_portram, ws_portram_init, 256); |
215 | | |
| 256 | |
| 257 | /* Initialize VDP */ |
| 258 | memset(&m_vdp, 0, sizeof(m_vdp)); |
| 259 | |
| 260 | m_vdp.vram = (UINT8*)space.get_read_ptr(0); |
| 261 | m_vdp.palette_vram = (UINT8*)space.get_read_ptr(( m_system_type == TYPE_WSC ) ? 0xFE00 : 0 ); |
| 262 | m_vdp.current_line = 145; /* Randomly chosen, beginning of VBlank period to give cart some time to boot up */ |
| 263 | m_vdp.color_mode = 0; |
| 264 | m_vdp.colors_16 = 0; |
| 265 | m_vdp.tile_packed = 0; |
| 266 | |
216 | 267 | render_target *target = machine().render().first_target(); |
217 | 268 | target->set_view(m_rotate); |
218 | | |
| 269 | |
219 | 270 | /* Initialize sound DMA */ |
220 | 271 | memset(&m_sound_dma, 0, sizeof(m_sound_dma)); |
221 | 272 | } |
r241553 | r241554 | |
231 | 282 | READ8_MEMBER( wswan_state::port_r ) |
232 | 283 | { |
233 | 284 | UINT8 value = m_ws_portram[offset]; |
234 | | |
| 285 | |
235 | 286 | if (offset != 2) |
236 | 287 | logerror("PC=%X: port read %02X\n", m_maincpu->pc(), offset); |
237 | | |
238 | | if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0)) |
239 | | return m_vdp->reg_r(space, offset); |
240 | | |
241 | 288 | switch (offset) |
242 | 289 | { |
| 290 | case 0x02: // Current line |
| 291 | value = m_vdp.current_line; |
| 292 | break; |
243 | 293 | case 0x4a: // Sound DMA source address (low) |
244 | 294 | value = m_sound_dma.source & 0xff; |
245 | 295 | break; |
r241553 | r241554 | |
258 | 308 | case 0x52: // Sound DMA start/stop |
259 | 309 | value = m_sound_dma.enable; |
260 | 310 | break; |
261 | | case 0x60: |
262 | | value = m_vdp->reg_r(space, offset); |
263 | | break; |
264 | 311 | case 0xa0: // Hardware type |
265 | | // Bit 0 - Disable/enable Bios |
266 | | // Bit 1 - Determine mono/color |
267 | | // Bit 2 - Determine color/crystal |
| 312 | // Bit 0 - Disable/enable Bios |
| 313 | // Bit 1 - Determine mono/color |
| 314 | // Bit 2 - Determine color/crystal |
268 | 315 | value = value & ~ 0x02; |
269 | 316 | if (m_system_type == TYPE_WSC) |
270 | 317 | value |= 2; |
271 | 318 | break; |
| 319 | case 0xa8: |
| 320 | value = m_vdp.timer_hblank_count & 0xff; |
| 321 | break; |
| 322 | case 0xa9: |
| 323 | value = m_vdp.timer_hblank_count >> 8; |
| 324 | break; |
| 325 | case 0xaa: |
| 326 | value = m_vdp.timer_vblank_count & 0xff; |
| 327 | break; |
| 328 | case 0xab: |
| 329 | value = m_vdp.timer_vblank_count >> 8; |
| 330 | break; |
272 | 331 | case 0xc0: |
273 | 332 | case 0xc1: |
274 | 333 | case 0xc2: |
r241553 | r241554 | |
288 | 347 | value = m_cart->read_io(space, offset & 0x0f); |
289 | 348 | break; |
290 | 349 | } |
291 | | |
| 350 | |
292 | 351 | return value; |
293 | 352 | } |
294 | 353 | |
r241553 | r241554 | |
297 | 356 | address_space &mem = m_maincpu->space(AS_PROGRAM); |
298 | 357 | UINT8 input; |
299 | 358 | logerror("PC=%X: port write %02X <- %02X\n", m_maincpu->pc(), offset, data); |
300 | | |
301 | | if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0)) |
302 | | { |
303 | | m_vdp->reg_w(space, offset, data); |
304 | | return; |
305 | | } |
306 | | |
307 | 359 | switch (offset) |
308 | 360 | { |
| 361 | case 0x00: /* Display control |
| 362 | Bit 0 - Background layer enable |
| 363 | Bit 1 - Foreground layer enable |
| 364 | Bit 2 - Sprites enable |
| 365 | Bit 3 - Sprite window enable |
| 366 | Bit 4-5 - Foreground window configuration |
| 367 | 00 - Foreground layer is displayed inside and outside foreground window area |
| 368 | 01 - Unknown |
| 369 | 10 - Foreground layer is displayed only inside foreground window area |
| 370 | 11 - Foreground layer is displayed outside foreground window area |
| 371 | Bit 6-7 - Unknown |
| 372 | */ |
| 373 | m_vdp.layer_bg_enable = data & 0x1; |
| 374 | m_vdp.layer_fg_enable = (data & 0x2) >> 1; |
| 375 | m_vdp.sprites_enable = (data & 0x4) >> 2; |
| 376 | m_vdp.window_sprites_enable = (data & 0x8) >> 3; |
| 377 | m_vdp.window_fg_mode = (data & 0x30) >> 4; |
| 378 | break; |
| 379 | case 0x01: /* Background colour |
| 380 | In 16 colour mode: |
| 381 | Bit 0-3 - Palette index |
| 382 | Bit 4-7 - Palette number |
| 383 | Otherwise: |
| 384 | Bit 0-2 - Main palette index |
| 385 | Bit 3-7 - Unknown |
| 386 | */ |
| 387 | break; |
| 388 | case 0x02: /* Current scanline |
| 389 | Bit 0-7 - Current scanline (Most likely read-only) |
| 390 | */ |
| 391 | logerror( "Write to current scanline! Current value: %d Data to write: %d\n", m_vdp.current_line, data ); |
| 392 | /* Returning so we don't overwrite the value here, not that it |
| 393 | * really matters */ |
| 394 | return; |
| 395 | case 0x03: /* Line compare |
| 396 | Bit 0-7 - Line compare |
| 397 | */ |
| 398 | m_vdp.line_compare = data; |
| 399 | logerror( "Write to line compare: %d\n", data ); |
| 400 | break; |
| 401 | case 0x04: /* Sprite table base address |
| 402 | Bit 0-5 - Determine sprite table base address 0 0xxxxxx0 00000000 |
| 403 | Bit 6-7 - Unknown |
| 404 | */ |
| 405 | m_vdp.sprite_table_address = ( data & 0x3F ) << 9; |
| 406 | break; |
| 407 | case 0x05: /* Number of sprite to start drawing with |
| 408 | Bit 0-7 - First sprite number |
| 409 | */ |
| 410 | //m_vdp.sprite_first = data; |
| 411 | if (data) logerror("non-zero first sprite %d\n", m_vdp.sprite_first); |
| 412 | break; |
| 413 | case 0x06: /* Number of sprites to draw |
| 414 | Bit 0-7 - Number of sprites to draw |
| 415 | */ |
| 416 | //m_vdp.sprite_count = data; |
| 417 | break; |
| 418 | case 0x07: /* Background/Foreground table base addresses |
| 419 | Bit 0-2 - Determine background table base address 00xxx000 00000000 |
| 420 | Bit 3 - Unknown |
| 421 | Bit 4-6 - Determine foreground table base address 00xxx000 00000000 |
| 422 | Bit 7 - Unknown |
| 423 | */ |
| 424 | m_vdp.layer_bg_address = (data & 0x7) << 11; |
| 425 | m_vdp.layer_fg_address = (data & 0x70) << 7; |
| 426 | break; |
| 427 | case 0x08: /* Left coordinate of foreground window |
| 428 | Bit 0-7 - Left coordinate of foreground window area |
| 429 | */ |
| 430 | m_vdp.window_fg_left = data; |
| 431 | break; |
| 432 | case 0x09: /* Top coordinate of foreground window |
| 433 | Bit 0-7 - Top coordinatte of foreground window area |
| 434 | */ |
| 435 | m_vdp.window_fg_top = data; |
| 436 | break; |
| 437 | case 0x0a: /* Right coordinate of foreground window |
| 438 | Bit 0-7 - Right coordinate of foreground window area |
| 439 | */ |
| 440 | m_vdp.window_fg_right = data; |
| 441 | break; |
| 442 | case 0x0b: /* Bottom coordinate of foreground window |
| 443 | Bit 0-7 - Bottom coordinate of foreground window area |
| 444 | */ |
| 445 | m_vdp.window_fg_bottom = data; |
| 446 | break; |
| 447 | case 0x0c: /* Left coordinate of sprite window |
| 448 | Bit 0-7 - Left coordinate of sprite window area |
| 449 | */ |
| 450 | m_vdp.window_sprites_left = data; |
| 451 | break; |
| 452 | case 0x0d: /* Top coordinate of sprite window |
| 453 | Bit 0-7 - Top coordinate of sprite window area |
| 454 | */ |
| 455 | m_vdp.window_sprites_top = data; |
| 456 | break; |
| 457 | case 0x0e: /* Right coordinate of sprite window |
| 458 | Bit 0-7 - Right coordinate of sprite window area |
| 459 | */ |
| 460 | m_vdp.window_sprites_right = data; |
| 461 | break; |
| 462 | case 0x0f: /* Bottom coordinate of sprite window |
| 463 | Bit 0-7 - Bottom coordiante of sprite window area |
| 464 | */ |
| 465 | m_vdp.window_sprites_bottom = data; |
| 466 | break; |
| 467 | case 0x10: /* Background layer X scroll |
| 468 | Bit 0-7 - Background layer X scroll |
| 469 | */ |
| 470 | m_vdp.layer_bg_scroll_x = data; |
| 471 | break; |
| 472 | case 0x11: /* Background layer Y scroll |
| 473 | Bit 0-7 - Background layer Y scroll |
| 474 | */ |
| 475 | m_vdp.layer_bg_scroll_y = data; |
| 476 | break; |
| 477 | case 0x12: /* Foreground layer X scroll |
| 478 | Bit 0-7 - Foreground layer X scroll |
| 479 | */ |
| 480 | m_vdp.layer_fg_scroll_x = data; |
| 481 | break; |
| 482 | case 0x13: /* Foreground layer Y scroll |
| 483 | Bit 0-7 - Foreground layer Y scroll |
| 484 | */ |
| 485 | m_vdp.layer_fg_scroll_y = data; |
| 486 | break; |
| 487 | case 0x14: /* LCD control |
| 488 | Bit 0 - LCD enable |
| 489 | Bit 1-7 - Unknown |
| 490 | */ |
| 491 | m_vdp.lcd_enable = data & 0x1; |
| 492 | break; |
| 493 | case 0x15: /* LCD icons |
| 494 | Bit 0 - LCD sleep icon enable |
| 495 | Bit 1 - Vertical position icon enable |
| 496 | Bit 2 - Horizontal position icon enable |
| 497 | Bit 3 - Dot 1 icon enable |
| 498 | Bit 4 - Dot 2 icon enable |
| 499 | Bit 5 - Dot 3 icon enable |
| 500 | Bit 6-7 - Unknown |
| 501 | */ |
| 502 | m_vdp.icons = data; /* ummmmm */ |
| 503 | break; |
| 504 | case 0x1c: /* Palette colors 0 and 1 |
| 505 | Bit 0-3 - Gray tone setting for main palette index 0 |
| 506 | Bit 4-7 - Gray tone setting for main palette index 1 |
| 507 | */ |
| 508 | if (m_system_type == TYPE_WSC) |
| 509 | { |
| 510 | int i = 15 - ( data & 0x0F ); |
| 511 | int j = 15 - ( ( data & 0xF0 ) >> 4 ); |
| 512 | m_vdp.main_palette[0] = ( i << 8 ) | ( i << 4 ) | i; |
| 513 | m_vdp.main_palette[1] = ( j << 8 ) | ( j << 4 ) | j; |
| 514 | } |
| 515 | else |
| 516 | { |
| 517 | m_vdp.main_palette[0] = data & 0x0F; |
| 518 | m_vdp.main_palette[1] = ( data & 0xF0 ) >> 4; |
| 519 | } |
| 520 | break; |
| 521 | case 0x1d: /* Palette colors 2 and 3 |
| 522 | Bit 0-3 - Gray tone setting for main palette index 2 |
| 523 | Bit 4-7 - Gray tone setting for main palette index 3 |
| 524 | */ |
| 525 | if (m_system_type == TYPE_WSC) |
| 526 | { |
| 527 | int i = 15 - ( data & 0x0F ); |
| 528 | int j = 15 - ( ( data & 0xF0 ) >> 4 ); |
| 529 | m_vdp.main_palette[2] = ( i << 8 ) | ( i << 4 ) | i; |
| 530 | m_vdp.main_palette[3] = ( j << 8 ) | ( j << 4 ) | j; |
| 531 | } |
| 532 | else |
| 533 | { |
| 534 | m_vdp.main_palette[2] = data & 0x0F; |
| 535 | m_vdp.main_palette[3] = ( data & 0xF0 ) >> 4; |
| 536 | } |
| 537 | break; |
| 538 | case 0x1e: /* Palette colors 4 and 5 |
| 539 | Bit 0-3 - Gray tone setting for main palette index 4 |
| 540 | Bit 4-7 - Gray tone setting for main paeltte index 5 |
| 541 | */ |
| 542 | if (m_system_type == TYPE_WSC) |
| 543 | { |
| 544 | int i = 15 - ( data & 0x0F ); |
| 545 | int j = 15 - ( ( data & 0xF0 ) >> 4 ); |
| 546 | m_vdp.main_palette[4] = ( i << 8 ) | ( i << 4 ) | i; |
| 547 | m_vdp.main_palette[5] = ( j << 8 ) | ( j << 4 ) | j; |
| 548 | } |
| 549 | else |
| 550 | { |
| 551 | m_vdp.main_palette[4] = data & 0x0F; |
| 552 | m_vdp.main_palette[5] = ( data & 0xF0 ) >> 4; |
| 553 | } |
| 554 | break; |
| 555 | case 0x1f: /* Palette colors 6 and 7 |
| 556 | Bit 0-3 - Gray tone setting for main palette index 6 |
| 557 | Bit 4-7 - Gray tone setting for main palette index 7 |
| 558 | */ |
| 559 | if (m_system_type == TYPE_WSC) |
| 560 | { |
| 561 | int i = 15 - ( data & 0x0F ); |
| 562 | int j = 15 - ( ( data & 0xF0 ) >> 4 ); |
| 563 | m_vdp.main_palette[6] = ( i << 8 ) | ( i << 4 ) | i; |
| 564 | m_vdp.main_palette[7] = ( j << 8 ) | ( j << 4 ) | j; |
| 565 | } |
| 566 | else |
| 567 | { |
| 568 | m_vdp.main_palette[6] = data & 0x0F; |
| 569 | m_vdp.main_palette[7] = ( data & 0xF0 ) >> 4; |
| 570 | } |
| 571 | break; |
| 572 | case 0x20: /* tile/sprite palette settings |
| 573 | Bit 0-3 - Palette 0 index 0 |
| 574 | Bit 4-7 - Palette 0 index 1 */ |
| 575 | case 0x21: /* Bit 0-3 - Palette 0 index 2 |
| 576 | Bit 4-7 - Palette 0 index 3 */ |
| 577 | case 0x22: /* Bit 0-3 - Palette 1 index 0 |
| 578 | Bit 4-7 - Palette 1 index 1 */ |
| 579 | case 0x23: /* Bit 0-3 - Palette 1 index 2 |
| 580 | Bit 4-7 - Palette 1 index 3 */ |
| 581 | case 0x24: /* Bit 0-3 - Palette 2 index 0 |
| 582 | Bit 4-7 - Palette 2 index 1 */ |
| 583 | case 0x25: /* Bit 0-3 - Palette 2 index 2 |
| 584 | Bit 4-7 - Palette 2 index 3 */ |
| 585 | case 0x26: /* Bit 0-3 - Palette 3 index 0 |
| 586 | Bit 4-7 - Palette 3 index 1 */ |
| 587 | case 0x27: /* Bit 0-3 - Palette 3 index 2 |
| 588 | Bit 4-7 - Palette 3 index 3 */ |
| 589 | case 0x28: /* Bit 0-3 - Palette 4 index 0 |
| 590 | Bit 4-7 - Palette 4 index 1 */ |
| 591 | case 0x29: /* Bit 0-3 - Palette 4 index 2 |
| 592 | Bit 4-7 - Palette 4 index 3 */ |
| 593 | case 0x2a: /* Bit 0-3 - Palette 5 index 0 |
| 594 | Bit 4-7 - Palette 5 index 1 */ |
| 595 | case 0x2b: /* Bit 0-3 - Palette 5 index 2 |
| 596 | Bit 4-7 - Palette 5 index 3 */ |
| 597 | case 0x2c: /* Bit 0-3 - Palette 6 index 0 |
| 598 | Bit 4-7 - Palette 6 index 1 */ |
| 599 | case 0x2d: /* Bit 0-3 - Palette 6 index 2 |
| 600 | Bit 4-7 - Palette 6 index 3 */ |
| 601 | case 0x2e: /* Bit 0-3 - Palette 7 index 0 |
| 602 | Bit 4-7 - Palette 7 index 1 */ |
| 603 | case 0x2f: /* Bit 0-3 - Palette 7 index 2 |
| 604 | Bit 4-7 - Palette 7 index 3 */ |
| 605 | case 0x30: /* Bit 0-3 - Palette 8 / Sprite Palette 0 index 0 |
| 606 | Bit 4-7 - Palette 8 / Sprite Palette 0 index 1 */ |
| 607 | case 0x31: /* Bit 0-3 - Palette 8 / Sprite Palette 0 index 2 |
| 608 | Bit 4-7 - Palette 8 / Sprite Palette 0 index 3 */ |
| 609 | case 0x32: /* Bit 0-3 - Palette 9 / Sprite Palette 1 index 0 |
| 610 | Bit 4-7 - Palette 9 / Sprite Palette 1 index 1 */ |
| 611 | case 0x33: /* Bit 0-3 - Palette 9 / Sprite Palette 1 index 2 |
| 612 | Bit 4-7 - Palette 9 / Sprite Palette 1 index 3 */ |
| 613 | case 0x34: /* Bit 0-3 - Palette 10 / Sprite Palette 2 index 0 |
| 614 | Bit 4-7 - Palette 10 / Sprite Palette 2 index 1 */ |
| 615 | case 0x35: /* Bit 0-3 - Palette 10 / Sprite Palette 2 index 2 |
| 616 | Bit 4-7 - Palette 10 / Sprite Palette 2 index 3 */ |
| 617 | case 0x36: /* Bit 0-3 - Palette 11 / Sprite Palette 3 index 0 |
| 618 | Bit 4-7 - Palette 11 / Sprite Palette 3 index 1 */ |
| 619 | case 0x37: /* Bit 0-3 - Palette 11 / Sprite Palette 3 index 2 |
| 620 | Bit 4-7 - Palette 11 / Sprite Palette 3 index 3 */ |
| 621 | case 0x38: /* Bit 0-3 - Palette 12 / Sprite Palette 4 index 0 |
| 622 | Bit 4-7 - Palette 12 / Sprite Palette 4 index 1 */ |
| 623 | case 0x39: /* Bit 0-3 - Palette 12 / Sprite Palette 4 index 2 |
| 624 | Bit 4-7 - Palette 12 / Sprite Palette 4 index 3 */ |
| 625 | case 0x3a: /* Bit 0-3 - Palette 13 / Sprite Palette 5 index 0 |
| 626 | Bit 4-7 - Palette 13 / Sprite Palette 5 index 1 */ |
| 627 | case 0x3b: /* Bit 0-3 - Palette 13 / Sprite Palette 5 index 2 |
| 628 | Bit 4-7 - Palette 13 / Sprite Palette 5 index 3 */ |
| 629 | case 0x3c: /* Bit 0-3 - Palette 14 / Sprite Palette 6 index 0 |
| 630 | Bit 4-7 - Palette 14 / Sprite Palette 6 index 1 */ |
| 631 | case 0x3d: /* Bit 0-3 - Palette 14 / Sprite Palette 6 index 2 |
| 632 | Bit 4-7 - Palette 14 / Sprite Palette 6 index 3 */ |
| 633 | case 0x3e: /* Bit 0-3 - Palette 15 / Sprite Palette 7 index 0 |
| 634 | Bit 4-7 - Palette 15 / Sprite Palette 7 index 1 */ |
| 635 | case 0x3f: /* Bit 0-3 - Palette 15 / Sprite Palette 7 index 2 |
| 636 | Bit 4-7 - Palette 15 / Sprite Palette 7 index 3 */ |
| 637 | break; |
309 | 638 | case 0x40: /* DMA source address (low) |
310 | | Bit 0-7 - DMA source address bit 0-7 |
311 | | */ |
| 639 | Bit 0-7 - DMA source address bit 0-7 |
| 640 | */ |
312 | 641 | case 0x41: /* DMA source address (high) |
313 | | Bit 0-7 - DMA source address bit 8-15 |
314 | | */ |
| 642 | Bit 0-7 - DMA source address bit 8-15 |
| 643 | */ |
315 | 644 | case 0x42: /* DMA source bank |
316 | | Bit 0-7 - DMA source bank number |
317 | | */ |
| 645 | Bit 0-7 - DMA source bank number |
| 646 | */ |
318 | 647 | case 0x43: /* DMA destination bank |
319 | | Bit 0-7 - DMA destination bank number |
320 | | */ |
| 648 | Bit 0-7 - DMA destination bank number |
| 649 | */ |
321 | 650 | case 0x44: /* DMA destination address (low) |
322 | | Bit 0-7 - DMA destination address bit 0-7 |
323 | | */ |
| 651 | Bit 0-7 - DMA destination address bit 0-7 |
| 652 | */ |
324 | 653 | case 0x45: /* DMA destination address (high) |
325 | | Bit 0-7 - DMA destination address bit 8-15 |
326 | | */ |
| 654 | Bit 0-7 - DMA destination address bit 8-15 |
| 655 | */ |
327 | 656 | case 0x46: /* Size of copied data (low) |
328 | | Bit 0-7 - DMA size bit 0-7 |
329 | | */ |
| 657 | Bit 0-7 - DMA size bit 0-7 |
| 658 | */ |
330 | 659 | case 0x47: /* Size of copied data (high) |
331 | | Bit 0-7 - DMA size bit 8-15 |
332 | | */ |
| 660 | Bit 0-7 - DMA size bit 8-15 |
| 661 | */ |
333 | 662 | break; |
334 | 663 | case 0x48: /* DMA control |
335 | | Bit 0-6 - Unknown |
336 | | Bit 7 - DMA stop/start |
337 | | */ |
| 664 | Bit 0-6 - Unknown |
| 665 | Bit 7 - DMA stop/start |
| 666 | */ |
338 | 667 | if (data & 0x80) |
339 | 668 | { |
340 | 669 | UINT32 src, dst; |
341 | 670 | UINT16 length; |
342 | | |
| 671 | |
343 | 672 | src = m_ws_portram[0x40] + (m_ws_portram[0x41] << 8) + (m_ws_portram[0x42] << 16); |
344 | 673 | dst = m_ws_portram[0x44] + (m_ws_portram[0x45] << 8) + (m_ws_portram[0x43] << 16); |
345 | 674 | length = m_ws_portram[0x46] + (m_ws_portram[0x47] << 8); |
r241553 | r241554 | |
350 | 679 | dst++; |
351 | 680 | } |
352 | 681 | #ifdef MAME_DEBUG |
353 | | logerror("DMA src:%X dst:%X length:%d\n", src, dst, length); |
| 682 | logerror("DMA src:%X dst:%X length:%d\n", src, dst, length); |
354 | 683 | #endif |
355 | 684 | m_ws_portram[0x40] = src & 0xff; |
356 | 685 | m_ws_portram[0x41] = (src >> 8) & 0xff; |
r241553 | r241554 | |
362 | 691 | } |
363 | 692 | break; |
364 | 693 | case 0x4a: /* Sound DMA source address (low) |
365 | | Bit 0-7 - Sound DMA source address bit 0-7 |
366 | | */ |
| 694 | Bit 0-7 - Sound DMA source address bit 0-7 |
| 695 | */ |
367 | 696 | m_sound_dma.source = (m_sound_dma.source & 0x0fff00) | data; |
368 | 697 | break; |
369 | 698 | case 0x4b: /* Sound DMA source address (high) |
370 | | Bit 0-7 - Sound DMA source address bit 8-15 |
371 | | */ |
| 699 | Bit 0-7 - Sound DMA source address bit 8-15 |
| 700 | */ |
372 | 701 | m_sound_dma.source = (m_sound_dma.source & 0x0f00ff) | (data << 8); |
373 | 702 | break; |
374 | 703 | case 0x4c: /* Sound DMA source memory segment |
375 | | Bit 0-3 - Sound DMA source address segment |
376 | | Bit 4-7 - Unknown |
377 | | */ |
| 704 | Bit 0-3 - Sound DMA source address segment |
| 705 | Bit 4-7 - Unknown |
| 706 | */ |
378 | 707 | m_sound_dma.source = (m_sound_dma.source & 0xffff) | ((data & 0x0f) << 16); |
379 | 708 | break; |
380 | 709 | case 0x4d: /* Unknown */ |
381 | 710 | break; |
382 | 711 | case 0x4e: /* Sound DMA transfer size (low) |
383 | | Bit 0-7 - Sound DMA transfer size bit 0-7 |
384 | | */ |
| 712 | Bit 0-7 - Sound DMA transfer size bit 0-7 |
| 713 | */ |
385 | 714 | m_sound_dma.size = (m_sound_dma.size & 0xff00) | data; |
386 | 715 | break; |
387 | 716 | case 0x4f: /* Sound DMA transfer size (high) |
388 | | Bit 0-7 - Sound DMA transfer size bit 8-15 |
389 | | */ |
| 717 | Bit 0-7 - Sound DMA transfer size bit 8-15 |
| 718 | */ |
390 | 719 | m_sound_dma.size = (m_sound_dma.size & 0xff) | (data << 8); |
391 | 720 | break; |
392 | 721 | case 0x50: /* Unknown */ |
393 | 722 | case 0x51: /* Unknown */ |
394 | 723 | break; |
395 | 724 | case 0x52: /* Sound DMA start/stop |
396 | | Bit 0-6 - Unknown |
397 | | Bit 7 - Sound DMA stop/start |
398 | | */ |
| 725 | Bit 0-6 - Unknown |
| 726 | Bit 7 - Sound DMA stop/start |
| 727 | */ |
399 | 728 | m_sound_dma.enable = data; |
400 | 729 | break; |
401 | | case 0x60: |
402 | | m_vdp->reg_w(space, offset, data); |
| 730 | case 0x60: /* Video mode |
| 731 | Bit 0-4 - Unknown |
| 732 | Bit 5 - Packed mode 0 = not packed mode, 1 = packed mode |
| 733 | Bit 6 - 4/16 colour mode select: 0 = 4 colour mode, 1 = 16 colour mode |
| 734 | Bit 7 - monochrome/colour mode select: 0 = monochrome mode, 1 = colour mode |
| 735 | */ |
| 736 | /* |
| 737 | * 111 - packed, 16 color, use 4000/8000, color |
| 738 | * 110 - not packed, 16 color, use 4000/8000, color |
| 739 | * 101 - packed, 4 color, use 2000, color |
| 740 | * 100 - not packed, 4 color, use 2000, color |
| 741 | * 011 - packed, 16 color, use 4000/8000, monochrome |
| 742 | * 010 - not packed, 16 color , use 4000/8000, monochrome |
| 743 | * 001 - packed, 4 color, use 2000, monochrome |
| 744 | * 000 - not packed, 4 color, use 2000, monochrome - Regular WS monochrome |
| 745 | */ |
| 746 | if (m_system_type == TYPE_WSC) |
| 747 | { |
| 748 | m_vdp.color_mode = data & 0x80; |
| 749 | m_vdp.colors_16 = data & 0x40; |
| 750 | m_vdp.tile_packed = data & 0x20; |
| 751 | } |
403 | 752 | break; |
404 | 753 | case 0x80: /* Audio 1 freq (lo) |
405 | | Bit 0-7 - Audio channel 1 frequency bit 0-7 |
406 | | */ |
| 754 | Bit 0-7 - Audio channel 1 frequency bit 0-7 |
| 755 | */ |
407 | 756 | case 0x81: /* Audio 1 freq (hi) |
408 | | Bit 0-7 - Audio channel 1 frequency bit 8-15 |
409 | | */ |
| 757 | Bit 0-7 - Audio channel 1 frequency bit 8-15 |
| 758 | */ |
410 | 759 | case 0x82: /* Audio 2 freq (lo) |
411 | | Bit 0-7 - Audio channel 2 frequency bit 0-7 |
412 | | */ |
| 760 | Bit 0-7 - Audio channel 2 frequency bit 0-7 |
| 761 | */ |
413 | 762 | case 0x83: /* Audio 2 freq (hi) |
414 | | Bit 0-7 - Audio channel 2 frequency bit 8-15 |
415 | | */ |
| 763 | Bit 0-7 - Audio channel 2 frequency bit 8-15 |
| 764 | */ |
416 | 765 | case 0x84: /* Audio 3 freq (lo) |
417 | | Bit 0-7 - Audio channel 3 frequency bit 0-7 |
418 | | */ |
| 766 | Bit 0-7 - Audio channel 3 frequency bit 0-7 |
| 767 | */ |
419 | 768 | case 0x85: /* Audio 3 freq (hi) |
420 | | Bit 0-7 - Audio channel 3 frequency bit 8-15 |
421 | | */ |
| 769 | Bit 0-7 - Audio channel 3 frequency bit 8-15 |
| 770 | */ |
422 | 771 | case 0x86: /* Audio 4 freq (lo) |
423 | | Bit 0-7 - Audio channel 4 frequency bit 0-7 |
424 | | */ |
| 772 | Bit 0-7 - Audio channel 4 frequency bit 0-7 |
| 773 | */ |
425 | 774 | case 0x87: /* Audio 4 freq (hi) |
426 | | Bit 0-7 - Audio channel 4 frequency bit 8-15 |
427 | | */ |
| 775 | Bit 0-7 - Audio channel 4 frequency bit 8-15 |
| 776 | */ |
428 | 777 | case 0x88: /* Audio 1 volume |
429 | | Bit 0-3 - Right volume audio channel 1 |
430 | | Bit 4-7 - Left volume audio channel 1 |
431 | | */ |
| 778 | Bit 0-3 - Right volume audio channel 1 |
| 779 | Bit 4-7 - Left volume audio channel 1 |
| 780 | */ |
432 | 781 | case 0x89: /* Audio 2 volume |
433 | | Bit 0-3 - Right volume audio channel 2 |
434 | | Bit 4-7 - Left volume audio channel 2 |
435 | | */ |
| 782 | Bit 0-3 - Right volume audio channel 2 |
| 783 | Bit 4-7 - Left volume audio channel 2 |
| 784 | */ |
436 | 785 | case 0x8a: /* Audio 3 volume |
437 | | Bit 0-3 - Right volume audio channel 3 |
438 | | Bit 4-7 - Left volume audio channel 3 |
439 | | */ |
| 786 | Bit 0-3 - Right volume audio channel 3 |
| 787 | Bit 4-7 - Left volume audio channel 3 |
| 788 | */ |
440 | 789 | case 0x8b: /* Audio 4 volume |
441 | | Bit 0-3 - Right volume audio channel 4 |
442 | | Bit 4-7 - Left volume audio channel 4 |
443 | | */ |
| 790 | Bit 0-3 - Right volume audio channel 4 |
| 791 | Bit 4-7 - Left volume audio channel 4 |
| 792 | */ |
444 | 793 | case 0x8c: /* Sweep step |
445 | | Bit 0-7 - Sweep step |
446 | | */ |
| 794 | Bit 0-7 - Sweep step |
| 795 | */ |
447 | 796 | case 0x8d: /* Sweep time |
448 | | Bit 0-7 - Sweep time |
449 | | */ |
| 797 | Bit 0-7 - Sweep time |
| 798 | */ |
450 | 799 | case 0x8e: /* Noise control |
451 | | Bit 0-2 - Noise generator type |
452 | | Bit 3 - Reset |
453 | | Bit 4 - Enable |
454 | | Bit 5-7 - Unknown |
455 | | */ |
| 800 | Bit 0-2 - Noise generator type |
| 801 | Bit 3 - Reset |
| 802 | Bit 4 - Enable |
| 803 | Bit 5-7 - Unknown |
| 804 | */ |
456 | 805 | case 0x8f: /* Sample location |
457 | | Bit 0-7 - Sample address location 0 00xxxxxx xx000000 |
458 | | */ |
| 806 | Bit 0-7 - Sample address location 0 00xxxxxx xx000000 |
| 807 | */ |
459 | 808 | case 0x90: /* Audio control |
460 | | Bit 0 - Audio 1 enable |
461 | | Bit 1 - Audio 2 enable |
462 | | Bit 2 - Audio 3 enable |
463 | | Bit 3 - Audio 4 enable |
464 | | Bit 4 - Unknown |
465 | | Bit 5 - Audio 2 voice mode enable |
466 | | Bit 6 - Audio 3 sweep mode enable |
467 | | Bit 7 - Audio 4 noise mode enable |
468 | | */ |
| 809 | Bit 0 - Audio 1 enable |
| 810 | Bit 1 - Audio 2 enable |
| 811 | Bit 2 - Audio 3 enable |
| 812 | Bit 3 - Audio 4 enable |
| 813 | Bit 4 - Unknown |
| 814 | Bit 5 - Audio 2 voice mode enable |
| 815 | Bit 6 - Audio 3 sweep mode enable |
| 816 | Bit 7 - Audio 4 noise mode enable |
| 817 | */ |
469 | 818 | case 0x91: /* Audio output |
470 | | Bit 0 - Mono select |
471 | | Bit 1-2 - Output volume |
472 | | Bit 3 - External stereo |
473 | | Bit 4-6 - Unknown |
474 | | Bit 7 - External speaker (Read-only, set by hardware) |
475 | | */ |
| 819 | Bit 0 - Mono select |
| 820 | Bit 1-2 - Output volume |
| 821 | Bit 3 - External stereo |
| 822 | Bit 4-6 - Unknown |
| 823 | Bit 7 - External speaker (Read-only, set by hardware) |
| 824 | */ |
476 | 825 | case 0x92: /* Noise counter shift register (lo) |
477 | | Bit 0-7 - Noise counter shift register bit 0-7 |
478 | | */ |
| 826 | Bit 0-7 - Noise counter shift register bit 0-7 |
| 827 | */ |
479 | 828 | case 0x93: /* Noise counter shift register (hi) |
480 | | Bit 0-6 - Noise counter shift register bit 8-14 |
481 | | bit 7 - Unknown |
482 | | */ |
| 829 | Bit 0-6 - Noise counter shift register bit 8-14 |
| 830 | bit 7 - Unknown |
| 831 | */ |
483 | 832 | case 0x94: /* Master volume |
484 | | Bit 0-3 - Master volume |
485 | | Bit 4-7 - Unknown |
486 | | */ |
| 833 | Bit 0-3 - Master volume |
| 834 | Bit 4-7 - Unknown |
| 835 | */ |
487 | 836 | m_sound->port_w(space, offset, data); |
488 | 837 | break; |
489 | 838 | case 0xa0: /* Hardware type - this is probably read only |
490 | | Bit 0 - Enable cartridge slot and/or disable bios |
491 | | Bit 1 - Hardware type: 0 = WS, 1 = WSC |
492 | | Bit 2-7 - Unknown |
493 | | */ |
| 839 | Bit 0 - Enable cartridge slot and/or disable bios |
| 840 | Bit 1 - Hardware type: 0 = WS, 1 = WSC |
| 841 | Bit 2-7 - Unknown |
| 842 | */ |
494 | 843 | if ((data & 0x01) && !m_bios_disabled) |
495 | 844 | m_bios_disabled = 1; |
496 | 845 | break; |
497 | | |
| 846 | case 0xa2: /* Timer control |
| 847 | Bit 0 - HBlank Timer enable |
| 848 | Bit 1 - HBlank Timer mode: 0 = one shot, 1 = auto reset |
| 849 | Bit 2 - VBlank Timer(1/75s) enable |
| 850 | Bit 3 - VBlank Timer mode: 0 = one shot, 1 = auto reset |
| 851 | Bit 4-7 - Unknown |
| 852 | */ |
| 853 | m_vdp.timer_hblank_enable = BIT(data, 0); |
| 854 | m_vdp.timer_hblank_mode = BIT(data, 1); |
| 855 | m_vdp.timer_vblank_enable = BIT(data, 2); |
| 856 | m_vdp.timer_vblank_mode = BIT(data, 3); |
| 857 | break; |
| 858 | case 0xa4: /* HBlank timer frequency (low) - reload value |
| 859 | Bit 0-7 - HBlank timer reload value bit 0-7 |
| 860 | */ |
| 861 | m_vdp.timer_hblank_reload &= 0xff00; |
| 862 | m_vdp.timer_hblank_reload += data; |
| 863 | m_vdp.timer_hblank_count = m_vdp.timer_hblank_reload; |
| 864 | break; |
| 865 | case 0xa5: /* HBlank timer frequency (high) - reload value |
| 866 | Bit 8-15 - HBlank timer reload value bit 8-15 |
| 867 | */ |
| 868 | m_vdp.timer_hblank_reload &= 0xff; |
| 869 | m_vdp.timer_hblank_reload += data << 8; |
| 870 | m_vdp.timer_hblank_count = m_vdp.timer_hblank_reload; |
| 871 | break; |
| 872 | case 0xa6: /* VBlank timer frequency (low) - reload value |
| 873 | Bit 0-7 - VBlank timer reload value bit 0-7 |
| 874 | */ |
| 875 | m_vdp.timer_vblank_reload &= 0xff00; |
| 876 | m_vdp.timer_vblank_reload += data; |
| 877 | m_vdp.timer_vblank_count = m_vdp.timer_vblank_reload; |
| 878 | break; |
| 879 | case 0xa7: /* VBlank timer frequency (high) - reload value |
| 880 | Bit 0-7 - VBlank timer reload value bit 8-15 |
| 881 | */ |
| 882 | m_vdp.timer_vblank_reload &= 0xff; |
| 883 | m_vdp.timer_vblank_reload += data << 8; |
| 884 | m_vdp.timer_vblank_count = m_vdp.timer_vblank_reload; |
| 885 | break; |
| 886 | case 0xa8: /* HBlank counter (low) |
| 887 | Bit 0-7 - HBlank counter bit 0-7 |
| 888 | */ |
| 889 | case 0xa9: /* HBlank counter (high) |
| 890 | Bit 0-7 - HBlank counter bit 8-15 |
| 891 | */ |
| 892 | case 0xaa: /* VBlank counter (low) |
| 893 | Bit 0-7 - VBlank counter bit 0-7 |
| 894 | */ |
| 895 | case 0xab: /* VBlank counter (high) |
| 896 | Bit 0-7 - VBlank counter bit 8-15 |
| 897 | */ |
| 898 | break; |
| 899 | |
498 | 900 | case 0xb0: /* Interrupt base vector |
499 | | Bit 0-7 - Interrupt base vector |
500 | | */ |
| 901 | Bit 0-7 - Interrupt base vector |
| 902 | */ |
501 | 903 | break; |
502 | 904 | case 0xb1: /* Communication byte |
503 | | Bit 0-7 - Communication byte |
504 | | */ |
| 905 | Bit 0-7 - Communication byte |
| 906 | */ |
505 | 907 | break; |
506 | 908 | case 0xb2: /* Interrupt enable |
507 | | Bit 0 - Serial transmit interrupt enable |
508 | | Bit 1 - Key press interrupt enable |
509 | | Bit 2 - RTC alarm interrupt enable |
510 | | Bit 3 - Serial receive interrupt enable |
511 | | Bit 4 - Drawing line detection interrupt enable |
512 | | Bit 5 - VBlank timer interrupt enable |
513 | | Bit 6 - VBlank interrupt enable |
514 | | Bit 7 - HBlank timer interrupt enable |
515 | | */ |
| 909 | Bit 0 - Serial transmit interrupt enable |
| 910 | Bit 1 - Key press interrupt enable |
| 911 | Bit 2 - RTC alarm interrupt enable |
| 912 | Bit 3 - Serial receive interrupt enable |
| 913 | Bit 4 - Drawing line detection interrupt enable |
| 914 | Bit 5 - VBlank timer interrupt enable |
| 915 | Bit 6 - VBlank interrupt enable |
| 916 | Bit 7 - HBlank timer interrupt enable |
| 917 | */ |
516 | 918 | break; |
517 | 919 | case 0xb3: /* serial communication control |
518 | | Bit 0 - Receive complete |
519 | | Bit 1 - Error |
520 | | Bit 2 - Send complete |
521 | | Bit 3-4 - Unknown |
522 | | Bit 5 - Send data interrupt generation |
523 | | Bit 6 - Connection speed: 0 = 9600 bps, 1 = 38400 bps |
524 | | bit 7 - Receive data interrupt generation |
525 | | */ |
526 | | // data |= 0x02; |
| 920 | Bit 0 - Receive complete |
| 921 | Bit 1 - Error |
| 922 | Bit 2 - Send complete |
| 923 | Bit 3-4 - Unknown |
| 924 | Bit 5 - Send data interrupt generation |
| 925 | Bit 6 - Connection speed: 0 = 9600 bps, 1 = 38400 bps |
| 926 | bit 7 - Receive data interrupt generation |
| 927 | */ |
| 928 | // data |= 0x02; |
527 | 929 | m_ws_portram[0xb1] = 0xff; |
528 | 930 | if (data & 0x80) |
529 | 931 | { |
530 | | // m_ws_portram[0xb1] = 0x00; |
| 932 | // m_ws_portram[0xb1] = 0x00; |
531 | 933 | data |= 0x04; |
532 | 934 | } |
533 | 935 | if (data & 0x20) |
534 | 936 | { |
535 | | // data |= 0x01; |
| 937 | // data |= 0x01; |
536 | 938 | } |
537 | 939 | break; |
538 | 940 | case 0xb5: /* Read controls |
539 | | Bit 0-3 - Current state of input lines (read-only) |
540 | | Bit 4-6 - Select line of inputs to read |
541 | | 001 - Read Y cursors |
542 | | 010 - Read X cursors |
543 | | 100 - Read START,A,B buttons |
544 | | Bit 7 - Unknown |
545 | | */ |
| 941 | Bit 0-3 - Current state of input lines (read-only) |
| 942 | Bit 4-6 - Select line of inputs to read |
| 943 | 001 - Read Y cursors |
| 944 | 010 - Read X cursors |
| 945 | 100 - Read START,A,B buttons |
| 946 | Bit 7 - Unknown |
| 947 | */ |
546 | 948 | data = data & 0xf0; |
547 | 949 | switch (data) |
548 | | { |
549 | | case 0x10: /* Read Y cursors: Y1 - Y2 - Y3 - Y4 */ |
550 | | input = m_cursy->read(); |
551 | | if (m_rotate) // reorient controls if the console is rotated |
552 | | { |
553 | | if (input & 0x01) data |= 0x02; |
554 | | if (input & 0x02) data |= 0x04; |
555 | | if (input & 0x04) data |= 0x08; |
556 | | if (input & 0x08) data |= 0x01; |
557 | | } |
558 | | else |
559 | | data = data | input; |
| 950 | { |
| 951 | case 0x10: /* Read Y cursors: Y1 - Y2 - Y3 - Y4 */ |
| 952 | input = m_cursy->read(); |
| 953 | if (m_rotate) // reorient controls if the console is rotated |
| 954 | { |
| 955 | if (input & 0x01) data |= 0x02; |
| 956 | if (input & 0x02) data |= 0x04; |
| 957 | if (input & 0x04) data |= 0x08; |
| 958 | if (input & 0x08) data |= 0x01; |
| 959 | } |
| 960 | else |
| 961 | data = data | input; |
560 | 962 | break; |
561 | | case 0x20: /* Read X cursors: X1 - X2 - X3 - X4 */ |
562 | | input = m_cursx->read(); |
563 | | if (m_rotate) // reorient controls if the console is rotated |
564 | | { |
565 | | if (input & 0x01) data |= 0x02; |
566 | | if (input & 0x02) data |= 0x04; |
567 | | if (input & 0x04) data |= 0x08; |
568 | | if (input & 0x08) data |= 0x01; |
569 | | } |
570 | | else |
571 | | data = data | input; |
| 963 | case 0x20: /* Read X cursors: X1 - X2 - X3 - X4 */ |
| 964 | input = m_cursx->read(); |
| 965 | if (m_rotate) // reorient controls if the console is rotated |
| 966 | { |
| 967 | if (input & 0x01) data |= 0x02; |
| 968 | if (input & 0x02) data |= 0x04; |
| 969 | if (input & 0x04) data |= 0x08; |
| 970 | if (input & 0x08) data |= 0x01; |
| 971 | } |
| 972 | else |
| 973 | data = data | input; |
572 | 974 | break; |
573 | | case 0x40: /* Read buttons: START - A - B */ |
574 | | data = data | m_buttons->read(); |
| 975 | case 0x40: /* Read buttons: START - A - B */ |
| 976 | data = data | m_buttons->read(); |
575 | 977 | break; |
576 | | } |
| 978 | } |
577 | 979 | break; |
578 | 980 | case 0xb6: /* Interrupt acknowledge |
579 | | Bit 0 - Serial transmit interrupt acknowledge |
580 | | Bit 1 - Key press interrupt acknowledge |
581 | | Bit 2 - RTC alarm interrupt acknowledge |
582 | | Bit 3 - Serial receive interrupt acknowledge |
583 | | Bit 4 - Drawing line detection interrupt acknowledge |
584 | | Bit 5 - VBlank timer interrupt acknowledge |
585 | | Bit 6 - VBlank interrupt acknowledge |
586 | | Bit 7 - HBlank timer interrupt acknowledge |
587 | | */ |
588 | | clear_irq_line(data); |
| 981 | Bit 0 - Serial transmit interrupt acknowledge |
| 982 | Bit 1 - Key press interrupt acknowledge |
| 983 | Bit 2 - RTC alarm interrupt acknowledge |
| 984 | Bit 3 - Serial receive interrupt acknowledge |
| 985 | Bit 4 - Drawing line detection interrupt acknowledge |
| 986 | Bit 5 - VBlank timer interrupt acknowledge |
| 987 | Bit 6 - VBlank interrupt acknowledge |
| 988 | Bit 7 - HBlank timer interrupt acknowledge |
| 989 | */ |
| 990 | wswan_clear_irq_line(data); |
589 | 991 | data = m_ws_portram[0xb6]; |
590 | 992 | break; |
591 | 993 | case 0xba: /* Internal EEPROM data (low) |
592 | | Bit 0-7 - Internal EEPROM data transfer bit 0-7 |
593 | | */ |
| 994 | Bit 0-7 - Internal EEPROM data transfer bit 0-7 |
| 995 | */ |
594 | 996 | case 0xbb: /* Internal EEPROM data (high) |
595 | | Bit 0-7 - Internal EEPROM data transfer bit 8-15 |
596 | | */ |
| 997 | Bit 0-7 - Internal EEPROM data transfer bit 8-15 |
| 998 | */ |
597 | 999 | break; |
598 | 1000 | case 0xbc: /* Internal EEPROM address (low) |
599 | | Bit 0-7 - Internal EEPROM address bit 1-8 |
600 | | */ |
| 1001 | Bit 0-7 - Internal EEPROM address bit 1-8 |
| 1002 | */ |
601 | 1003 | case 0xbd: /* Internal EEPROM address (high) |
602 | | Bit 0 - Internal EEPROM address bit 9(?) |
603 | | Bit 1-7 - Unknown |
604 | | Only 1KByte internal EEPROM?? |
605 | | */ |
| 1004 | Bit 0 - Internal EEPROM address bit 9(?) |
| 1005 | Bit 1-7 - Unknown |
| 1006 | Only 1KByte internal EEPROM?? |
| 1007 | */ |
606 | 1008 | break; |
607 | 1009 | case 0xbe: /* Internal EEPROM command |
608 | | Bit 0 - Read complete (read only) |
609 | | Bit 1 - Write complete (read only) |
610 | | Bit 2-3 - Unknown |
611 | | Bit 4 - Read |
612 | | Bit 5 - Write |
613 | | Bit 6 - Protect |
614 | | Bit 7 - Initialize |
615 | | */ |
| 1010 | Bit 0 - Read complete (read only) |
| 1011 | Bit 1 - Write complete (read only) |
| 1012 | Bit 2-3 - Unknown |
| 1013 | Bit 4 - Read |
| 1014 | Bit 5 - Write |
| 1015 | Bit 6 - Protect |
| 1016 | Bit 7 - Initialize |
| 1017 | */ |
616 | 1018 | if (data & 0x20) |
617 | 1019 | { |
618 | 1020 | UINT16 addr = ( ( ( m_ws_portram[0xbd] << 8 ) | m_ws_portram[0xbc] ) << 1 ) & 0x1FF; |
r241553 | r241554 | |
654 | 1056 | logerror( "Write to unsupported port: %X - %X\n", offset, data ); |
655 | 1057 | break; |
656 | 1058 | } |
657 | | |
| 1059 | |
658 | 1060 | /* Update the port value */ |
659 | 1061 | m_ws_portram[offset] = data; |
660 | 1062 | } |
| 1063 | |
| 1064 | |
| 1065 | TIMER_CALLBACK_MEMBER(wswan_state::wswan_scanline_interrupt) |
| 1066 | { |
| 1067 | if( m_vdp.current_line < 144 ) |
| 1068 | { |
| 1069 | wswan_refresh_scanline(); |
| 1070 | } |
| 1071 | |
| 1072 | /* Decrement 12kHz (HBlank) counter */ |
| 1073 | if ( m_vdp.timer_hblank_enable && m_vdp.timer_hblank_reload != 0 ) |
| 1074 | { |
| 1075 | m_vdp.timer_hblank_count--; |
| 1076 | logerror( "timer_hblank_count: %X\n", m_vdp.timer_hblank_count ); |
| 1077 | if ( m_vdp.timer_hblank_count == 0 ) |
| 1078 | { |
| 1079 | if ( m_vdp.timer_hblank_mode ) |
| 1080 | { |
| 1081 | m_vdp.timer_hblank_count = m_vdp.timer_hblank_reload; |
| 1082 | } |
| 1083 | else |
| 1084 | { |
| 1085 | m_vdp.timer_hblank_reload = 0; |
| 1086 | } |
| 1087 | logerror( "trigerring hbltmr interrupt\n" ); |
| 1088 | wswan_set_irq_line( WSWAN_IFLAG_HBLTMR ); |
| 1089 | } |
| 1090 | } |
| 1091 | |
| 1092 | /* Handle Sound DMA */ |
| 1093 | if ( ( m_sound_dma.enable & 0x88 ) == 0x80 ) |
| 1094 | { |
| 1095 | address_space &space = m_maincpu->space(AS_PROGRAM ); |
| 1096 | /* TODO: Output sound DMA byte */ |
| 1097 | port_w( space, 0x89, space.read_byte(m_sound_dma.source ) ); |
| 1098 | m_sound_dma.size--; |
| 1099 | m_sound_dma.source = ( m_sound_dma.source + 1 ) & 0x0FFFFF; |
| 1100 | if ( m_sound_dma.size == 0 ) |
| 1101 | { |
| 1102 | m_sound_dma.enable &= 0x7F; |
| 1103 | } |
| 1104 | } |
| 1105 | |
| 1106 | // m_vdp.current_line = (m_vdp.current_line + 1) % 159; |
| 1107 | |
| 1108 | if( m_vdp.current_line == 144 ) // buffer sprite table |
| 1109 | { |
| 1110 | memcpy(m_vdp.sprite_table_buffer, &m_vdp.vram[m_vdp.sprite_table_address], 512); |
| 1111 | m_vdp.sprite_count = m_ws_portram[0x06]; |
| 1112 | m_vdp.sprite_first = m_ws_portram[0x05]; // always zero? |
| 1113 | } |
| 1114 | |
| 1115 | if( m_vdp.current_line == 144 ) |
| 1116 | { |
| 1117 | wswan_set_irq_line( WSWAN_IFLAG_VBL ); |
| 1118 | /* Decrement 75Hz (VBlank) counter */ |
| 1119 | if ( m_vdp.timer_vblank_enable && m_vdp.timer_vblank_reload != 0 ) |
| 1120 | { |
| 1121 | m_vdp.timer_vblank_count--; |
| 1122 | logerror( "timer_vblank_count: %X\n", m_vdp.timer_vblank_count ); |
| 1123 | if ( m_vdp.timer_vblank_count == 0 ) |
| 1124 | { |
| 1125 | if ( m_vdp.timer_vblank_mode ) |
| 1126 | { |
| 1127 | m_vdp.timer_vblank_count = m_vdp.timer_vblank_reload; |
| 1128 | } |
| 1129 | else |
| 1130 | { |
| 1131 | m_vdp.timer_vblank_reload = 0; |
| 1132 | } |
| 1133 | logerror( "triggering vbltmr interrupt\n" ); |
| 1134 | wswan_set_irq_line( WSWAN_IFLAG_VBLTMR ); |
| 1135 | } |
| 1136 | } |
| 1137 | } |
| 1138 | |
| 1139 | // m_vdp.current_line = (m_vdp.current_line + 1) % 159; |
| 1140 | |
| 1141 | if ( m_vdp.current_line == m_vdp.line_compare ) |
| 1142 | { |
| 1143 | wswan_set_irq_line( WSWAN_IFLAG_LCMP ); |
| 1144 | } |
| 1145 | |
| 1146 | m_vdp.current_line = (m_vdp.current_line + 1) % 159; |
| 1147 | } |
trunk/src/mess/video/wswan.c
r0 | r241554 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | wswan.c |
| 4 | |
| 5 | File to handle video emulation of the Bandai WonderSwan. |
| 6 | |
| 7 | Anthony Kruize |
| 8 | Wilbert Pol |
| 9 | |
| 10 | ***************************************************************************/ |
| 11 | |
| 12 | #include "includes/wswan.h" |
| 13 | |
| 14 | void wswan_state::wswan_setup_palettes() |
| 15 | { |
| 16 | int i,j; |
| 17 | |
| 18 | if ( m_vdp.color_mode ) { |
| 19 | for( i = 0; i < 16; i++ ) { |
| 20 | for( j = 0; j < 16; j++ ) { |
| 21 | m_pal[i][j] = ( ( m_vdp.palette_vram[ ( i << 5 ) + j*2 + 1 ] << 8 ) | m_vdp.palette_vram[ ( i << 5 ) + j*2 ] ) & 0x0FFF; |
| 22 | } |
| 23 | } |
| 24 | } else { |
| 25 | for( i = 0; i < 16; i++ ) { |
| 26 | m_pal[i][0] = m_ws_portram[ 0x20 + ( i << 1 ) ] & 0x07; |
| 27 | m_pal[i][1] = ( m_ws_portram[ 0x20 + ( i << 1 ) ] >> 4 ) & 0x07; |
| 28 | m_pal[i][2] = m_ws_portram[ 0x21 + ( i << 1 ) ] & 0x07; |
| 29 | m_pal[i][3] = ( m_ws_portram[ 0x21 + ( i << 1 ) ] >> 4 ) & 0x07; |
| 30 | } |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | void wswan_state::wswan_draw_background() |
| 35 | { |
| 36 | UINT16 map_addr; |
| 37 | UINT8 start_column; |
| 38 | int column; |
| 39 | |
| 40 | map_addr = m_vdp.layer_bg_address + ( ( ( m_vdp.current_line + m_vdp.layer_bg_scroll_y ) & 0xF8 ) << 3 ); |
| 41 | start_column = ( m_vdp.layer_bg_scroll_x >> 3 ); |
| 42 | for( column = 0; column < 29; column++ ) { |
| 43 | int tile_data, tile_number, tile_palette, tile_line, tile_address; |
| 44 | UINT32 plane0=0, plane1=0, plane2=0, plane3=0; |
| 45 | int x, x_offset; |
| 46 | |
| 47 | tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) |
| 48 | | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; |
| 49 | tile_number = tile_data & 0x01FF; |
| 50 | tile_palette = ( tile_data >> 9 ) & 0x0F; |
| 51 | |
| 52 | tile_line = ( m_vdp.current_line + m_vdp.layer_bg_scroll_y ) & 0x07; |
| 53 | if ( tile_data & 0x8000 ) { |
| 54 | tile_line = 7 - tile_line; |
| 55 | } |
| 56 | |
| 57 | if ( m_vdp.colors_16 ) { |
| 58 | tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); |
| 59 | if ( m_vdp.tile_packed ) { |
| 60 | 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 ]; |
| 61 | } else { |
| 62 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 63 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 64 | plane2 = m_vdp.vram[ tile_address + 2 ] << 2; |
| 65 | plane3 = m_vdp.vram[ tile_address + 3 ] << 3; |
| 66 | } |
| 67 | } else { |
| 68 | tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); |
| 69 | if ( m_vdp.tile_packed ) { |
| 70 | plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; |
| 71 | } else { |
| 72 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 73 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 74 | plane2 = 0; |
| 75 | plane3 = 0; |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | for( x = 0; x < 8; x++ ) { |
| 80 | int col; |
| 81 | if ( m_vdp.tile_packed ) { |
| 82 | if ( m_vdp.colors_16 ) { |
| 83 | col = plane0 & 0x0F; |
| 84 | plane0 = plane0 >> 4; |
| 85 | } else { |
| 86 | col = plane0 & 0x03; |
| 87 | plane0 = plane0 >> 2; |
| 88 | } |
| 89 | } else { |
| 90 | col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); |
| 91 | plane3 = plane3 >> 1; |
| 92 | plane2 = plane2 >> 1; |
| 93 | plane1 = plane1 >> 1; |
| 94 | plane0 = plane0 >> 1; |
| 95 | } |
| 96 | if ( tile_data & 0x4000 ) { |
| 97 | x_offset = x + ( column << 3 ) - ( m_vdp.layer_bg_scroll_x & 0x07 ); |
| 98 | } else { |
| 99 | x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_bg_scroll_x & 0x07 ); |
| 100 | } |
| 101 | if ( x_offset >= 0 && x_offset < WSWAN_X_PIXELS ) { |
| 102 | if ( m_vdp.colors_16 ) { |
| 103 | if ( col ) { |
| 104 | if ( m_vdp.color_mode ) { |
| 105 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 106 | } else { |
| 107 | /* Hmmmm, what should we do here... Is this correct?? */ |
| 108 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 109 | } |
| 110 | } |
| 111 | } else { |
| 112 | if ( col || !(tile_palette & 4 ) ) { |
| 113 | if ( m_vdp.color_mode ) { |
| 114 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 115 | } else { |
| 116 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | void wswan_state::wswan_draw_foreground_0() |
| 126 | { |
| 127 | UINT16 map_addr; |
| 128 | UINT8 start_column; |
| 129 | int column; |
| 130 | map_addr = m_vdp.layer_fg_address + ( ( ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0xF8 ) << 3 ); |
| 131 | start_column = ( m_vdp.layer_fg_scroll_x >> 3 ); |
| 132 | for( column = 0; column < 29; column++ ) { |
| 133 | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
| 134 | int x, x_offset, tile_line, tile_address; |
| 135 | int tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) |
| 136 | | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; |
| 137 | int tile_number = tile_data & 0x01FF; |
| 138 | int tile_palette = ( tile_data >> 9 ) & 0x0F; |
| 139 | |
| 140 | tile_line = ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0x07; |
| 141 | if ( tile_data & 0x8000 ) { |
| 142 | tile_line = 7 - tile_line; |
| 143 | } |
| 144 | |
| 145 | if ( m_vdp.colors_16 ) { |
| 146 | tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); |
| 147 | if ( m_vdp.tile_packed ) { |
| 148 | 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 ]; |
| 149 | } else { |
| 150 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 151 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 152 | plane2 = m_vdp.vram[ tile_address + 2 ] << 2; |
| 153 | plane3 = m_vdp.vram[ tile_address + 3 ] << 3; |
| 154 | } |
| 155 | } else { |
| 156 | tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); |
| 157 | if ( m_vdp.tile_packed ) { |
| 158 | plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; |
| 159 | } else { |
| 160 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 161 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 162 | plane2 = 0; |
| 163 | plane3 = 0; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | for( x = 0; x < 8; x++ ) { |
| 168 | int col; |
| 169 | if ( m_vdp.tile_packed ) { |
| 170 | if ( m_vdp.colors_16 ) { |
| 171 | col = plane0 & 0x0F; |
| 172 | plane0 = plane0 >> 4; |
| 173 | } else { |
| 174 | col = plane0 & 0x03; |
| 175 | plane0 = plane0 >> 2; |
| 176 | } |
| 177 | } else { |
| 178 | col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); |
| 179 | plane3 = plane3 >> 1; |
| 180 | plane2 = plane2 >> 1; |
| 181 | plane1 = plane1 >> 1; |
| 182 | plane0 = plane0 >> 1; |
| 183 | } |
| 184 | if ( tile_data & 0x4000 ) { |
| 185 | x_offset = x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); |
| 186 | } else { |
| 187 | x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); |
| 188 | } |
| 189 | if ( x_offset >= 0 && x_offset < WSWAN_X_PIXELS ) { |
| 190 | if ( m_vdp.colors_16 ) { |
| 191 | if ( col ) { |
| 192 | // if ( m_vdp.color_mode ) { |
| 193 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 194 | // } else { |
| 195 | // /* Hmmmm, what should we do here... Is this correct?? */ |
| 196 | // m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 197 | // } |
| 198 | } |
| 199 | } else { |
| 200 | if ( col || !(tile_palette & 4 ) ) { |
| 201 | if ( m_vdp.color_mode ) { |
| 202 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 203 | } else { |
| 204 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | } |
| 209 | } |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | void wswan_state::wswan_draw_foreground_2() |
| 214 | { |
| 215 | UINT16 map_addr; |
| 216 | UINT8 start_column; |
| 217 | int column; |
| 218 | map_addr = m_vdp.layer_fg_address + ( ( ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0xF8 ) << 3 ); |
| 219 | start_column = ( m_vdp.layer_fg_scroll_x >> 3 ); |
| 220 | for( column = 0; column < 29; column++ ) { |
| 221 | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
| 222 | int x, x_offset, tile_line, tile_address; |
| 223 | int tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) |
| 224 | | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; |
| 225 | int tile_number = tile_data & 0x01FF; |
| 226 | int tile_palette = ( tile_data >> 9 ) & 0x0F; |
| 227 | |
| 228 | tile_line = ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0x07; |
| 229 | if ( tile_data & 0x8000 ) { |
| 230 | tile_line = 7 - tile_line; |
| 231 | } |
| 232 | |
| 233 | if ( m_vdp.colors_16 ) { |
| 234 | tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); |
| 235 | if ( m_vdp.tile_packed ) { |
| 236 | 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 ]; |
| 237 | } else { |
| 238 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 239 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 240 | plane2 = m_vdp.vram[ tile_address + 2 ] << 2; |
| 241 | plane3 = m_vdp.vram[ tile_address + 3 ] << 3; |
| 242 | } |
| 243 | } else { |
| 244 | tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); |
| 245 | if ( m_vdp.tile_packed ) { |
| 246 | plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; |
| 247 | } else { |
| 248 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 249 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 250 | plane2 = 0; |
| 251 | plane3 = 0; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | for( x = 0; x < 8; x++ ) { |
| 256 | int col; |
| 257 | if ( m_vdp.tile_packed ) { |
| 258 | if ( m_vdp.colors_16 ) { |
| 259 | col = plane0 & 0x0F; |
| 260 | plane0 = plane0 >> 4; |
| 261 | } else { |
| 262 | col = plane0 & 0x03; |
| 263 | plane0 = plane0 >> 2; |
| 264 | } |
| 265 | } else { |
| 266 | col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); |
| 267 | plane3 = plane3 >> 1; |
| 268 | plane2 = plane2 >> 1; |
| 269 | plane1 = plane1 >> 1; |
| 270 | plane0 = plane0 >> 1; |
| 271 | } |
| 272 | if ( tile_data & 0x4000 ) { |
| 273 | x_offset = x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); |
| 274 | } else { |
| 275 | x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); |
| 276 | } |
| 277 | if ( x_offset >= 0 && x_offset >= m_vdp.window_fg_left && x_offset < m_vdp.window_fg_right && x_offset < WSWAN_X_PIXELS ) { |
| 278 | if ( m_vdp.colors_16 ) { |
| 279 | if ( col ) { |
| 280 | if ( m_vdp.color_mode ) { |
| 281 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 282 | } else { |
| 283 | /* Hmmmm, what should we do here... Is this correct?? */ |
| 284 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 285 | } |
| 286 | } |
| 287 | } else { |
| 288 | if ( col || !(tile_palette & 4 ) ) { |
| 289 | if ( m_vdp.color_mode ) { |
| 290 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 291 | } else { |
| 292 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | } |
| 297 | } |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | void wswan_state::wswan_draw_foreground_3() |
| 302 | { |
| 303 | UINT16 map_addr; |
| 304 | UINT8 start_column; |
| 305 | int column; |
| 306 | map_addr = m_vdp.layer_fg_address + ( ( ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0xF8 ) << 3 ); |
| 307 | start_column = ( m_vdp.layer_fg_scroll_x >> 3 ); |
| 308 | for( column = 0; column < 29; column++ ) { |
| 309 | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
| 310 | int x, x_offset, tile_line, tile_address; |
| 311 | int tile_data = ( m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) + 1 ] << 8 ) |
| 312 | | m_vdp.vram[ map_addr + ( ( ( start_column + column ) & 0x1F ) << 1 ) ]; |
| 313 | int tile_number = tile_data & 0x01FF; |
| 314 | int tile_palette = ( tile_data >> 9 ) & 0x0F; |
| 315 | |
| 316 | tile_line = ( m_vdp.current_line + m_vdp.layer_fg_scroll_y ) & 0x07; |
| 317 | if ( tile_data & 0x8000 ) { // vflip |
| 318 | tile_line = 7 - tile_line; |
| 319 | } |
| 320 | |
| 321 | if ( m_vdp.colors_16 ) { |
| 322 | tile_address = ( ( tile_data & 0x2000 ) ? 0x8000 : 0x4000 ) + ( tile_number * 32 ) + ( tile_line << 2 ); |
| 323 | if ( m_vdp.tile_packed ) { |
| 324 | 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 ]; |
| 325 | } else { |
| 326 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 327 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 328 | plane2 = m_vdp.vram[ tile_address + 2 ] << 2; |
| 329 | plane3 = m_vdp.vram[ tile_address + 3 ] << 3; |
| 330 | } |
| 331 | } else { |
| 332 | tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); |
| 333 | if ( m_vdp.tile_packed ) { |
| 334 | plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; |
| 335 | } else { |
| 336 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 337 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 338 | plane2 = 0; |
| 339 | plane3 = 0; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | for( x = 0; x < 8; x++ ) { |
| 344 | int col; |
| 345 | if ( m_vdp.tile_packed ) { |
| 346 | if ( m_vdp.colors_16 ) { |
| 347 | col = plane0 & 0x0F; |
| 348 | plane0 = plane0 >> 4; |
| 349 | } else { |
| 350 | col = plane0 & 0x03; |
| 351 | plane0 = plane0 >> 2; |
| 352 | } |
| 353 | } else { |
| 354 | col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); |
| 355 | plane3 = plane3 >> 1; |
| 356 | plane2 = plane2 >> 1; |
| 357 | plane1 = plane1 >> 1; |
| 358 | plane0 = plane0 >> 1; |
| 359 | } |
| 360 | if ( tile_data & 0x4000 ) { |
| 361 | x_offset = x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); |
| 362 | } else { |
| 363 | x_offset = 7 - x + ( column << 3 ) - ( m_vdp.layer_fg_scroll_x & 0x07 ); |
| 364 | } |
| 365 | if ( ( x_offset >= 0 && x_offset < m_vdp.window_fg_left ) || ( x_offset >= m_vdp.window_fg_right && x_offset < WSWAN_X_PIXELS ) ) { |
| 366 | if ( m_vdp.colors_16 ) { |
| 367 | if ( col ) { |
| 368 | if ( m_vdp.color_mode ) { |
| 369 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 370 | } else { |
| 371 | /* Hmmmm, what should we do here... Is this correct?? */ |
| 372 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 373 | } |
| 374 | } |
| 375 | } else { |
| 376 | if ( col || !(tile_palette & 4 ) ) { |
| 377 | if ( m_vdp.color_mode ) { |
| 378 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 379 | } else { |
| 380 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; |
| 381 | } |
| 382 | } |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | } |
| 387 | } |
| 388 | |
| 389 | void wswan_state::wswan_handle_sprites(int mask ) |
| 390 | { |
| 391 | int i; |
| 392 | if ( m_vdp.sprite_count == 0 ) |
| 393 | return; |
| 394 | for( i = m_vdp.sprite_first + m_vdp.sprite_count - 1; i >= m_vdp.sprite_first; i-- ) { |
| 395 | UINT8 x, y; |
| 396 | UINT16 tile_data; |
| 397 | int tile_line; |
| 398 | |
| 399 | tile_data = ( m_vdp.sprite_table_buffer[ i * 4 + 1 ] << 8 ) | m_vdp.sprite_table_buffer[ i * 4 ]; |
| 400 | y = m_vdp.sprite_table_buffer[ i * 4 + 2 ]; |
| 401 | x = m_vdp.sprite_table_buffer[ i * 4 + 3 ]; |
| 402 | tile_line = m_vdp.current_line - y; |
| 403 | tile_line = tile_line & 0xFF; |
| 404 | if ( ( tile_line >= 0 ) && ( tile_line < 8 ) && ( ( tile_data & 0x2000 ) == mask ) ) { |
| 405 | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
| 406 | int j, x_offset, tile_address; |
| 407 | int tile_number = tile_data & 0x01FF; |
| 408 | int tile_palette = 8 + ( ( tile_data >> 9 ) & 0x07 ); |
| 409 | int check_clip = 0; |
| 410 | if ( tile_data & 0x8000 ) { |
| 411 | tile_line = 7 - tile_line; |
| 412 | } |
| 413 | |
| 414 | if ( m_vdp.colors_16 ) { |
| 415 | tile_address = 0x4000 + ( tile_number * 32 ) + ( tile_line << 2 ); |
| 416 | if ( m_vdp.tile_packed ) { |
| 417 | 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 ]; |
| 418 | } else { |
| 419 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 420 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 421 | plane2 = m_vdp.vram[ tile_address + 2 ] << 2; |
| 422 | plane3 = m_vdp.vram[ tile_address + 3 ] << 3; |
| 423 | } |
| 424 | } else { |
| 425 | tile_address = 0x2000 + ( tile_number * 16 ) + ( tile_line << 1 ); |
| 426 | if ( m_vdp.tile_packed ) { |
| 427 | plane0 = ( m_vdp.vram[ tile_address + 0 ] << 8 ) | m_vdp.vram[ tile_address + 1 ]; |
| 428 | } else { |
| 429 | plane0 = m_vdp.vram[ tile_address + 0 ]; |
| 430 | plane1 = m_vdp.vram[ tile_address + 1 ] << 1; |
| 431 | plane2 = 0; |
| 432 | plane3 = 0; |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | if ( m_vdp.window_sprites_enable ) { |
| 437 | if ( tile_data & 0x1000 ) { |
| 438 | if ( m_vdp.current_line >= m_vdp.window_sprites_top && m_vdp.current_line <= m_vdp.window_sprites_bottom ) { |
| 439 | check_clip = 1; |
| 440 | } |
| 441 | } else { |
| 442 | if ( m_vdp.current_line < m_vdp.window_sprites_top || m_vdp.current_line > m_vdp.window_sprites_bottom ) { |
| 443 | continue; |
| 444 | } |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | for ( j = 0; j < 8; j++ ) { |
| 449 | int col; |
| 450 | if ( m_vdp.tile_packed ) { |
| 451 | if ( m_vdp.colors_16 ) { |
| 452 | col = plane0 & 0x0F; |
| 453 | plane0 = plane0 >> 4; |
| 454 | } else { |
| 455 | col = plane0 & 0x03; |
| 456 | plane0 = plane0 >> 2; |
| 457 | } |
| 458 | } else { |
| 459 | col = ( plane3 & 8 ) | ( plane2 & 4 ) | ( plane1 & 2 ) | ( plane0 & 1 ); |
| 460 | plane3 = plane3 >> 1; |
| 461 | plane2 = plane2 >> 1; |
| 462 | plane1 = plane1 >> 1; |
| 463 | plane0 = plane0 >> 1; |
| 464 | } |
| 465 | if ( tile_data & 0x4000 ) { |
| 466 | x_offset = x + j; |
| 467 | } else { |
| 468 | x_offset = x + 7 - j; |
| 469 | } |
| 470 | x_offset = x_offset & 0xFF; |
| 471 | if ( m_vdp.window_sprites_enable ) { |
| 472 | if ( tile_data & 0x1000 && check_clip ) { |
| 473 | if ( x_offset >= m_vdp.window_sprites_left && x_offset <= m_vdp.window_sprites_right ) { |
| 474 | continue; |
| 475 | } |
| 476 | } else { |
| 477 | if ( x_offset < m_vdp.window_sprites_left || x_offset > m_vdp.window_sprites_right ) { |
| 478 | // continue; |
| 479 | } |
| 480 | } |
| 481 | } |
| 482 | if ( x_offset >= 0 && x_offset < WSWAN_X_PIXELS ) { |
| 483 | if ( m_vdp.colors_16 ) { |
| 484 | if ( col ) { |
| 485 | if ( m_vdp.color_mode ) { |
| 486 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 487 | } else { |
| 488 | /* Hmmmm, what should we do here... Is this correct?? */ |
| 489 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 490 | } |
| 491 | } |
| 492 | } else { |
| 493 | if ( col || !(tile_palette & 4 ) ) { |
| 494 | if ( m_vdp.color_mode ) { |
| 495 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_pal[tile_palette][col]; |
| 496 | } else { |
| 497 | m_bitmap.pix16(m_vdp.current_line, x_offset) = m_vdp.main_palette[m_pal[tile_palette][col]]; |
| 498 | } |
| 499 | } |
| 500 | } |
| 501 | } |
| 502 | } |
| 503 | } |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | void wswan_state::wswan_refresh_scanline() |
| 508 | { |
| 509 | wswan_setup_palettes(); |
| 510 | |
| 511 | rectangle rec(0, WSWAN_X_PIXELS, m_vdp.current_line, m_vdp.current_line); |
| 512 | if ( m_ws_portram[0x14] ) { |
| 513 | /* Not sure if these background color checks and settings are correct */ |
| 514 | if ( m_vdp.color_mode && m_vdp.colors_16 ) { |
| 515 | m_bitmap.fill( m_pal[m_ws_portram[0x01]>>4][m_ws_portram[0x01]&0x0F], rec ); |
| 516 | } else { |
| 517 | m_bitmap.fill( m_vdp.main_palette[m_ws_portram[0x01]&0x07], rec ); |
| 518 | } |
| 519 | } else { |
| 520 | m_bitmap.fill( 0, rec ); |
| 521 | return; |
| 522 | } |
| 523 | |
| 524 | /* |
| 525 | * Draw background layer |
| 526 | */ |
| 527 | if ( m_vdp.layer_bg_enable ) { |
| 528 | wswan_draw_background(); |
| 529 | } |
| 530 | |
| 531 | /* |
| 532 | * Draw sprites between background and foreground layers |
| 533 | */ |
| 534 | if ( m_vdp.sprites_enable ) { |
| 535 | wswan_handle_sprites(0); |
| 536 | } |
| 537 | |
| 538 | /* |
| 539 | * Draw foreground layer, taking window settings into account |
| 540 | */ |
| 541 | if ( m_vdp.layer_fg_enable ) { |
| 542 | switch( m_vdp.window_fg_mode ) { |
| 543 | case 0: /* FG inside & outside window area */ |
| 544 | wswan_draw_foreground_0(); |
| 545 | break; |
| 546 | case 1: /* ??? */ |
| 547 | logerror( "Unknown foreground mode 1 set\n" ); |
| 548 | break; |
| 549 | case 2: /* FG only inside window area */ |
| 550 | if ( m_vdp.current_line >= m_vdp.window_fg_top && m_vdp.current_line <= m_vdp.window_fg_bottom ) { |
| 551 | wswan_draw_foreground_2(); |
| 552 | } |
| 553 | break; |
| 554 | case 3: /* FG only outside window area */ |
| 555 | if ( m_vdp.current_line < m_vdp.window_fg_top || m_vdp.current_line > m_vdp.window_fg_bottom ) { |
| 556 | wswan_draw_foreground_0(); |
| 557 | } else { |
| 558 | wswan_draw_foreground_3(); |
| 559 | } |
| 560 | break; |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | /* |
| 565 | * Draw sprites in front of foreground layer |
| 566 | */ |
| 567 | if ( m_vdp.sprites_enable ) { |
| 568 | wswan_handle_sprites(0x2000); |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | |
| 573 | void wswan_state::video_start() |
| 574 | { |
| 575 | machine().first_screen()->register_screen_bitmap(m_bitmap); |
| 576 | save_item(NAME(m_bitmap)); |
| 577 | } |
| 578 | |
| 579 | UINT32 wswan_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 580 | { |
| 581 | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
| 582 | return 0; |
| 583 | } |
trunk/src/mess/video/wswan_video.c
r241553 | r241554 | |
1 | | /*************************************************************************** |
2 | | |
3 | | wswan_video.c |
4 | | |
5 | | File to handle video emulation of the Bandai WonderSwan VDP. |
6 | | |
7 | | Anthony Kruize |
8 | | Wilbert Pol |
9 | | |
10 | | TODO: |
11 | | - remove the redundant parts of m_regs |
12 | | - split the Color VDP from the Mono VDP? |
13 | | |
14 | | ***************************************************************************/ |
15 | | |
16 | | #include "wswan_video.h" |
17 | | |
18 | | const device_type WSWAN_VIDEO = &device_creator<wswan_video_device>; |
19 | | |
20 | | |
21 | | wswan_video_device::wswan_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
22 | | : device_t(mconfig, WSWAN_VIDEO, "Bandai WonderSwan VDP", tag, owner, clock, "wswan_video", __FILE__), |
23 | | m_vdp_type(VDP_TYPE_WSWAN) |
24 | | { |
25 | | } |
26 | | |
27 | | |
28 | | void wswan_video_device::common_save() |
29 | | { |
30 | | save_item(NAME(m_bitmap)); |
31 | | save_item(NAME(m_vram)); |
32 | | save_item(NAME(m_palette_port)); |
33 | | save_item(NAME(m_pal)); |
34 | | save_item(NAME(m_regs)); |
35 | | |
36 | | save_item(NAME(m_layer_bg_enable)); |
37 | | save_item(NAME(m_layer_fg_enable)); |
38 | | save_item(NAME(m_sprites_enable)); |
39 | | save_item(NAME(m_window_sprites_enable)); |
40 | | save_item(NAME(m_window_fg_mode)); |
41 | | save_item(NAME(m_bg_control)); |
42 | | save_item(NAME(m_current_line)); |
43 | | save_item(NAME(m_line_compare)); |
44 | | save_item(NAME(m_sprite_table_address)); |
45 | | save_item(NAME(m_sprite_table_buffer)); |
46 | | save_item(NAME(m_sprite_first)); |
47 | | save_item(NAME(m_sprite_count)); |
48 | | save_item(NAME(m_sprite_first_latch)); |
49 | | save_item(NAME(m_sprite_count_latch)); |
50 | | save_item(NAME(m_layer_bg_address)); |
51 | | save_item(NAME(m_layer_fg_address)); |
52 | | save_item(NAME(m_window_fg_left)); |
53 | | save_item(NAME(m_window_fg_top)); |
54 | | save_item(NAME(m_window_fg_right)); |
55 | | save_item(NAME(m_window_fg_bottom)); |
56 | | save_item(NAME(m_window_sprites_left)); |
57 | | save_item(NAME(m_window_sprites_top)); |
58 | | save_item(NAME(m_window_sprites_right)); |
59 | | save_item(NAME(m_window_sprites_bottom)); |
60 | | save_item(NAME(m_layer_bg_scroll_x)); |
61 | | save_item(NAME(m_layer_bg_scroll_y)); |
62 | | save_item(NAME(m_layer_fg_scroll_x)); |
63 | | save_item(NAME(m_layer_fg_scroll_y)); |
64 | | save_item(NAME(m_lcd_control)); |
65 | | save_item(NAME(m_icons)); |
66 | | save_item(NAME(m_color_mode)); |
67 | | save_item(NAME(m_colors_16)); |
68 | | save_item(NAME(m_tile_packed)); |
69 | | save_item(NAME(m_timer_hblank_enable)); |
70 | | save_item(NAME(m_timer_hblank_mode)); |
71 | | save_item(NAME(m_timer_hblank_reload)); |
72 | | save_item(NAME(m_timer_vblank_enable)); |
73 | | save_item(NAME(m_timer_vblank_mode)); |
74 | | save_item(NAME(m_timer_vblank_reload)); |
75 | | save_item(NAME(m_timer_vblank_count)); |
76 | | save_item(NAME(m_main_palette)); |
77 | | } |
78 | | |
79 | | void wswan_video_device::device_start() |
80 | | { |
81 | | machine().first_screen()->register_screen_bitmap(m_bitmap); |
82 | | |
83 | | m_timer = timer_alloc(TIMER_SCANLINE); |
84 | | m_timer->adjust(attotime::from_ticks(256, 3072000), 0, attotime::from_ticks(256, 3072000)); |
85 | | |
86 | | // bind callbacks |
87 | | m_set_irq_cb.bind_relative_to(*owner()); |
88 | | m_snd_dma_cb.bind_relative_to(*owner()); |
89 | | |
90 | | if (m_vdp_type == VDP_TYPE_WSC) |
91 | | { |
92 | | m_vram.resize_and_clear(0x10000); |
93 | | m_palette_vram = m_vram + 0xfe00; |
94 | | } |
95 | | else |
96 | | { |
97 | | m_vram.resize_and_clear(0x4000); |
98 | | m_palette_vram = m_vram; |
99 | | } |
100 | | |
101 | | common_save(); |
102 | | } |
103 | | |
104 | | // This is a copy of ws_portram_init |
105 | | // TODO: remove unneeded parts! |
106 | | static const UINT8 vdp_regs_init[256] = |
107 | | { |
108 | | 0x00, 0x00, 0x00/*?*/, 0xbb, 0x00, 0x00, 0x00, 0x26, 0xfe, 0xde, 0xf9, 0xfb, 0xdb, 0xd7, 0x7f, 0xf5, |
109 | | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x99, 0xfd, 0xb7, 0xdf, |
110 | | 0x30, 0x57, 0x75, 0x76, 0x15, 0x73, 0x70/*77?*/, 0x77, 0x20, 0x75, 0x50, 0x36, 0x70, 0x67, 0x50, 0x77, |
111 | | 0x57, 0x54, 0x75, 0x77, 0x75, 0x17, 0x37, 0x73, 0x50, 0x57, 0x60, 0x77, 0x70, 0x77, 0x10, 0x73, |
112 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
113 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
114 | | 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, |
115 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
116 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, |
117 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, |
118 | | 0x87, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
119 | | 0x00, 0xdb, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x83, 0x00, |
120 | | 0x2f, 0x3f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, |
121 | | 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, |
122 | | 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, |
123 | | 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 |
124 | | }; |
125 | | |
126 | | |
127 | | void wswan_video_device::device_reset() |
128 | | { |
129 | | m_layer_bg_enable = 0; |
130 | | m_layer_fg_enable = 0; |
131 | | m_sprites_enable = 0; |
132 | | m_window_sprites_enable = 0; |
133 | | m_window_fg_mode = 0; |
134 | | m_bg_control = 0; |
135 | | m_current_line = 145; // Randomly chosen, beginning of VBlank period to give cart some time to boot up |
136 | | m_line_compare = 0; |
137 | | m_sprite_table_address = 0; |
138 | | m_sprite_first = 0; |
139 | | m_sprite_count = 0; |
140 | | m_sprite_first_latch = 0; |
141 | | m_sprite_count_latch = 0; |
142 | | m_layer_bg_address = 0; |
143 | | m_layer_fg_address = 0; |
144 | | m_window_fg_left = 0; |
145 | | m_window_fg_top = 0; |
146 | | m_window_fg_right = 0; |
147 | | m_window_fg_bottom = 0; |
148 | | m_window_sprites_left = 0; |
149 | | m_window_sprites_top = 0; |
150 | | m_window_sprites_right = 0; |
151 | | m_window_sprites_bottom = 0; |
152 | | m_layer_bg_scroll_x = 0; |
153 | | m_layer_bg_scroll_y = 0; |
154 | | m_layer_fg_scroll_x = 0; |
155 | | m_layer_fg_scroll_y = 0; |
156 | | m_lcd_control = 0x01; |
157 | | m_icons = 0; |
158 | | m_color_mode = 0; |
159 | | m_colors_16 = 0; |
160 | | m_tile_packed = 0; |
161 | | m_timer_hblank_enable = 0; |
162 | | m_timer_hblank_mode = 0; |
163 | | m_timer_hblank_reload = 0; |
164 | | m_timer_hblank_count = 0; |
165 | | m_timer_vblank_enable = 0; |
166 | | m_timer_vblank_mode = 0; |
167 | | m_timer_vblank_reload = 0; |
168 | | m_timer_vblank_count = 0; /* Vertical blank timer counter value */ |
169 | | |
170 | | memset(m_sprite_table_buffer, 0, sizeof(m_sprite_table_buffer)); |
171 | | memset(m_main_palette, 0, sizeof(m_main_palette)); |
172 | | memcpy(m_regs, vdp_regs_init, 256); |
173 | | for (int i = 0; i < 0x20; i++) |
174 | | m_palette_port[i] = m_regs[i + 0x20]; |
175 | | |
176 | | setup_palettes(); |
177 | | } |
178 | | |
179 | | |
180 | | void wswan_video_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
181 | | { |
182 | | switch (id) |
183 | | { |
184 | | case TIMER_SCANLINE: |
185 | | scanline_interrupt(); |
186 | | break; |
187 | | } |
188 | | } |
189 | | |
190 | | |
191 | | void wswan_video_device::setup_palettes() |
192 | | { |
193 | | if (m_color_mode) |
194 | | { |
195 | | for (int i = 0; i < 16; i++) |
196 | | for (int j = 0; j < 16; j++) |
197 | | m_pal[i][j] = ((m_palette_vram[(i << 5) + j * 2 + 1] << 8) | m_palette_vram[(i << 5) + j * 2]) & 0x0fff; |
198 | | } |
199 | | else |
200 | | { |
201 | | for (int i = 0; i < 16; i++) |
202 | | { |
203 | | m_pal[i][0] = (m_palette_port[(i << 1)] >> 0) & 0x07; |
204 | | m_pal[i][1] = (m_palette_port[(i << 1)] >> 4) & 0x07; |
205 | | m_pal[i][2] = (m_palette_port[(i << 1) + 1] >> 0) & 0x07; |
206 | | m_pal[i][3] = (m_palette_port[(i << 1) + 1] >> 4) & 0x07; |
207 | | } |
208 | | } |
209 | | } |
210 | | |
211 | | void wswan_video_device::draw_background() |
212 | | { |
213 | | UINT16 map_addr = m_layer_bg_address + (((m_current_line + m_layer_bg_scroll_y) & 0xf8) << 3); |
214 | | UINT8 start_column = (m_layer_bg_scroll_x >> 3); |
215 | | |
216 | | for (int column = 0; column < 29; column++) |
217 | | { |
218 | | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
219 | | int x_offset, tile_line, tile_address; |
220 | | int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) |
221 | | | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; |
222 | | int tile_number = tile_data & 0x01ff; |
223 | | int tile_palette = (tile_data >> 9) & 0x0f; |
224 | | |
225 | | tile_line = (m_current_line + m_layer_bg_scroll_y) & 0x07; |
226 | | if (tile_data & 0x8000) // vflip |
227 | | tile_line = 7 - tile_line; |
228 | | |
229 | | if (m_colors_16) |
230 | | { |
231 | | tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); |
232 | | if (m_tile_packed) |
233 | | { |
234 | | plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; |
235 | | } |
236 | | else |
237 | | { |
238 | | plane0 = m_vram[tile_address + 0]; |
239 | | plane1 = m_vram[tile_address + 1] << 1; |
240 | | plane2 = m_vram[tile_address + 2] << 2; |
241 | | plane3 = m_vram[tile_address + 3] << 3; |
242 | | } |
243 | | } |
244 | | else |
245 | | { |
246 | | tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); |
247 | | if (m_tile_packed) |
248 | | { |
249 | | plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; |
250 | | } |
251 | | else |
252 | | { |
253 | | plane0 = m_vram[tile_address + 0]; |
254 | | plane1 = m_vram[tile_address + 1] << 1; |
255 | | plane2 = 0; |
256 | | plane3 = 0; |
257 | | } |
258 | | } |
259 | | |
260 | | for (int x = 0; x < 8; x++) |
261 | | { |
262 | | int col; |
263 | | if (m_tile_packed) |
264 | | { |
265 | | if (m_colors_16) |
266 | | { |
267 | | col = plane0 & 0x0f; |
268 | | plane0 = plane0 >> 4; |
269 | | } |
270 | | else |
271 | | { |
272 | | col = plane0 & 0x03; |
273 | | plane0 = plane0 >> 2; |
274 | | } |
275 | | } |
276 | | else |
277 | | { |
278 | | col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); |
279 | | plane3 = plane3 >> 1; |
280 | | plane2 = plane2 >> 1; |
281 | | plane1 = plane1 >> 1; |
282 | | plane0 = plane0 >> 1; |
283 | | } |
284 | | |
285 | | if (tile_data & 0x4000) |
286 | | x_offset = x + (column << 3) - (m_layer_bg_scroll_x & 0x07); |
287 | | else |
288 | | x_offset = 7 - x + (column << 3) - (m_layer_bg_scroll_x & 0x07); |
289 | | |
290 | | if (x_offset >= 0 && x_offset < WSWAN_X_PIXELS) |
291 | | { |
292 | | if (m_colors_16) |
293 | | { |
294 | | if (col) |
295 | | { |
296 | | if (m_color_mode) |
297 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
298 | | else |
299 | | { |
300 | | /* Hmmmm, what should we do here... Is this correct?? */ |
301 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
302 | | } |
303 | | } |
304 | | } |
305 | | else |
306 | | { |
307 | | if (col || !(tile_palette & 4)) |
308 | | { |
309 | | if (m_color_mode) |
310 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
311 | | else |
312 | | m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; |
313 | | } |
314 | | } |
315 | | } |
316 | | } |
317 | | } |
318 | | } |
319 | | |
320 | | void wswan_video_device::draw_foreground_0() |
321 | | { |
322 | | UINT16 map_addr = m_layer_fg_address + (((m_current_line + m_layer_fg_scroll_y) & 0xf8) << 3); |
323 | | UINT8 start_column = (m_layer_fg_scroll_x >> 3); |
324 | | |
325 | | for (int column = 0; column < 29; column++) |
326 | | { |
327 | | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
328 | | int x_offset, tile_line, tile_address; |
329 | | int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) |
330 | | | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; |
331 | | int tile_number = tile_data & 0x01ff; |
332 | | int tile_palette = (tile_data >> 9) & 0x0f; |
333 | | |
334 | | tile_line = (m_current_line + m_layer_fg_scroll_y) & 0x07; |
335 | | if (tile_data & 0x8000) // vflip |
336 | | tile_line = 7 - tile_line; |
337 | | |
338 | | if (m_colors_16) |
339 | | { |
340 | | tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); |
341 | | if (m_tile_packed) |
342 | | { |
343 | | plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; |
344 | | } |
345 | | else |
346 | | { |
347 | | plane0 = m_vram[tile_address + 0]; |
348 | | plane1 = m_vram[tile_address + 1] << 1; |
349 | | plane2 = m_vram[tile_address + 2] << 2; |
350 | | plane3 = m_vram[tile_address + 3] << 3; |
351 | | } |
352 | | } |
353 | | else |
354 | | { |
355 | | tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); |
356 | | if (m_tile_packed) |
357 | | { |
358 | | plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; |
359 | | } |
360 | | else |
361 | | { |
362 | | plane0 = m_vram[tile_address + 0]; |
363 | | plane1 = m_vram[tile_address + 1] << 1; |
364 | | plane2 = 0; |
365 | | plane3 = 0; |
366 | | } |
367 | | } |
368 | | |
369 | | for (int x = 0; x < 8; x++ ) |
370 | | { |
371 | | int col; |
372 | | if (m_tile_packed) |
373 | | { |
374 | | if (m_colors_16) |
375 | | { |
376 | | col = plane0 & 0x0f; |
377 | | plane0 = plane0 >> 4; |
378 | | } |
379 | | else |
380 | | { |
381 | | col = plane0 & 0x03; |
382 | | plane0 = plane0 >> 2; |
383 | | } |
384 | | } |
385 | | else |
386 | | { |
387 | | col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); |
388 | | plane3 = plane3 >> 1; |
389 | | plane2 = plane2 >> 1; |
390 | | plane1 = plane1 >> 1; |
391 | | plane0 = plane0 >> 1; |
392 | | } |
393 | | |
394 | | if (tile_data & 0x4000) |
395 | | x_offset = x + (column << 3) - (m_layer_fg_scroll_x & 0x07); |
396 | | else |
397 | | x_offset = 7 - x + (column << 3) - (m_layer_fg_scroll_x & 0x07); |
398 | | |
399 | | if (x_offset >= 0 && x_offset < WSWAN_X_PIXELS) |
400 | | { |
401 | | if (m_colors_16) |
402 | | { |
403 | | if (col) |
404 | | { |
405 | | // if (m_color_mode) { |
406 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
407 | | // } else { |
408 | | // /* Hmmmm, what should we do here... Is this correct?? */ |
409 | | // m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
410 | | // } |
411 | | } |
412 | | } |
413 | | else |
414 | | { |
415 | | if (col || !(tile_palette & 4)) |
416 | | { |
417 | | if (m_color_mode) |
418 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
419 | | else |
420 | | m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; |
421 | | } |
422 | | } |
423 | | } |
424 | | } |
425 | | } |
426 | | } |
427 | | |
428 | | void wswan_video_device::draw_foreground_2() |
429 | | { |
430 | | UINT16 map_addr = m_layer_fg_address + (((m_current_line + m_layer_fg_scroll_y) & 0xf8) << 3); |
431 | | UINT8 start_column = (m_layer_fg_scroll_x >> 3); |
432 | | |
433 | | for (int column = 0; column < 29; column++) |
434 | | { |
435 | | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
436 | | int x_offset, tile_line, tile_address; |
437 | | int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) |
438 | | | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; |
439 | | int tile_number = tile_data & 0x01ff; |
440 | | int tile_palette = (tile_data >> 9) & 0x0f; |
441 | | |
442 | | tile_line = (m_current_line + m_layer_fg_scroll_y) & 0x07; |
443 | | if (tile_data & 0x8000) // vflip |
444 | | tile_line = 7 - tile_line; |
445 | | |
446 | | |
447 | | if (m_colors_16) |
448 | | { |
449 | | tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); |
450 | | if (m_tile_packed) |
451 | | { |
452 | | plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; |
453 | | } |
454 | | else |
455 | | { |
456 | | plane0 = m_vram[tile_address + 0]; |
457 | | plane1 = m_vram[tile_address + 1] << 1; |
458 | | plane2 = m_vram[tile_address + 2] << 2; |
459 | | plane3 = m_vram[tile_address + 3] << 3; |
460 | | } |
461 | | } |
462 | | else |
463 | | { |
464 | | tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); |
465 | | if (m_tile_packed) |
466 | | { |
467 | | plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; |
468 | | } |
469 | | else |
470 | | { |
471 | | plane0 = m_vram[tile_address + 0]; |
472 | | plane1 = m_vram[tile_address + 1] << 1; |
473 | | plane2 = 0; |
474 | | plane3 = 0; |
475 | | } |
476 | | } |
477 | | |
478 | | for (int x = 0; x < 8; x++) |
479 | | { |
480 | | int col; |
481 | | if (m_tile_packed) |
482 | | { |
483 | | if (m_colors_16) |
484 | | { |
485 | | col = plane0 & 0x0f; |
486 | | plane0 = plane0 >> 4; |
487 | | } |
488 | | else |
489 | | { |
490 | | col = plane0 & 0x03; |
491 | | plane0 = plane0 >> 2; |
492 | | } |
493 | | } |
494 | | else |
495 | | { |
496 | | col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); |
497 | | plane3 = plane3 >> 1; |
498 | | plane2 = plane2 >> 1; |
499 | | plane1 = plane1 >> 1; |
500 | | plane0 = plane0 >> 1; |
501 | | } |
502 | | |
503 | | if (tile_data & 0x4000) |
504 | | x_offset = x + (column << 3) - (m_layer_fg_scroll_x & 0x07); |
505 | | else |
506 | | x_offset = 7 - x + (column << 3) - (m_layer_fg_scroll_x & 0x07); |
507 | | |
508 | | if (x_offset >= 0 && x_offset >= m_window_fg_left && x_offset < m_window_fg_right && x_offset < WSWAN_X_PIXELS) |
509 | | { |
510 | | if (m_colors_16) |
511 | | { |
512 | | if (col) |
513 | | { |
514 | | if (m_color_mode) |
515 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
516 | | else |
517 | | /* Hmmmm, what should we do here... Is this correct?? */ |
518 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
519 | | } |
520 | | } |
521 | | else |
522 | | { |
523 | | if (col || !(tile_palette & 4)) |
524 | | { |
525 | | if (m_color_mode) |
526 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
527 | | else |
528 | | m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; |
529 | | } |
530 | | } |
531 | | } |
532 | | } |
533 | | } |
534 | | } |
535 | | |
536 | | void wswan_video_device::draw_foreground_3() |
537 | | { |
538 | | UINT16 map_addr = m_layer_fg_address + (((m_current_line + m_layer_fg_scroll_y) & 0xf8) << 3); |
539 | | UINT8 start_column = (m_layer_fg_scroll_x >> 3); |
540 | | |
541 | | for (int column = 0; column < 29; column++) |
542 | | { |
543 | | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
544 | | int x_offset, tile_line, tile_address; |
545 | | int tile_data = (m_vram[map_addr + (((start_column + column) & 0x1f) << 1) + 1] << 8) |
546 | | | m_vram[map_addr + (((start_column + column) & 0x1f) << 1)]; |
547 | | int tile_number = tile_data & 0x01ff; |
548 | | int tile_palette = (tile_data >> 9) & 0x0f; |
549 | | |
550 | | tile_line = (m_current_line + m_layer_fg_scroll_y) & 0x07; |
551 | | if (tile_data & 0x8000) // vflip |
552 | | tile_line = 7 - tile_line; |
553 | | |
554 | | if (m_colors_16) |
555 | | { |
556 | | tile_address = ((tile_data & 0x2000) ? 0x8000 : 0x4000) + (tile_number * 32) + (tile_line << 2); |
557 | | if (m_tile_packed) |
558 | | { |
559 | | plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; |
560 | | } |
561 | | else |
562 | | { |
563 | | plane0 = m_vram[tile_address + 0]; |
564 | | plane1 = m_vram[tile_address + 1] << 1; |
565 | | plane2 = m_vram[tile_address + 2] << 2; |
566 | | plane3 = m_vram[tile_address + 3] << 3; |
567 | | } |
568 | | } |
569 | | else |
570 | | { |
571 | | tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); |
572 | | if (m_tile_packed) |
573 | | { |
574 | | plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; |
575 | | } |
576 | | else |
577 | | { |
578 | | plane0 = m_vram[tile_address + 0]; |
579 | | plane1 = m_vram[tile_address + 1] << 1; |
580 | | plane2 = 0; |
581 | | plane3 = 0; |
582 | | } |
583 | | } |
584 | | |
585 | | for (int x = 0; x < 8; x++) |
586 | | { |
587 | | int col; |
588 | | if (m_tile_packed) |
589 | | { |
590 | | if (m_colors_16) |
591 | | { |
592 | | col = plane0 & 0x0f; |
593 | | plane0 = plane0 >> 4; |
594 | | } |
595 | | else |
596 | | { |
597 | | col = plane0 & 0x03; |
598 | | plane0 = plane0 >> 2; |
599 | | } |
600 | | } |
601 | | else |
602 | | { |
603 | | col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); |
604 | | plane3 = plane3 >> 1; |
605 | | plane2 = plane2 >> 1; |
606 | | plane1 = plane1 >> 1; |
607 | | plane0 = plane0 >> 1; |
608 | | } |
609 | | |
610 | | if (tile_data & 0x4000) |
611 | | x_offset = x + (column << 3) - (m_layer_fg_scroll_x & 0x07); |
612 | | else |
613 | | x_offset = 7 - x + (column << 3) - (m_layer_fg_scroll_x & 0x07); |
614 | | |
615 | | if ((x_offset >= 0 && x_offset < m_window_fg_left) || (x_offset >= m_window_fg_right && x_offset < WSWAN_X_PIXELS)) |
616 | | { |
617 | | if (m_colors_16) |
618 | | { |
619 | | if (col) |
620 | | { |
621 | | if (m_color_mode) |
622 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
623 | | else |
624 | | /* Hmmmm, what should we do here... Is this correct?? */ |
625 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
626 | | } |
627 | | } |
628 | | else |
629 | | { |
630 | | if (col || !(tile_palette & 4)) |
631 | | { |
632 | | if (m_color_mode) |
633 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
634 | | else |
635 | | m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; |
636 | | } |
637 | | } |
638 | | } |
639 | | } |
640 | | } |
641 | | } |
642 | | |
643 | | void wswan_video_device::handle_sprites(int mask) |
644 | | { |
645 | | if (m_sprite_count == 0) |
646 | | return; |
647 | | |
648 | | for (int i = m_sprite_first + m_sprite_count - 1; i >= m_sprite_first; i--) |
649 | | { |
650 | | UINT16 tile_data = (m_sprite_table_buffer[i * 4 + 1] << 8) | m_sprite_table_buffer[i * 4]; |
651 | | UINT8 y = m_sprite_table_buffer[ i * 4 + 2 ]; |
652 | | UINT8 x = m_sprite_table_buffer[ i * 4 + 3 ]; |
653 | | int tile_line = (m_current_line - y) & 0xff; |
654 | | |
655 | | if ((tile_line >= 0) && (tile_line < 8) && ((tile_data & 0x2000) == mask)) |
656 | | { |
657 | | UINT32 plane0 = 0, plane1 = 0, plane2 = 0, plane3 = 0; |
658 | | int x_offset, tile_address; |
659 | | int tile_number = tile_data & 0x01ff; |
660 | | int tile_palette = 8 + ((tile_data >> 9) & 0x07); |
661 | | int check_clip = 0; |
662 | | |
663 | | if (tile_data & 0x8000) |
664 | | tile_line = 7 - tile_line; |
665 | | |
666 | | if (m_colors_16) |
667 | | { |
668 | | tile_address = 0x4000 + (tile_number * 32) + (tile_line << 2); |
669 | | if (m_tile_packed) |
670 | | { |
671 | | plane0 = (m_vram[tile_address + 0] << 24) | (m_vram[tile_address + 1] << 16) | (m_vram[tile_address + 2] << 8) | m_vram[tile_address + 3]; |
672 | | } |
673 | | else |
674 | | { |
675 | | plane0 = m_vram[tile_address + 0]; |
676 | | plane1 = m_vram[tile_address + 1] << 1; |
677 | | plane2 = m_vram[tile_address + 2] << 2; |
678 | | plane3 = m_vram[tile_address + 3] << 3; |
679 | | } |
680 | | } |
681 | | else |
682 | | { |
683 | | tile_address = 0x2000 + (tile_number * 16) + (tile_line << 1); |
684 | | if (m_tile_packed) |
685 | | { |
686 | | plane0 = (m_vram[tile_address + 0] << 8) | m_vram[tile_address + 1]; |
687 | | } |
688 | | else |
689 | | { |
690 | | plane0 = m_vram[tile_address + 0]; |
691 | | plane1 = m_vram[tile_address + 1] << 1; |
692 | | plane2 = 0; |
693 | | plane3 = 0; |
694 | | } |
695 | | } |
696 | | |
697 | | if (m_window_sprites_enable) |
698 | | { |
699 | | if (tile_data & 0x1000) |
700 | | { |
701 | | if (m_current_line >= m_window_sprites_top && m_current_line <= m_window_sprites_bottom) |
702 | | check_clip = 1; |
703 | | } |
704 | | else |
705 | | { |
706 | | if (m_current_line < m_window_sprites_top || m_current_line > m_window_sprites_bottom) |
707 | | continue; |
708 | | } |
709 | | } |
710 | | |
711 | | for (int j = 0; j < 8; j++) |
712 | | { |
713 | | int col; |
714 | | if (m_tile_packed) |
715 | | { |
716 | | if (m_colors_16) |
717 | | { |
718 | | col = plane0 & 0x0f; |
719 | | plane0 = plane0 >> 4; |
720 | | } |
721 | | else |
722 | | { |
723 | | col = plane0 & 0x03; |
724 | | plane0 = plane0 >> 2; |
725 | | } |
726 | | } |
727 | | else |
728 | | { |
729 | | col = (plane3 & 8) | (plane2 & 4) | (plane1 & 2) | (plane0 & 1); |
730 | | plane3 = plane3 >> 1; |
731 | | plane2 = plane2 >> 1; |
732 | | plane1 = plane1 >> 1; |
733 | | plane0 = plane0 >> 1; |
734 | | } |
735 | | |
736 | | if (tile_data & 0x4000) |
737 | | x_offset = x + j; |
738 | | else |
739 | | x_offset = x + 7 - j; |
740 | | |
741 | | x_offset = x_offset & 0xff; |
742 | | |
743 | | if (m_window_sprites_enable) |
744 | | { |
745 | | if (tile_data & 0x1000 && check_clip) |
746 | | { |
747 | | if (x_offset >= m_window_sprites_left && x_offset <= m_window_sprites_right) |
748 | | continue; |
749 | | } |
750 | | else |
751 | | { |
752 | | if (x_offset < m_window_sprites_left || x_offset > m_window_sprites_right) |
753 | | { |
754 | | // continue; |
755 | | } |
756 | | } |
757 | | } |
758 | | if (x_offset >= 0 && x_offset < WSWAN_X_PIXELS) |
759 | | { |
760 | | if (m_colors_16) |
761 | | { |
762 | | if (col) |
763 | | { |
764 | | if (m_color_mode) |
765 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
766 | | else |
767 | | /* Hmmmm, what should we do here... Is this correct?? */ |
768 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
769 | | } |
770 | | } |
771 | | else |
772 | | { |
773 | | if (col || !(tile_palette & 4)) |
774 | | { |
775 | | if (m_color_mode) |
776 | | m_bitmap.pix16(m_current_line, x_offset) = m_pal[tile_palette][col]; |
777 | | else |
778 | | m_bitmap.pix16(m_current_line, x_offset) = m_main_palette[m_pal[tile_palette][col]]; |
779 | | } |
780 | | } |
781 | | } |
782 | | } |
783 | | } |
784 | | } |
785 | | } |
786 | | |
787 | | |
788 | | void wswan_video_device::refresh_scanline() |
789 | | { |
790 | | setup_palettes(); |
791 | | |
792 | | rectangle rec(0, WSWAN_X_PIXELS, m_current_line, m_current_line); |
793 | | if (m_lcd_control) |
794 | | { |
795 | | /* Not sure if these background color checks and settings are correct */ |
796 | | if (m_color_mode && m_colors_16) |
797 | | m_bitmap.fill(m_pal[m_bg_control >> 4][m_bg_control & 0x0f], rec); |
798 | | else |
799 | | m_bitmap.fill(m_main_palette[m_bg_control & 0x07], rec); |
800 | | } |
801 | | else |
802 | | { |
803 | | m_bitmap.fill(0, rec); |
804 | | return; |
805 | | } |
806 | | |
807 | | // Draw background layer |
808 | | if (m_layer_bg_enable) |
809 | | draw_background(); |
810 | | |
811 | | // Draw sprites between background and foreground layers |
812 | | if (m_sprites_enable) |
813 | | handle_sprites(0); |
814 | | |
815 | | // Draw foreground layer, taking window settings into account |
816 | | if (m_layer_fg_enable) |
817 | | { |
818 | | switch (m_window_fg_mode) |
819 | | { |
820 | | case 0: // FG inside & outside window area |
821 | | draw_foreground_0(); |
822 | | break; |
823 | | case 1: // ??? |
824 | | logerror("Unknown foreground mode 1 set\n"); |
825 | | break; |
826 | | case 2: // FG only inside window area |
827 | | if (m_current_line >= m_window_fg_top && m_current_line <= m_window_fg_bottom) |
828 | | draw_foreground_2(); |
829 | | break; |
830 | | case 3: // FG only outside window area |
831 | | if (m_current_line < m_window_fg_top || m_current_line > m_window_fg_bottom) |
832 | | draw_foreground_0(); |
833 | | else |
834 | | draw_foreground_3(); |
835 | | break; |
836 | | } |
837 | | } |
838 | | |
839 | | // Draw sprites in front of foreground layer |
840 | | if (m_sprites_enable) |
841 | | handle_sprites(0x2000); |
842 | | } |
843 | | |
844 | | |
845 | | |
846 | | UINT32 wswan_video_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
847 | | { |
848 | | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
849 | | return 0; |
850 | | } |
851 | | |
852 | | |
853 | | READ8_MEMBER(wswan_video_device::reg_r) |
854 | | { |
855 | | UINT8 value = m_regs[offset]; |
856 | | |
857 | | if (offset >= 0x20 && offset < 0x40) |
858 | | return m_palette_port[offset & 0x1f]; |
859 | | |
860 | | switch (offset) |
861 | | { |
862 | | case 0x01: |
863 | | value = m_bg_control; |
864 | | break; |
865 | | case 0x02: |
866 | | value = m_current_line; |
867 | | break; |
868 | | case 0x14: |
869 | | value = m_lcd_control; |
870 | | break; |
871 | | case 0xa8: |
872 | | value = m_timer_hblank_count & 0xff; |
873 | | break; |
874 | | case 0xa9: |
875 | | value = m_timer_hblank_count >> 8; |
876 | | break; |
877 | | case 0xaa: |
878 | | value = m_timer_vblank_count & 0xff; |
879 | | break; |
880 | | case 0xab: |
881 | | value = m_timer_vblank_count >> 8; |
882 | | break; |
883 | | } |
884 | | |
885 | | return value; |
886 | | } |
887 | | |
888 | | |
889 | | WRITE8_MEMBER(wswan_video_device::reg_w) |
890 | | { |
891 | | if (offset >= 0x20 && offset < 0x40) |
892 | | { |
893 | | // 0x20-0x3f tile/sprite palette settings |
894 | | // even offs |
895 | | // Bit 0-3 - Palette (offs & 0x1f)/2 index 0 |
896 | | // Bit 4-7 - Palette (offs & 0x1f)/2 index 1 |
897 | | // odd offs |
898 | | // Bit 0-3 - Palette (offs & 0x1f)/2 index 2 |
899 | | // Bit 4-7 - Palette (offs & 0x1f)/2 index 3 |
900 | | m_palette_port[offset & 0x1f] = data; |
901 | | return; |
902 | | } |
903 | | |
904 | | switch (offset) |
905 | | { |
906 | | case 0x00: // Display control |
907 | | // Bit 0 - Background layer enable |
908 | | // Bit 1 - Foreground layer enable |
909 | | // Bit 2 - Sprites enable |
910 | | // Bit 3 - Sprite window enable |
911 | | // Bit 4-5 - Foreground window configuration |
912 | | // 00 - Foreground layer is displayed inside and outside foreground window area |
913 | | // 01 - Unknown |
914 | | // 10 - Foreground layer is displayed only inside foreground window area |
915 | | // 11 - Foreground layer is displayed outside foreground window area |
916 | | // Bit 6-7 - Unknown |
917 | | m_layer_bg_enable = data & 0x1; |
918 | | m_layer_fg_enable = (data & 0x2) >> 1; |
919 | | m_sprites_enable = (data & 0x4) >> 2; |
920 | | m_window_sprites_enable = (data & 0x8) >> 3; |
921 | | m_window_fg_mode = (data & 0x30) >> 4; |
922 | | break; |
923 | | case 0x01: // Background colour |
924 | | // In 16 colour mode: |
925 | | // Bit 0-3 - Palette index |
926 | | // Bit 4-7 - Palette number |
927 | | // Otherwise: |
928 | | // Bit 0-2 - Main palette index |
929 | | // Bit 3-7 - Unknown |
930 | | m_bg_control = data; |
931 | | break; |
932 | | case 0x02: // Current scanline (Most likely read-only) |
933 | | logerror("Write to current scanline! Current value: %d Data to write: %d\n", m_current_line, data); |
934 | | // Returning so we don't overwrite the value here, not that it really matters |
935 | | return; |
936 | | case 0x03: // Line compare |
937 | | m_line_compare = data; |
938 | | logerror("Write to line compare: %d\n", data); |
939 | | break; |
940 | | case 0x04: // Sprite table base address |
941 | | // Bit 0-5 - Determine sprite table base address 0 0xxxxxx0 00000000 |
942 | | // Bit 6-7 - Unknown |
943 | | m_sprite_table_address = (data & 0x3f) << 9; |
944 | | break; |
945 | | case 0x05: // First sprite number (the one we start drawing with) |
946 | | m_sprite_first_latch = data; |
947 | | if (data) logerror("non-zero first sprite %d\n", data); |
948 | | break; |
949 | | case 0x06: // Number of sprites to draw |
950 | | m_sprite_count_latch = data; |
951 | | break; |
952 | | case 0x07: // Background/Foreground table base addresses |
953 | | // Bit 0-2 - Determine background table base address 00xxx000 00000000 |
954 | | // Bit 3 - Unknown |
955 | | // Bit 4-6 - Determine foreground table base address 00xxx000 00000000 |
956 | | // Bit 7 - Unknown |
957 | | m_layer_bg_address = (data & 0x7) << 11; |
958 | | m_layer_fg_address = (data & 0x70) << 7; |
959 | | break; |
960 | | case 0x08: // Left coordinate of foreground window |
961 | | m_window_fg_left = data; |
962 | | break; |
963 | | case 0x09: // Top coordinate of foreground window |
964 | | m_window_fg_top = data; |
965 | | break; |
966 | | case 0x0a: // Right coordinate of foreground window |
967 | | m_window_fg_right = data; |
968 | | break; |
969 | | case 0x0b: // Bottom coordinate of foreground window |
970 | | m_window_fg_bottom = data; |
971 | | break; |
972 | | case 0x0c: // Left coordinate of sprite window |
973 | | m_window_sprites_left = data; |
974 | | break; |
975 | | case 0x0d: // Top coordinate of sprite window |
976 | | m_window_sprites_top = data; |
977 | | break; |
978 | | case 0x0e: // Right coordinate of sprite window |
979 | | m_window_sprites_right = data; |
980 | | break; |
981 | | case 0x0f: // Bottom coordinate of sprite window |
982 | | m_window_sprites_bottom = data; |
983 | | break; |
984 | | case 0x10: // Background layer X scroll |
985 | | m_layer_bg_scroll_x = data; |
986 | | break; |
987 | | case 0x11: // Background layer Y scroll |
988 | | m_layer_bg_scroll_y = data; |
989 | | break; |
990 | | case 0x12: // Foreground layer X scroll |
991 | | m_layer_fg_scroll_x = data; |
992 | | break; |
993 | | case 0x13: // Foreground layer Y scroll |
994 | | m_layer_fg_scroll_y = data; |
995 | | break; |
996 | | case 0x14: // LCD control |
997 | | // Bit 0 - LCD enable |
998 | | // Bit 1-7 - Unknown |
999 | | m_lcd_control = data; |
1000 | | break; |
1001 | | case 0x15: // LCD icons |
1002 | | // Bit 0 - LCD sleep icon enable |
1003 | | // Bit 1 - Vertical position icon enable |
1004 | | // Bit 2 - Horizontal position icon enable |
1005 | | // Bit 3 - Dot 1 icon enable |
1006 | | // Bit 4 - Dot 2 icon enable |
1007 | | // Bit 5 - Dot 3 icon enable |
1008 | | // Bit 6-7 - Unknown |
1009 | | m_icons = data; /* ummmmm */ |
1010 | | break; |
1011 | | case 0x1c: // Palette colors 0 and 1 |
1012 | | // Bit 0-3 - Gray tone setting for main palette index 0 |
1013 | | // Bit 4-7 - Gray tone setting for main palette index 1 |
1014 | | if (m_vdp_type == VDP_TYPE_WSC) |
1015 | | { |
1016 | | int i = 15 - (data & 0x0f); |
1017 | | int j = 15 - ((data & 0xf0) >> 4); |
1018 | | m_main_palette[0] = (i << 8) | (i << 4) | i; |
1019 | | m_main_palette[1] = (j << 8) | (j << 4) | j; |
1020 | | } |
1021 | | else |
1022 | | { |
1023 | | m_main_palette[0] = data & 0x0f; |
1024 | | m_main_palette[1] = (data & 0xf0) >> 4; |
1025 | | } |
1026 | | break; |
1027 | | case 0x1d: // Palette colors 2 and 3 |
1028 | | // Bit 0-3 - Gray tone setting for main palette index 2 |
1029 | | // Bit 4-7 - Gray tone setting for main palette index 3 |
1030 | | if (m_vdp_type == VDP_TYPE_WSC) |
1031 | | { |
1032 | | int i = 15 - (data & 0x0f); |
1033 | | int j = 15 - ((data & 0xf0) >> 4); |
1034 | | m_main_palette[2] = (i << 8) | (i << 4) | i; |
1035 | | m_main_palette[3] = (j << 8) | (j << 4) | j; |
1036 | | } |
1037 | | else |
1038 | | { |
1039 | | m_main_palette[2] = data & 0x0f; |
1040 | | m_main_palette[3] = (data & 0xf0) >> 4; |
1041 | | } |
1042 | | break; |
1043 | | case 0x1e: // Palette colors 4 and 5 |
1044 | | // Bit 0-3 - Gray tone setting for main palette index 4 |
1045 | | // Bit 4-7 - Gray tone setting for main palette index 5 |
1046 | | if (m_vdp_type == VDP_TYPE_WSC) |
1047 | | { |
1048 | | int i = 15 - (data & 0x0f); |
1049 | | int j = 15 - ((data & 0xf0) >> 4); |
1050 | | m_main_palette[4] = (i << 8) | (i << 4) | i; |
1051 | | m_main_palette[5] = (j << 8) | (j << 4) | j; |
1052 | | } |
1053 | | else |
1054 | | { |
1055 | | m_main_palette[4] = data & 0x0f; |
1056 | | m_main_palette[5] = (data & 0xf0) >> 4; |
1057 | | } |
1058 | | break; |
1059 | | case 0x1f: // Palette colors 6 and 7 |
1060 | | // Bit 0-3 - Gray tone setting for main palette index 6 |
1061 | | // Bit 4-7 - Gray tone setting for main palette index 7 |
1062 | | if (m_vdp_type == VDP_TYPE_WSC) |
1063 | | { |
1064 | | int i = 15 - (data & 0x0f); |
1065 | | int j = 15 - ((data & 0xf0) >> 4); |
1066 | | m_main_palette[6] = (i << 8) | (i << 4) | i; |
1067 | | m_main_palette[7] = (j << 8) | (j << 4) | j; |
1068 | | } |
1069 | | else |
1070 | | { |
1071 | | m_main_palette[6] = data & 0x0f; |
1072 | | m_main_palette[7] = (data & 0xf0) >> 4; |
1073 | | } |
1074 | | break; |
1075 | | case 0x60: // Video mode |
1076 | | // Bit 0-4 - Unknown |
1077 | | // Bit 5 - Packed mode 0 = not packed mode, 1 = packed mode |
1078 | | // Bit 6 - 4/16 colour mode select: 0 = 4 colour mode, 1 = 16 colour mode |
1079 | | // Bit 7 - monochrome/colour mode select: 0 = monochrome mode, 1 = colour mode |
1080 | | /* |
1081 | | * 111 - packed, 16 color, use 4000/8000, color |
1082 | | * 110 - not packed, 16 color, use 4000/8000, color |
1083 | | * 101 - packed, 4 color, use 2000, color |
1084 | | * 100 - not packed, 4 color, use 2000, color |
1085 | | * 011 - packed, 16 color, use 4000/8000, monochrome |
1086 | | * 010 - not packed, 16 color , use 4000/8000, monochrome |
1087 | | * 001 - packed, 4 color, use 2000, monochrome |
1088 | | * 000 - not packed, 4 color, use 2000, monochrome - Regular WS monochrome |
1089 | | */ |
1090 | | if (m_vdp_type == VDP_TYPE_WSC) |
1091 | | { |
1092 | | m_color_mode = data & 0x80; |
1093 | | m_colors_16 = data & 0x40; |
1094 | | m_tile_packed = data & 0x20; |
1095 | | } |
1096 | | break; |
1097 | | case 0xa2: // Timer control |
1098 | | // Bit 0 - HBlank Timer enable |
1099 | | // Bit 1 - HBlank Timer mode: 0 = one shot, 1 = auto reset |
1100 | | // Bit 2 - VBlank Timer(1/75s) enable |
1101 | | // Bit 3 - VBlank Timer mode: 0 = one shot, 1 = auto reset |
1102 | | // Bit 4-7 - Unknown |
1103 | | m_timer_hblank_enable = BIT(data, 0); |
1104 | | m_timer_hblank_mode = BIT(data, 1); |
1105 | | m_timer_vblank_enable = BIT(data, 2); |
1106 | | m_timer_vblank_mode = BIT(data, 3); |
1107 | | break; |
1108 | | case 0xa4: // HBlank timer frequency reload value (bits 0-7) |
1109 | | m_timer_hblank_reload &= 0xff00; |
1110 | | m_timer_hblank_reload += data; |
1111 | | m_timer_hblank_count = m_timer_hblank_reload; |
1112 | | break; |
1113 | | case 0xa5: // HBlank timer frequency reload value (bits 8-15) |
1114 | | m_timer_hblank_reload &= 0xff; |
1115 | | m_timer_hblank_reload += data << 8; |
1116 | | m_timer_hblank_count = m_timer_hblank_reload; |
1117 | | break; |
1118 | | case 0xa6: // VBlank timer frequency reload value (bits 0-7) |
1119 | | m_timer_vblank_reload &= 0xff00; |
1120 | | m_timer_vblank_reload += data; |
1121 | | m_timer_vblank_count = m_timer_vblank_reload; |
1122 | | break; |
1123 | | case 0xa7: // VBlank timer frequency reload value (bits 8-15) |
1124 | | m_timer_vblank_reload &= 0xff; |
1125 | | m_timer_vblank_reload += data << 8; |
1126 | | m_timer_vblank_count = m_timer_vblank_reload; |
1127 | | break; |
1128 | | case 0xa8: // HBlank counter (bits 0-7) |
1129 | | case 0xa9: // HBlank counter (bits 8-15) |
1130 | | case 0xaa: // VBlank counter (bits 0-7) |
1131 | | case 0xab: // VBlank counter (bits 8-15) |
1132 | | break; |
1133 | | } |
1134 | | |
1135 | | m_regs[offset] = data; |
1136 | | } |
1137 | | |
1138 | | |
1139 | | void wswan_video_device::scanline_interrupt() |
1140 | | { |
1141 | | if (m_current_line < 144) |
1142 | | refresh_scanline(); |
1143 | | |
1144 | | // Decrement 12kHz (HBlank) counter |
1145 | | if (m_timer_hblank_enable && m_timer_hblank_reload != 0) |
1146 | | { |
1147 | | m_timer_hblank_count--; |
1148 | | logerror("timer_hblank_count: %X\n", m_timer_hblank_count); |
1149 | | if (m_timer_hblank_count == 0) |
1150 | | { |
1151 | | if (m_timer_hblank_mode) |
1152 | | m_timer_hblank_count = m_timer_hblank_reload; |
1153 | | else |
1154 | | m_timer_hblank_reload = 0; |
1155 | | |
1156 | | logerror( "trigerring hbltmr interrupt\n" ); |
1157 | | m_set_irq_cb(WSWAN_VIDEO_IFLAG_HBLTMR); |
1158 | | } |
1159 | | } |
1160 | | |
1161 | | // Handle Sound DMA |
1162 | | m_snd_dma_cb(); |
1163 | | |
1164 | | // m_current_line = (m_current_line + 1) % 159; |
1165 | | |
1166 | | if (m_current_line == 144) // buffer sprite table |
1167 | | { |
1168 | | memcpy(m_sprite_table_buffer, &m_vram[m_sprite_table_address], 512); |
1169 | | m_sprite_first = m_sprite_first_latch; // always zero? |
1170 | | m_sprite_count = m_sprite_count_latch; |
1171 | | } |
1172 | | |
1173 | | if (m_current_line == 144) |
1174 | | { |
1175 | | m_set_irq_cb(WSWAN_VIDEO_IFLAG_VBL); |
1176 | | /* Decrement 75Hz (VBlank) counter */ |
1177 | | if (m_timer_vblank_enable && m_timer_vblank_reload != 0) |
1178 | | { |
1179 | | m_timer_vblank_count--; |
1180 | | logerror("timer_vblank_count: %X\n", m_timer_vblank_count); |
1181 | | if (m_timer_vblank_count == 0) |
1182 | | { |
1183 | | if (m_timer_vblank_mode) |
1184 | | m_timer_vblank_count = m_timer_vblank_reload; |
1185 | | else |
1186 | | m_timer_vblank_reload = 0; |
1187 | | |
1188 | | logerror("triggering vbltmr interrupt\n"); |
1189 | | m_set_irq_cb(WSWAN_VIDEO_IFLAG_VBLTMR); |
1190 | | } |
1191 | | } |
1192 | | } |
1193 | | |
1194 | | // m_current_line = (m_current_line + 1) % 159; |
1195 | | |
1196 | | if (m_current_line == m_line_compare) |
1197 | | m_set_irq_cb(WSWAN_VIDEO_IFLAG_LCMP); |
1198 | | |
1199 | | m_current_line = (m_current_line + 1) % 159; |
1200 | | } |
1201 | | |
1202 | | |
1203 | | READ8_MEMBER(wswan_video_device::vram_r) |
1204 | | { |
1205 | | return m_vram[offset]; |
1206 | | } |
1207 | | |
1208 | | WRITE8_MEMBER(wswan_video_device::vram_w) |
1209 | | { |
1210 | | m_vram[offset] = data; |
1211 | | } |