trunk/src/emu/sound/upd7759.c
| r17776 | r17777 | |
| 6 | 6 | |
| 7 | 7 | TODO: |
| 8 | 8 | - is there a doable method to dump the internal maskrom? :( |
| 9 | As far as we know, decapping is the only option |
| 9 | 10 | - low-level emulation |
| 10 | 11 | - watchdog? - according to uPD775x datasheet, the chip goes into standy mode |
| 11 | 12 | if CS/ST/RESET have not been accessed for more than 3 seconds |
| r17776 | r17777 | |
| 15 | 16 | |
| 16 | 17 | uPD7759 Description: |
| 17 | 18 | |
| 18 | | The UPD7759 is a speech processing LSI that utilizes ADPCM to produce |
| 19 | The uPD7759 is a speech processing LSI that utilizes ADPCM to produce |
| 19 | 20 | speech or other sampled sounds. It can directly address up to 1Mbit |
| 20 | 21 | (128k) of external data ROM, or the host CPU can control the speech |
| 21 | | data transfer. The UPD7759 is usually hooked up to a 640 kHz clock and |
| 22 | data transfer. The uPD7759 is usually hooked up to a 640 kHz clock and |
| 22 | 23 | has one 8-bit input port, a start pin, a busy pin, and a clock output. |
| 23 | 24 | |
| 24 | 25 | The chip is composed of 3 parts: |
| r17776 | r17777 | |
| 63 | 64 | This allows the engine to be a little more adaptative than a |
| 64 | 65 | classical ADPCM algorithm. |
| 65 | 66 | |
| 66 | | The UPD7759 can run in two modes, master (also known as standalone) |
| 67 | The uPD7759 can run in two modes, master (also known as standalone) |
| 67 | 68 | and slave. The mode is selected through the "md" pin. No known |
| 68 | 69 | game changes modes on the fly, and it's unsure if that's even |
| 69 | 70 | possible to do. |
| r17776 | r17777 | |
| 84 | 85 | them by two gives the sample start offset in the rom. A 0x00 marks |
| 85 | 86 | the end of each sample. |
| 86 | 87 | |
| 87 | | It seems that the UPD7759 reads at least part of the rom header at |
| 88 | It seems that the uPD7759 reads at least part of the rom header at |
| 88 | 89 | startup. Games doing rom banking are careful to reset the chip after |
| 89 | 90 | each change. |
| 90 | 91 | |
| r17776 | r17777 | |
| 111 | 112 | 55G 24-pin SOP 96 Kbit ROM |
| 112 | 113 | 56C 18-pin DIP 256 Kbit ROM |
| 113 | 114 | 56G 24-pin SOP 256 Kbit ROM |
| 114 | | P56CR 20-pin DIP 256 Kbit ROM (OTP) |
| 115 | | P56G 24-pin SOP 256 Kbit ROM (OTP) |
| 115 | P56CR 20-pin DIP 256 Kbit ROM (OTP) - dumping the ROM is trivial |
| 116 | P56G 24-pin SOP 256 Kbit ROM (OTP) - " |
| 116 | 117 | 57C 18-pin DIP 512 Kbit ROM |
| 117 | 118 | 57G 24-pin SOP 512 Kbit ROM |
| 118 | 119 | 58C 18-pin DIP 1 Mbit ROM |
| r17776 | r17777 | |
| 302 | 303 | /* Start state: we begin here as soon as a sample is triggered */ |
| 303 | 304 | case STATE_START: |
| 304 | 305 | chip->req_sample = chip->rom ? chip->fifo_in : 0x10; |
| 305 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: req_sample = %02X\n", chip->req_sample); |
| 306 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: req_sample = %02X\n", chip->req_sample); |
| 306 | 307 | |
| 307 | 308 | /* 35+ cycles after we get here, the /DRQ goes low |
| 308 | 309 | * (first byte (number of samples in ROM) should be sent in response) |
| r17776 | r17777 | |
| 318 | 319 | /* First request state: issue a request for the first byte */ |
| 319 | 320 | /* The expected response will be the index of the last sample */ |
| 320 | 321 | case STATE_FIRST_REQ: |
| 321 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: first data request\n"); |
| 322 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: first data request\n"); |
| 322 | 323 | chip->drq = 1; |
| 323 | 324 | |
| 324 | 325 | /* 44 cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 330 | 331 | /* The second byte read will be just a dummy */ |
| 331 | 332 | case STATE_LAST_SAMPLE: |
| 332 | 333 | chip->last_sample = chip->rom ? chip->rom[0] : chip->fifo_in; |
| 333 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: last_sample = %02X, requesting dummy 1\n", chip->last_sample); |
| 334 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: last_sample = %02X, requesting dummy 1\n", chip->last_sample); |
| 334 | 335 | chip->drq = 1; |
| 335 | 336 | |
| 336 | 337 | /* 28 cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 341 | 342 | /* First dummy state: ignore any data here and issue a request for the third byte */ |
| 342 | 343 | /* The expected response will be the MSB of the sample address */ |
| 343 | 344 | case STATE_DUMMY1: |
| 344 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: dummy1, requesting offset_hi\n"); |
| 345 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: dummy1, requesting offset_hi\n"); |
| 345 | 346 | chip->drq = 1; |
| 346 | 347 | |
| 347 | 348 | /* 32 cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 353 | 354 | /* The expected response will be the LSB of the sample address */ |
| 354 | 355 | case STATE_ADDR_MSB: |
| 355 | 356 | chip->offset = (chip->rom ? chip->rom[chip->req_sample * 2 + 5] : chip->fifo_in) << (8 + chip->sample_offset_shift); |
| 356 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: offset_hi = %02X, requesting offset_lo\n", chip->offset >> (8 + chip->sample_offset_shift)); |
| 357 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: offset_hi = %02X, requesting offset_lo\n", chip->offset >> (8 + chip->sample_offset_shift)); |
| 357 | 358 | chip->drq = 1; |
| 358 | 359 | |
| 359 | 360 | /* 44 cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 365 | 366 | /* The expected response will be just a dummy */ |
| 366 | 367 | case STATE_ADDR_LSB: |
| 367 | 368 | chip->offset |= (chip->rom ? chip->rom[chip->req_sample * 2 + 6] : chip->fifo_in) << chip->sample_offset_shift; |
| 368 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: offset_lo = %02X, requesting dummy 2\n", (chip->offset >> chip->sample_offset_shift) & 0xff); |
| 369 | | if (chip->offset > chip->rommask) logerror("upd7759 offset %X > rommask %X\n",chip->offset, chip->rommask); |
| 369 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: offset_lo = %02X, requesting dummy 2\n", (chip->offset >> chip->sample_offset_shift) & 0xff); |
| 370 | if (chip->offset > chip->rommask) logerror("uPD7759 offset %X > rommask %X\n",chip->offset, chip->rommask); |
| 370 | 371 | chip->drq = 1; |
| 371 | 372 | |
| 372 | 373 | /* 36 cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 379 | 380 | case STATE_DUMMY2: |
| 380 | 381 | chip->offset++; |
| 381 | 382 | chip->first_valid_header = 0; |
| 382 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: dummy2, requesting block header\n"); |
| 383 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: dummy2, requesting block header\n"); |
| 383 | 384 | chip->drq = 1; |
| 384 | 385 | |
| 385 | 386 | /* 36?? cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 397 | 398 | chip->offset = chip->repeat_offset; |
| 398 | 399 | } |
| 399 | 400 | chip->block_header = chip->rom ? chip->rom[chip->offset++ & chip->rommask] : chip->fifo_in; |
| 400 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: header (@%05X) = %02X, requesting next byte\n", chip->offset, chip->block_header); |
| 401 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: header (@%05X) = %02X, requesting next byte\n", chip->offset, chip->block_header); |
| 401 | 402 | chip->drq = 1; |
| 402 | 403 | |
| 403 | 404 | /* our next step depends on the top two bits */ |
| r17776 | r17777 | |
| 440 | 441 | /* The expected response will be the first data byte */ |
| 441 | 442 | case STATE_NIBBLE_COUNT: |
| 442 | 443 | chip->nibbles_left = (chip->rom ? chip->rom[chip->offset++ & chip->rommask] : chip->fifo_in) + 1; |
| 443 | | if (DEBUG_STATES) DEBUG_METHOD("UPD7759: nibble_count = %u, requesting next byte\n", (unsigned)chip->nibbles_left); |
| 444 | if (DEBUG_STATES) DEBUG_METHOD("uPD7759: nibble_count = %u, requesting next byte\n", (unsigned)chip->nibbles_left); |
| 444 | 445 | chip->drq = 1; |
| 445 | 446 | |
| 446 | 447 | /* 36?? cycles later, we will latch this value and request another byte */ |
| r17776 | r17777 | |
| 788 | 789 | const device_type UPD7759 = &device_creator<upd7759_device>; |
| 789 | 790 | |
| 790 | 791 | upd7759_device::upd7759_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 791 | | : device_t(mconfig, UPD7759, "UPD7759", tag, owner, clock), |
| 792 | : device_t(mconfig, UPD7759, "uPD7759", tag, owner, clock), |
| 792 | 793 | device_sound_interface(mconfig, *this) |
| 793 | 794 | { |
| 794 | 795 | m_token = global_alloc_array_clear(UINT8, sizeof(upd7759_state)); |
| r17776 | r17777 | |
| 842 | 843 | const device_type UPD7756 = &device_creator<upd7756_device>; |
| 843 | 844 | |
| 844 | 845 | upd7756_device::upd7756_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 845 | | : upd7759_device(mconfig, UPD7756, "UPD7756", tag, owner, clock) |
| 846 | : upd7759_device(mconfig, UPD7756, "uPD7756", tag, owner, clock) |
| 846 | 847 | { |
| 847 | 848 | } |
| 848 | 849 | |