trunk/src/emu/machine/seibu_cop.c
| r18224 | r18225 | |
| 20 | 20 | |
| 21 | 21 | |
| 22 | 22 | static ADDRESS_MAP_START( seibu_cop_io, AS_0, 16, seibu_cop_device ) |
| 23 | | AM_RANGE(0x0428, 0x0429) AM_WRITE(dma_fill_val_lo_w) |
| 24 | | AM_RANGE(0x042a, 0x042b) AM_WRITE(dma_fill_val_hi_w) |
| 23 | AM_RANGE(0x0428, 0x0429) AM_WRITE(fill_val_lo_w) |
| 24 | AM_RANGE(0x042a, 0x042b) AM_WRITE(fill_val_hi_w) |
| 25 | 25 | |
| 26 | 26 | AM_RANGE(0x045a, 0x045b) AM_WRITE(pal_brightness_val_w) |
| 27 | 27 | AM_RANGE(0x045c, 0x045d) AM_WRITE(pal_brightness_mode_w) |
| r18224 | r18225 | |
| 91 | 91 | // or initialize to defaults if none provided |
| 92 | 92 | else |
| 93 | 93 | { |
| 94 | | memset(&m_in_mreq_cb, 0, sizeof(m_in_mreq_cb)); |
| 95 | | memset(&m_out_mreq_cb, 0, sizeof(m_out_mreq_cb)); |
| 94 | memset(&m_in_byte_cb, 0, sizeof(m_in_byte_cb)); |
| 95 | memset(&m_in_word_cb, 0, sizeof(m_in_word_cb)); |
| 96 | memset(&m_in_dword_cb, 0, sizeof(m_in_dword_cb)); |
| 97 | memset(&m_out_byte_cb, 0, sizeof(m_out_byte_cb)); |
| 98 | memset(&m_out_word_cb, 0, sizeof(m_out_word_cb)); |
| 99 | memset(&m_out_dword_cb, 0, sizeof(m_out_dword_cb)); |
| 96 | 100 | } |
| 97 | 101 | } |
| 98 | 102 | |
| r18224 | r18225 | |
| 112 | 116 | |
| 113 | 117 | void seibu_cop_device::device_start() |
| 114 | 118 | { |
| 119 | // resolve callbacks |
| 120 | m_in_byte_func.resolve(m_in_byte_cb, *this); |
| 121 | m_in_word_func.resolve(m_in_word_cb, *this); |
| 122 | m_in_word_func.resolve(m_in_dword_cb, *this); |
| 123 | m_out_byte_func.resolve(m_out_byte_cb, *this); |
| 124 | m_out_word_func.resolve(m_out_word_cb, *this); |
| 125 | m_out_dword_func.resolve(m_out_dword_cb, *this); |
| 115 | 126 | |
| 116 | 127 | } |
| 117 | 128 | |
| r18224 | r18225 | |
| 138 | 149 | // READ/WRITE HANDLERS |
| 139 | 150 | //************************************************************************** |
| 140 | 151 | |
| 141 | | WRITE16_MEMBER(seibu_cop_device::dma_fill_val_lo_w) |
| 152 | WRITE16_MEMBER(seibu_cop_device::fill_val_lo_w) |
| 142 | 153 | { |
| 143 | | COMBINE_DATA(&m_dma_fill_val_lo); |
| 144 | | m_dma_fill_val = (m_dma_fill_val_lo) | (m_dma_fill_val_hi << 16); |
| 154 | COMBINE_DATA(&m_fill_val_lo); |
| 155 | m_fill_val = (m_fill_val_lo) | (m_fill_val_hi << 16); |
| 145 | 156 | } |
| 146 | 157 | |
| 147 | | WRITE16_MEMBER(seibu_cop_device::dma_fill_val_hi_w) |
| 158 | WRITE16_MEMBER(seibu_cop_device::fill_val_hi_w) |
| 148 | 159 | { |
| 149 | | COMBINE_DATA(&m_dma_fill_val_hi); |
| 150 | | m_dma_fill_val = (m_dma_fill_val_lo) | (m_dma_fill_val_hi << 16); |
| 160 | COMBINE_DATA(&m_fill_val_hi); |
| 161 | m_fill_val = (m_fill_val_lo) | (m_fill_val_hi << 16); |
| 151 | 162 | } |
| 152 | 163 | |
| 153 | 164 | WRITE16_MEMBER(seibu_cop_device::pal_brightness_val_w) |
| r18224 | r18225 | |
| 204 | 215 | m_dma_trigger = m_dma_exec_param & 7; |
| 205 | 216 | } |
| 206 | 217 | |
| 218 | //************************************************************************** |
| 219 | // READ/WRITE HANDLERS (device to CPU / CPU to device) |
| 220 | //************************************************************************** |
| 221 | |
| 207 | 222 | READ16_MEMBER( seibu_cop_device::read ) |
| 208 | 223 | { |
| 209 | 224 | return read_word(offset + (0x400/2)); |
| r18224 | r18225 | |
| 213 | 228 | { |
| 214 | 229 | write_word(offset + (0x400/2),data); |
| 215 | 230 | } |
| 231 | |
| 232 | void seibu_cop_device::normal_dma_transfer(void) |
| 233 | { |
| 234 | UINT32 src,dst,size,i; |
| 235 | |
| 236 | src = (m_dma_src[m_dma_trigger] << 6); |
| 237 | dst = (m_dma_dst[m_dma_trigger] << 6); |
| 238 | size = ((m_dma_size[m_dma_trigger] << 5) - (m_dma_dst[m_dma_trigger] << 6) + 0x20)/2; |
| 239 | |
| 240 | for(i = 0;i < size;i++) |
| 241 | { |
| 242 | m_out_word_func(dst, m_in_word_func(src)); |
| 243 | src+=2; |
| 244 | dst+=2; |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | /* RE from Seibu Cup Soccer bootleg */ |
| 249 | const UINT8 seibu_cop_device::fade_table(int v) |
| 250 | { |
| 251 | int low = v & 0x001f; |
| 252 | int high = v & 0x03e0; |
| 253 | |
| 254 | return (low * (high | (high >> 5)) + 0x210) >> 10; |
| 255 | } |
| 256 | |
| 257 | void seibu_cop_device::palette_dma_transfer(void) |
| 258 | { |
| 259 | UINT32 src,dst,size,i; |
| 260 | |
| 261 | /* |
| 262 | Apparently all of those are just different DMA channels, brightness effects are done through a RAM table and the pal_brightness_val / mode |
| 263 | 0x80 is used by Legionnaire |
| 264 | 0x81 is used by SD Gundam and Godzilla |
| 265 | 0x82 is used by Zero Team and X Se Dae |
| 266 | 0x86 is used by Seibu Cup Soccer |
| 267 | 0x87 is used by Denjin Makai |
| 268 | |
| 269 | TODO: |
| 270 | - Denjin Makai mode 4 is totally guessworked. |
| 271 | - SD Gundam doesn't fade colors correctly, it should have the text layer / sprites with normal gradient and the rest dimmed in most cases, |
| 272 | presumably bad RAM table or bad algorithm |
| 273 | */ |
| 274 | |
| 275 | src = (m_dma_src[m_dma_trigger] << 6); |
| 276 | dst = (m_dma_dst[m_dma_trigger] << 6); |
| 277 | size = ((m_dma_size[m_dma_trigger] << 5) - (m_dma_dst[m_dma_trigger] << 6) + 0x20)/2; |
| 278 | |
| 279 | //printf("SRC: %08x %08x DST:%08x SIZE:%08x TRIGGER: %08x %02x %02x\n",cop_dma_src[cop_dma_trigger] << 6,cop_dma_fade_table * 0x400,cop_dma_dst[cop_dma_trigger] << 6,cop_dma_size[cop_dma_trigger] << 5,cop_dma_trigger,pal_brightness_val,pal_brightness_mode); |
| 280 | |
| 281 | for(i = 0;i < size;i++) |
| 282 | { |
| 283 | UINT16 pal_val; |
| 284 | int r,g,b; |
| 285 | int rt,gt,bt; |
| 286 | |
| 287 | if(m_pal_brightness_mode == 5) |
| 288 | { |
| 289 | bt = ((m_in_word_func(src + (m_dma_pal_fade_table * 0x400))) & 0x7c00) >> 5; |
| 290 | bt = fade_table(bt|(m_pal_brightness_val ^ 0)); |
| 291 | b = ((m_in_word_func(src)) & 0x7c00) >> 5; |
| 292 | b = fade_table(b|(m_pal_brightness_val ^ 0x1f)); |
| 293 | pal_val = ((b + bt) & 0x1f) << 10; |
| 294 | gt = ((m_in_word_func(src + (m_dma_pal_fade_table * 0x400))) & 0x03e0); |
| 295 | gt = fade_table(gt|(m_pal_brightness_val ^ 0)); |
| 296 | g = ((m_in_word_func(src)) & 0x03e0); |
| 297 | g = fade_table(g|(m_pal_brightness_val ^ 0x1f)); |
| 298 | pal_val |= ((g + gt) & 0x1f) << 5; |
| 299 | rt = ((m_in_word_func(src + (m_dma_pal_fade_table * 0x400))) & 0x001f) << 5; |
| 300 | rt = fade_table(rt|(m_pal_brightness_val ^ 0)); |
| 301 | r = ((m_in_word_func(src)) & 0x001f) << 5; |
| 302 | r = fade_table(r|(m_pal_brightness_val ^ 0x1f)); |
| 303 | pal_val |= ((r + rt) & 0x1f); |
| 304 | } |
| 305 | else if(m_pal_brightness_mode == 4) //Denjin Makai |
| 306 | { |
| 307 | bt =(m_in_word_func(src + (m_dma_pal_fade_table * 0x400)) & 0x7c00) >> 10; |
| 308 | b = (m_in_word_func(src) & 0x7c00) >> 10; |
| 309 | gt =(m_in_word_func(src + (m_dma_pal_fade_table * 0x400)) & 0x03e0) >> 5; |
| 310 | g = (m_in_word_func(src) & 0x03e0) >> 5; |
| 311 | rt =(m_in_word_func(src + (m_dma_pal_fade_table * 0x400)) & 0x001f) >> 0; |
| 312 | r = (m_in_word_func(src) & 0x001f) >> 0; |
| 313 | |
| 314 | if(m_pal_brightness_val == 0x10) |
| 315 | pal_val = bt << 10 | gt << 5 | rt << 0; |
| 316 | else if(m_pal_brightness_val == 0xff) // TODO: might be the back plane or it still doesn't do any mod, needs PCB tests |
| 317 | pal_val = 0; |
| 318 | else |
| 319 | { |
| 320 | bt = fade_table(bt<<5|((m_pal_brightness_val*2) ^ 0)); |
| 321 | b = fade_table(b<<5|((m_pal_brightness_val*2) ^ 0x1f)); |
| 322 | pal_val = ((b + bt) & 0x1f) << 10; |
| 323 | gt = fade_table(gt<<5|((m_pal_brightness_val*2) ^ 0)); |
| 324 | g = fade_table(g<<5|((m_pal_brightness_val*2) ^ 0x1f)); |
| 325 | pal_val |= ((g + gt) & 0x1f) << 5; |
| 326 | rt = fade_table(rt<<5|((m_pal_brightness_val*2) ^ 0)); |
| 327 | r = fade_table(r<<5|((m_pal_brightness_val*2) ^ 0x1f)); |
| 328 | pal_val |= ((r + rt) & 0x1f); |
| 329 | } |
| 330 | } |
| 331 | else |
| 332 | { |
| 333 | printf("Seibu COP: palette DMA used with mode %02x!\n",m_pal_brightness_mode); |
| 334 | pal_val = m_in_word_func(src); |
| 335 | } |
| 336 | |
| 337 | m_out_word_func(dst, pal_val); |
| 338 | src+=2; |
| 339 | dst+=2; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | void seibu_cop_device::fill_word_transfer(void) |
| 344 | { |
| 345 | UINT32 length, address; |
| 346 | int i; |
| 347 | |
| 348 | //if(cop_dma_dst[cop_dma_trigger] != 0x0000) // Invalid? |
| 349 | // return; |
| 350 | |
| 351 | address = (m_dma_src[m_dma_trigger] << 6); |
| 352 | length = ((m_dma_size[m_dma_trigger]+1) << 4); |
| 353 | |
| 354 | for (i=address;i<address+length;i+=4) |
| 355 | { |
| 356 | m_out_dword_func(i, m_fill_val); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | void seibu_cop_device::fill_dword_transfer(void) |
| 361 | { |
| 362 | UINT32 length, address; |
| 363 | int i; |
| 364 | if(m_dma_dst[m_dma_trigger] != 0x0000) // Invalid? TODO: log & check this |
| 365 | return; |
| 366 | |
| 367 | address = (m_dma_src[m_dma_trigger] << 6); |
| 368 | length = (m_dma_size[m_dma_trigger]+1) << 5; |
| 369 | |
| 370 | //printf("%08x %08x\n",address,length); |
| 371 | |
| 372 | for (i=address;i<address+length;i+=4) |
| 373 | { |
| 374 | m_out_dword_func(i, m_fill_val); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | WRITE16_MEMBER( seibu_cop_device::dma_write_trigger_w ) |
| 379 | { |
| 380 | switch(m_dma_exec_param & 0x1f8) |
| 381 | { |
| 382 | case 0x008: normal_dma_transfer(); break; |
| 383 | case 0x010: break; // private buffer copy, TODO |
| 384 | case 0x080: palette_dma_transfer(); break; |
| 385 | case 0x110: fill_word_transfer(); break; // Godzilla uses this |
| 386 | case 0x118: fill_dword_transfer(); break; |
| 387 | default: |
| 388 | logerror("Seibu COP: used unemulated DMA type %04x\n",m_dma_exec_param); |
| 389 | } |
| 390 | } |
trunk/src/emu/machine/seibu_cop.h
| r18224 | r18225 | |
| 25 | 25 | struct seibu_cop_interface |
| 26 | 26 | { |
| 27 | 27 | // memory accessors |
| 28 | | devcb_read8 m_in_mreq_cb; |
| 29 | | devcb_write8 m_out_mreq_cb; |
| 28 | devcb_read16 m_in_byte_cb; |
| 29 | devcb_read16 m_in_word_cb; |
| 30 | devcb_read16 m_in_dword_cb; |
| 31 | devcb_write16 m_out_byte_cb; |
| 32 | devcb_write16 m_out_word_cb; |
| 33 | devcb_write16 m_out_dword_cb; |
| 30 | 34 | }; |
| 31 | 35 | |
| 32 | 36 | |
| r18224 | r18225 | |
| 47 | 51 | // I/O operations |
| 48 | 52 | DECLARE_WRITE16_MEMBER( write ); |
| 49 | 53 | DECLARE_READ16_MEMBER( read ); |
| 50 | | DECLARE_WRITE16_MEMBER(dma_fill_val_lo_w); |
| 51 | | DECLARE_WRITE16_MEMBER(dma_fill_val_hi_w); |
| 54 | DECLARE_WRITE16_MEMBER( dma_write_trigger_w ); |
| 55 | DECLARE_WRITE16_MEMBER(fill_val_lo_w); |
| 56 | DECLARE_WRITE16_MEMBER(fill_val_hi_w); |
| 52 | 57 | DECLARE_WRITE16_MEMBER(pal_brightness_val_w); |
| 53 | 58 | DECLARE_WRITE16_MEMBER(pal_brightness_mode_w); |
| 54 | 59 | DECLARE_WRITE16_MEMBER(dma_unk_param_w); |
| r18224 | r18225 | |
| 67 | 72 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const; |
| 68 | 73 | |
| 69 | 74 | private: |
| 70 | | devcb_resolved_read8 m_in_mreq_func; |
| 71 | | devcb_resolved_write8 m_out_mreq_func; |
| 75 | devcb_resolved_read16 m_in_byte_func; |
| 76 | devcb_resolved_read16 m_in_word_func; |
| 77 | devcb_resolved_read16 m_in_dword_func; |
| 78 | devcb_resolved_write16 m_out_byte_func; |
| 79 | devcb_resolved_write16 m_out_word_func; |
| 80 | devcb_resolved_write16 m_out_dword_func; |
| 72 | 81 | inline UINT16 read_word(offs_t address); |
| 73 | 82 | inline void write_word(offs_t address, UINT16 data); |
| 74 | 83 | |
| 75 | 84 | UINT16 m_dma_unk_param, m_dma_pal_fade_table, m_dma_src[8], m_dma_dst[8], m_dma_size[8], m_dma_exec_param; |
| 76 | 85 | UINT8 m_dma_trigger; |
| 77 | | UINT16 m_dma_fill_val_lo,m_dma_fill_val_hi; |
| 78 | | UINT32 m_dma_fill_val; |
| 86 | UINT16 m_fill_val_lo,m_fill_val_hi; |
| 87 | UINT32 m_fill_val; |
| 79 | 88 | UINT16 m_pal_brightness_val, m_pal_brightness_mode; |
| 80 | 89 | |
| 81 | 90 | const address_space_config m_space_config; |
| 91 | |
| 92 | const UINT8 fade_table(int v); |
| 93 | void normal_dma_transfer(void); |
| 94 | void palette_dma_transfer(void); |
| 95 | void fill_word_transfer(void); |
| 96 | void fill_dword_transfer(void); |
| 82 | 97 | }; |
| 83 | 98 | |
| 84 | 99 | |