trunk/src/emu/video/mb_vcu.c
| r26023 | r26024 | |
| 4 | 4 | |
| 5 | 5 | Device for Mazer Blazer/Great Guns custom Video Controller Unit |
| 6 | 6 | |
| 7 | Written by Angelo Salese, based off old implementation by Jarek Burczynski |
| 8 | |
| 9 | TODO: |
| 10 | - understand what exactly modes 0x03 and 0x13 really reads in set_clr() and |
| 11 | where it puts results (yeah, shared VCU RAM, but exactly where?). Almost |
| 12 | surely Mazer Blazer tries to read the pixel data for collision detection and |
| 13 | Great Guns read backs VRAM for VCU test (patched for now, btw). |
| 14 | - Understand look-up tables in i/o space. |
| 15 | - Understand how to handle layer clearance. |
| 16 | - Understand how planes are really handled. |
| 17 | - Understand how transparent pens are handled (is 0x0f always transparent or |
| 18 | there's some clut gimmick? Great Guns title screen makes me think of the |
| 19 | latter option) |
| 20 | |
| 7 | 21 | ***************************************************************************/ |
| 8 | 22 | |
| 9 | 23 | #include "emu.h" |
| r26023 | r26024 | |
| 22 | 36 | AM_RANGE(0x00000,0x7ffff) AM_RAM // enough for a 256x256x4 x 2 pages of framebuffer with 4 layers (TODO: doubled for simplicity) |
| 23 | 37 | ADDRESS_MAP_END |
| 24 | 38 | |
| 39 | |
| 40 | static ADDRESS_MAP_START( mb_vcu_pal_ram, AS_1, 8, mb_vcu_device ) |
| 41 | AM_RANGE(0x0000, 0x00ff) AM_RAM |
| 42 | AM_RANGE(0x0200, 0x02ff) AM_RAM |
| 43 | AM_RANGE(0x0400, 0x04ff) AM_RAM |
| 44 | AM_RANGE(0x0600, 0x06ff) AM_WRITE(mb_vcu_paletteram_w) |
| 45 | ADDRESS_MAP_END |
| 46 | |
| 47 | WRITE8_MEMBER( mb_vcu_device::mb_vcu_paletteram_w ) |
| 48 | { |
| 49 | int r,g,b, bit0, bit1, bit2; |
| 50 | |
| 51 | UINT8 colour = data; |
| 52 | |
| 53 | /* red component */ |
| 54 | bit1 = (colour >> 7) & 0x01; |
| 55 | bit0 = (colour >> 6) & 0x01; |
| 56 | r = combine_2_weights(m_weights_r, bit0, bit1); |
| 57 | |
| 58 | /* green component */ |
| 59 | bit2 = (colour >> 5) & 0x01; |
| 60 | bit1 = (colour >> 4) & 0x01; |
| 61 | bit0 = (colour >> 3) & 0x01; |
| 62 | g = combine_3_weights(m_weights_g, bit0, bit1, bit2); |
| 63 | |
| 64 | /* blue component */ |
| 65 | bit2 = (colour >> 2) & 0x01; |
| 66 | bit1 = (colour >> 1) & 0x01; |
| 67 | bit0 = (colour >> 0) & 0x01; |
| 68 | b = combine_3_weights(m_weights_b, bit0, bit1, bit2); |
| 69 | |
| 70 | palette_set_color(machine(), offset, MAKE_RGB(r, g, b)); |
| 71 | } |
| 72 | |
| 25 | 73 | //------------------------------------------------- |
| 26 | 74 | // memory_space_config - return a description of |
| 27 | 75 | // any address spaces owned by this device |
| r26023 | r26024 | |
| 29 | 77 | |
| 30 | 78 | const address_space_config *mb_vcu_device::memory_space_config(address_spacenum spacenum) const |
| 31 | 79 | { |
| 32 | | return (spacenum == AS_0) ? &m_space_config : NULL; |
| 80 | switch (spacenum) |
| 81 | { |
| 82 | case AS_0: return &m_videoram_space_config; |
| 83 | case AS_1: return &m_paletteram_space_config; |
| 84 | default: return NULL; |
| 85 | } |
| 33 | 86 | } |
| 34 | 87 | |
| 35 | 88 | //************************************************************************** |
| r26023 | r26024 | |
| 40 | 93 | // read_byte - read a byte at the given address |
| 41 | 94 | //------------------------------------------------- |
| 42 | 95 | |
| 43 | | inline UINT16 mb_vcu_device::read_byte(offs_t address) |
| 96 | inline UINT8 mb_vcu_device::read_byte(offs_t address) |
| 44 | 97 | { |
| 45 | | return space().read_byte(address); |
| 98 | return space(AS_0).read_byte(address); |
| 46 | 99 | } |
| 47 | 100 | |
| 48 | 101 | //------------------------------------------------- |
| 49 | | // write_word - write a word at the given address |
| 102 | // write_byte - write a byte at the given address |
| 50 | 103 | //------------------------------------------------- |
| 51 | 104 | |
| 52 | 105 | inline void mb_vcu_device::write_byte(offs_t address, UINT8 data) |
| 53 | 106 | { |
| 54 | | space().write_byte(address, data); |
| 107 | space(AS_0).write_byte(address, data); |
| 55 | 108 | } |
| 56 | 109 | |
| 110 | //------------------------------------------------- |
| 111 | // read_byte - read a byte at the given i/o |
| 112 | //------------------------------------------------- |
| 113 | |
| 114 | inline UINT8 mb_vcu_device::read_io(offs_t address) |
| 115 | { |
| 116 | return space(AS_1).read_byte(address); |
| 117 | } |
| 118 | |
| 119 | //------------------------------------------------- |
| 120 | // write_byte - write a byte at the given i/o |
| 121 | //------------------------------------------------- |
| 122 | |
| 123 | inline void mb_vcu_device::write_io(offs_t address, UINT8 data) |
| 124 | { |
| 125 | space(AS_1).write_byte(address, data); |
| 126 | } |
| 127 | |
| 128 | |
| 57 | 129 | //************************************************************************** |
| 58 | 130 | // LIVE DEVICE |
| 59 | 131 | //************************************************************************** |
| r26023 | r26024 | |
| 66 | 138 | : device_t(mconfig, MB_VCU, "Mazer Blazer custom VCU", tag, owner, clock, "mb_vcu", __FILE__), |
| 67 | 139 | device_memory_interface(mconfig, *this), |
| 68 | 140 | device_video_interface(mconfig, *this), |
| 69 | | m_space_config("videoram", ENDIANNESS_LITTLE, 8, 19, 0, NULL, *ADDRESS_MAP_NAME(mb_vcu_vram)) |
| 141 | m_videoram_space_config("videoram", ENDIANNESS_LITTLE, 8, 19, 0, NULL, *ADDRESS_MAP_NAME(mb_vcu_vram)), |
| 142 | m_paletteram_space_config("palram", ENDIANNESS_LITTLE, 8, 16, 0, NULL, *ADDRESS_MAP_NAME(mb_vcu_pal_ram)) |
| 70 | 143 | { |
| 71 | 144 | } |
| 72 | 145 | |
| r26023 | r26024 | |
| 256 | 329 | if(dstx >= 0 && dsty >= 0 && dstx < 256 && dsty < 256) |
| 257 | 330 | { |
| 258 | 331 | dot = m_cpu->space(AS_PROGRAM).read_byte(((offset + (bits >> 3)) & 0x1fff) + 0x4000) >> (6-(bits & 7)); |
| 259 | | dot&= 3; |
| 260 | 332 | |
| 261 | | switch(dot) |
| 333 | switch(dot & 3) |
| 262 | 334 | { |
| 263 | 335 | case 0: |
| 264 | 336 | pen = m_color1 & 0xf; |
| r26023 | r26024 | |
| 292 | 364 | return 0; // open bus? |
| 293 | 365 | } |
| 294 | 366 | |
| 367 | /* |
| 368 | ---0 -111 (0x07) write to i/o? |
| 369 | ---0 -011 (0x03) read to i/o? |
| 370 | ---1 -011 (0x13) read to vram? |
| 371 | */ |
| 295 | 372 | READ8_MEMBER( mb_vcu_device::load_set_clr ) |
| 296 | 373 | { |
| 297 | 374 | int xi,yi; |
| r26023 | r26024 | |
| 355 | 432 | break; |
| 356 | 433 | |
| 357 | 434 | case 0x07: |
| 358 | | switch(m_ypos) |
| 359 | | { |
| 360 | | case 6: |
| 361 | | int r,g,b, bit0, bit1, bit2; |
| 435 | for(int i=0;i<m_pix_xsize;i++) |
| 436 | write_io(i+(m_ypos<<8),m_ram[offset + i]); |
| 362 | 437 | |
| 363 | | for(int i=0;i<m_pix_xsize;i++) |
| 364 | | { |
| 365 | | UINT8 colour = m_ram[offset + i]; |
| 366 | | /* red component */ |
| 367 | | bit1 = (colour >> 7) & 0x01; |
| 368 | | bit0 = (colour >> 6) & 0x01; |
| 369 | | r = combine_2_weights(m_weights_r, bit0, bit1); |
| 370 | | |
| 371 | | /* green component */ |
| 372 | | bit2 = (colour >> 5) & 0x01; |
| 373 | | bit1 = (colour >> 4) & 0x01; |
| 374 | | bit0 = (colour >> 3) & 0x01; |
| 375 | | g = combine_3_weights(m_weights_g, bit0, bit1, bit2); |
| 376 | | |
| 377 | | /* blue component */ |
| 378 | | bit2 = (colour >> 2) & 0x01; |
| 379 | | bit1 = (colour >> 1) & 0x01; |
| 380 | | bit0 = (colour >> 0) & 0x01; |
| 381 | | b = combine_3_weights(m_weights_b, bit0, bit1, bit2); |
| 382 | | |
| 383 | | palette_set_color(machine(), i, MAKE_RGB(r, g, b)); |
| 384 | | } |
| 385 | | break; |
| 386 | | } |
| 387 | 438 | break; |
| 388 | 439 | } |
| 389 | 440 | |