trunk/src/mame/drivers/tmnt.c
| r32562 | r32563 | |
| 59 | 59 | #include "sound/2151intf.h" |
| 60 | 60 | #include "sound/okim6295.h" |
| 61 | 61 | #include "sound/samples.h" |
| 62 | | #include "sound/k053260.h" |
| 63 | 62 | #include "sound/k054539.h" |
| 64 | 63 | #include "machine/nvram.h" |
| 65 | 64 | #include "includes/tmnt.h" |
| r32562 | r32563 | |
| 163 | 162 | device.execute().set_input_line(M68K_IRQ_5, HOLD_LINE); |
| 164 | 163 | } |
| 165 | 164 | |
| 166 | | READ8_MEMBER(tmnt_state::punkshot_sound_r) |
| 167 | | { |
| 168 | | /* If the sound CPU is running, read the status, otherwise |
| 169 | | just make it pass the test */ |
| 170 | | return m_k053260->k053260_r(space, 2 + offset); |
| 171 | | } |
| 172 | | |
| 173 | 165 | WRITE8_MEMBER(tmnt_state::glfgreat_sound_w) |
| 174 | 166 | { |
| 175 | | m_k053260->k053260_w(space, offset, data); |
| 167 | m_k053260->main_write(space, offset, data); |
| 176 | 168 | |
| 177 | 169 | if (offset) |
| 178 | 170 | m_audiocpu->set_input_line_and_vector(0, HOLD_LINE, 0xff); |
| r32562 | r32563 | |
| 543 | 535 | AM_RANGE(0x0a0004, 0x0a0005) AM_READ_PORT("P3/P4") |
| 544 | 536 | AM_RANGE(0x0a0006, 0x0a0007) AM_READ_PORT("P1/P2") |
| 545 | 537 | AM_RANGE(0x0a0020, 0x0a0021) AM_WRITE(punkshot_0a0020_w) |
| 546 | | AM_RANGE(0x0a0040, 0x0a0043) AM_READ8(punkshot_sound_r, 0x00ff) /* K053260 */ |
| 547 | | AM_RANGE(0x0a0040, 0x0a0041) AM_DEVWRITE8("k053260", k053260_device, k053260_w, 0x00ff) |
| 538 | AM_RANGE(0x0a0040, 0x0a0043) AM_DEVREADWRITE8("k053260", k053260_device, main_read, main_write, 0x00ff) |
| 548 | 539 | AM_RANGE(0x0a0060, 0x0a007f) AM_DEVWRITE("k053251", k053251_device, lsb_w) |
| 549 | 540 | AM_RANGE(0x0a0080, 0x0a0081) AM_WRITE(watchdog_reset16_w) |
| 550 | 541 | AM_RANGE(0x100000, 0x107fff) AM_READWRITE(k052109_word_noA12_r, punkshot_k052109_word_noA12_w) |
| r32562 | r32563 | |
| 565 | 556 | AM_RANGE(0x0a0008, 0x0a0009) AM_READ_PORT("DSW2") |
| 566 | 557 | AM_RANGE(0x0a0010, 0x0a0011) AM_READ_PORT("DSW3") |
| 567 | 558 | AM_RANGE(0x0a0018, 0x0a0019) AM_WRITE(lgtnfght_0a0018_w) |
| 568 | | AM_RANGE(0x0a0020, 0x0a0023) AM_READ8(punkshot_sound_r, 0x00ff) /* K053260 */ |
| 569 | | AM_RANGE(0x0a0020, 0x0a0021) AM_DEVWRITE8("k053260", k053260_device, k053260_w, 0x00ff) |
| 559 | AM_RANGE(0x0a0020, 0x0a0023) AM_DEVREADWRITE8("k053260", k053260_device, main_read, main_write, 0x00ff) |
| 570 | 560 | AM_RANGE(0x0a0028, 0x0a0029) AM_WRITE(watchdog_reset16_w) |
| 571 | 561 | AM_RANGE(0x0b0000, 0x0b3fff) AM_READWRITE(k053245_scattered_word_r, k053245_scattered_word_w) AM_SHARE("spriteram") |
| 572 | 562 | AM_RANGE(0x0c0000, 0x0c001f) AM_READWRITE(k053244_word_noA1_r, k053244_word_noA1_w) |
| r32562 | r32563 | |
| 595 | 585 | AM_RANGE(0x700006, 0x700007) AM_READ_PORT("EEPROM") |
| 596 | 586 | AM_RANGE(0x700200, 0x700201) AM_WRITE(blswhstl_eeprom_w) |
| 597 | 587 | AM_RANGE(0x700300, 0x700301) AM_WRITE(blswhstl_700300_w) |
| 598 | | AM_RANGE(0x700400, 0x700401) AM_WRITE(watchdog_reset16_w) |
| 599 | | AM_RANGE(0x780600, 0x780603) AM_READ8(punkshot_sound_r, 0x00ff) /* K053260 */ |
| 600 | | AM_RANGE(0x780600, 0x780601) AM_DEVWRITE8("k053260", k053260_device, k053260_w, 0x00ff) |
| 588 | AM_RANGE(0x700400, 0x700401) AM_READWRITE(watchdog_reset16_r, watchdog_reset16_w) |
| 589 | AM_RANGE(0x780600, 0x780603) AM_DEVREADWRITE8("k053260", k053260_device, main_read, main_write, 0x00ff) |
| 601 | 590 | AM_RANGE(0x780604, 0x780605) AM_WRITE(ssriders_soundkludge_w) |
| 602 | 591 | AM_RANGE(0x780700, 0x78071f) AM_DEVWRITE("k053251", k053251_device, lsb_w) |
| 603 | 592 | ADDRESS_MAP_END |
| r32562 | r32563 | |
| 642 | 631 | AM_RANGE(0x121000, 0x121001) AM_READ(glfgreat_ball_r) /* returns the color of the center pixel of the roz layer */ |
| 643 | 632 | AM_RANGE(0x122000, 0x122001) AM_WRITE(glfgreat_122000_w) |
| 644 | 633 | AM_RANGE(0x124000, 0x124001) AM_WRITE(watchdog_reset16_w) |
| 645 | | AM_RANGE(0x125000, 0x125003) AM_READWRITE8(punkshot_sound_r, glfgreat_sound_w, 0xff00) /* K053260 */ |
| 634 | AM_RANGE(0x125000, 0x125003) AM_DEVREAD8("k053260", k053260_device, main_read, 0xff00) AM_WRITE8(glfgreat_sound_w, 0xff00) |
| 646 | 635 | AM_RANGE(0x200000, 0x207fff) AM_READWRITE(k052109_word_noA12_r, k052109_word_noA12_w) |
| 647 | 636 | AM_RANGE(0x300000, 0x3fffff) AM_READ(glfgreat_rom_r) |
| 648 | 637 | ADDRESS_MAP_END |
| r32562 | r32563 | |
| 926 | 915 | // AM_RANGE(0x1c0800, 0x1c0801) AM_READ(ssriders_protection_r) /* protection device */ |
| 927 | 916 | AM_RANGE(0x1c0800, 0x1c081f) AM_WRITE(tmnt2_1c0800_w) AM_SHARE("tmnt2_1c0800") /* protection device */ |
| 928 | 917 | AM_RANGE(0x5a0000, 0x5a001f) AM_READWRITE(k053244_word_noA1_r, k053244_word_noA1_w) |
| 929 | | AM_RANGE(0x5c0600, 0x5c0603) AM_READ8(punkshot_sound_r, 0x00ff) /* K053260 */ |
| 930 | | AM_RANGE(0x5c0600, 0x5c0601) AM_DEVWRITE8("k053260", k053260_device, k053260_w, 0x00ff) |
| 918 | AM_RANGE(0x5c0600, 0x5c0603) AM_DEVREADWRITE8("k053260", k053260_device, main_read, main_write, 0x00ff) |
| 931 | 919 | AM_RANGE(0x5c0604, 0x5c0605) AM_WRITE(ssriders_soundkludge_w) |
| 932 | 920 | AM_RANGE(0x5c0700, 0x5c071f) AM_DEVWRITE("k053251", k053251_device, lsb_w) |
| 933 | 921 | AM_RANGE(0x600000, 0x603fff) AM_DEVREADWRITE("k052109", k052109_device, word_r, word_w) |
| r32562 | r32563 | |
| 952 | 940 | AM_RANGE(0x1c0800, 0x1c0801) AM_READ(ssriders_protection_r) |
| 953 | 941 | AM_RANGE(0x1c0800, 0x1c0803) AM_WRITE(ssriders_protection_w) |
| 954 | 942 | AM_RANGE(0x5a0000, 0x5a001f) AM_READWRITE(k053244_word_noA1_r, k053244_word_noA1_w) |
| 955 | | AM_RANGE(0x5c0600, 0x5c0603) AM_READ8(punkshot_sound_r, 0x00ff) /* K053260 */ |
| 956 | | AM_RANGE(0x5c0600, 0x5c0601) AM_DEVWRITE8("k053260", k053260_device, k053260_w, 0x00ff) |
| 943 | AM_RANGE(0x5c0600, 0x5c0603) AM_DEVREADWRITE8("k053260", k053260_device, main_read, main_write, 0x00ff) |
| 957 | 944 | AM_RANGE(0x5c0604, 0x5c0605) AM_WRITE(ssriders_soundkludge_w) |
| 958 | 945 | AM_RANGE(0x5c0700, 0x5c071f) AM_DEVWRITE("k053251", k053251_device, lsb_w) |
| 959 | 946 | AM_RANGE(0x600000, 0x603fff) AM_DEVREADWRITE("k052109", k052109_device, word_r, word_w) |
| r32562 | r32563 | |
| 991 | 978 | AM_RANGE(0x100000, 0x103fff) AM_RAM /* main RAM */ |
| 992 | 979 | AM_RANGE(0x200000, 0x200fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette") |
| 993 | 980 | AM_RANGE(0x300000, 0x30001f) AM_DEVWRITE("k053251", k053251_device, lsb_w) |
| 994 | | AM_RANGE(0x400000, 0x400003) AM_READ8(punkshot_sound_r, 0x00ff) /* K053260 */ |
| 995 | | AM_RANGE(0x400000, 0x400001) AM_DEVWRITE8("k053260", k053260_device, k053260_w, 0x00ff) |
| 981 | AM_RANGE(0x400000, 0x400003) AM_DEVREADWRITE8("k053260", k053260_device, main_read, main_write, 0x00ff) |
| 996 | 982 | AM_RANGE(0x500000, 0x50003f) AM_DEVREADWRITE("k054000", k054000_device, lsb_r, lsb_w) |
| 997 | 983 | AM_RANGE(0x500100, 0x500101) AM_WRITE(thndrx2_eeprom_w) |
| 998 | 984 | AM_RANGE(0x500200, 0x500201) AM_READ_PORT("P1/COINS") |
| r32562 | r32563 | |
| 1032 | 1018 | AM_RANGE(0xf000, 0xf7ff) AM_RAM |
| 1033 | 1019 | AM_RANGE(0xf800, 0xf801) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write) |
| 1034 | 1020 | AM_RANGE(0xfa00, 0xfa00) AM_WRITE(sound_arm_nmi_w) |
| 1035 | | AM_RANGE(0xfc00, 0xfc2f) AM_DEVREADWRITE("k053260", k053260_device, k053260_r, k053260_w) |
| 1021 | AM_RANGE(0xfc00, 0xfc2f) AM_DEVREADWRITE("k053260", k053260_device, read, write) |
| 1036 | 1022 | ADDRESS_MAP_END |
| 1037 | 1023 | |
| 1038 | 1024 | |
| r32562 | r32563 | |
| 1040 | 1026 | AM_RANGE(0x0000, 0x7fff) AM_ROM |
| 1041 | 1027 | AM_RANGE(0x8000, 0x87ff) AM_RAM |
| 1042 | 1028 | AM_RANGE(0xa000, 0xa001) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write) |
| 1043 | | AM_RANGE(0xc000, 0xc02f) AM_DEVREADWRITE("k053260", k053260_device, k053260_r, k053260_w) |
| 1029 | AM_RANGE(0xc000, 0xc02f) AM_DEVREADWRITE("k053260", k053260_device, read, write) |
| 1044 | 1030 | ADDRESS_MAP_END |
| 1045 | 1031 | |
| 1046 | 1032 | |
| 1047 | 1033 | static ADDRESS_MAP_START( glfgreat_audio_map, AS_PROGRAM, 8, tmnt_state ) |
| 1048 | 1034 | AM_RANGE(0x0000, 0x7fff) AM_ROM |
| 1049 | 1035 | AM_RANGE(0xf000, 0xf7ff) AM_RAM |
| 1050 | | AM_RANGE(0xf800, 0xf82f) AM_DEVREADWRITE("k053260", k053260_device, k053260_r, k053260_w) |
| 1036 | AM_RANGE(0xf800, 0xf82f) AM_DEVREADWRITE("k053260", k053260_device, read, write) |
| 1051 | 1037 | AM_RANGE(0xfa00, 0xfa00) AM_WRITE(sound_arm_nmi_w) |
| 1052 | 1038 | ADDRESS_MAP_END |
| 1053 | 1039 | |
| r32562 | r32563 | |
| 1056 | 1042 | AM_RANGE(0x0000, 0xefff) AM_ROM |
| 1057 | 1043 | AM_RANGE(0xf000, 0xf7ff) AM_RAM |
| 1058 | 1044 | AM_RANGE(0xf800, 0xf801) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write) |
| 1059 | | AM_RANGE(0xfa00, 0xfa2f) AM_DEVREADWRITE("k053260", k053260_device, k053260_r, k053260_w) |
| 1045 | AM_RANGE(0xfa00, 0xfa2f) AM_DEVREADWRITE("k053260", k053260_device, read, write) |
| 1060 | 1046 | AM_RANGE(0xfc00, 0xfc00) AM_WRITE(sound_arm_nmi_w) |
| 1061 | 1047 | ADDRESS_MAP_END |
| 1062 | 1048 | |
| r32562 | r32563 | |
| 1066 | 1052 | AM_RANGE(0xf000, 0xf7ff) AM_RAM |
| 1067 | 1053 | AM_RANGE(0xf800, 0xf801) AM_MIRROR(0x0010) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write) |
| 1068 | 1054 | AM_RANGE(0xfa00, 0xfa00) AM_WRITE(sound_arm_nmi_w) |
| 1069 | | AM_RANGE(0xfc00, 0xfc2f) AM_DEVREADWRITE("k053260", k053260_device, k053260_r, k053260_w) |
| 1055 | AM_RANGE(0xfc00, 0xfc2f) AM_DEVREADWRITE("k053260", k053260_device, read, write) |
| 1070 | 1056 | ADDRESS_MAP_END |
| 1071 | 1057 | |
| 1072 | 1058 | |
trunk/src/emu/sound/k053260.c
| r32562 | r32563 | |
| 1 | 1 | /********************************************************* |
| 2 | 2 | |
| 3 | | Konami 053260 PCM Sound Chip |
| 3 | Konami 053260 KDSC |
| 4 | 4 | |
| 5 | The 053260 is a four voice PCM/ADPCM sound chip that |
| 6 | also incorporates four 8-bit ports for communication |
| 7 | between a main CPU and audio CPU. The chip's output |
| 8 | is compatible with a YM3012 DAC, and it has a digital |
| 9 | auxiliary input compatible with the output of a YM2151. |
| 10 | Some games (e.g. Simpsons) only connect one channel of |
| 11 | the YM2151, but others (e.g. Thunder Cross II) connect |
| 12 | both channels for stereo mixing. |
| 13 | |
| 14 | The 053260 has a 21-bit address bus and 8-bit data bus |
| 15 | to ROM, allowing it to access up to 2 megabytes of |
| 16 | sample data. Sample data can be either signed 8-bit |
| 17 | PCM or a custom 4-bit ADPCM format. It is possible for |
| 18 | two 053260 chips to share access to the same ROMs |
| 19 | (used by Over Drive) |
| 20 | |
| 21 | The 053260 has separate address and data buses to the |
| 22 | audio CPU controlling it and to the main CPU. Both data |
| 23 | buses are 8 bit. The audio CPU address bus has 6 lines |
| 24 | (64 addressable registers, but fewer than 48 are |
| 25 | actually used) while the main CPU "bus" has only 1 line |
| 26 | (2 addressable registers). All registers on the audio |
| 27 | CPU side seem to be either read-only or write-only, |
| 28 | although some games write 0 to all the registers in a |
| 29 | loop at startup (including otherwise read-only or |
| 30 | entirely unused registers). |
| 31 | On the main CPU side, reads and writes to the same |
| 32 | address access different communication ports. |
| 33 | |
| 34 | The sound data ROMs of Simpsons and Vendetta have |
| 35 | "headers" listing all the samples in the ROM, their |
| 36 | formats ("PCM" or "KADPCM"), start and end addresses. |
| 37 | The header data doesn't seem to be used by the hardware |
| 38 | (none of the other games have headers) but provides |
| 39 | useful information about the chip. |
| 40 | |
| 41 | 2004-02-28 (Oliver Achten) |
| 42 | Fixed ADPCM decoding. Games sound much better now. |
| 43 | |
| 44 | 2014-10-06 (Alex W. Jackson) |
| 45 | Rewrote from scratch in C++; implemented communication |
| 46 | ports properly; used the actual up counters instead of |
| 47 | converting to fractional sample position; fixed ADPCM |
| 48 | decoding bugs; added documentation. |
| 49 | |
| 50 | |
| 5 | 51 | *********************************************************/ |
| 6 | 52 | |
| 7 | 53 | #include "emu.h" |
| 8 | 54 | #include "k053260.h" |
| 9 | 55 | |
| 10 | | /* 2004-02-28: Fixed PPCM decoding. Games sound much better now.*/ |
| 11 | | |
| 12 | 56 | #define LOG 0 |
| 13 | 57 | |
| 14 | | #define BASE_SHIFT 16 |
| 58 | #define CLOCKS_PER_SAMPLE 32 |
| 15 | 59 | |
| 16 | 60 | |
| 61 | |
| 17 | 62 | // device type definition |
| 18 | 63 | const device_type K053260 = &device_creator<k053260_device>; |
| 19 | 64 | |
| r32562 | r32563 | |
| 27 | 72 | //------------------------------------------------- |
| 28 | 73 | |
| 29 | 74 | k053260_device::k053260_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 30 | | : device_t(mconfig, K053260, "K053260 PCM", tag, owner, clock, "k053260", __FILE__), |
| 75 | : device_t(mconfig, K053260, "K053260 KDSC", tag, owner, clock, "k053260", __FILE__), |
| 31 | 76 | device_sound_interface(mconfig, *this), |
| 32 | | m_channel(NULL), |
| 33 | | m_mode(0), |
| 77 | m_rgnoverride(NULL), |
| 78 | m_stream(NULL), |
| 34 | 79 | m_rom(NULL), |
| 35 | 80 | m_rom_size(0), |
| 36 | | m_delta_table(NULL), |
| 37 | | m_rgnoverride(NULL) |
| 81 | m_keyon(0), |
| 82 | m_mode(0) |
| 38 | 83 | { |
| 39 | | memset(m_regs, 0, sizeof(int)*0x30); |
| 84 | memset(m_portdata, 0, sizeof(m_portdata)); |
| 40 | 85 | } |
| 41 | 86 | |
| 42 | 87 | |
| r32562 | r32563 | |
| 46 | 91 | |
| 47 | 92 | void k053260_device::device_start() |
| 48 | 93 | { |
| 49 | | int rate = clock() / 32; |
| 94 | memory_region *ROM = (m_rgnoverride) ? owner()->memregion(m_rgnoverride) : region(); |
| 95 | m_rom = *ROM; |
| 96 | m_rom_size = ROM->bytes(); |
| 50 | 97 | |
| 51 | | m_mode = 0; |
| 98 | m_stream = stream_alloc( 0, 2, clock() / CLOCKS_PER_SAMPLE ); |
| 52 | 99 | |
| 53 | | memory_region *region = (m_rgnoverride) ? memregion(m_rgnoverride) : this->region(); |
| 54 | | m_rom = *region; |
| 55 | | m_rom_size = region->bytes(); |
| 56 | | |
| 57 | | device_reset(); |
| 58 | | |
| 59 | | for (int i = 0; i < 0x30; i++) |
| 60 | | m_regs[i] = 0; |
| 61 | | |
| 62 | | m_delta_table = auto_alloc_array( machine(), UINT32, 0x1000 ); |
| 63 | | |
| 64 | | m_channel = stream_alloc( 0, 2, rate ); |
| 65 | | |
| 66 | | InitDeltaTable( rate, clock() ); |
| 67 | | |
| 68 | 100 | /* register with the save state system */ |
| 101 | save_item(NAME(m_portdata)); |
| 102 | save_item(NAME(m_keyon)); |
| 69 | 103 | save_item(NAME(m_mode)); |
| 70 | | save_item(NAME(m_regs)); |
| 71 | 104 | |
| 72 | 105 | for (int i = 0; i < 4; i++) |
| 73 | | { |
| 74 | | save_item(NAME(m_channels[i].rate), i); |
| 75 | | save_item(NAME(m_channels[i].size), i); |
| 76 | | save_item(NAME(m_channels[i].start), i); |
| 77 | | save_item(NAME(m_channels[i].bank), i); |
| 78 | | save_item(NAME(m_channels[i].volume), i); |
| 79 | | save_item(NAME(m_channels[i].play), i); |
| 80 | | save_item(NAME(m_channels[i].pan), i); |
| 81 | | save_item(NAME(m_channels[i].pos), i); |
| 82 | | save_item(NAME(m_channels[i].loop), i); |
| 83 | | save_item(NAME(m_channels[i].ppcm), i); |
| 84 | | save_item(NAME(m_channels[i].ppcm_data), i); |
| 85 | | } |
| 106 | m_voice[i].voice_start(*this, i); |
| 86 | 107 | } |
| 87 | 108 | |
| 88 | 109 | |
| r32562 | r32563 | |
| 93 | 114 | void k053260_device::device_reset() |
| 94 | 115 | { |
| 95 | 116 | for (int i = 0; i < 4; i++) |
| 96 | | { |
| 97 | | m_channels[i].rate = 0; |
| 98 | | m_channels[i].size = 0; |
| 99 | | m_channels[i].start = 0; |
| 100 | | m_channels[i].bank = 0; |
| 101 | | m_channels[i].volume = 0; |
| 102 | | m_channels[i].play = 0; |
| 103 | | m_channels[i].pan = 0; |
| 104 | | m_channels[i].pos = 0; |
| 105 | | m_channels[i].loop = 0; |
| 106 | | m_channels[i].ppcm = 0; |
| 107 | | m_channels[i].ppcm_data = 0; |
| 108 | | } |
| 117 | m_voice[i].voice_reset(); |
| 109 | 118 | } |
| 110 | 119 | |
| 111 | 120 | |
| 112 | | INLINE int limit( int val, int max, int min ) |
| 121 | READ8_MEMBER( k053260_device::main_read ) |
| 113 | 122 | { |
| 114 | | if ( val > max ) |
| 115 | | val = max; |
| 116 | | else if ( val < min ) |
| 117 | | val = min; |
| 123 | // sub-to-main ports |
| 124 | return m_portdata[2 + (offset & 1)]; |
| 125 | } |
| 118 | 126 | |
| 119 | | return val; |
| 127 | |
| 128 | WRITE8_MEMBER( k053260_device::main_write ) |
| 129 | { |
| 130 | // main-to-sub ports |
| 131 | m_portdata[offset & 1] = data; |
| 120 | 132 | } |
| 121 | 133 | |
| 122 | | #define MAXOUT 0x7fff |
| 123 | | #define MINOUT -0x8000 |
| 124 | 134 | |
| 125 | | //------------------------------------------------- |
| 126 | | // sound_stream_update - handle a stream update |
| 127 | | //------------------------------------------------- |
| 128 | | |
| 129 | | void k053260_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 135 | READ8_MEMBER( k053260_device::read ) |
| 130 | 136 | { |
| 131 | | static const INT8 dpcmcnv[] = { 0,1,2,4,8,16,32,64, -128, -64, -32, -16, -8, -4, -2, -1}; |
| 137 | offset &= 0x3f; |
| 138 | UINT8 ret = 0; |
| 132 | 139 | |
| 133 | | int lvol[4], rvol[4], play[4], loop[4], ppcm[4]; |
| 134 | | UINT8 *rom[4]; |
| 135 | | UINT32 delta[4], end[4], pos[4]; |
| 136 | | INT8 ppcm_data[4]; |
| 137 | | int dataL, dataR; |
| 138 | | INT8 d; |
| 140 | switch (offset) |
| 141 | { |
| 142 | case 0x00: // main-to-sub ports |
| 143 | case 0x01: |
| 144 | ret = m_portdata[offset]; |
| 145 | break; |
| 139 | 146 | |
| 140 | | /* precache some values */ |
| 141 | | for ( int i = 0; i < 4; i++ ) { |
| 142 | | rom[i]= &m_rom[m_channels[i].start + ( m_channels[i].bank << 16 )]; |
| 143 | | delta[i] = m_delta_table[m_channels[i].rate]; |
| 144 | | lvol[i] = m_channels[i].volume * m_channels[i].pan; |
| 145 | | rvol[i] = m_channels[i].volume * ( 8 - m_channels[i].pan ); |
| 146 | | end[i] = m_channels[i].size; |
| 147 | | pos[i] = m_channels[i].pos; |
| 148 | | play[i] = m_channels[i].play; |
| 149 | | loop[i] = m_channels[i].loop; |
| 150 | | ppcm[i] = m_channels[i].ppcm; |
| 151 | | ppcm_data[i] = m_channels[i].ppcm_data; |
| 152 | | if ( ppcm[i] ) |
| 153 | | delta[i] /= 2; |
| 147 | case 0x29: // voice status |
| 148 | m_stream->update(); |
| 149 | for (int i = 0; i < 4; i++) |
| 150 | ret |= m_voice[i].playing() << i; |
| 151 | break; |
| 152 | |
| 153 | case 0x2e: // read ROM |
| 154 | if (m_mode & 1) |
| 155 | ret = m_voice[0].read_rom(); |
| 156 | else |
| 157 | logerror("%s: Attempting to read K053260 ROM without mode bit set\n", machine().describe_context()); |
| 158 | break; |
| 159 | |
| 160 | default: |
| 161 | logerror("%s: Read from unknown K053260 register %02x\n", machine().describe_context(), offset); |
| 154 | 162 | } |
| 163 | return ret; |
| 164 | } |
| 155 | 165 | |
| 156 | | for ( int j = 0; j < samples; j++ ) { |
| 157 | | dataL = dataR = 0; |
| 158 | 166 | |
| 159 | | for ( int i = 0; i < 4; i++ ) { |
| 160 | | /* see if the voice is on */ |
| 161 | | if ( play[i] ) { |
| 162 | | /* see if we're done */ |
| 163 | | if ( ( pos[i] >> BASE_SHIFT ) >= end[i] ) { |
| 164 | | ppcm_data[i] = 0; |
| 165 | | if ( loop[i] ) |
| 166 | | pos[i] = 0; |
| 167 | | else { |
| 168 | | play[i] = 0; |
| 169 | | continue; |
| 170 | | } |
| 171 | | } |
| 167 | WRITE8_MEMBER( k053260_device::write ) |
| 168 | { |
| 169 | offset &= 0x3f; |
| 172 | 170 | |
| 173 | | if ( ppcm[i] ) { /* Packed PCM */ |
| 174 | | /* we only update the signal if we're starting or a real sound sample has gone by */ |
| 175 | | /* this is all due to the dynamic sample rate convertion */ |
| 176 | | if ( pos[i] == 0 || ( ( pos[i] ^ ( pos[i] - delta[i] ) ) & 0x8000 ) == 0x8000 ) |
| 171 | m_stream->update(); |
| 177 | 172 | |
| 178 | | { |
| 179 | | int newdata; |
| 180 | | if ( pos[i] & 0x8000 ){ |
| 181 | | newdata = ((rom[i][pos[i] >> BASE_SHIFT]) >> 4) & 0x0f; /*high nybble*/ |
| 182 | | } |
| 183 | | else{ |
| 184 | | newdata = ( ( rom[i][pos[i] >> BASE_SHIFT] ) ) & 0x0f; /*low nybble*/ |
| 185 | | } |
| 173 | // per voice registers |
| 174 | if ((offset >= 0x08) && (offset <= 0x27)) |
| 175 | { |
| 176 | m_voice[(offset - 8) / 8].set_register(offset, data); |
| 177 | return; |
| 178 | } |
| 186 | 179 | |
| 187 | | ppcm_data[i] += dpcmcnv[newdata]; |
| 188 | | } |
| 180 | switch (offset) |
| 181 | { |
| 182 | // 0x00 and 0x01 are read registers |
| 189 | 183 | |
| 184 | case 0x02: // sub-to-main ports |
| 185 | case 0x03: |
| 186 | m_portdata[offset] = data; |
| 187 | break; |
| 190 | 188 | |
| 189 | // 0x04 through 0x07 seem to be unused |
| 191 | 190 | |
| 192 | | d = ppcm_data[i]; |
| 191 | case 0x28: // key on/off |
| 192 | { |
| 193 | UINT8 rising_edge = data & ~m_keyon; |
| 193 | 194 | |
| 194 | | pos[i] += delta[i]; |
| 195 | | } else { /* PCM */ |
| 196 | | d = rom[i][pos[i] >> BASE_SHIFT]; |
| 195 | for (int i = 0; i < 4; i++) |
| 196 | { |
| 197 | if (rising_edge & (1 << i)) |
| 198 | m_voice[i].key_on(); |
| 199 | else if (!(data & (1 << i))) |
| 200 | m_voice[i].key_off(); |
| 201 | } |
| 202 | m_keyon = data; |
| 203 | break; |
| 204 | } |
| 197 | 205 | |
| 198 | | pos[i] += delta[i]; |
| 199 | | } |
| 206 | // 0x29 is a read register |
| 200 | 207 | |
| 201 | | if ( m_mode & 2 ) { |
| 202 | | dataL += ( d * lvol[i] ) >> 2; |
| 203 | | dataR += ( d * rvol[i] ) >> 2; |
| 204 | | } |
| 205 | | } |
| 208 | case 0x2a: // loop and pcm/adpcm select |
| 209 | for (int i = 0; i < 4; i++) |
| 210 | { |
| 211 | m_voice[i].set_loop_kadpcm(data); |
| 212 | data >>= 1; |
| 206 | 213 | } |
| 214 | break; |
| 207 | 215 | |
| 208 | | outputs[1][j] = limit( dataL, MAXOUT, MINOUT ); |
| 209 | | outputs[0][j] = limit( dataR, MAXOUT, MINOUT ); |
| 210 | | } |
| 216 | // 0x2b seems to be unused |
| 211 | 217 | |
| 212 | | /* update the regs now */ |
| 213 | | for ( int i = 0; i < 4; i++ ) { |
| 214 | | m_channels[i].pos = pos[i]; |
| 215 | | m_channels[i].play = play[i]; |
| 216 | | m_channels[i].ppcm_data = ppcm_data[i]; |
| 217 | | } |
| 218 | | } |
| 218 | case 0x2c: // pan, voices 0 and 1 |
| 219 | m_voice[0].set_pan(data); |
| 220 | m_voice[1].set_pan(data >> 3); |
| 221 | break; |
| 219 | 222 | |
| 223 | case 0x2d: // pan, voices 2 and 3 |
| 224 | m_voice[2].set_pan(data); |
| 225 | m_voice[3].set_pan(data >> 3); |
| 226 | break; |
| 220 | 227 | |
| 221 | | void k053260_device::InitDeltaTable( int rate, int clock ) |
| 222 | | { |
| 223 | | int i; |
| 224 | | double base = ( double )rate; |
| 225 | | double max = (double)(clock); /* Hz */ |
| 226 | | UINT32 val; |
| 228 | // 0x2e is a read register |
| 227 | 229 | |
| 228 | | for( i = 0; i < 0x1000; i++ ) { |
| 229 | | double v = ( double )( 0x1000 - i ); |
| 230 | | double target = (max) / v; |
| 231 | | double fixed = ( double )( 1 << BASE_SHIFT ); |
| 230 | case 0x2f: // control |
| 231 | m_mode = data; |
| 232 | // bit 0 = enable ROM read from register 0x2e |
| 233 | // bit 1 = enable sound output |
| 234 | // bit 2 = enable aux input? |
| 235 | // (set by all games except Golfing Greats and Rollergames, both of which |
| 236 | // don't have a YM2151. Over Drive only sets it on one of the two chips) |
| 237 | // bit 3 = aux input or ROM sharing related? |
| 238 | // (only set by Over Drive, and only on the same chip that bit 2 is set on) |
| 239 | break; |
| 232 | 240 | |
| 233 | | if ( target && base ) { |
| 234 | | target = fixed / ( base / target ); |
| 235 | | val = ( UINT32 )target; |
| 236 | | if ( val == 0 ) |
| 237 | | val = 1; |
| 238 | | } else |
| 239 | | val = 1; |
| 240 | | |
| 241 | | m_delta_table[i] = val; |
| 241 | default: |
| 242 | logerror("%s: Write to unknown K053260 register %02x (data = %02x)\n", |
| 243 | machine().describe_context(), offset, data); |
| 242 | 244 | } |
| 243 | 245 | } |
| 244 | 246 | |
| 245 | 247 | |
| 246 | | void k053260_device::check_bounds( int channel ) |
| 248 | INLINE int limit( int val, int max, int min ) |
| 247 | 249 | { |
| 248 | | int channel_start = ( m_channels[channel].bank << 16 ) + m_channels[channel].start; |
| 249 | | int channel_end = channel_start + m_channels[channel].size - 1; |
| 250 | if ( val > max ) |
| 251 | val = max; |
| 252 | else if ( val < min ) |
| 253 | val = min; |
| 250 | 254 | |
| 251 | | if ( channel_start > m_rom_size ) { |
| 252 | | logerror("K053260: Attempting to start playing past the end of the ROM ( start = %06x, end = %06x ).\n", channel_start, channel_end ); |
| 255 | return val; |
| 256 | } |
| 253 | 257 | |
| 254 | | m_channels[channel].play = 0; |
| 258 | #define MAXOUT 0x7fff |
| 259 | #define MINOUT -0x8000 |
| 255 | 260 | |
| 256 | | return; |
| 257 | | } |
| 261 | //------------------------------------------------- |
| 262 | // sound_stream_update - handle a stream update |
| 263 | //------------------------------------------------- |
| 258 | 264 | |
| 259 | | if ( channel_end > m_rom_size ) { |
| 260 | | logerror("K53260: Attempting to play past the end of the ROM ( start = %06x, end = %06x ).\n", channel_start, channel_end ); |
| 265 | void k053260_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 266 | { |
| 267 | if (m_mode & 2) |
| 268 | { |
| 269 | for ( int j = 0; j < samples; j++ ) |
| 270 | { |
| 271 | stream_sample_t buffer[2] = {0, 0}; |
| 261 | 272 | |
| 262 | | m_channels[channel].size = m_rom_size - channel_start; |
| 273 | for (int i = 0; i < 4; i++) |
| 274 | { |
| 275 | KDSC_Voice &voice = m_voice[i]; |
| 276 | if (voice.playing()) |
| 277 | voice.play(buffer); |
| 278 | } |
| 279 | |
| 280 | outputs[0][j] = limit( buffer[0] >> 1, MAXOUT, MINOUT ); |
| 281 | outputs[1][j] = limit( buffer[1] >> 1, MAXOUT, MINOUT ); |
| 282 | } |
| 263 | 283 | } |
| 264 | | if (LOG) logerror("K053260: Sample Start = %06x, Sample End = %06x, Sample rate = %04x, PPCM = %s\n", channel_start, channel_end, m_channels[channel].rate, m_channels[channel].ppcm ? "yes" : "no" ); |
| 284 | else |
| 285 | { |
| 286 | memset( outputs[0], 0, samples * sizeof(*outputs[0])); |
| 287 | memset( outputs[1], 0, samples * sizeof(*outputs[1])); |
| 288 | } |
| 265 | 289 | } |
| 266 | 290 | |
| 267 | 291 | |
| 268 | | WRITE8_MEMBER( k053260_device::k053260_w ) |
| 292 | //************************************************************************** |
| 293 | // KDSC_Voice - one of the four voices |
| 294 | //************************************************************************** |
| 295 | |
| 296 | void k053260_device::KDSC_Voice::voice_start(k053260_device &device, int index) |
| 269 | 297 | { |
| 270 | | int i, t; |
| 271 | | int r = offset; |
| 272 | | int v = data; |
| 298 | m_device = &device; |
| 273 | 299 | |
| 274 | | if ( r > 0x2f ) { |
| 275 | | logerror("K053260: Writing past registers\n" ); |
| 276 | | return; |
| 277 | | } |
| 300 | voice_reset(); |
| 278 | 301 | |
| 279 | | m_channel->update(); |
| 302 | device.save_item(NAME(m_position), index); |
| 303 | device.save_item(NAME(m_pan_volume), index); |
| 304 | device.save_item(NAME(m_counter), index); |
| 305 | device.save_item(NAME(m_output), index); |
| 306 | device.save_item(NAME(m_playing), index); |
| 307 | device.save_item(NAME(m_start), index); |
| 308 | device.save_item(NAME(m_length), index); |
| 309 | device.save_item(NAME(m_pitch), index); |
| 310 | device.save_item(NAME(m_volume), index); |
| 311 | device.save_item(NAME(m_pan), index); |
| 312 | device.save_item(NAME(m_loop), index); |
| 313 | device.save_item(NAME(m_kadpcm), index); |
| 314 | } |
| 280 | 315 | |
| 281 | | /* before we update the regs, we need to check for a latched reg */ |
| 282 | | if ( r == 0x28 ) { |
| 283 | | t = m_regs[r] ^ v; |
| 316 | void k053260_device::KDSC_Voice::voice_reset() |
| 317 | { |
| 318 | m_position = 0; |
| 319 | m_counter = 0; |
| 320 | m_output = 0; |
| 321 | m_playing = false; |
| 322 | m_start = 0; |
| 323 | m_length = 0; |
| 324 | m_pitch = 0; |
| 325 | m_volume = 0; |
| 326 | m_pan = 0; |
| 327 | m_loop = false; |
| 328 | m_kadpcm = false; |
| 329 | update_pan_volume(); |
| 330 | } |
| 284 | 331 | |
| 285 | | for ( i = 0; i < 4; i++ ) { |
| 286 | | if ( t & ( 1 << i ) ) { |
| 287 | | if ( v & ( 1 << i ) ) { |
| 288 | | m_channels[i].play = 1; |
| 289 | | m_channels[i].pos = 0; |
| 290 | | m_channels[i].ppcm_data = 0; |
| 291 | | check_bounds( i ); |
| 292 | | } else |
| 293 | | m_channels[i].play = 0; |
| 294 | | } |
| 295 | | } |
| 296 | | |
| 297 | | m_regs[r] = v; |
| 298 | | return; |
| 299 | | } |
| 300 | | |
| 301 | | /* update regs */ |
| 302 | | m_regs[r] = v; |
| 303 | | |
| 304 | | /* communication registers */ |
| 305 | | if ( r < 8 ) |
| 306 | | return; |
| 307 | | |
| 308 | | /* channel setup */ |
| 309 | | if ( r < 0x28 ) { |
| 310 | | int channel = ( r - 8 ) / 8; |
| 311 | | |
| 312 | | switch ( ( r - 8 ) & 0x07 ) { |
| 313 | | case 0: /* sample rate low */ |
| 314 | | m_channels[channel].rate &= 0x0f00; |
| 315 | | m_channels[channel].rate |= v; |
| 332 | void k053260_device::KDSC_Voice::set_register(offs_t offset, UINT8 data) |
| 333 | { |
| 334 | switch (offset & 0x7) |
| 335 | { |
| 336 | case 0: // pitch, lower 8 bits |
| 337 | m_pitch = (m_pitch & 0x0f00) | data; |
| 316 | 338 | break; |
| 317 | | |
| 318 | | case 1: /* sample rate high */ |
| 319 | | m_channels[channel].rate &= 0x00ff; |
| 320 | | m_channels[channel].rate |= ( v & 0x0f ) << 8; |
| 339 | case 1: // pitch, upper 4 bits |
| 340 | m_pitch = (m_pitch & 0x00ff) | ((data << 8) & 0x0f00); |
| 321 | 341 | break; |
| 322 | | |
| 323 | | case 2: /* size low */ |
| 324 | | m_channels[channel].size &= 0xff00; |
| 325 | | m_channels[channel].size |= v; |
| 342 | case 2: // length, lower 8 bits |
| 343 | m_length = (m_length & 0xff00) | data; |
| 326 | 344 | break; |
| 327 | | |
| 328 | | case 3: /* size high */ |
| 329 | | m_channels[channel].size &= 0x00ff; |
| 330 | | m_channels[channel].size |= v << 8; |
| 345 | case 3: // length, upper 8 bits |
| 346 | m_length = (m_length & 0x00ff) | (data << 8); |
| 331 | 347 | break; |
| 332 | | |
| 333 | | case 4: /* start low */ |
| 334 | | m_channels[channel].start &= 0xff00; |
| 335 | | m_channels[channel].start |= v; |
| 348 | case 4: // start, lower 8 bits |
| 349 | m_start = (m_start & 0x1fff00) | data; |
| 336 | 350 | break; |
| 337 | | |
| 338 | | case 5: /* start high */ |
| 339 | | m_channels[channel].start &= 0x00ff; |
| 340 | | m_channels[channel].start |= v << 8; |
| 351 | case 5: // start, middle 8 bits |
| 352 | m_start = (m_start & 0x1f00ff) | (data << 8); |
| 341 | 353 | break; |
| 342 | | |
| 343 | | case 6: /* bank */ |
| 344 | | m_channels[channel].bank = v & 0xff; |
| 354 | case 6: // start, upper 5 bits |
| 355 | m_start = (m_start & 0x00ffff) | ((data << 16) & 0x1f0000); |
| 345 | 356 | break; |
| 357 | case 7: // volume, 7 bits |
| 358 | m_volume = data & 0x7f; |
| 359 | update_pan_volume(); |
| 360 | } |
| 361 | } |
| 346 | 362 | |
| 347 | | case 7: /* volume is 7 bits. Convert to 8 bits now. */ |
| 348 | | m_channels[channel].volume = ( ( v & 0x7f ) << 1 ) | ( v & 1 ); |
| 349 | | break; |
| 350 | | } |
| 363 | void k053260_device::KDSC_Voice::set_loop_kadpcm(UINT8 data) |
| 364 | { |
| 365 | m_loop = BIT(data, 0); |
| 366 | m_kadpcm = BIT(data, 4); |
| 367 | } |
| 351 | 368 | |
| 352 | | return; |
| 353 | | } |
| 369 | void k053260_device::KDSC_Voice::set_pan(UINT8 data) |
| 370 | { |
| 371 | m_pan = data & 0x7; |
| 372 | update_pan_volume(); |
| 373 | } |
| 354 | 374 | |
| 355 | | switch( r ) { |
| 356 | | case 0x2a: /* loop, ppcm */ |
| 357 | | for ( i = 0; i < 4; i++ ) |
| 358 | | m_channels[i].loop = ( v & ( 1 << i ) ) != 0; |
| 375 | void k053260_device::KDSC_Voice::update_pan_volume() |
| 376 | { |
| 377 | m_pan_volume[0] = m_volume * (8 - m_pan); |
| 378 | m_pan_volume[1] = m_volume * m_pan; |
| 379 | } |
| 359 | 380 | |
| 360 | | for ( i = 4; i < 8; i++ ) |
| 361 | | m_channels[i-4].ppcm = ( v & ( 1 << i ) ) != 0; |
| 362 | | break; |
| 381 | void k053260_device::KDSC_Voice::key_on() |
| 382 | { |
| 383 | if (m_start >= m_device->m_rom_size) |
| 384 | logerror("K053260: Attempting to start playing past the end of the ROM ( start = %06x, length = %06x )\n", m_start, m_length); |
| 363 | 385 | |
| 364 | | case 0x2c: /* pan */ |
| 365 | | m_channels[0].pan = v & 7; |
| 366 | | m_channels[1].pan = ( v >> 3 ) & 7; |
| 367 | | break; |
| 386 | else if (m_start + m_length >= m_device->m_rom_size) |
| 387 | logerror("K053260: Attempting to play past the end of the ROM ( start = %06x, length = %06x )\n", |
| 388 | m_start, m_length); |
| 368 | 389 | |
| 369 | | case 0x2d: /* more pan */ |
| 370 | | m_channels[2].pan = v & 7; |
| 371 | | m_channels[3].pan = ( v >> 3 ) & 7; |
| 372 | | break; |
| 373 | | |
| 374 | | case 0x2f: /* control */ |
| 375 | | m_mode = v & 7; |
| 376 | | /* bit 0 = read ROM */ |
| 377 | | /* bit 1 = enable sound output */ |
| 378 | | /* bit 2 = unknown */ |
| 379 | | break; |
| 390 | else |
| 391 | { |
| 392 | m_position = m_kadpcm; // for kadpcm low bit is nybble offset, so must start at 1 due to preincrement |
| 393 | m_counter = 0x1000 - CLOCKS_PER_SAMPLE; // force update on next sound_stream_update |
| 394 | m_output = 0; |
| 395 | m_playing = true; |
| 396 | if (LOG) logerror("K053260: start = %06x, length = %06x, pitch = %04x, vol = %02x, loop = %s, %s\n", |
| 397 | m_start, m_length, m_pitch, m_volume, m_loop ? "yes" : "no", m_kadpcm ? "KADPCM" : "PCM" ); |
| 380 | 398 | } |
| 381 | 399 | } |
| 382 | 400 | |
| 383 | | READ8_MEMBER( k053260_device::k053260_r ) |
| 401 | void k053260_device::KDSC_Voice::key_off() |
| 384 | 402 | { |
| 385 | | switch ( offset ) { |
| 386 | | case 0x29: /* channel status */ |
| 387 | | { |
| 388 | | int i, status = 0; |
| 403 | m_position = 0; |
| 404 | m_output = 0; |
| 405 | m_playing = false; |
| 406 | } |
| 389 | 407 | |
| 390 | | for ( i = 0; i < 4; i++ ) |
| 391 | | status |= m_channels[i].play << i; |
| 408 | void k053260_device::KDSC_Voice::play(stream_sample_t *outputs) |
| 409 | { |
| 410 | m_counter += CLOCKS_PER_SAMPLE; |
| 392 | 411 | |
| 393 | | return status; |
| 394 | | } |
| 412 | while (m_counter >= 0x1000) |
| 413 | { |
| 414 | m_counter = m_counter - 0x1000 + m_pitch; |
| 395 | 415 | |
| 396 | | case 0x2e: /* read ROM */ |
| 397 | | if ( m_mode & 1 ) |
| 416 | UINT32 bytepos = ++m_position >> m_kadpcm; |
| 417 | /* |
| 418 | Yes, _pre_increment. Playback must start 1 byte position after the |
| 419 | start address written to the register, or else ADPCM sounds will |
| 420 | have DC offsets (e.g. TMNT2 theme song) or will overflow and be |
| 421 | distorted (e.g. various Vendetta sound effects) |
| 422 | The "headers" in the Simpsons and Vendetta sound ROMs provide |
| 423 | further evidence of this quirk (the start addresses listed in the |
| 424 | ROM header are all 1 greater than the addresses the CPU writes |
| 425 | into the register) |
| 426 | */ |
| 427 | if (bytepos > m_length) |
| 428 | { |
| 429 | if (m_loop) |
| 398 | 430 | { |
| 399 | | UINT32 offs = m_channels[0].start + ( m_channels[0].pos >> BASE_SHIFT ) + ( m_channels[0].bank << 16 ); |
| 431 | m_position = m_output = bytepos = 0; |
| 432 | } |
| 433 | else |
| 434 | { |
| 435 | m_playing = false; |
| 436 | return; |
| 437 | } |
| 438 | } |
| 400 | 439 | |
| 401 | | m_channels[0].pos += ( 1 << 16 ); |
| 440 | UINT8 romdata = m_device->m_rom[m_start + bytepos]; |
| 402 | 441 | |
| 403 | | if ( offs > m_rom_size ) { |
| 404 | | logerror("%s: K53260: Attempting to read past ROM size in ROM Read Mode (offs = %06x, size = %06x).\n", machine().describe_context(),offs,m_rom_size ); |
| 442 | if (m_kadpcm) |
| 443 | { |
| 444 | if (m_position & 1) romdata >>= 4; // decode low nybble, then high nybble |
| 445 | static const INT8 kadpcm_table[] = {0,1,2,4,8,16,32,64,-128,-64,-32,-16,-8,-4,-2,-1}; |
| 446 | m_output += kadpcm_table[romdata & 0xf]; |
| 447 | } |
| 448 | else |
| 449 | { |
| 450 | m_output = romdata; |
| 451 | } |
| 452 | } |
| 405 | 453 | |
| 406 | | return 0; |
| 407 | | } |
| 454 | outputs[0] += m_output * m_pan_volume[0]; |
| 455 | outputs[1] += m_output * m_pan_volume[1]; |
| 456 | } |
| 408 | 457 | |
| 409 | | return m_rom[offs]; |
| 410 | | } |
| 411 | | break; |
| 458 | UINT8 k053260_device::KDSC_Voice::read_rom() |
| 459 | { |
| 460 | UINT32 offs = m_start + m_position; |
| 461 | |
| 462 | m_position = (m_position + 1) & 0xffff; |
| 463 | |
| 464 | if (offs >= m_device->m_rom_size) |
| 465 | { |
| 466 | logerror("%s: K053260: Attempting to read past the end of the ROM (offs = %06x, size = %06x)\n", |
| 467 | m_device->machine().describe_context(), offs, m_device->m_rom_size); |
| 468 | return 0; |
| 412 | 469 | } |
| 413 | 470 | |
| 414 | | return m_regs[offset]; |
| 471 | return m_device->m_rom[offs]; |
| 415 | 472 | } |