src/emu/sound/asc.c
| r9431 | r9432 | |
| 4 | 4 | |
| 5 | 5 | Apple Sound Chip (ASC) 344S0063 |
| 6 | 6 | Enhanced Apple Sound Chip (EASC) 343S1063 |
| 7 | | |
| 7 | |
| 8 | 8 | Emulation by R. Belmont |
| 9 | 9 | |
| 10 | 10 | Registers: |
| r9431 | r9432 | |
| 101 | 101 | // LIVE DEVICE |
| 102 | 102 | //************************************************************************** |
| 103 | 103 | |
| 104 | // does nothing, this timer exists only to make MAME sync itself at our audio rate |
| 105 | static TIMER_CALLBACK( sync_timer_cb ) |
| 106 | { |
| 107 | asc_device *pDevice = (asc_device *)ptr; |
| 108 | |
| 109 | stream_update(pDevice->m_stream); |
| 110 | } |
| 111 | |
| 104 | 112 | //------------------------------------------------- |
| 105 | 113 | // asc_device - constructor |
| 106 | 114 | //------------------------------------------------- |
| r9431 | r9432 | |
| 125 | 133 | m_stream = stream_create(this, 0, 2, 22257, this, static_stream_generate); |
| 126 | 134 | |
| 127 | 135 | memset(m_regs, 0, sizeof(m_regs)); |
| 136 | |
| 137 | m_sync_timer = timer_alloc(this->machine, sync_timer_cb, this); |
| 128 | 138 | } |
| 129 | 139 | |
| 130 | 140 | |
| r9431 | r9432 | |
| 190 | 200 | m_fifo_a_rdptr &= 0x3ff; |
| 191 | 201 | m_fifo_cap_a--; |
| 192 | 202 | } |
| 193 | | |
| 203 | |
| 194 | 204 | if (m_fifo_cap_b) |
| 195 | 205 | { |
| 196 | 206 | m_fifo_b_rdptr++; |
| r9431 | r9432 | |
| 198 | 208 | m_fifo_cap_b--; |
| 199 | 209 | } |
| 200 | 210 | |
| 201 | | if ((m_fifo_cap_a) || (m_fifo_cap_b)) |
| 211 | switch (m_chip_type) |
| 202 | 212 | { |
| 203 | | switch (m_chip_type) |
| 204 | | { |
| 205 | | case ASC_TYPE_SONORA: |
| 206 | | if (m_fifo_cap_a <= 0x200) |
| 213 | case ASC_TYPE_SONORA: |
| 214 | if (m_fifo_cap_a < 0x200) |
| 215 | { |
| 216 | m_regs[R_FIFOSTAT-0x800] |= 0x4; // fifo less than half full |
| 217 | m_regs[R_FIFOSTAT-0x800] |= 0x8; // just pass the damn test |
| 218 | if (m_irq_cb) |
| 207 | 219 | { |
| 208 | | m_regs[R_FIFOSTAT-0x800] |= 0x4; // fifo less than half full |
| 209 | | m_regs[R_FIFOSTAT-0x800] |= 0x8; // just pass the damn test |
| 210 | | if (m_irq_cb) |
| 211 | | { |
| 212 | | m_irq_cb(this, 1); |
| 213 | | } |
| 220 | m_irq_cb(this, 1); |
| 214 | 221 | } |
| 215 | | break; |
| 222 | } |
| 223 | break; |
| 216 | 224 | |
| 217 | | default: |
| 218 | | if (m_fifo_cap_a <= 0x200) |
| 225 | default: |
| 226 | if (m_fifo_cap_a == 0x1ff) |
| 227 | { |
| 228 | m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A half-empty |
| 229 | if (m_irq_cb) |
| 219 | 230 | { |
| 220 | | m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A half-empty |
| 221 | | if (m_irq_cb) |
| 222 | | { |
| 223 | | m_irq_cb(this, 1); |
| 224 | | } |
| 231 | m_irq_cb(this, 1); |
| 225 | 232 | } |
| 233 | } |
| 234 | else if (m_fifo_cap_a == 0x1) // fifo A fully empty |
| 235 | { |
| 236 | m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A empty |
| 237 | if (m_irq_cb) |
| 238 | { |
| 239 | m_irq_cb(this, 1); |
| 240 | } |
| 241 | } |
| 226 | 242 | |
| 227 | | // don't update for non-(E)ASC |
| 228 | | if (m_fifo_cap_b <= 0x200) |
| 243 | if (m_fifo_cap_b == 0x1ff) |
| 244 | { |
| 245 | m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B half-empty |
| 246 | if (m_irq_cb) |
| 229 | 247 | { |
| 230 | | m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B half-empty |
| 231 | | if (m_irq_cb) |
| 232 | | { |
| 233 | | m_irq_cb(this, 1); |
| 234 | | } |
| 248 | m_irq_cb(this, 1); |
| 235 | 249 | } |
| 236 | | break; |
| 237 | | } |
| 250 | } |
| 251 | else if (m_fifo_cap_b == 0x1) // fifo B fully empty |
| 252 | { |
| 253 | m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B empty |
| 254 | if (m_irq_cb) |
| 255 | { |
| 256 | m_irq_cb(this, 1); |
| 257 | } |
| 258 | } |
| 259 | break; |
| 238 | 260 | } |
| 239 | 261 | |
| 240 | 262 | outL[i] = smpll * 64; |
| r9431 | r9432 | |
| 249 | 271 | INT8 smpl; |
| 250 | 272 | |
| 251 | 273 | mixL = mixR = 0; |
| 252 | | |
| 274 | |
| 253 | 275 | // update channel pointers |
| 254 | 276 | for (ch = 0; ch < 4; ch++) |
| 255 | 277 | { |
| r9431 | r9432 | |
| 274 | 296 | } |
| 275 | 297 | break; |
| 276 | 298 | } |
| 299 | |
| 300 | // printf("rdA %04x rdB %04x wrA %04x wrB %04x (capA %04x B %04x)\n", m_fifo_a_rdptr, m_fifo_b_rdptr, m_fifo_a_wrptr, m_fifo_b_wrptr, m_fifo_cap_a, m_fifo_cap_b); |
| 277 | 301 | } |
| 278 | 302 | |
| 279 | 303 | //------------------------------------------------- |
| r9431 | r9432 | |
| 284 | 308 | { |
| 285 | 309 | UINT8 rv; |
| 286 | 310 | |
| 287 | | // printf("ASC: read at %x\n", offset); |
| 311 | // printf("ASC: read at %x\n", offset); |
| 288 | 312 | |
| 289 | 313 | // not sure what actually happens when the CPU reads the FIFO... |
| 290 | 314 | if (offset < 0x400) |
| r9431 | r9432 | |
| 358 | 382 | rv = m_regs[R_FIFOSTAT-0x800]; |
| 359 | 383 | } |
| 360 | 384 | |
| 385 | // printf("Read FIFO stat = %02x\n", rv); |
| 386 | |
| 361 | 387 | // reading this register clears all bits |
| 362 | 388 | m_regs[R_FIFOSTAT-0x800] = 0; |
| 363 | 389 | |
| 364 | | // reading this clears interrupts? |
| 390 | // reading this clears interrupts |
| 365 | 391 | if (m_irq_cb) |
| 366 | 392 | { |
| 367 | 393 | m_irq_cb(this, 0); |
| r9431 | r9432 | |
| 416 | 442 | |
| 417 | 443 | void asc_device::write(UINT16 offset, UINT8 data) |
| 418 | 444 | { |
| 419 | | // printf("ASC: write %02x to %x\n", data, offset); |
| 445 | // printf("ASC: write %02x to %x\n", data, offset); |
| 420 | 446 | |
| 421 | 447 | if (offset < 0x400) |
| 422 | 448 | { |
| r9431 | r9432 | |
| 425 | 451 | m_fifo_a[m_fifo_a_wrptr++] = data; |
| 426 | 452 | m_fifo_cap_a++; |
| 427 | 453 | |
| 428 | | if (m_fifo_cap_a == 0x800) |
| 454 | if (m_fifo_cap_a == 0x3ff) |
| 429 | 455 | { |
| 430 | 456 | m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A full |
| 431 | 457 | } |
| r9431 | r9432 | |
| 444 | 470 | m_fifo_b[m_fifo_b_wrptr++] = data; |
| 445 | 471 | m_fifo_cap_b++; |
| 446 | 472 | |
| 447 | | if (m_fifo_cap_b == 0x800) |
| 473 | if (m_fifo_cap_b == 0x3ff) |
| 448 | 474 | { |
| 449 | 475 | m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B full |
| 450 | 476 | } |
| 451 | 477 | |
| 452 | 478 | m_fifo_b_wrptr &= 0x3ff; |
| 453 | | } |
| 479 | } |
| 454 | 480 | else |
| 455 | 481 | { |
| 456 | 482 | m_fifo_b[offset-0x400] = data; |
| r9431 | r9432 | |
| 458 | 484 | } |
| 459 | 485 | else |
| 460 | 486 | { |
| 461 | | // printf("ASC: %02x to %x (was %x)\n", data, offset, m_regs[offset-0x800]); |
| 487 | // printf("ASC: %02x to %x (was %x)\n", data, offset, m_regs[offset-0x800]); |
| 462 | 488 | |
| 463 | 489 | stream_update(m_stream); |
| 464 | 490 | switch (offset) |
| r9431 | r9432 | |
| 471 | 497 | m_fifo_a_rdptr = m_fifo_b_rdptr = 0; |
| 472 | 498 | m_fifo_a_wrptr = m_fifo_b_wrptr = 0; |
| 473 | 499 | m_fifo_cap_a = m_fifo_cap_b = 0; |
| 500 | |
| 501 | if (data != 0) |
| 502 | { |
| 503 | timer_adjust_periodic(m_sync_timer, attotime_zero, 0, ATTOTIME_IN_HZ(22257/4)); |
| 504 | } |
| 505 | else |
| 506 | { |
| 507 | timer_adjust_oneshot(m_sync_timer, attotime_never, 0); |
| 508 | } |
| 474 | 509 | } |
| 475 | 510 | break; |
| 476 | 511 | |
| r9431 | r9432 | |
| 484 | 519 | break; |
| 485 | 520 | |
| 486 | 521 | case R_WTCONTROL: |
| 487 | | // printf("One-shot wavetable %02x\n", data); |
| 522 | // printf("One-shot wavetable %02x\n", data); |
| 488 | 523 | break; |
| 489 | 524 | |
| 490 | | case 0x811: |
| 525 | case 0x811: |
| 491 | 526 | m_phase[0] &= 0x00ffff; |
| 492 | 527 | m_phase[0] |= data<<16; |
| 493 | 528 | break; |
| r9431 | r9432 | |
| 502 | 537 | m_phase[0] |= data; |
| 503 | 538 | break; |
| 504 | 539 | |
| 505 | | case 0x815: |
| 540 | case 0x815: |
| 506 | 541 | m_incr[0] &= 0x00ffff; |
| 507 | 542 | m_incr[0] |= data<<16; |
| 508 | 543 | break; |
| r9431 | r9432 | |
| 517 | 552 | m_incr[0] |= data; |
| 518 | 553 | break; |
| 519 | 554 | |
| 520 | | case 0x819: |
| 555 | case 0x819: |
| 521 | 556 | m_phase[1] &= 0x00ffff; |
| 522 | 557 | m_phase[1] |= data<<16; |
| 523 | 558 | break; |
| r9431 | r9432 | |
| 532 | 567 | m_phase[1] |= data; |
| 533 | 568 | break; |
| 534 | 569 | |
| 535 | | case 0x81d: |
| 570 | case 0x81d: |
| 536 | 571 | m_incr[1] &= 0x00ffff; |
| 537 | 572 | m_incr[1] |= data<<16; |
| 538 | 573 | break; |
| r9431 | r9432 | |
| 547 | 582 | m_incr[1] |= data; |
| 548 | 583 | break; |
| 549 | 584 | |
| 550 | | case 0x821: |
| 585 | case 0x821: |
| 551 | 586 | m_phase[2] &= 0x00ffff; |
| 552 | 587 | m_phase[2] |= data<<16; |
| 553 | 588 | break; |
| r9431 | r9432 | |
| 562 | 597 | m_phase[2] |= data; |
| 563 | 598 | break; |
| 564 | 599 | |
| 565 | | case 0x825: |
| 600 | case 0x825: |
| 566 | 601 | m_incr[2] &= 0x00ffff; |
| 567 | 602 | m_incr[2] |= data<<16; |
| 568 | 603 | break; |
| r9431 | r9432 | |
| 577 | 612 | m_incr[2] |= data; |
| 578 | 613 | break; |
| 579 | 614 | |
| 580 | | case 0x829: |
| 615 | case 0x829: |
| 581 | 616 | m_phase[3] &= 0x00ffff; |
| 582 | 617 | m_phase[3] |= data<<16; |
| 583 | 618 | break; |
| r9431 | r9432 | |
| 592 | 627 | m_phase[3] |= data; |
| 593 | 628 | break; |
| 594 | 629 | |
| 595 | | case 0x82d: |
| 630 | case 0x82d: |
| 596 | 631 | m_incr[3] &= 0x00ffff; |
| 597 | 632 | m_incr[3] |= data<<16; |
| 598 | 633 | break; |