src/mame/drivers/megadriv.c
| r9223 | r9224 | |
| 2343 | 2343 | } |
| 2344 | 2344 | } |
| 2345 | 2345 | |
| 2346 | /**********************************************************************************************/ |
| 2347 | // 68k side a15112 |
| 2348 | // FIFO |
| 2349 | /**********************************************************************************************/ |
| 2346 | 2350 | |
| 2351 | static UINT16 fifo_block_a[4]; |
| 2352 | static UINT16 fifo_block_b[4]; |
| 2353 | static UINT16* current_fifo_block; |
| 2354 | static UINT16* current_fifo_readblock; |
| 2355 | int current_fifo_write_pos; |
| 2356 | int current_fifo_read_pos; |
| 2357 | int fifo_block_a_full; |
| 2358 | int fifo_block_b_full; |
| 2347 | 2359 | |
| 2360 | static READ16_HANDLER( _32x_68k_a15112_r) |
| 2361 | { |
| 2362 | printf("read write-only FIFO register\n"); |
| 2363 | return 0; |
| 2364 | } |
| 2365 | |
| 2366 | static WRITE16_HANDLER( _32x_68k_a15112_w ) |
| 2367 | { |
| 2368 | //printf("write to FIFO %04x!\n", data); |
| 2369 | |
| 2370 | if (current_fifo_block==fifo_block_a && fifo_block_a_full) |
| 2371 | { |
| 2372 | printf("attempt to write to Full Fifo block a!\n"); |
| 2373 | return; |
| 2374 | } |
| 2375 | |
| 2376 | if (current_fifo_block==fifo_block_b && fifo_block_b_full) |
| 2377 | { |
| 2378 | printf("attempt to write to Full Fifo block b!\n"); |
| 2379 | return; |
| 2380 | } |
| 2381 | |
| 2382 | current_fifo_block[current_fifo_write_pos] = data; |
| 2383 | current_fifo_write_pos++; |
| 2384 | |
| 2385 | if (current_fifo_write_pos==4) |
| 2386 | { |
| 2387 | if (current_fifo_block==fifo_block_a) |
| 2388 | { |
| 2389 | fifo_block_a_full = 1; |
| 2390 | if (!fifo_block_b_full) |
| 2391 | { |
| 2392 | current_fifo_block = fifo_block_b; |
| 2393 | current_fifo_readblock = fifo_block_a; |
| 2394 | } |
| 2395 | current_fifo_write_pos = 0; |
| 2396 | } |
| 2397 | else |
| 2398 | { |
| 2399 | fifo_block_b_full = 1; |
| 2400 | |
| 2401 | if (!fifo_block_a_full) |
| 2402 | { |
| 2403 | current_fifo_block = fifo_block_a; |
| 2404 | current_fifo_readblock = fifo_block_b; |
| 2405 | } |
| 2406 | |
| 2407 | current_fifo_write_pos = 0; |
| 2408 | } |
| 2409 | } |
| 2410 | } |
| 2411 | |
| 2412 | |
| 2413 | |
| 2348 | 2414 | /* |
| 2349 | 2415 | |
| 2350 | 2416 | 15106 DREQ |
| r9223 | r9224 | |
| 2367 | 2433 | |
| 2368 | 2434 | retval = a15106_reg; |
| 2369 | 2435 | |
| 2370 | | //if (fifo_full) retval |= 0x0080; |
| 2436 | if (fifo_block_a_full && fifo_block_b_full) retval |= 0x8080; |
| 2371 | 2437 | |
| 2372 | 2438 | return retval; |
| 2373 | 2439 | } |
| r9223 | r9224 | |
| 2409 | 2475 | return 0x0000; |
| 2410 | 2476 | } |
| 2411 | 2477 | |
| 2478 | |
| 2412 | 2479 | /**********************************************************************************************/ |
| 2413 | 2480 | // 68k side a15100 |
| 2414 | 2481 | // control register - used to enable 32x etc. |
| r9223 | r9224 | |
| 2910 | 2977 | // 68k To SH2 DReq Length Register |
| 2911 | 2978 | /**********************************************************************************************/ |
| 2912 | 2979 | |
| 2980 | static READ16_HANDLER( _32x_sh2_common_4010_r ) |
| 2981 | { |
| 2982 | // printf("reading DReq Length!\n"); |
| 2983 | return 0x0000; |
| 2984 | } |
| 2985 | |
| 2913 | 2986 | /**********************************************************************************************/ |
| 2914 | 2987 | // SH2 side 4012 |
| 2915 | 2988 | // FIFO Register (read) |
| 2916 | 2989 | /**********************************************************************************************/ |
| 2917 | 2990 | |
| 2991 | static READ16_HANDLER( _32x_sh2_common_4012_r ) |
| 2992 | { |
| 2993 | UINT16 retdat = current_fifo_readblock[current_fifo_read_pos]; |
| 2994 | |
| 2995 | current_fifo_read_pos++; |
| 2996 | |
| 2997 | // printf("reading FIFO!\n"); |
| 2998 | |
| 2999 | if (current_fifo_readblock == fifo_block_a && !fifo_block_a_full) |
| 3000 | printf("Fifo block a isn't filled!\n"); |
| 3001 | |
| 3002 | if (current_fifo_readblock == fifo_block_b && !fifo_block_b_full) |
| 3003 | printf("Fifo block b isn't filled!\n"); |
| 3004 | |
| 3005 | |
| 3006 | if (current_fifo_read_pos==4) |
| 3007 | { |
| 3008 | if (current_fifo_readblock == fifo_block_a) |
| 3009 | { |
| 3010 | fifo_block_a_full = 0; |
| 3011 | |
| 3012 | if (fifo_block_b_full) |
| 3013 | { |
| 3014 | current_fifo_readblock = fifo_block_b; |
| 3015 | current_fifo_block = fifo_block_a; |
| 3016 | } |
| 3017 | |
| 3018 | current_fifo_read_pos = 0; |
| 3019 | } |
| 3020 | else if (current_fifo_readblock == fifo_block_b) |
| 3021 | { |
| 3022 | fifo_block_b_full = 0; |
| 3023 | |
| 3024 | if (fifo_block_a_full) |
| 3025 | { |
| 3026 | current_fifo_readblock = fifo_block_a; |
| 3027 | current_fifo_block = fifo_block_b; |
| 3028 | } |
| 3029 | |
| 3030 | current_fifo_read_pos = 0; |
| 3031 | } |
| 3032 | } |
| 3033 | |
| 3034 | return retdat; |
| 3035 | } |
| 3036 | |
| 3037 | |
| 3038 | |
| 2918 | 3039 | /**********************************************************************************************/ |
| 2919 | 3040 | // SH2 side 4014 |
| 2920 | 3041 | // VRES (md reset button interrupt) clear |
| r9223 | r9224 | |
| 3184 | 3305 | _32X_MAP_RAM_READHANDLERS(commsram) // _32x_sh2_commsram_r |
| 3185 | 3306 | _32X_MAP_RAM_WRITEHANDLERS(commsram) // _32x_sh2_commsram_w |
| 3186 | 3307 | |
| 3308 | _32X_MAP_READHANDLERS(common_4010,common_4012) |
| 3309 | |
| 3187 | 3310 | _32X_MAP_READHANDLERS(common_4100,common_4102) // _32x_sh2_common_4100_common_4102_r |
| 3188 | 3311 | _32X_MAP_WRITEHANDLERS(common_4100,common_4102) // _32x_sh2_common_4100_common_4102_w |
| 3189 | 3312 | |
| 3313 | |
| 3190 | 3314 | _32X_MAP_READHANDLERS(common_4104,common_4106) // _32x_sh2_common_4104_common_4106_r |
| 3191 | 3315 | _32X_MAP_WRITEHANDLERS(common_4104,common_4106) // _32x_sh2_common_4104_common_4106_w |
| 3192 | 3316 | |
| r9223 | r9224 | |
| 3213 | 3337 | |
| 3214 | 3338 | AM_RANGE(0x00004000, 0x00004003) AM_READWRITE( _32x_sh2_master_4000_common_4002_r, _32x_sh2_master_4000_common_4002_w ) |
| 3215 | 3339 | |
| 3340 | AM_RANGE(0x00004010, 0x00004013) AM_READ( _32x_sh2_common_4010_common_4012_r ) |
| 3341 | |
| 3216 | 3342 | AM_RANGE(0x00004014, 0x00004017) AM_WRITE( _32x_sh2_master_4014_master_4016_w ) // IRQ clear |
| 3217 | 3343 | AM_RANGE(0x00004018, 0x0000401b) AM_WRITE( _32x_sh2_master_4018_master_401a_w ) // IRQ clear |
| 3218 | 3344 | AM_RANGE(0x0000401c, 0x0000401f) AM_WRITE( _32x_sh2_master_401c_master_401e_w ) // IRQ clear |
| r9223 | r9224 | |
| 3237 | 3363 | |
| 3238 | 3364 | AM_RANGE(0x00004000, 0x00004003) AM_READWRITE( _32x_sh2_slave_4000_common_4002_r, _32x_sh2_slave_4000_common_4002_w ) |
| 3239 | 3365 | |
| 3366 | AM_RANGE(0x00004010, 0x00004013) AM_READ( _32x_sh2_common_4010_common_4012_r ) |
| 3367 | |
| 3240 | 3368 | AM_RANGE(0x00004014, 0x00004017) AM_WRITE( _32x_sh2_slave_4014_slave_4016_w ) // IRQ clear |
| 3241 | 3369 | AM_RANGE(0x00004018, 0x0000401b) AM_WRITE( _32x_sh2_slave_4018_slave_401a_w ) // IRQ clear |
| 3242 | 3370 | AM_RANGE(0x0000401c, 0x0000401f) AM_WRITE( _32x_sh2_slave_401c_slave_401e_w ) // IRQ clear |
| r9223 | r9224 | |
| 5804 | 5932 | cpu_set_input_line(_segacd_68k_cpu, INPUT_LINE_HALT, ASSERT_LINE); |
| 5805 | 5933 | } |
| 5806 | 5934 | |
| 5935 | current_fifo_block = fifo_block_a; |
| 5936 | current_fifo_readblock = fifo_block_b; |
| 5937 | current_fifo_write_pos = 0; |
| 5938 | current_fifo_read_pos = 0; |
| 5939 | fifo_block_a_full = 0; |
| 5940 | fifo_block_b_full = 0; |
| 5941 | |
| 5807 | 5942 | } |
| 5808 | 5943 | |
| 5809 | 5944 | void megadriv_stop_scanline_timer(void) |
| r9223 | r9224 | |
| 6063 | 6198 | |
| 6064 | 6199 | |
| 6065 | 6200 | |
| 6066 | | static const sh2_cpu_core sh2_conf_master = { 0, NULL }; |
| 6067 | | static const sh2_cpu_core sh2_conf_slave = { 1, NULL }; |
| 6201 | static int _32x_fifo_available_callback(UINT32 src, UINT32 dst, UINT32 data, int size) |
| 6202 | { |
| 6203 | if (src==0x4012) |
| 6204 | { |
| 6205 | if (current_fifo_readblock==fifo_block_a && fifo_block_a_full) |
| 6206 | return 1; |
| 6068 | 6207 | |
| 6208 | if (current_fifo_readblock==fifo_block_b && fifo_block_b_full) |
| 6209 | return 1; |
| 6210 | |
| 6211 | return 0; |
| 6212 | } |
| 6213 | |
| 6214 | return 1; |
| 6215 | } |
| 6216 | |
| 6217 | |
| 6218 | static const sh2_cpu_core sh2_conf_master = { 0, NULL, _32x_fifo_available_callback }; |
| 6219 | static const sh2_cpu_core sh2_conf_slave = { 1, NULL, _32x_fifo_available_callback }; |
| 6220 | |
| 6069 | 6221 | MACHINE_CONFIG_DERIVED( genesis_32x, megadriv ) |
| 6070 | 6222 | |
| 6071 | 6223 | MDRV_CPU_ADD("32x_master_sh2", SH2, (MASTER_CLOCK_NTSC*3)/7 ) |
| r9223 | r9224 | |
| 6378 | 6530 | memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa15104, 0xa15105, 0, 0, _32x_68k_a15104_r, _32x_68k_a15104_w); // 68k BANK rom set |
| 6379 | 6531 | memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa15106, 0xa15107, 0, 0, _32x_68k_a15106_r, _32x_68k_a15106_w); // dreq stuff |
| 6380 | 6532 | |
| 6533 | memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa15112, 0xa15113, 0, 0, _32x_68k_a15112_r, _32x_68k_a15112_w); // fifo |
| 6534 | |
| 6535 | |
| 6381 | 6536 | memory_install_readwrite16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xa15120, 0xa1512f, 0, 0, _32x_68k_commsram_r, _32x_68k_commsram_w); // comms reg 0-7 |
| 6382 | 6537 | |
| 6383 | 6538 | memory_install_read16_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x0a130ec, 0x0a130ef, 0, 0, _32x_68k_MARS_r); // system ID |
src/emu/cpu/sh2/sh2comn.c
| r9223 | r9224 | |
| 133 | 133 | sh2_timer_activate(sh2); |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | | static TIMER_CALLBACK( sh2_dmac_callback ) |
| 136 | |
| 137 | |
| 138 | /* |
| 139 | We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it. |
| 140 | The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most |
| 141 | can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible |
| 142 | because the game is expecting the 68k of the system to feed data into the FIFO at the same |
| 143 | time as the SH2 is transfering it out via DMA |
| 144 | |
| 145 | It might be possible to avoid the timer (which causes a performance hit) by calling this |
| 146 | from the CPU_EXECUTE loop instead when there is active DMA |
| 147 | */ |
| 148 | |
| 149 | static void sh2_do_dma(sh2_state *sh2, int dma) |
| 137 | 150 | { |
| 151 | UINT32 dmadata; |
| 152 | |
| 153 | UINT32 tempsrc, tempdst; |
| 154 | |
| 155 | if (sh2->active_dma_count[dma] > 0) |
| 156 | { |
| 157 | // schedule next DMA callback |
| 158 | timer_adjust_oneshot(sh2->dma_current_active_timer[dma], sh2->device->cycles_to_attotime(2), dma); |
| 159 | |
| 160 | // process current DMA |
| 161 | switch(sh2->active_dma_size[dma]) |
| 162 | { |
| 163 | case 0: |
| 164 | { |
| 165 | // we need to know the src / dest ahead of time without changing them |
| 166 | // to allow for the callback to check if we can process the DMA at this |
| 167 | // time (we need to know where we're reading / writing to/from) |
| 168 | |
| 169 | if(sh2->active_dma_incs[dma] == 2) |
| 170 | tempsrc = sh2->active_dma_src[dma] - 1; |
| 171 | else |
| 172 | tempsrc = sh2->active_dma_src[dma]; |
| 173 | |
| 174 | if(sh2->active_dma_incd[dma] == 2) |
| 175 | tempdst = sh2->active_dma_dst[dma] - 1; |
| 176 | else |
| 177 | tempdst = sh2->active_dma_dst[dma]; |
| 178 | |
| 179 | if (sh2->dma_callback_fifo_data_available) |
| 180 | { |
| 181 | int available = sh2->dma_callback_fifo_data_available(tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 182 | |
| 183 | if (!available) |
| 184 | return; |
| 185 | } |
| 186 | |
| 187 | |
| 188 | dmadata = sh2->program->read_byte(tempsrc); |
| 189 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 190 | sh2->program->write_byte(tempdst, dmadata); |
| 191 | |
| 192 | if(sh2->active_dma_incs[dma] == 2) |
| 193 | sh2->active_dma_src[dma] --; |
| 194 | if(sh2->active_dma_incd[dma] == 2) |
| 195 | sh2->active_dma_dst[dma] --; |
| 196 | |
| 197 | |
| 198 | if(sh2->active_dma_incs[dma] == 1) |
| 199 | sh2->active_dma_src[dma] ++; |
| 200 | if(sh2->active_dma_incd[dma] == 1) |
| 201 | sh2->active_dma_dst[dma] ++; |
| 202 | |
| 203 | sh2->active_dma_count[dma] --; |
| 204 | } |
| 205 | break; |
| 206 | case 1: |
| 207 | { |
| 208 | if(sh2->active_dma_incs[dma] == 2) |
| 209 | tempsrc = sh2->active_dma_src[dma] - 2; |
| 210 | else |
| 211 | tempsrc = sh2->active_dma_src[dma]; |
| 212 | |
| 213 | if(sh2->active_dma_incd[dma] == 2) |
| 214 | tempdst = sh2->active_dma_dst[dma] - 2; |
| 215 | else |
| 216 | tempdst = sh2->active_dma_dst[dma]; |
| 217 | |
| 218 | if (sh2->dma_callback_fifo_data_available) |
| 219 | { |
| 220 | int available = sh2->dma_callback_fifo_data_available(tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 221 | |
| 222 | if (!available) |
| 223 | return; |
| 224 | } |
| 225 | |
| 226 | // check: should this really be using read_word_32 / write_word_32? |
| 227 | dmadata = sh2->program->read_word(tempsrc); |
| 228 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 229 | sh2->program->write_word(tempdst, dmadata); |
| 230 | |
| 231 | if(sh2->active_dma_incs[dma] == 2) |
| 232 | sh2->active_dma_src[dma] -= 2; |
| 233 | if(sh2->active_dma_incd[dma] == 2) |
| 234 | sh2->active_dma_dst[dma] -= 2; |
| 235 | |
| 236 | if(sh2->active_dma_incs[dma] == 1) |
| 237 | sh2->active_dma_src[dma] += 2; |
| 238 | if(sh2->active_dma_incd[dma] == 1) |
| 239 | sh2->active_dma_dst[dma] += 2; |
| 240 | |
| 241 | sh2->active_dma_count[dma] --; |
| 242 | } |
| 243 | break; |
| 244 | case 2: |
| 245 | { |
| 246 | if(sh2->active_dma_incs[dma] == 2) |
| 247 | tempsrc = sh2->active_dma_src[dma] - 4; |
| 248 | else |
| 249 | tempsrc = sh2->active_dma_src[dma]; |
| 250 | |
| 251 | if(sh2->active_dma_incd[dma] == 2) |
| 252 | tempdst = sh2->active_dma_dst[dma] - 4; |
| 253 | else |
| 254 | tempdst = sh2->active_dma_dst[dma]; |
| 255 | |
| 256 | if (sh2->dma_callback_fifo_data_available) |
| 257 | { |
| 258 | int available = sh2->dma_callback_fifo_data_available(tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 259 | |
| 260 | if (!available) |
| 261 | return; |
| 262 | } |
| 263 | |
| 264 | dmadata = sh2->program->read_dword(tempsrc); |
| 265 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 266 | sh2->program->write_dword(tempdst, dmadata); |
| 267 | |
| 268 | if(sh2->active_dma_incs[dma] == 2) |
| 269 | sh2->active_dma_src[dma] -= 4; |
| 270 | if(sh2->active_dma_incd[dma] == 2) |
| 271 | sh2->active_dma_dst[dma] -= 4; |
| 272 | |
| 273 | if(sh2->active_dma_incs[dma] == 1) |
| 274 | sh2->active_dma_src[dma] += 4; |
| 275 | if(sh2->active_dma_incd[dma] == 1) |
| 276 | sh2->active_dma_dst[dma] += 4; |
| 277 | |
| 278 | sh2->active_dma_count[dma] --; |
| 279 | } |
| 280 | break; |
| 281 | case 3: |
| 282 | { |
| 283 | // shouldn't this really be 4 calls here instead? |
| 284 | |
| 285 | tempsrc = sh2->active_dma_src[dma]; |
| 286 | |
| 287 | if(sh2->active_dma_incd[dma] == 2) |
| 288 | tempdst = sh2->active_dma_dst[dma] - 16; |
| 289 | else |
| 290 | tempdst = sh2->active_dma_dst[dma]; |
| 291 | |
| 292 | if (sh2->dma_callback_fifo_data_available) |
| 293 | { |
| 294 | int available = sh2->dma_callback_fifo_data_available(tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 295 | |
| 296 | if (!available) |
| 297 | fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode"); |
| 298 | } |
| 299 | |
| 300 | dmadata = sh2->program->read_dword(tempsrc); |
| 301 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 302 | sh2->program->write_dword(tempdst, dmadata); |
| 303 | |
| 304 | dmadata = sh2->program->read_dword(tempsrc+4); |
| 305 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 306 | sh2->program->write_dword(tempdst+4, dmadata); |
| 307 | |
| 308 | dmadata = sh2->program->read_dword(tempsrc+8); |
| 309 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 310 | sh2->program->write_dword(tempdst+8, dmadata); |
| 311 | |
| 312 | dmadata = sh2->program->read_dword(tempsrc+12); |
| 313 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 314 | sh2->program->write_dword(tempdst+12, dmadata); |
| 315 | |
| 316 | if(sh2->active_dma_incd[dma] == 2) |
| 317 | sh2->active_dma_dst[dma] -= 16; |
| 318 | |
| 319 | sh2->active_dma_src[dma] += 16; |
| 320 | if(sh2->active_dma_incd[dma] == 1) |
| 321 | sh2->active_dma_dst[dma] += 16; |
| 322 | |
| 323 | sh2->active_dma_count[dma]-=4; |
| 324 | } |
| 325 | break; |
| 326 | } |
| 327 | } |
| 328 | else // the dma is complete |
| 329 | { |
| 330 | // int dma = param & 1; |
| 331 | // sh2_state *sh2 = (sh2_state *)ptr; |
| 332 | |
| 333 | LOG(("SH2.%s: DMA %d complete\n", sh2->device->tag(), dma)); |
| 334 | sh2->m[0x63+4*dma] |= 2; |
| 335 | sh2->dma_timer_active[dma] = 0; |
| 336 | sh2_recalc_irq(sh2); |
| 337 | |
| 338 | } |
| 339 | } |
| 340 | |
| 341 | static TIMER_CALLBACK( sh2_dma_current_active_callback ) |
| 342 | { |
| 138 | 343 | int dma = param & 1; |
| 139 | 344 | sh2_state *sh2 = (sh2_state *)ptr; |
| 140 | 345 | |
| 141 | | LOG(("SH2.%s: DMA %d complete\n", sh2->device->tag(), dma)); |
| 142 | | sh2->m[0x63+4*dma] |= 2; |
| 143 | | sh2->dma_timer_active[dma] = 0; |
| 144 | | sh2_recalc_irq(sh2); |
| 346 | sh2_do_dma(sh2, dma); |
| 145 | 347 | } |
| 146 | 348 | |
| 349 | |
| 147 | 350 | static void sh2_dmac_check(sh2_state *sh2, int dma) |
| 148 | 351 | { |
| 149 | 352 | if(sh2->m[0x63+4*dma] & sh2->m[0x6c] & 1) |
| 150 | 353 | { |
| 151 | 354 | if(!sh2->dma_timer_active[dma] && !(sh2->m[0x63+4*dma] & 2)) |
| 152 | 355 | { |
| 153 | | int incs, incd, size; |
| 154 | | UINT32 src, dst, count; |
| 155 | | UINT32 dmadata; |
| 156 | | incd = (sh2->m[0x63+4*dma] >> 14) & 3; |
| 157 | | incs = (sh2->m[0x63+4*dma] >> 12) & 3; |
| 158 | | size = (sh2->m[0x63+4*dma] >> 10) & 3; |
| 159 | | if(incd == 3 || incs == 3) |
| 356 | |
| 357 | sh2->active_dma_incd[dma] = (sh2->m[0x63+4*dma] >> 14) & 3; |
| 358 | sh2->active_dma_incs[dma] = (sh2->m[0x63+4*dma] >> 12) & 3; |
| 359 | sh2->active_dma_size[dma] = (sh2->m[0x63+4*dma] >> 10) & 3; |
| 360 | if(sh2->active_dma_incd[dma] == 3 || sh2->active_dma_incs[dma] == 3) |
| 160 | 361 | { |
| 161 | | logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, sh2->m[0x63+4*dma]); |
| 362 | logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", sh2->active_dma_incd[dma], sh2->active_dma_incs[dma], sh2->active_dma_size[dma], sh2->m[0x63+4*dma]); |
| 162 | 363 | return; |
| 163 | 364 | } |
| 164 | | src = sh2->m[0x60+4*dma]; |
| 165 | | dst = sh2->m[0x61+4*dma]; |
| 166 | | count = sh2->m[0x62+4*dma]; |
| 167 | | if(!count) |
| 168 | | count = 0x1000000; |
| 365 | sh2->active_dma_src[dma] = sh2->m[0x60+4*dma]; |
| 366 | sh2->active_dma_dst[dma] = sh2->m[0x61+4*dma]; |
| 367 | sh2->active_dma_count[dma] = sh2->m[0x62+4*dma]; |
| 368 | if(!sh2->active_dma_count[dma]) |
| 369 | sh2->active_dma_count[dma] = 0x1000000; |
| 169 | 370 | |
| 170 | | LOG(("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, src, dst, count, sh2->m[0x63+4*dma], incs, incd, size)); |
| 371 | LOG(("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, sh2->active_dma_src[dma], sh2->active_dma_dst[dma], sh2->active_dma_count[dma], sh2->m[0x63+4*dma], sh2->active_dma_incs[dma], sh2->active_dma_incd[dma], sh2->active_dma_size[dma])); |
| 171 | 372 | |
| 172 | 373 | sh2->dma_timer_active[dma] = 1; |
| 173 | | timer_adjust_oneshot(sh2->dma_timer[dma], sh2->device->cycles_to_attotime(2*count+1), dma); |
| 174 | 374 | |
| 175 | | src &= AM; |
| 176 | | dst &= AM; |
| 375 | sh2->active_dma_src[dma] &= AM; |
| 376 | sh2->active_dma_dst[dma] &= AM; |
| 177 | 377 | |
| 178 | | switch(size) |
| 378 | switch(sh2->active_dma_size[dma]) |
| 179 | 379 | { |
| 180 | 380 | case 0: |
| 181 | | for(;count > 0; count --) |
| 182 | | { |
| 183 | | if(incs == 2) |
| 184 | | src --; |
| 185 | | if(incd == 2) |
| 186 | | dst --; |
| 187 | | |
| 188 | | dmadata = sh2->program->read_byte(src); |
| 189 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 190 | | sh2->program->write_byte(dst, dmadata); |
| 191 | | |
| 192 | | if(incs == 1) |
| 193 | | src ++; |
| 194 | | if(incd == 1) |
| 195 | | dst ++; |
| 196 | | } |
| 197 | 381 | break; |
| 198 | 382 | case 1: |
| 199 | | src &= ~1; |
| 200 | | dst &= ~1; |
| 201 | | for(;count > 0; count --) |
| 202 | | { |
| 203 | | |
| 204 | | if(incs == 2) |
| 205 | | src -= 2; |
| 206 | | if(incd == 2) |
| 207 | | dst -= 2; |
| 208 | | |
| 209 | | // check: should this really be using read_word_32 / write_word_32? |
| 210 | | dmadata = sh2->program->read_word(src); |
| 211 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 212 | | sh2->program->write_word(dst, dmadata); |
| 213 | | |
| 214 | | if(incs == 1) |
| 215 | | src += 2; |
| 216 | | if(incd == 1) |
| 217 | | dst += 2; |
| 218 | | } |
| 383 | sh2->active_dma_src[dma] &= ~1; |
| 384 | sh2->active_dma_dst[dma] &= ~1; |
| 219 | 385 | break; |
| 220 | 386 | case 2: |
| 221 | | src &= ~3; |
| 222 | | dst &= ~3; |
| 223 | | for(;count > 0; count --) |
| 224 | | { |
| 225 | | if(incs == 2) |
| 226 | | src -= 4; |
| 227 | | if(incd == 2) |
| 228 | | dst -= 4; |
| 229 | | |
| 230 | | dmadata = sh2->program->read_dword(src); |
| 231 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 232 | | sh2->program->write_dword(dst, dmadata); |
| 233 | | |
| 234 | | if(incs == 1) |
| 235 | | src += 4; |
| 236 | | if(incd == 1) |
| 237 | | dst += 4; |
| 238 | | |
| 239 | | } |
| 387 | sh2->active_dma_src[dma] &= ~3; |
| 388 | sh2->active_dma_dst[dma] &= ~3; |
| 240 | 389 | break; |
| 241 | 390 | case 3: |
| 242 | | src &= ~3; |
| 243 | | dst &= ~3; |
| 244 | | count &= ~3; |
| 245 | | for(;count > 0; count -= 4) |
| 246 | | { |
| 247 | | if(incd == 2) |
| 248 | | dst -= 16; |
| 391 | sh2->active_dma_src[dma] &= ~3; |
| 392 | sh2->active_dma_dst[dma] &= ~3; |
| 393 | sh2->active_dma_count[dma] &= ~3; |
| 394 | break; |
| 395 | } |
| 249 | 396 | |
| 250 | | dmadata = sh2->program->read_dword(src); |
| 251 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 252 | | sh2->program->write_dword(dst, dmadata); |
| 397 | // start DMA timer |
| 398 | timer_adjust_oneshot(sh2->dma_current_active_timer[dma], sh2->device->cycles_to_attotime(2), dma); |
| 253 | 399 | |
| 254 | | dmadata = sh2->program->read_dword(src+4); |
| 255 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 256 | | sh2->program->write_dword(dst+4, dmadata); |
| 257 | 400 | |
| 258 | | dmadata = sh2->program->read_dword(src+8); |
| 259 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 260 | | sh2->program->write_dword(dst+8, dmadata); |
| 261 | | |
| 262 | | dmadata = sh2->program->read_dword(src+12); |
| 263 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 264 | | sh2->program->write_dword(dst+12, dmadata); |
| 265 | | |
| 266 | | src += 16; |
| 267 | | if(incd == 1) |
| 268 | | dst += 16; |
| 269 | | } |
| 270 | | break; |
| 271 | | } |
| 272 | 401 | } |
| 273 | 402 | } |
| 274 | 403 | else |
| r9223 | r9224 | |
| 276 | 405 | if(sh2->dma_timer_active[dma]) |
| 277 | 406 | { |
| 278 | 407 | logerror("SH2: DMA %d cancelled in-flight\n", dma); |
| 279 | | timer_adjust_oneshot(sh2->dma_timer[dma], attotime_never, 0); |
| 408 | //timer_adjust_oneshot(sh2->dma_complete_timer[dma], attotime_never, 0); |
| 409 | timer_adjust_oneshot(sh2->dma_current_active_timer[dma], attotime_never, 0); |
| 410 | |
| 280 | 411 | sh2->dma_timer_active[dma] = 0; |
| 281 | 412 | } |
| 282 | 413 | } |
| r9223 | r9224 | |
| 707 | 838 | sh2->timer = timer_alloc(device->machine, sh2_timer_callback, sh2); |
| 708 | 839 | timer_adjust_oneshot(sh2->timer, attotime_never, 0); |
| 709 | 840 | |
| 710 | | sh2->dma_timer[0] = timer_alloc(device->machine, sh2_dmac_callback, sh2); |
| 711 | | timer_adjust_oneshot(sh2->dma_timer[0], attotime_never, 0); |
| 841 | sh2->dma_current_active_timer[0] = timer_alloc(device->machine, sh2_dma_current_active_callback, sh2); |
| 842 | timer_adjust_oneshot(sh2->dma_current_active_timer[0], attotime_never, 0); |
| 712 | 843 | |
| 713 | | sh2->dma_timer[1] = timer_alloc(device->machine, sh2_dmac_callback, sh2); |
| 714 | | timer_adjust_oneshot(sh2->dma_timer[1], attotime_never, 0); |
| 844 | sh2->dma_current_active_timer[1] = timer_alloc(device->machine, sh2_dma_current_active_callback, sh2); |
| 845 | timer_adjust_oneshot(sh2->dma_current_active_timer[1], attotime_never, 0); |
| 715 | 846 | |
| 847 | |
| 716 | 848 | sh2->m = auto_alloc_array(device->machine, UINT32, 0x200/4); |
| 717 | 849 | |
| 718 | 850 | if(conf) |
| 719 | 851 | { |
| 720 | 852 | sh2->is_slave = conf->is_slave; |
| 721 | 853 | sh2->dma_callback_kludge = conf->dma_callback_kludge; |
| 854 | sh2->dma_callback_fifo_data_available = conf->dma_callback_fifo_data_available; |
| 722 | 855 | } |
| 723 | 856 | else |
| 724 | 857 | { |
| 725 | 858 | sh2->is_slave = 0; |
| 726 | 859 | sh2->dma_callback_kludge = NULL; |
| 860 | sh2->dma_callback_fifo_data_available = NULL; |
| 727 | 861 | |
| 728 | 862 | } |
| 729 | 863 | sh2->irq_callback = irqcallback; |