trunk/src/mess/machine/wswan.c
r241555 | r241556 | |
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::wswan_handle_irqs() |
| 81 | void wswan_state::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::wswan_set_irq_line(int irq) |
| 121 | void wswan_state::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 | | wswan_handle_irqs(); |
| 126 | handle_irqs(); |
127 | 127 | } |
128 | 128 | } |
129 | 129 | |
130 | | void wswan_state::wswan_clear_irq_line(int irq) |
| 130 | void wswan_state::dma_sound_cb() |
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 | { |
132 | 148 | m_ws_portram[0xb6] &= ~irq; |
133 | | wswan_handle_irqs(); |
| 149 | handle_irqs(); |
134 | 150 | } |
135 | 151 | |
136 | | void wswan_state::wswan_register_save() |
| 152 | void wswan_state::register_save() |
137 | 153 | { |
138 | 154 | save_item(NAME(m_ws_portram)); |
139 | 155 | save_item(NAME(m_internal_eeprom)); |
140 | 156 | save_item(NAME(m_bios_disabled)); |
141 | 157 | save_item(NAME(m_rotate)); |
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 | | |
| 158 | |
182 | 159 | save_item(NAME(m_sound_dma.source)); |
183 | 160 | save_item(NAME(m_sound_dma.size)); |
184 | 161 | save_item(NAME(m_sound_dma.enable)); |
185 | | |
| 162 | |
186 | 163 | if (m_cart->exists()) |
187 | 164 | m_cart->save_nvram(); |
188 | | |
189 | | machine().save().register_postload(save_prepost_delegate(FUNC(wswan_state::wswan_postload), this)); |
190 | 165 | } |
191 | 166 | |
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 | | |
200 | 167 | void wswan_state::common_start() |
201 | 168 | { |
202 | 169 | m_ws_bios_bank = auto_alloc_array(machine(), UINT8, 0x10000); |
203 | 170 | memcpy(m_ws_bios_bank + 0xffc0, ws_fake_bios_code, 0x40); |
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 | | |
| 171 | |
| 172 | register_save(); |
| 173 | |
210 | 174 | machine().device<nvram_device>("nvram")->set_base(m_internal_eeprom, INTERNAL_EEPROM_SIZE); |
211 | | |
| 175 | |
212 | 176 | if (m_cart->exists()) |
213 | 177 | { |
214 | 178 | // ROM |
215 | 179 | 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)); |
216 | 180 | 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)); |
217 | 181 | 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)); |
218 | | |
| 182 | |
219 | 183 | // SRAM |
220 | 184 | if (m_cart->get_type() == WS_SRAM) |
221 | 185 | { |
r241555 | r241556 | |
231 | 195 | m_system_type = TYPE_WSWAN; |
232 | 196 | } |
233 | 197 | |
234 | | MACHINE_START_MEMBER(wswan_state,wscolor) |
| 198 | MACHINE_START_MEMBER(wswan_state, wscolor) |
235 | 199 | { |
236 | 200 | common_start(); |
237 | 201 | m_system_type = TYPE_WSC; |
r241555 | r241556 | |
239 | 203 | |
240 | 204 | void wswan_state::machine_reset() |
241 | 205 | { |
242 | | address_space &space = m_maincpu->space(AS_PROGRAM); |
243 | | |
244 | 206 | m_bios_disabled = 0; |
245 | | |
246 | | m_ws_ram = (UINT8*) m_maincpu->space(AS_PROGRAM).get_read_ptr(0); |
247 | | memset(m_ws_ram, 0, 0xffff); |
248 | | |
| 207 | |
249 | 208 | if (m_cart->exists()) |
250 | 209 | m_rotate = m_cart->get_is_rotated(); |
251 | 210 | else |
252 | 211 | m_rotate = 0; |
253 | | |
| 212 | |
254 | 213 | /* Intialize ports */ |
255 | 214 | memcpy(m_ws_portram, ws_portram_init, 256); |
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 | | |
| 215 | |
267 | 216 | render_target *target = machine().render().first_target(); |
268 | 217 | target->set_view(m_rotate); |
269 | | |
| 218 | |
270 | 219 | /* Initialize sound DMA */ |
271 | 220 | memset(&m_sound_dma, 0, sizeof(m_sound_dma)); |
272 | 221 | } |
r241555 | r241556 | |
282 | 231 | READ8_MEMBER( wswan_state::port_r ) |
283 | 232 | { |
284 | 233 | UINT8 value = m_ws_portram[offset]; |
285 | | |
| 234 | |
286 | 235 | if (offset != 2) |
287 | 236 | 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 | |
288 | 241 | switch (offset) |
289 | 242 | { |
290 | | case 0x02: // Current line |
291 | | value = m_vdp.current_line; |
292 | | break; |
293 | 243 | case 0x4a: // Sound DMA source address (low) |
294 | 244 | value = m_sound_dma.source & 0xff; |
295 | 245 | break; |
r241555 | r241556 | |
308 | 258 | case 0x52: // Sound DMA start/stop |
309 | 259 | value = m_sound_dma.enable; |
310 | 260 | break; |
| 261 | case 0x60: |
| 262 | value = m_vdp->reg_r(space, offset); |
| 263 | break; |
311 | 264 | case 0xa0: // Hardware type |
312 | | // Bit 0 - Disable/enable Bios |
313 | | // Bit 1 - Determine mono/color |
314 | | // Bit 2 - Determine color/crystal |
| 265 | // Bit 0 - Disable/enable Bios |
| 266 | // Bit 1 - Determine mono/color |
| 267 | // Bit 2 - Determine color/crystal |
315 | 268 | value = value & ~ 0x02; |
316 | 269 | if (m_system_type == TYPE_WSC) |
317 | 270 | value |= 2; |
318 | 271 | 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; |
331 | 272 | case 0xc0: |
332 | 273 | case 0xc1: |
333 | 274 | case 0xc2: |
r241555 | r241556 | |
347 | 288 | value = m_cart->read_io(space, offset & 0x0f); |
348 | 289 | break; |
349 | 290 | } |
350 | | |
| 291 | |
351 | 292 | return value; |
352 | 293 | } |
353 | 294 | |
r241555 | r241556 | |
356 | 297 | address_space &mem = m_maincpu->space(AS_PROGRAM); |
357 | 298 | UINT8 input; |
358 | 299 | 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 | |
359 | 307 | switch (offset) |
360 | 308 | { |
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; |
638 | 309 | case 0x40: /* DMA source address (low) |
639 | | Bit 0-7 - DMA source address bit 0-7 |
640 | | */ |
| 310 | Bit 0-7 - DMA source address bit 0-7 |
| 311 | */ |
641 | 312 | case 0x41: /* DMA source address (high) |
642 | | Bit 0-7 - DMA source address bit 8-15 |
643 | | */ |
| 313 | Bit 0-7 - DMA source address bit 8-15 |
| 314 | */ |
644 | 315 | case 0x42: /* DMA source bank |
645 | | Bit 0-7 - DMA source bank number |
646 | | */ |
| 316 | Bit 0-7 - DMA source bank number |
| 317 | */ |
647 | 318 | case 0x43: /* DMA destination bank |
648 | | Bit 0-7 - DMA destination bank number |
649 | | */ |
| 319 | Bit 0-7 - DMA destination bank number |
| 320 | */ |
650 | 321 | case 0x44: /* DMA destination address (low) |
651 | | Bit 0-7 - DMA destination address bit 0-7 |
652 | | */ |
| 322 | Bit 0-7 - DMA destination address bit 0-7 |
| 323 | */ |
653 | 324 | case 0x45: /* DMA destination address (high) |
654 | | Bit 0-7 - DMA destination address bit 8-15 |
655 | | */ |
| 325 | Bit 0-7 - DMA destination address bit 8-15 |
| 326 | */ |
656 | 327 | case 0x46: /* Size of copied data (low) |
657 | | Bit 0-7 - DMA size bit 0-7 |
658 | | */ |
| 328 | Bit 0-7 - DMA size bit 0-7 |
| 329 | */ |
659 | 330 | case 0x47: /* Size of copied data (high) |
660 | | Bit 0-7 - DMA size bit 8-15 |
661 | | */ |
| 331 | Bit 0-7 - DMA size bit 8-15 |
| 332 | */ |
662 | 333 | break; |
663 | 334 | case 0x48: /* DMA control |
664 | | Bit 0-6 - Unknown |
665 | | Bit 7 - DMA stop/start |
666 | | */ |
| 335 | Bit 0-6 - Unknown |
| 336 | Bit 7 - DMA stop/start |
| 337 | */ |
667 | 338 | if (data & 0x80) |
668 | 339 | { |
669 | 340 | UINT32 src, dst; |
670 | 341 | UINT16 length; |
671 | | |
| 342 | |
672 | 343 | src = m_ws_portram[0x40] + (m_ws_portram[0x41] << 8) + (m_ws_portram[0x42] << 16); |
673 | 344 | dst = m_ws_portram[0x44] + (m_ws_portram[0x45] << 8) + (m_ws_portram[0x43] << 16); |
674 | 345 | length = m_ws_portram[0x46] + (m_ws_portram[0x47] << 8); |
r241555 | r241556 | |
679 | 350 | dst++; |
680 | 351 | } |
681 | 352 | #ifdef MAME_DEBUG |
682 | | logerror("DMA src:%X dst:%X length:%d\n", src, dst, length); |
| 353 | logerror("DMA src:%X dst:%X length:%d\n", src, dst, length); |
683 | 354 | #endif |
684 | 355 | m_ws_portram[0x40] = src & 0xff; |
685 | 356 | m_ws_portram[0x41] = (src >> 8) & 0xff; |
r241555 | r241556 | |
691 | 362 | } |
692 | 363 | break; |
693 | 364 | case 0x4a: /* Sound DMA source address (low) |
694 | | Bit 0-7 - Sound DMA source address bit 0-7 |
695 | | */ |
| 365 | Bit 0-7 - Sound DMA source address bit 0-7 |
| 366 | */ |
696 | 367 | m_sound_dma.source = (m_sound_dma.source & 0x0fff00) | data; |
697 | 368 | break; |
698 | 369 | case 0x4b: /* Sound DMA source address (high) |
699 | | Bit 0-7 - Sound DMA source address bit 8-15 |
700 | | */ |
| 370 | Bit 0-7 - Sound DMA source address bit 8-15 |
| 371 | */ |
701 | 372 | m_sound_dma.source = (m_sound_dma.source & 0x0f00ff) | (data << 8); |
702 | 373 | break; |
703 | 374 | case 0x4c: /* Sound DMA source memory segment |
704 | | Bit 0-3 - Sound DMA source address segment |
705 | | Bit 4-7 - Unknown |
706 | | */ |
| 375 | Bit 0-3 - Sound DMA source address segment |
| 376 | Bit 4-7 - Unknown |
| 377 | */ |
707 | 378 | m_sound_dma.source = (m_sound_dma.source & 0xffff) | ((data & 0x0f) << 16); |
708 | 379 | break; |
709 | 380 | case 0x4d: /* Unknown */ |
710 | 381 | break; |
711 | 382 | case 0x4e: /* Sound DMA transfer size (low) |
712 | | Bit 0-7 - Sound DMA transfer size bit 0-7 |
713 | | */ |
| 383 | Bit 0-7 - Sound DMA transfer size bit 0-7 |
| 384 | */ |
714 | 385 | m_sound_dma.size = (m_sound_dma.size & 0xff00) | data; |
715 | 386 | break; |
716 | 387 | case 0x4f: /* Sound DMA transfer size (high) |
717 | | Bit 0-7 - Sound DMA transfer size bit 8-15 |
718 | | */ |
| 388 | Bit 0-7 - Sound DMA transfer size bit 8-15 |
| 389 | */ |
719 | 390 | m_sound_dma.size = (m_sound_dma.size & 0xff) | (data << 8); |
720 | 391 | break; |
721 | 392 | case 0x50: /* Unknown */ |
722 | 393 | case 0x51: /* Unknown */ |
723 | 394 | break; |
724 | 395 | case 0x52: /* Sound DMA start/stop |
725 | | Bit 0-6 - Unknown |
726 | | Bit 7 - Sound DMA stop/start |
727 | | */ |
| 396 | Bit 0-6 - Unknown |
| 397 | Bit 7 - Sound DMA stop/start |
| 398 | */ |
728 | 399 | m_sound_dma.enable = data; |
729 | 400 | break; |
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 | | } |
| 401 | case 0x60: |
| 402 | m_vdp->reg_w(space, offset, data); |
752 | 403 | break; |
753 | 404 | case 0x80: /* Audio 1 freq (lo) |
754 | | Bit 0-7 - Audio channel 1 frequency bit 0-7 |
755 | | */ |
| 405 | Bit 0-7 - Audio channel 1 frequency bit 0-7 |
| 406 | */ |
756 | 407 | case 0x81: /* Audio 1 freq (hi) |
757 | | Bit 0-7 - Audio channel 1 frequency bit 8-15 |
758 | | */ |
| 408 | Bit 0-7 - Audio channel 1 frequency bit 8-15 |
| 409 | */ |
759 | 410 | case 0x82: /* Audio 2 freq (lo) |
760 | | Bit 0-7 - Audio channel 2 frequency bit 0-7 |
761 | | */ |
| 411 | Bit 0-7 - Audio channel 2 frequency bit 0-7 |
| 412 | */ |
762 | 413 | case 0x83: /* Audio 2 freq (hi) |
763 | | Bit 0-7 - Audio channel 2 frequency bit 8-15 |
764 | | */ |
| 414 | Bit 0-7 - Audio channel 2 frequency bit 8-15 |
| 415 | */ |
765 | 416 | case 0x84: /* Audio 3 freq (lo) |
766 | | Bit 0-7 - Audio channel 3 frequency bit 0-7 |
767 | | */ |
| 417 | Bit 0-7 - Audio channel 3 frequency bit 0-7 |
| 418 | */ |
768 | 419 | case 0x85: /* Audio 3 freq (hi) |
769 | | Bit 0-7 - Audio channel 3 frequency bit 8-15 |
770 | | */ |
| 420 | Bit 0-7 - Audio channel 3 frequency bit 8-15 |
| 421 | */ |
771 | 422 | case 0x86: /* Audio 4 freq (lo) |
772 | | Bit 0-7 - Audio channel 4 frequency bit 0-7 |
773 | | */ |
| 423 | Bit 0-7 - Audio channel 4 frequency bit 0-7 |
| 424 | */ |
774 | 425 | case 0x87: /* Audio 4 freq (hi) |
775 | | Bit 0-7 - Audio channel 4 frequency bit 8-15 |
776 | | */ |
| 426 | Bit 0-7 - Audio channel 4 frequency bit 8-15 |
| 427 | */ |
777 | 428 | case 0x88: /* Audio 1 volume |
778 | | Bit 0-3 - Right volume audio channel 1 |
779 | | Bit 4-7 - Left volume audio channel 1 |
780 | | */ |
| 429 | Bit 0-3 - Right volume audio channel 1 |
| 430 | Bit 4-7 - Left volume audio channel 1 |
| 431 | */ |
781 | 432 | case 0x89: /* Audio 2 volume |
782 | | Bit 0-3 - Right volume audio channel 2 |
783 | | Bit 4-7 - Left volume audio channel 2 |
784 | | */ |
| 433 | Bit 0-3 - Right volume audio channel 2 |
| 434 | Bit 4-7 - Left volume audio channel 2 |
| 435 | */ |
785 | 436 | case 0x8a: /* Audio 3 volume |
786 | | Bit 0-3 - Right volume audio channel 3 |
787 | | Bit 4-7 - Left volume audio channel 3 |
788 | | */ |
| 437 | Bit 0-3 - Right volume audio channel 3 |
| 438 | Bit 4-7 - Left volume audio channel 3 |
| 439 | */ |
789 | 440 | case 0x8b: /* Audio 4 volume |
790 | | Bit 0-3 - Right volume audio channel 4 |
791 | | Bit 4-7 - Left volume audio channel 4 |
792 | | */ |
| 441 | Bit 0-3 - Right volume audio channel 4 |
| 442 | Bit 4-7 - Left volume audio channel 4 |
| 443 | */ |
793 | 444 | case 0x8c: /* Sweep step |
794 | | Bit 0-7 - Sweep step |
795 | | */ |
| 445 | Bit 0-7 - Sweep step |
| 446 | */ |
796 | 447 | case 0x8d: /* Sweep time |
797 | | Bit 0-7 - Sweep time |
798 | | */ |
| 448 | Bit 0-7 - Sweep time |
| 449 | */ |
799 | 450 | case 0x8e: /* Noise control |
800 | | Bit 0-2 - Noise generator type |
801 | | Bit 3 - Reset |
802 | | Bit 4 - Enable |
803 | | Bit 5-7 - Unknown |
804 | | */ |
| 451 | Bit 0-2 - Noise generator type |
| 452 | Bit 3 - Reset |
| 453 | Bit 4 - Enable |
| 454 | Bit 5-7 - Unknown |
| 455 | */ |
805 | 456 | case 0x8f: /* Sample location |
806 | | Bit 0-7 - Sample address location 0 00xxxxxx xx000000 |
807 | | */ |
| 457 | Bit 0-7 - Sample address location 0 00xxxxxx xx000000 |
| 458 | */ |
808 | 459 | case 0x90: /* Audio control |
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 | | */ |
| 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 | */ |
818 | 469 | case 0x91: /* Audio output |
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 | | */ |
| 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 | */ |
825 | 476 | case 0x92: /* Noise counter shift register (lo) |
826 | | Bit 0-7 - Noise counter shift register bit 0-7 |
827 | | */ |
| 477 | Bit 0-7 - Noise counter shift register bit 0-7 |
| 478 | */ |
828 | 479 | case 0x93: /* Noise counter shift register (hi) |
829 | | Bit 0-6 - Noise counter shift register bit 8-14 |
830 | | bit 7 - Unknown |
831 | | */ |
| 480 | Bit 0-6 - Noise counter shift register bit 8-14 |
| 481 | bit 7 - Unknown |
| 482 | */ |
832 | 483 | case 0x94: /* Master volume |
833 | | Bit 0-3 - Master volume |
834 | | Bit 4-7 - Unknown |
835 | | */ |
| 484 | Bit 0-3 - Master volume |
| 485 | Bit 4-7 - Unknown |
| 486 | */ |
836 | 487 | m_sound->port_w(space, offset, data); |
837 | 488 | break; |
838 | 489 | case 0xa0: /* Hardware type - this is probably read only |
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 | | */ |
| 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 | */ |
843 | 494 | if ((data & 0x01) && !m_bios_disabled) |
844 | 495 | m_bios_disabled = 1; |
845 | 496 | break; |
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 | | |
| 497 | |
900 | 498 | case 0xb0: /* Interrupt base vector |
901 | | Bit 0-7 - Interrupt base vector |
902 | | */ |
| 499 | Bit 0-7 - Interrupt base vector |
| 500 | */ |
903 | 501 | break; |
904 | 502 | case 0xb1: /* Communication byte |
905 | | Bit 0-7 - Communication byte |
906 | | */ |
| 503 | Bit 0-7 - Communication byte |
| 504 | */ |
907 | 505 | break; |
908 | 506 | case 0xb2: /* Interrupt enable |
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 | | */ |
| 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 | */ |
918 | 516 | break; |
919 | 517 | case 0xb3: /* serial communication control |
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; |
| 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; |
929 | 527 | m_ws_portram[0xb1] = 0xff; |
930 | 528 | if (data & 0x80) |
931 | 529 | { |
932 | | // m_ws_portram[0xb1] = 0x00; |
| 530 | // m_ws_portram[0xb1] = 0x00; |
933 | 531 | data |= 0x04; |
934 | 532 | } |
935 | 533 | if (data & 0x20) |
936 | 534 | { |
937 | | // data |= 0x01; |
| 535 | // data |= 0x01; |
938 | 536 | } |
939 | 537 | break; |
940 | 538 | case 0xb5: /* Read controls |
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 | | */ |
| 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 | */ |
948 | 546 | data = data & 0xf0; |
949 | 547 | switch (data) |
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; |
| 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; |
962 | 560 | break; |
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; |
| 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; |
974 | 572 | break; |
975 | | case 0x40: /* Read buttons: START - A - B */ |
976 | | data = data | m_buttons->read(); |
| 573 | case 0x40: /* Read buttons: START - A - B */ |
| 574 | data = data | m_buttons->read(); |
977 | 575 | break; |
978 | | } |
| 576 | } |
979 | 577 | break; |
980 | 578 | case 0xb6: /* Interrupt acknowledge |
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); |
| 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); |
991 | 589 | data = m_ws_portram[0xb6]; |
992 | 590 | break; |
993 | 591 | case 0xba: /* Internal EEPROM data (low) |
994 | | Bit 0-7 - Internal EEPROM data transfer bit 0-7 |
995 | | */ |
| 592 | Bit 0-7 - Internal EEPROM data transfer bit 0-7 |
| 593 | */ |
996 | 594 | case 0xbb: /* Internal EEPROM data (high) |
997 | | Bit 0-7 - Internal EEPROM data transfer bit 8-15 |
998 | | */ |
| 595 | Bit 0-7 - Internal EEPROM data transfer bit 8-15 |
| 596 | */ |
999 | 597 | break; |
1000 | 598 | case 0xbc: /* Internal EEPROM address (low) |
1001 | | Bit 0-7 - Internal EEPROM address bit 1-8 |
1002 | | */ |
| 599 | Bit 0-7 - Internal EEPROM address bit 1-8 |
| 600 | */ |
1003 | 601 | case 0xbd: /* Internal EEPROM address (high) |
1004 | | Bit 0 - Internal EEPROM address bit 9(?) |
1005 | | Bit 1-7 - Unknown |
1006 | | Only 1KByte internal EEPROM?? |
1007 | | */ |
| 602 | Bit 0 - Internal EEPROM address bit 9(?) |
| 603 | Bit 1-7 - Unknown |
| 604 | Only 1KByte internal EEPROM?? |
| 605 | */ |
1008 | 606 | break; |
1009 | 607 | case 0xbe: /* Internal EEPROM command |
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 | | */ |
| 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 | */ |
1018 | 616 | if (data & 0x20) |
1019 | 617 | { |
1020 | 618 | UINT16 addr = ( ( ( m_ws_portram[0xbd] << 8 ) | m_ws_portram[0xbc] ) << 1 ) & 0x1FF; |
r241555 | r241556 | |
1056 | 654 | logerror( "Write to unsupported port: %X - %X\n", offset, data ); |
1057 | 655 | break; |
1058 | 656 | } |
1059 | | |
| 657 | |
1060 | 658 | /* Update the port value */ |
1061 | 659 | m_ws_portram[offset] = data; |
1062 | 660 | } |
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
r241555 | r241556 | |
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
r0 | r241556 | |
| 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 | } |