trunk/src/mame/drivers/mpu4vid.c
| r21519 | r21520 | |
| 1410 | 1410 | AM_RANGE(0x000000, 0x7fffff) AM_ROM |
| 1411 | 1411 | AM_RANGE(0x800000, 0x80ffff) AM_RAM AM_SHARE("vid_mainram") |
| 1412 | 1412 | // AM_RANGE(0x810000, 0x81ffff) AM_RAM /* ? */ |
| 1413 | | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8_LEGACY("saa", saa1099_data_w, 0x00ff) |
| 1414 | | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8_LEGACY("saa", saa1099_control_w, 0x00ff) |
| 1413 | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, saa1099_data_w, 0x00ff) |
| 1414 | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, saa1099_control_w, 0x00ff) |
| 1415 | 1415 | AM_RANGE(0xa00000, 0xa00003) AM_READWRITE_LEGACY(ef9369_r, ef9369_w) |
| 1416 | 1416 | /* AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE_LEGACY(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */ |
| 1417 | 1417 | |
| r21519 | r21520 | |
| 1430 | 1430 | AM_RANGE(0x600000, 0x63ffff) AM_RAM /* The Mating Game has an extra 256kB RAM on the program card */ |
| 1431 | 1431 | // AM_RANGE(0x640000, 0x7fffff) AM_NOP /* Possible bug, reads and writes here */ |
| 1432 | 1432 | AM_RANGE(0x800000, 0x80ffff) AM_RAM AM_SHARE("vid_mainram") |
| 1433 | | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8_LEGACY("saa", saa1099_data_w, 0x00ff) |
| 1434 | | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8_LEGACY("saa", saa1099_control_w, 0x00ff) |
| 1433 | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, saa1099_data_w, 0x00ff) |
| 1434 | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, saa1099_control_w, 0x00ff) |
| 1435 | 1435 | AM_RANGE(0xa00000, 0xa00003) AM_READWRITE_LEGACY(ef9369_r, ef9369_w) |
| 1436 | 1436 | |
| 1437 | 1437 | AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE("scn2674_vid", scn2674_device, mpu4_vid_scn2674_r, mpu4_vid_scn2674_w) |
| r21519 | r21520 | |
| 1452 | 1452 | AM_RANGE(0x000000, 0x7fffff) AM_ROM |
| 1453 | 1453 | AM_RANGE(0x800000, 0x80ffff) AM_RAM AM_SHARE("vid_mainram") |
| 1454 | 1454 | AM_RANGE(0x810000, 0x81ffff) AM_RAM /* ? */ |
| 1455 | | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8_LEGACY("saa", saa1099_data_w, 0x00ff) |
| 1456 | | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8_LEGACY("saa", saa1099_control_w, 0x00ff) |
| 1455 | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, saa1099_data_w, 0x00ff) |
| 1456 | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, saa1099_control_w, 0x00ff) |
| 1457 | 1457 | AM_RANGE(0xa00000, 0xa00003) AM_READWRITE_LEGACY(ef9369_r, ef9369_w) |
| 1458 | 1458 | // AM_RANGE(0xa00000, 0xa0000f) AM_READWRITE_LEGACY(bt471_r,bt471_w) //Some games use this |
| 1459 | 1459 | /* AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE_LEGACY(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */ |
| r21519 | r21520 | |
| 1470 | 1470 | AM_RANGE(0x000000, 0x7fffff) AM_ROM |
| 1471 | 1471 | AM_RANGE(0x800000, 0x80ffff) AM_RAM AM_SHARE("vid_mainram") |
| 1472 | 1472 | AM_RANGE(0x810000, 0x81ffff) AM_RAM /* ? */ |
| 1473 | | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8_LEGACY("saa", saa1099_data_w, 0x00ff) |
| 1474 | | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8_LEGACY("saa", saa1099_control_w, 0x00ff) |
| 1473 | AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, saa1099_data_w, 0x00ff) |
| 1474 | AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, saa1099_control_w, 0x00ff) |
| 1475 | 1475 | AM_RANGE(0xa00000, 0xa00003) AM_READWRITE_LEGACY(ef9369_r, ef9369_w) |
| 1476 | 1476 | //AM_RANGE(0xa00000, 0xa00003) AM_READWRITE_LEGACY(bt471_r,bt471_w) Some games use this |
| 1477 | 1477 | /* AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE_LEGACY(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */ |
| r21519 | r21520 | |
| 1549 | 1549 | MCFG_PTM6840_ADD("6840ptm_68k", ptm_vid_intf) |
| 1550 | 1550 | /* Present on all video cards */ |
| 1551 | 1551 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1552 | | MCFG_SOUND_ADD("saa", SAA1099, 8000000) |
| 1552 | MCFG_SAA1099_ADD("saa", 8000000) |
| 1553 | 1553 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.5) |
| 1554 | 1554 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.5) |
| 1555 | 1555 | |
trunk/src/mame/drivers/namcos2.c
| r21519 | r21520 | |
| 737 | 737 | static ADDRESS_MAP_START( sound_default_am, AS_PROGRAM, 8, namcos2_state ) |
| 738 | 738 | AM_RANGE(0x0000, 0x3fff) AM_ROMBANK("bank6") /* banked */ |
| 739 | 739 | AM_RANGE(0x4000, 0x4001) AM_DEVREADWRITE("ymsnd", ym2151_device,read,write) |
| 740 | | AM_RANGE(0x5000, 0x6fff) AM_DEVREADWRITE_LEGACY("c140", c140_r,c140_w) |
| 740 | AM_RANGE(0x5000, 0x6fff) AM_DEVREADWRITE("c140", c140_device, c140_r,c140_w) |
| 741 | 741 | AM_RANGE(0x7000, 0x77ff) AM_READWRITE(dpram_byte_r,dpram_byte_w) AM_SHARE("dpram") |
| 742 | 742 | AM_RANGE(0x7800, 0x7fff) AM_READWRITE(dpram_byte_r,dpram_byte_w) /* mirror */ |
| 743 | 743 | AM_RANGE(0x8000, 0x9fff) AM_RAM |
| r21519 | r21520 | |
| 1640 | 1640 | |
| 1641 | 1641 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1642 | 1642 | |
| 1643 | | MCFG_SOUND_ADD("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1643 | MCFG_C140_ADD("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1644 | 1644 | MCFG_SOUND_CONFIG(c140_config) |
| 1645 | 1645 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.75) |
| 1646 | 1646 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.75) |
| r21519 | r21520 | |
| 1653 | 1653 | /* adjusted machine driver start */ |
| 1654 | 1654 | static MACHINE_CONFIG_DERIVED( default2, default ) |
| 1655 | 1655 | |
| 1656 | | MCFG_SOUND_REPLACE("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1656 | MCFG_C140_REPLACE("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1657 | 1657 | MCFG_SOUND_CONFIG(c140_config) |
| 1658 | 1658 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 1659 | 1659 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
| r21519 | r21520 | |
| 1667 | 1667 | |
| 1668 | 1668 | static MACHINE_CONFIG_DERIVED( default3, default ) |
| 1669 | 1669 | |
| 1670 | | MCFG_SOUND_REPLACE("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1670 | MCFG_C140_REPLACE("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1671 | 1671 | MCFG_SOUND_CONFIG(c140_config) |
| 1672 | 1672 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.45) |
| 1673 | 1673 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.45) |
| r21519 | r21520 | |
| 1714 | 1714 | |
| 1715 | 1715 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1716 | 1716 | |
| 1717 | | MCFG_SOUND_ADD("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1717 | MCFG_C140_ADD("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1718 | 1718 | MCFG_SOUND_CONFIG(c140_config) |
| 1719 | 1719 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.75) |
| 1720 | 1720 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.75) |
| r21519 | r21520 | |
| 1765 | 1765 | |
| 1766 | 1766 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1767 | 1767 | |
| 1768 | | MCFG_SOUND_ADD("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1768 | MCFG_C140_ADD("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1769 | 1769 | MCFG_SOUND_CONFIG(c140_config) |
| 1770 | 1770 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.75) |
| 1771 | 1771 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.75) |
| r21519 | r21520 | |
| 1814 | 1814 | |
| 1815 | 1815 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1816 | 1816 | |
| 1817 | | MCFG_SOUND_ADD("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1817 | MCFG_C140_ADD("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1818 | 1818 | MCFG_SOUND_CONFIG(c140_config) |
| 1819 | 1819 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.75) |
| 1820 | 1820 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.75) |
| r21519 | r21520 | |
| 1865 | 1865 | |
| 1866 | 1866 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1867 | 1867 | |
| 1868 | | MCFG_SOUND_ADD("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1868 | MCFG_C140_ADD("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1869 | 1869 | MCFG_SOUND_CONFIG(c140_config) |
| 1870 | 1870 | MCFG_SOUND_ROUTE(0, "lspeaker", 0.75) |
| 1871 | 1871 | MCFG_SOUND_ROUTE(1, "rspeaker", 0.75) |
| r21519 | r21520 | |
| 1914 | 1914 | |
| 1915 | 1915 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1916 | 1916 | |
| 1917 | | MCFG_SOUND_ADD("c140", C140, C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1917 | MCFG_C140_ADD("c140", C140_SOUND_CLOCK) /* 21.333kHz */ |
| 1918 | 1918 | MCFG_SOUND_CONFIG(c140_config) |
| 1919 | 1919 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 1920 | 1920 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
trunk/src/mame/audio/gomoku.c
| r21519 | r21520 | |
| 9 | 9 | #include "emu.h" |
| 10 | 10 | #include "includes/gomoku.h" |
| 11 | 11 | |
| 12 | | |
| 13 | | /* 4 voices max */ |
| 14 | | #define MAX_VOICES 4 |
| 15 | | |
| 16 | | |
| 17 | 12 | static const int samplerate = 48000; |
| 18 | 13 | static const int defgain = 48; |
| 19 | 14 | |
| 20 | 15 | |
| 21 | | /* this structure defines the parameters for a channel */ |
| 22 | | struct sound_channel |
| 23 | | { |
| 24 | | int channel; |
| 25 | | int frequency; |
| 26 | | int counter; |
| 27 | | int volume; |
| 28 | | int oneshotplaying; |
| 29 | | }; |
| 16 | // device type definition |
| 17 | const device_type GOMOKU = &device_creator<gomoku_sound_device>; |
| 30 | 18 | |
| 31 | 19 | |
| 32 | | struct gomoku_sound_state |
| 33 | | { |
| 34 | | /* data about the sound system */ |
| 35 | | sound_channel m_channel_list[MAX_VOICES]; |
| 36 | | sound_channel *m_last_channel; |
| 20 | //************************************************************************** |
| 21 | // LIVE DEVICE |
| 22 | //************************************************************************** |
| 37 | 23 | |
| 38 | | /* global sound parameters */ |
| 39 | | const UINT8 *m_sound_rom; |
| 40 | | int m_num_voices; |
| 41 | | int m_sound_enable; |
| 42 | | sound_stream *m_stream; |
| 24 | //------------------------------------------------- |
| 25 | // gomoku_sound_device - constructor |
| 26 | //------------------------------------------------- |
| 43 | 27 | |
| 44 | | /* mixer tables and internal buffers */ |
| 45 | | INT16 *m_mixer_table; |
| 46 | | INT16 *m_mixer_lookup; |
| 47 | | short *m_mixer_buffer; |
| 48 | | short *m_mixer_buffer_2; |
| 28 | gomoku_sound_device::gomoku_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 29 | : device_t(mconfig, GOMOKU, "Gomoku Custom", tag, owner, clock), |
| 30 | device_sound_interface(mconfig, *this), |
| 31 | m_last_channel(NULL), |
| 32 | m_sound_rom(NULL), |
| 33 | m_num_voices(0), |
| 34 | m_sound_enable(0), |
| 35 | m_stream(NULL), |
| 36 | m_mixer_table(NULL), |
| 37 | m_mixer_lookup(NULL), |
| 38 | m_mixer_buffer(NULL), |
| 39 | m_mixer_buffer_2(NULL) |
| 40 | { |
| 41 | memset(m_channel_list, 0, sizeof(gomoku_sound_channel)*GOMOKU_MAX_VOICES); |
| 42 | memset(m_soundregs1, 0, sizeof(UINT8)*0x20); |
| 43 | memset(m_soundregs2, 0, sizeof(UINT8)*0x20); |
| 44 | } |
| 49 | 45 | |
| 50 | | UINT8 m_soundregs1[0x20]; |
| 51 | | UINT8 m_soundregs2[0x20]; |
| 52 | | }; |
| 53 | 46 | |
| 54 | | INLINE gomoku_sound_state *get_safe_token( device_t *device ) |
| 47 | //------------------------------------------------- |
| 48 | // device_start - device-specific startup |
| 49 | //------------------------------------------------- |
| 50 | |
| 51 | void gomoku_sound_device::device_start() |
| 55 | 52 | { |
| 56 | | assert(device != NULL); |
| 57 | | assert(device->type() == GOMOKU); |
| 53 | gomoku_sound_channel *voice; |
| 54 | int ch; |
| 58 | 55 | |
| 59 | | return (gomoku_sound_state *)downcast<gomoku_sound_device *>(device)->token(); |
| 60 | | } |
| 56 | /* get stream channels */ |
| 57 | m_stream = stream_alloc(0, 1, samplerate); |
| 61 | 58 | |
| 59 | /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */ |
| 60 | m_mixer_buffer = auto_alloc_array(machine(), short, 2 * samplerate); |
| 61 | m_mixer_buffer_2 = m_mixer_buffer + samplerate; |
| 62 | 62 | |
| 63 | | /* build a table to divide by the number of voices; gain is specified as gain*16 */ |
| 64 | | static void make_mixer_table(device_t *device, int voices, int gain) |
| 65 | | { |
| 66 | | gomoku_sound_state *state = get_safe_token(device); |
| 67 | | int count = voices * 128; |
| 68 | | int i; |
| 63 | /* build the mixer table */ |
| 64 | make_mixer_table(8, defgain); |
| 69 | 65 | |
| 70 | | /* allocate memory */ |
| 71 | | state->m_mixer_table = auto_alloc_array(device->machine(), INT16, 256 * voices); |
| 66 | /* extract globals from the interface */ |
| 67 | m_num_voices = GOMOKU_MAX_VOICES; |
| 68 | m_last_channel = m_channel_list + m_num_voices; |
| 72 | 69 | |
| 73 | | /* find the middle of the table */ |
| 74 | | state->m_mixer_lookup = state->m_mixer_table + (128 * voices); |
| 70 | m_sound_rom = memregion("gomoku")->base(); |
| 75 | 71 | |
| 76 | | /* fill in the table - 16 bit case */ |
| 77 | | for (i = 0; i < count; i++) |
| 72 | /* start with sound enabled, many games don't have a sound enable register */ |
| 73 | m_sound_enable = 1; |
| 74 | |
| 75 | /* reset all the voices */ |
| 76 | for (ch = 0, voice = m_channel_list; voice < m_last_channel; ch++, voice++) |
| 78 | 77 | { |
| 79 | | int val = i * gain * 16 / voices; |
| 80 | | if (val > 32767) val = 32767; |
| 81 | | state->m_mixer_lookup[ i] = val; |
| 82 | | state->m_mixer_lookup[-i] = -val; |
| 78 | voice->channel = ch; |
| 79 | voice->frequency = 0; |
| 80 | voice->counter = 0; |
| 81 | voice->volume = 0; |
| 82 | voice->oneshotplaying = 0; |
| 83 | 83 | } |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | |
| 87 | | /* generate sound to the mix buffer in mono */ |
| 88 | | static STREAM_UPDATE( gomoku_update_mono ) |
| 87 | //------------------------------------------------- |
| 88 | // sound_stream_update - handle a stream update in mono |
| 89 | //------------------------------------------------- |
| 90 | |
| 91 | void gomoku_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 89 | 92 | { |
| 90 | | gomoku_sound_state *state = get_safe_token(device); |
| 91 | 93 | stream_sample_t *buffer = outputs[0]; |
| 92 | | sound_channel *voice; |
| 94 | gomoku_sound_channel *voice; |
| 93 | 95 | short *mix; |
| 94 | 96 | int i, ch; |
| 95 | 97 | |
| 96 | 98 | /* if no sound, we're done */ |
| 97 | | if (state->m_sound_enable == 0) |
| 99 | if (m_sound_enable == 0) |
| 98 | 100 | { |
| 99 | 101 | memset(buffer, 0, samples * sizeof(*buffer)); |
| 100 | 102 | return; |
| 101 | 103 | } |
| 102 | 104 | |
| 103 | 105 | /* zap the contents of the mixer buffer */ |
| 104 | | memset(state->m_mixer_buffer, 0, samples * sizeof(short)); |
| 106 | memset(m_mixer_buffer, 0, samples * sizeof(short)); |
| 105 | 107 | |
| 106 | 108 | /* loop over each voice and add its contribution */ |
| 107 | | for (ch = 0, voice = state->m_channel_list; voice < state->m_last_channel; ch++, voice++) |
| 109 | for (ch = 0, voice = m_channel_list; voice < m_last_channel; ch++, voice++) |
| 108 | 110 | { |
| 109 | 111 | int f = 16 * voice->frequency; |
| 110 | 112 | int v = voice->volume; |
| r21519 | r21520 | |
| 116 | 118 | int c = voice->counter; |
| 117 | 119 | |
| 118 | 120 | if (ch < 3) |
| 119 | | w_base = 0x20 * (state->m_soundregs1[0x06 + (ch * 8)] & 0x0f); |
| 121 | w_base = 0x20 * (m_soundregs1[0x06 + (ch * 8)] & 0x0f); |
| 120 | 122 | else |
| 121 | | w_base = 0x100 * (state->m_soundregs2[0x1d] & 0x0f); |
| 123 | w_base = 0x100 * (m_soundregs2[0x1d] & 0x0f); |
| 122 | 124 | |
| 123 | | mix = state->m_mixer_buffer; |
| 125 | mix = m_mixer_buffer; |
| 124 | 126 | |
| 125 | 127 | /* add our contribution */ |
| 126 | 128 | for (i = 0; i < samples; i++) |
| r21519 | r21520 | |
| 133 | 135 | |
| 134 | 136 | /* use full byte, first the high 4 bits, then the low 4 bits */ |
| 135 | 137 | if (c & 0x8000) |
| 136 | | *mix++ += ((state->m_sound_rom[offs] & 0x0f) - 8) * v; |
| 138 | *mix++ += ((m_sound_rom[offs] & 0x0f) - 8) * v; |
| 137 | 139 | else |
| 138 | | *mix++ += (((state->m_sound_rom[offs]>>4) & 0x0f) - 8) * v; |
| 140 | *mix++ += (((m_sound_rom[offs]>>4) & 0x0f) - 8) * v; |
| 139 | 141 | } |
| 140 | 142 | else |
| 141 | 143 | { |
| 142 | 144 | int offs = (w_base + (c >> 16)) & 0x0fff; |
| 143 | 145 | |
| 144 | | if (state->m_sound_rom[offs] == 0xff) |
| 146 | if (m_sound_rom[offs] == 0xff) |
| 145 | 147 | { |
| 146 | 148 | voice->oneshotplaying = 0; |
| 147 | 149 | } |
| r21519 | r21520 | |
| 150 | 152 | { |
| 151 | 153 | /* use full byte, first the high 4 bits, then the low 4 bits */ |
| 152 | 154 | if (c & 0x8000) |
| 153 | | *mix++ += ((state->m_sound_rom[offs] & 0x0f) - 8) * v; |
| 155 | *mix++ += ((m_sound_rom[offs] & 0x0f) - 8) * v; |
| 154 | 156 | else |
| 155 | | *mix++ += (((state->m_sound_rom[offs]>>4) & 0x0f) - 8) * v; |
| 157 | *mix++ += (((m_sound_rom[offs]>>4) & 0x0f) - 8) * v; |
| 156 | 158 | } |
| 157 | 159 | } |
| 158 | 160 | |
| r21519 | r21520 | |
| 163 | 165 | } |
| 164 | 166 | |
| 165 | 167 | /* mix it down */ |
| 166 | | mix = state->m_mixer_buffer; |
| 168 | mix = m_mixer_buffer; |
| 167 | 169 | for (i = 0; i < samples; i++) |
| 168 | | *buffer++ = state->m_mixer_lookup[*mix++]; |
| 170 | *buffer++ = m_mixer_lookup[*mix++]; |
| 169 | 171 | } |
| 170 | 172 | |
| 171 | 173 | |
| 172 | | |
| 173 | | static DEVICE_START( gomoku_sound ) |
| 174 | /* build a table to divide by the number of voices; gain is specified as gain*16 */ |
| 175 | void gomoku_sound_device::make_mixer_table(int voices, int gain) |
| 174 | 176 | { |
| 175 | | gomoku_sound_state *state = get_safe_token(device); |
| 176 | | running_machine &machine = device->machine(); |
| 177 | | sound_channel *voice; |
| 178 | | int ch; |
| 177 | int count = voices * 128; |
| 178 | int i; |
| 179 | 179 | |
| 180 | | /* get stream channels */ |
| 181 | | state->m_stream = device->machine().sound().stream_alloc(*device, 0, 1, samplerate, NULL, gomoku_update_mono); |
| 180 | /* allocate memory */ |
| 181 | m_mixer_table = auto_alloc_array(machine(), INT16, 256 * voices); |
| 182 | 182 | |
| 183 | | /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */ |
| 184 | | state->m_mixer_buffer = auto_alloc_array(machine, short, 2 * samplerate); |
| 185 | | state->m_mixer_buffer_2 = state->m_mixer_buffer + samplerate; |
| 183 | /* find the middle of the table */ |
| 184 | m_mixer_lookup = m_mixer_table + (128 * voices); |
| 186 | 185 | |
| 187 | | /* build the mixer table */ |
| 188 | | make_mixer_table(device, 8, defgain); |
| 189 | | |
| 190 | | /* extract globals from the interface */ |
| 191 | | state->m_num_voices = MAX_VOICES; |
| 192 | | state->m_last_channel = state->m_channel_list + state->m_num_voices; |
| 193 | | |
| 194 | | state->m_sound_rom = machine.root_device().memregion("gomoku")->base(); |
| 195 | | |
| 196 | | /* start with sound enabled, many games don't have a sound enable register */ |
| 197 | | state->m_sound_enable = 1; |
| 198 | | |
| 199 | | /* reset all the voices */ |
| 200 | | for (ch = 0, voice = state->m_channel_list; voice < state->m_last_channel; ch++, voice++) |
| 186 | /* fill in the table - 16 bit case */ |
| 187 | for (i = 0; i < count; i++) |
| 201 | 188 | { |
| 202 | | voice->channel = ch; |
| 203 | | voice->frequency = 0; |
| 204 | | voice->counter = 0; |
| 205 | | voice->volume = 0; |
| 206 | | voice->oneshotplaying = 0; |
| 189 | int val = i * gain * 16 / voices; |
| 190 | if (val > 32767) val = 32767; |
| 191 | m_mixer_lookup[ i] = val; |
| 192 | m_mixer_lookup[-i] = -val; |
| 207 | 193 | } |
| 208 | 194 | } |
| 209 | 195 | |
| 210 | 196 | |
| 211 | 197 | /********************************************************************************/ |
| 212 | 198 | |
| 213 | | WRITE8_DEVICE_HANDLER( gomoku_sound1_w ) |
| 199 | WRITE8_MEMBER( gomoku_sound_device::sound1_w ) |
| 214 | 200 | { |
| 215 | | gomoku_sound_state *state = get_safe_token(device); |
| 216 | | sound_channel *voice; |
| 201 | gomoku_sound_channel *voice; |
| 217 | 202 | int base; |
| 218 | 203 | int ch; |
| 219 | 204 | |
| 220 | 205 | /* update the streams */ |
| 221 | | state->m_stream->update(); |
| 206 | m_stream->update(); |
| 222 | 207 | |
| 223 | 208 | /* set the register */ |
| 224 | | state->m_soundregs1[offset] = data; |
| 209 | m_soundregs1[offset] = data; |
| 225 | 210 | |
| 226 | 211 | /* recompute all the voice parameters */ |
| 227 | | for (ch = 0, base = 0, voice = state->m_channel_list; voice < state->m_channel_list + 3; ch++, voice++, base += 8) |
| 212 | for (ch = 0, base = 0, voice = m_channel_list; voice < m_channel_list + 3; ch++, voice++, base += 8) |
| 228 | 213 | { |
| 229 | 214 | voice->channel = ch; |
| 230 | | voice->frequency = state->m_soundregs1[0x02 + base] & 0x0f; |
| 231 | | voice->frequency = voice->frequency * 16 + ((state->m_soundregs1[0x01 + base]) & 0x0f); |
| 232 | | voice->frequency = voice->frequency * 16 + ((state->m_soundregs1[0x00 + base]) & 0x0f); |
| 215 | voice->frequency = m_soundregs1[0x02 + base] & 0x0f; |
| 216 | voice->frequency = voice->frequency * 16 + ((m_soundregs1[0x01 + base]) & 0x0f); |
| 217 | voice->frequency = voice->frequency * 16 + ((m_soundregs1[0x00 + base]) & 0x0f); |
| 233 | 218 | } |
| 234 | 219 | } |
| 235 | 220 | |
| 236 | | WRITE8_DEVICE_HANDLER( gomoku_sound2_w ) |
| 221 | WRITE8_MEMBER( gomoku_sound_device::sound2_w ) |
| 237 | 222 | { |
| 238 | | gomoku_sound_state *state = get_safe_token(device); |
| 239 | | sound_channel *voice; |
| 223 | gomoku_sound_channel *voice; |
| 240 | 224 | int base; |
| 241 | 225 | int ch; |
| 242 | 226 | |
| 243 | 227 | /* update the streams */ |
| 244 | | state->m_stream->update(); |
| 228 | m_stream->update(); |
| 245 | 229 | |
| 246 | 230 | /* set the register */ |
| 247 | | state->m_soundregs2[offset] = data; |
| 231 | m_soundregs2[offset] = data; |
| 248 | 232 | |
| 249 | 233 | /* recompute all the voice parameters */ |
| 250 | | for (ch = 0, base = 0, voice = state->m_channel_list; voice < state->m_channel_list + 3; ch++, voice++, base += 8) |
| 234 | for (ch = 0, base = 0, voice = m_channel_list; voice < m_channel_list + 3; ch++, voice++, base += 8) |
| 251 | 235 | { |
| 252 | 236 | voice->channel = ch; |
| 253 | | voice->volume = state->m_soundregs2[0x06 + base] & 0x0f; |
| 237 | voice->volume = m_soundregs2[0x06 + base] & 0x0f; |
| 254 | 238 | voice->oneshotplaying = 0; |
| 255 | 239 | } |
| 256 | 240 | |
| 257 | 241 | if (offset == 0x1d) |
| 258 | 242 | { |
| 259 | | voice = &state->m_channel_list[3]; |
| 243 | voice = &m_channel_list[3]; |
| 260 | 244 | voice->channel = 3; |
| 261 | 245 | |
| 262 | 246 | // oneshot frequency is hand tune... |
| 263 | | if ((state->m_soundregs2[0x1d] & 0x0f) < 0x0c) |
| 247 | if ((m_soundregs2[0x1d] & 0x0f) < 0x0c) |
| 264 | 248 | voice->frequency = 3000 / 16; // ichi, ni, san, yon, go |
| 265 | 249 | else |
| 266 | 250 | voice->frequency = 8000 / 16; // shoot |
| r21519 | r21520 | |
| 268 | 252 | voice->volume = 8; |
| 269 | 253 | voice->counter = 0; |
| 270 | 254 | |
| 271 | | if (state->m_soundregs2[0x1d] & 0x0f) |
| 255 | if (m_soundregs2[0x1d] & 0x0f) |
| 272 | 256 | voice->oneshotplaying = 1; |
| 273 | 257 | else |
| 274 | 258 | voice->oneshotplaying = 0; |
| 275 | 259 | } |
| 276 | 260 | } |
| 277 | 261 | |
| 278 | | |
| 279 | | const device_type GOMOKU = &device_creator<gomoku_sound_device>; |
| 280 | | |
| 281 | | gomoku_sound_device::gomoku_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 282 | | : device_t(mconfig, GOMOKU, "Gomoku Custom", tag, owner, clock), |
| 283 | | device_sound_interface(mconfig, *this) |
| 284 | | { |
| 285 | | m_token = global_alloc_clear(gomoku_sound_state); |
| 286 | | } |
| 287 | | |
| 288 | | //------------------------------------------------- |
| 289 | | // device_config_complete - perform any |
| 290 | | // operations now that the configuration is |
| 291 | | // complete |
| 292 | | //------------------------------------------------- |
| 293 | | |
| 294 | | void gomoku_sound_device::device_config_complete() |
| 295 | | { |
| 296 | | } |
| 297 | | |
| 298 | | //------------------------------------------------- |
| 299 | | // device_start - device-specific startup |
| 300 | | //------------------------------------------------- |
| 301 | | |
| 302 | | void gomoku_sound_device::device_start() |
| 303 | | { |
| 304 | | DEVICE_START_NAME( gomoku_sound )(this); |
| 305 | | } |
| 306 | | |
| 307 | | //------------------------------------------------- |
| 308 | | // sound_stream_update - handle a stream update |
| 309 | | //------------------------------------------------- |
| 310 | | |
| 311 | | void gomoku_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 312 | | { |
| 313 | | // should never get here |
| 314 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 315 | | } |
trunk/src/emu/sound/c140.c
| r21519 | r21520 | |
| 46 | 46 | #include "emu.h" |
| 47 | 47 | #include "c140.h" |
| 48 | 48 | |
| 49 | | #define MAX_VOICE 24 |
| 50 | | |
| 51 | 49 | struct voice_registers |
| 52 | 50 | { |
| 53 | 51 | UINT8 volume_right; |
| r21519 | r21520 | |
| 65 | 63 | UINT8 reserved[4]; |
| 66 | 64 | }; |
| 67 | 65 | |
| 68 | | struct VOICE |
| 69 | | { |
| 70 | | long ptoffset; |
| 71 | | long pos; |
| 72 | | long key; |
| 73 | | //--work |
| 74 | | long lastdt; |
| 75 | | long prevdt; |
| 76 | | long dltdt; |
| 77 | | //--reg |
| 78 | | long rvol; |
| 79 | | long lvol; |
| 80 | | long frequency; |
| 81 | | long bank; |
| 82 | | long mode; |
| 83 | 66 | |
| 84 | | long sample_start; |
| 85 | | long sample_end; |
| 86 | | long sample_loop; |
| 87 | | }; |
| 67 | // device type definition |
| 68 | const device_type C140 = &device_creator<c140_device>; |
| 88 | 69 | |
| 89 | | struct c140_state |
| 90 | | { |
| 91 | | int sample_rate; |
| 92 | | sound_stream *stream; |
| 93 | | int banking_type; |
| 94 | | /* internal buffers */ |
| 95 | | INT16 *mixer_buffer_left; |
| 96 | | INT16 *mixer_buffer_right; |
| 97 | 70 | |
| 98 | | int baserate; |
| 99 | | void *pRom; |
| 100 | | UINT8 REG[0x200]; |
| 71 | //************************************************************************** |
| 72 | // LIVE DEVICE |
| 73 | //************************************************************************** |
| 101 | 74 | |
| 102 | | INT16 pcmtbl[8]; //2000.06.26 CAB |
| 103 | | |
| 104 | | VOICE voi[MAX_VOICE]; |
| 105 | | }; |
| 106 | | |
| 107 | | INLINE c140_state *get_safe_token(device_t *device) |
| 75 | INLINE int limit(INT32 in) |
| 108 | 76 | { |
| 109 | | assert(device != NULL); |
| 110 | | assert(device->type() == C140); |
| 111 | | return (c140_state *)downcast<c140_device *>(device)->token(); |
| 77 | if(in>0x7fff) return 0x7fff; |
| 78 | else if(in<-0x8000) return -0x8000; |
| 79 | return in; |
| 112 | 80 | } |
| 113 | 81 | |
| 114 | 82 | |
| 115 | | static void init_voice( VOICE *v ) |
| 83 | //------------------------------------------------- |
| 84 | // c140_device - constructor |
| 85 | //------------------------------------------------- |
| 86 | |
| 87 | c140_device::c140_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 88 | : device_t(mconfig, C140, "C140", tag, owner, clock), |
| 89 | device_sound_interface(mconfig, *this), |
| 90 | m_sample_rate(0), |
| 91 | m_stream(NULL), |
| 92 | m_banking_type(0), |
| 93 | m_mixer_buffer_left(NULL), |
| 94 | m_mixer_buffer_right(NULL), |
| 95 | m_baserate(0), |
| 96 | m_pRom(NULL) |
| 116 | 97 | { |
| 117 | | v->key=0; |
| 118 | | v->ptoffset=0; |
| 119 | | v->rvol=0; |
| 120 | | v->lvol=0; |
| 121 | | v->frequency=0; |
| 122 | | v->bank=0; |
| 123 | | v->mode=0; |
| 124 | | v->sample_start=0; |
| 125 | | v->sample_end=0; |
| 126 | | v->sample_loop=0; |
| 98 | memset(m_REG, 0, sizeof(UINT8)*0x200); |
| 99 | memset(m_pcmtbl, 0, sizeof(INT16)*8); |
| 127 | 100 | } |
| 128 | | READ8_DEVICE_HANDLER( c140_r ) |
| 129 | | { |
| 130 | | c140_state *info = get_safe_token(device); |
| 131 | | offset&=0x1ff; |
| 132 | | return info->REG[offset]; |
| 133 | | } |
| 134 | 101 | |
| 135 | | /* |
| 136 | | find_sample: compute the actual address of a sample given it's |
| 137 | | address and banking registers, as well as the board type. |
| 138 | 102 | |
| 139 | | I suspect in "real life" this works like the Sega MultiPCM where the banking |
| 140 | | is done by a small PAL or GAL external to the sound chip, which can be switched |
| 141 | | per-game or at least per-PCB revision as addressing range needs grow. |
| 142 | | */ |
| 143 | | static long find_sample(c140_state *info, long adrs, long bank, int voice) |
| 103 | //------------------------------------------------- |
| 104 | // device_start - device-specific startup |
| 105 | //------------------------------------------------- |
| 106 | |
| 107 | void c140_device::device_start() |
| 144 | 108 | { |
| 145 | | long newadr = 0; |
| 109 | const c140_interface *intf = (const c140_interface *)static_config(); |
| 146 | 110 | |
| 147 | | static const INT16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 }; |
| 111 | m_sample_rate=m_baserate=clock(); |
| 148 | 112 | |
| 149 | | adrs=(bank<<16)+adrs; |
| 113 | m_banking_type = intf->banking_type; |
| 150 | 114 | |
| 151 | | switch (info->banking_type) |
| 152 | | { |
| 153 | | case C140_TYPE_SYSTEM2: |
| 154 | | // System 2 banking |
| 155 | | newadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff); |
| 156 | | break; |
| 115 | m_stream = stream_alloc(0, 2, m_sample_rate); |
| 157 | 116 | |
| 158 | | case C140_TYPE_SYSTEM21: |
| 159 | | // System 21 banking. |
| 160 | | // similar to System 2's. |
| 161 | | newadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff); |
| 162 | | break; |
| 117 | m_pRom=*region(); |
| 163 | 118 | |
| 164 | | case C140_TYPE_ASIC219: |
| 165 | | // ASIC219's banking is fairly simple |
| 166 | | newadr = ((info->REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs; |
| 167 | | break; |
| 168 | | } |
| 169 | | |
| 170 | | return (newadr); |
| 171 | | } |
| 172 | | WRITE8_DEVICE_HANDLER( c140_w ) |
| 173 | | { |
| 174 | | c140_state *info = get_safe_token(device); |
| 175 | | info->stream->update(); |
| 176 | | |
| 177 | | offset&=0x1ff; |
| 178 | | |
| 179 | | // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE) |
| 180 | | if ((offset >= 0x1f8) && (info->banking_type == C140_TYPE_ASIC219)) |
| 119 | /* make decompress pcm table */ //2000.06.26 CAB |
| 181 | 120 | { |
| 182 | | offset -= 8; |
| 121 | int i; |
| 122 | INT32 segbase=0; |
| 123 | for(i=0;i<8;i++) |
| 124 | { |
| 125 | m_pcmtbl[i]=segbase; //segment base value |
| 126 | segbase += 16<<i; |
| 127 | } |
| 183 | 128 | } |
| 184 | 129 | |
| 185 | | info->REG[offset]=data; |
| 186 | | if( offset<0x180 ) |
| 130 | memset(m_REG,0,sizeof(m_REG)); |
| 187 | 131 | { |
| 188 | | VOICE *v = &info->voi[offset>>4]; |
| 189 | | |
| 190 | | if( (offset&0xf)==0x5 ) |
| 191 | | { |
| 192 | | if( data&0x80 ) |
| 193 | | { |
| 194 | | const struct voice_registers *vreg = (struct voice_registers *) &info->REG[offset&0x1f0]; |
| 195 | | v->key=1; |
| 196 | | v->ptoffset=0; |
| 197 | | v->pos=0; |
| 198 | | v->lastdt=0; |
| 199 | | v->prevdt=0; |
| 200 | | v->dltdt=0; |
| 201 | | v->bank = vreg->bank; |
| 202 | | v->mode = data; |
| 203 | | |
| 204 | | // on the 219 asic, addresses are in words |
| 205 | | if (info->banking_type == C140_TYPE_ASIC219) |
| 206 | | { |
| 207 | | v->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2; |
| 208 | | v->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2; |
| 209 | | v->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2; |
| 210 | | |
| 211 | | #if 0 |
| 212 | | logerror("219: play v %d mode %02x start %x loop %x end %x\n", |
| 213 | | offset>>4, v->mode, |
| 214 | | find_sample(info, v->sample_start, v->bank, offset>>4), |
| 215 | | find_sample(info, v->sample_loop, v->bank, offset>>4), |
| 216 | | find_sample(info, v->sample_end, v->bank, offset>>4)); |
| 217 | | #endif |
| 218 | | } |
| 219 | | else |
| 220 | | { |
| 221 | | v->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb; |
| 222 | | v->sample_start = vreg->start_msb*256 + vreg->start_lsb; |
| 223 | | v->sample_end = vreg->end_msb*256 + vreg->end_lsb; |
| 224 | | } |
| 225 | | } |
| 226 | | else |
| 227 | | { |
| 228 | | v->key=0; |
| 229 | | } |
| 230 | | } |
| 132 | int i; |
| 133 | for(i=0;i<C140_MAX_VOICE;i++) init_voice( &m_voi[i] ); |
| 231 | 134 | } |
| 232 | | } |
| 233 | 135 | |
| 234 | | void c140_set_base(device_t *device, void *base) |
| 235 | | { |
| 236 | | c140_state *info = get_safe_token(device); |
| 237 | | info->pRom = base; |
| 136 | /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */ |
| 137 | m_mixer_buffer_left = auto_alloc_array(machine(), INT16, 2 * m_sample_rate); |
| 138 | m_mixer_buffer_right = m_mixer_buffer_left + m_sample_rate; |
| 238 | 139 | } |
| 239 | 140 | |
| 240 | | INLINE int limit(INT32 in) |
| 241 | | { |
| 242 | | if(in>0x7fff) return 0x7fff; |
| 243 | | else if(in<-0x8000) return -0x8000; |
| 244 | | return in; |
| 245 | | } |
| 246 | 141 | |
| 247 | | static STREAM_UPDATE( update_stereo ) |
| 142 | //------------------------------------------------- |
| 143 | // sound_stream_update - handle a stream update |
| 144 | //------------------------------------------------- |
| 145 | |
| 146 | void c140_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 248 | 147 | { |
| 249 | | c140_state *info = (c140_state *)param; |
| 250 | 148 | int i,j; |
| 251 | 149 | |
| 252 | 150 | INT32 rvol,lvol; |
| r21519 | r21520 | |
| 258 | 156 | INT32 frequency,delta,offset,pos; |
| 259 | 157 | INT32 cnt, voicecnt; |
| 260 | 158 | INT32 lastdt,prevdt,dltdt; |
| 261 | | float pbase=(float)info->baserate*2.0 / (float)info->sample_rate; |
| 159 | float pbase=(float)m_baserate*2.0 / (float)m_sample_rate; |
| 262 | 160 | |
| 263 | 161 | INT16 *lmix, *rmix; |
| 264 | 162 | |
| 265 | | if(samples>info->sample_rate) samples=info->sample_rate; |
| 163 | if(samples>m_sample_rate) samples=m_sample_rate; |
| 266 | 164 | |
| 267 | 165 | /* zap the contents of the mixer buffer */ |
| 268 | | memset(info->mixer_buffer_left, 0, samples * sizeof(INT16)); |
| 269 | | memset(info->mixer_buffer_right, 0, samples * sizeof(INT16)); |
| 166 | memset(m_mixer_buffer_left, 0, samples * sizeof(INT16)); |
| 167 | memset(m_mixer_buffer_right, 0, samples * sizeof(INT16)); |
| 270 | 168 | |
| 271 | 169 | /* get the number of voices to update */ |
| 272 | | voicecnt = (info->banking_type == C140_TYPE_ASIC219) ? 16 : 24; |
| 170 | voicecnt = (m_banking_type == C140_TYPE_ASIC219) ? 16 : 24; |
| 273 | 171 | |
| 274 | 172 | //--- audio update |
| 275 | 173 | for( i=0;i<voicecnt;i++ ) |
| 276 | 174 | { |
| 277 | | VOICE *v = &info->voi[i]; |
| 278 | | const struct voice_registers *vreg = (struct voice_registers *)&info->REG[i*16]; |
| 175 | C140_VOICE *v = &m_voi[i]; |
| 176 | const struct voice_registers *vreg = (struct voice_registers *)&m_REG[i*16]; |
| 279 | 177 | |
| 280 | 178 | if( v->key ) |
| 281 | 179 | { |
| r21519 | r21520 | |
| 288 | 186 | delta=(long)((float)frequency * pbase); |
| 289 | 187 | |
| 290 | 188 | /* Calculate left/right channel volumes */ |
| 291 | | lvol=(vreg->volume_left*32)/MAX_VOICE; //32ch -> 24ch |
| 292 | | rvol=(vreg->volume_right*32)/MAX_VOICE; |
| 189 | lvol=(vreg->volume_left*32)/C140_MAX_VOICE; //32ch -> 24ch |
| 190 | rvol=(vreg->volume_right*32)/C140_MAX_VOICE; |
| 293 | 191 | |
| 294 | 192 | /* Set mixer outputs base pointers */ |
| 295 | | lmix = info->mixer_buffer_left; |
| 296 | | rmix = info->mixer_buffer_right; |
| 193 | lmix = m_mixer_buffer_left; |
| 194 | rmix = m_mixer_buffer_right; |
| 297 | 195 | |
| 298 | 196 | /* Retrieve sample start/end and calculate size */ |
| 299 | 197 | st=v->sample_start; |
| r21519 | r21520 | |
| 301 | 199 | sz=ed-st; |
| 302 | 200 | |
| 303 | 201 | /* Retrieve base pointer to the sample data */ |
| 304 | | pSampleData=(signed char*)((FPTR)info->pRom + find_sample(info, st, v->bank, i)); |
| 202 | pSampleData=(signed char*)((FPTR)m_pRom + find_sample(st, v->bank, i)); |
| 305 | 203 | |
| 306 | 204 | /* Fetch back previous data pointers */ |
| 307 | 205 | offset=v->ptoffset; |
| r21519 | r21520 | |
| 311 | 209 | dltdt=v->dltdt; |
| 312 | 210 | |
| 313 | 211 | /* Switch on data type - compressed PCM is only for C140 */ |
| 314 | | if ((v->mode&8) && (info->banking_type != C140_TYPE_ASIC219)) |
| 212 | if ((v->mode&8) && (m_banking_type != C140_TYPE_ASIC219)) |
| 315 | 213 | { |
| 316 | 214 | //compressed PCM (maybe correct...) |
| 317 | 215 | /* Loop for enough to fill sample buffer as requested */ |
| r21519 | r21520 | |
| 343 | 241 | |
| 344 | 242 | /* decompress to 13bit range */ //2000.06.26 CAB |
| 345 | 243 | sdt=dt>>3; //signed |
| 346 | | if(sdt<0) sdt = (sdt<<(dt&7)) - info->pcmtbl[dt&7]; |
| 347 | | else sdt = (sdt<<(dt&7)) + info->pcmtbl[dt&7]; |
| 244 | if(sdt<0) sdt = (sdt<<(dt&7)) - m_pcmtbl[dt&7]; |
| 245 | else sdt = (sdt<<(dt&7)) + m_pcmtbl[dt&7]; |
| 348 | 246 | |
| 349 | 247 | prevdt=lastdt; |
| 350 | 248 | lastdt=sdt; |
| r21519 | r21520 | |
| 387 | 285 | { |
| 388 | 286 | prevdt=lastdt; |
| 389 | 287 | |
| 390 | | if (info->banking_type == C140_TYPE_ASIC219) |
| 288 | if (m_banking_type == C140_TYPE_ASIC219) |
| 391 | 289 | { |
| 392 | 290 | lastdt = pSampleData[BYTE_XOR_BE(pos)]; |
| 393 | 291 | |
| r21519 | r21520 | |
| 426 | 324 | } |
| 427 | 325 | |
| 428 | 326 | /* render to MAME's stream buffer */ |
| 429 | | lmix = info->mixer_buffer_left; |
| 430 | | rmix = info->mixer_buffer_right; |
| 327 | lmix = m_mixer_buffer_left; |
| 328 | rmix = m_mixer_buffer_right; |
| 431 | 329 | { |
| 432 | 330 | stream_sample_t *dest1 = outputs[0]; |
| 433 | 331 | stream_sample_t *dest2 = outputs[1]; |
| r21519 | r21520 | |
| 439 | 337 | } |
| 440 | 338 | } |
| 441 | 339 | |
| 442 | | static DEVICE_START( c140 ) |
| 340 | |
| 341 | READ8_MEMBER( c140_device::c140_r ) |
| 443 | 342 | { |
| 444 | | const c140_interface *intf = (const c140_interface *)device->static_config(); |
| 445 | | c140_state *info = get_safe_token(device); |
| 343 | offset&=0x1ff; |
| 344 | return m_REG[offset]; |
| 345 | } |
| 446 | 346 | |
| 447 | | info->sample_rate=info->baserate=device->clock(); |
| 448 | 347 | |
| 449 | | info->banking_type = intf->banking_type; |
| 348 | WRITE8_MEMBER( c140_device::c140_w ) |
| 349 | { |
| 350 | m_stream->update(); |
| 450 | 351 | |
| 451 | | info->stream = device->machine().sound().stream_alloc(*device,0,2,info->sample_rate,info,update_stereo); |
| 352 | offset&=0x1ff; |
| 452 | 353 | |
| 453 | | info->pRom=*device->region(); |
| 454 | | |
| 455 | | /* make decompress pcm table */ //2000.06.26 CAB |
| 354 | // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE) |
| 355 | if ((offset >= 0x1f8) && (m_banking_type == C140_TYPE_ASIC219)) |
| 456 | 356 | { |
| 457 | | int i; |
| 458 | | INT32 segbase=0; |
| 459 | | for(i=0;i<8;i++) |
| 460 | | { |
| 461 | | info->pcmtbl[i]=segbase; //segment base value |
| 462 | | segbase += 16<<i; |
| 463 | | } |
| 357 | offset -= 8; |
| 464 | 358 | } |
| 465 | 359 | |
| 466 | | memset(info->REG,0,sizeof(info->REG)); |
| 360 | m_REG[offset]=data; |
| 361 | if( offset<0x180 ) |
| 467 | 362 | { |
| 468 | | int i; |
| 469 | | for(i=0;i<MAX_VOICE;i++) init_voice( &info->voi[i] ); |
| 470 | | } |
| 363 | C140_VOICE *v = &m_voi[offset>>4]; |
| 471 | 364 | |
| 472 | | /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */ |
| 473 | | info->mixer_buffer_left = auto_alloc_array(device->machine(), INT16, 2 * info->sample_rate); |
| 474 | | info->mixer_buffer_right = info->mixer_buffer_left + info->sample_rate; |
| 475 | | } |
| 365 | if( (offset&0xf)==0x5 ) |
| 366 | { |
| 367 | if( data&0x80 ) |
| 368 | { |
| 369 | const struct voice_registers *vreg = (struct voice_registers *) &m_REG[offset&0x1f0]; |
| 370 | v->key=1; |
| 371 | v->ptoffset=0; |
| 372 | v->pos=0; |
| 373 | v->lastdt=0; |
| 374 | v->prevdt=0; |
| 375 | v->dltdt=0; |
| 376 | v->bank = vreg->bank; |
| 377 | v->mode = data; |
| 476 | 378 | |
| 477 | | const device_type C140 = &device_creator<c140_device>; |
| 379 | // on the 219 asic, addresses are in words |
| 380 | if (m_banking_type == C140_TYPE_ASIC219) |
| 381 | { |
| 382 | v->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2; |
| 383 | v->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2; |
| 384 | v->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2; |
| 478 | 385 | |
| 479 | | c140_device::c140_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 480 | | : device_t(mconfig, C140, "C140", tag, owner, clock), |
| 481 | | device_sound_interface(mconfig, *this) |
| 482 | | { |
| 483 | | m_token = global_alloc_clear(c140_state); |
| 386 | #if 0 |
| 387 | logerror("219: play v %d mode %02x start %x loop %x end %x\n", |
| 388 | offset>>4, v->mode, |
| 389 | find_sample(v->sample_start, v->bank, offset>>4), |
| 390 | find_sample(v->sample_loop, v->bank, offset>>4), |
| 391 | find_sample(v->sample_end, v->bank, offset>>4)); |
| 392 | #endif |
| 393 | } |
| 394 | else |
| 395 | { |
| 396 | v->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb; |
| 397 | v->sample_start = vreg->start_msb*256 + vreg->start_lsb; |
| 398 | v->sample_end = vreg->end_msb*256 + vreg->end_lsb; |
| 399 | } |
| 400 | } |
| 401 | else |
| 402 | { |
| 403 | v->key=0; |
| 404 | } |
| 405 | } |
| 406 | } |
| 484 | 407 | } |
| 485 | 408 | |
| 486 | | //------------------------------------------------- |
| 487 | | // device_config_complete - perform any |
| 488 | | // operations now that the configuration is |
| 489 | | // complete |
| 490 | | //------------------------------------------------- |
| 491 | 409 | |
| 492 | | void c140_device::device_config_complete() |
| 410 | void c140_device::set_base(void *base) |
| 493 | 411 | { |
| 412 | m_pRom = base; |
| 494 | 413 | } |
| 495 | 414 | |
| 496 | | //------------------------------------------------- |
| 497 | | // device_start - device-specific startup |
| 498 | | //------------------------------------------------- |
| 499 | 415 | |
| 500 | | void c140_device::device_start() |
| 416 | void c140_device::init_voice( C140_VOICE *v ) |
| 501 | 417 | { |
| 502 | | DEVICE_START_NAME( c140 )(this); |
| 418 | v->key=0; |
| 419 | v->ptoffset=0; |
| 420 | v->rvol=0; |
| 421 | v->lvol=0; |
| 422 | v->frequency=0; |
| 423 | v->bank=0; |
| 424 | v->mode=0; |
| 425 | v->sample_start=0; |
| 426 | v->sample_end=0; |
| 427 | v->sample_loop=0; |
| 503 | 428 | } |
| 504 | 429 | |
| 505 | | //------------------------------------------------- |
| 506 | | // sound_stream_update - handle a stream update |
| 507 | | //------------------------------------------------- |
| 508 | 430 | |
| 509 | | void c140_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 431 | /* |
| 432 | find_sample: compute the actual address of a sample given it's |
| 433 | address and banking registers, as well as the board type. |
| 434 | |
| 435 | I suspect in "real life" this works like the Sega MultiPCM where the banking |
| 436 | is done by a small PAL or GAL external to the sound chip, which can be switched |
| 437 | per-game or at least per-PCB revision as addressing range needs grow. |
| 438 | */ |
| 439 | long c140_device::find_sample(long adrs, long bank, int voice) |
| 510 | 440 | { |
| 511 | | // should never get here |
| 512 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 441 | long newadr = 0; |
| 442 | |
| 443 | static const INT16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 }; |
| 444 | |
| 445 | adrs=(bank<<16)+adrs; |
| 446 | |
| 447 | switch (m_banking_type) |
| 448 | { |
| 449 | case C140_TYPE_SYSTEM2: |
| 450 | // System 2 banking |
| 451 | newadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff); |
| 452 | break; |
| 453 | |
| 454 | case C140_TYPE_SYSTEM21: |
| 455 | // System 21 banking. |
| 456 | // similar to System 2's. |
| 457 | newadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff); |
| 458 | break; |
| 459 | |
| 460 | case C140_TYPE_ASIC219: |
| 461 | // ASIC219's banking is fairly simple |
| 462 | newadr = ((m_REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs; |
| 463 | break; |
| 464 | } |
| 465 | |
| 466 | return (newadr); |
| 513 | 467 | } |
trunk/src/emu/sound/astrocde.c
| r21519 | r21520 | |
| 43 | 43 | #include "astrocde.h" |
| 44 | 44 | |
| 45 | 45 | |
| 46 | | struct astrocade_state |
| 47 | | { |
| 48 | | sound_stream *stream; /* sound stream */ |
| 46 | // device type definition |
| 47 | const device_type ASTROCADE = &device_creator<astrocade_device>; |
| 49 | 48 | |
| 50 | | UINT8 reg[8]; /* 8 control registers */ |
| 51 | 49 | |
| 52 | | UINT8 master_count; /* current master oscillator count */ |
| 53 | | UINT16 vibrato_clock; /* current vibrato clock */ |
| 50 | //************************************************************************** |
| 51 | // LIVE DEVICE |
| 52 | //************************************************************************** |
| 54 | 53 | |
| 55 | | UINT8 noise_clock; /* current noise generator clock */ |
| 56 | | UINT16 noise_state; /* current noise LFSR state */ |
| 54 | //------------------------------------------------- |
| 55 | // astrocade_device - constructor |
| 56 | //------------------------------------------------- |
| 57 | 57 | |
| 58 | | UINT8 a_count; /* current tone generator A count */ |
| 59 | | UINT8 a_state; /* current tone generator A state */ |
| 58 | astrocade_device::astrocade_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 59 | : device_t(mconfig, ASTROCADE, "Astrocade", tag, owner, clock), |
| 60 | device_sound_interface(mconfig, *this), |
| 61 | m_stream(NULL), |
| 62 | m_master_count(0), |
| 63 | m_vibrato_clock(0), |
| 64 | m_noise_clock(0), |
| 65 | m_noise_state(0), |
| 66 | m_a_count(0), |
| 67 | m_a_state(0), |
| 68 | m_b_count(0), |
| 69 | m_b_state(0), |
| 70 | m_c_count(0), |
| 71 | m_c_state(0) |
| 72 | { |
| 73 | memset(m_reg, 0, sizeof(UINT8)*8); |
| 74 | memset(m_bitswap, 0, sizeof(UINT8)*256); |
| 75 | } |
| 60 | 76 | |
| 61 | | UINT8 b_count; /* current tone generator B count */ |
| 62 | | UINT8 b_state; /* current tone generator B state */ |
| 63 | 77 | |
| 64 | | UINT8 c_count; /* current tone generator C count */ |
| 65 | | UINT8 c_state; /* current tone generator C state */ |
| 78 | //------------------------------------------------- |
| 79 | // device_start - device-specific startup |
| 80 | //------------------------------------------------- |
| 66 | 81 | |
| 67 | | UINT8 bitswap[256]; /* bitswap table */ |
| 68 | | }; |
| 82 | void astrocade_device::device_start() |
| 83 | { |
| 84 | int i; |
| 69 | 85 | |
| 86 | /* generate a bitswap table for the noise */ |
| 87 | for (i = 0; i < 256; i++) |
| 88 | m_bitswap[i] = BITSWAP8(i, 0,1,2,3,4,5,6,7); |
| 70 | 89 | |
| 71 | | INLINE astrocade_state *get_safe_token(device_t *device) |
| 72 | | { |
| 73 | | assert(device != NULL); |
| 74 | | assert(device->type() == ASTROCADE); |
| 75 | | return (astrocade_state *)downcast<astrocade_device *>(device)->token(); |
| 90 | /* allocate a stream for output */ |
| 91 | m_stream = stream_alloc(0, 1, clock()); |
| 92 | |
| 93 | /* reset state */ |
| 94 | device_reset(); |
| 95 | state_save_register(); |
| 76 | 96 | } |
| 77 | 97 | |
| 78 | 98 | |
| 99 | //------------------------------------------------- |
| 100 | // sound_stream_update - handle a stream update |
| 101 | //------------------------------------------------- |
| 79 | 102 | |
| 80 | | /************************************* |
| 81 | | * |
| 82 | | * Core sound update |
| 83 | | * |
| 84 | | *************************************/ |
| 85 | | |
| 86 | | static STREAM_UPDATE( astrocade_update ) |
| 103 | void astrocade_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 87 | 104 | { |
| 88 | | astrocade_state *chip = (astrocade_state *)param; |
| 89 | 105 | stream_sample_t *dest = outputs[0]; |
| 90 | 106 | UINT16 noise_state; |
| 91 | 107 | UINT8 master_count; |
| 92 | 108 | UINT8 noise_clock; |
| 93 | 109 | |
| 94 | 110 | /* load some locals */ |
| 95 | | master_count = chip->master_count; |
| 96 | | noise_clock = chip->noise_clock; |
| 97 | | noise_state = chip->noise_state; |
| 111 | master_count = m_master_count; |
| 112 | noise_clock = m_noise_clock; |
| 113 | noise_state = m_noise_state; |
| 98 | 114 | |
| 99 | 115 | /* loop over samples */ |
| 100 | 116 | while (samples > 0) |
| r21519 | r21520 | |
| 110 | 126 | samples -= samples_this_time; |
| 111 | 127 | |
| 112 | 128 | /* sum the output of the tone generators */ |
| 113 | | if (chip->a_state) |
| 114 | | cursample += chip->reg[6] & 0x0f; |
| 115 | | if (chip->b_state) |
| 116 | | cursample += chip->reg[6] >> 4; |
| 117 | | if (chip->c_state) |
| 118 | | cursample += chip->reg[5] & 0x0f; |
| 129 | if (m_a_state) |
| 130 | cursample += m_reg[6] & 0x0f; |
| 131 | if (m_b_state) |
| 132 | cursample += m_reg[6] >> 4; |
| 133 | if (m_c_state) |
| 134 | cursample += m_reg[5] & 0x0f; |
| 119 | 135 | |
| 120 | 136 | /* add in the noise if it is enabled, based on the top bit of the LFSR */ |
| 121 | | if ((chip->reg[5] & 0x20) && (noise_state & 0x4000)) |
| 122 | | cursample += chip->reg[7] >> 4; |
| 137 | if ((m_reg[5] & 0x20) && (noise_state & 0x4000)) |
| 138 | cursample += m_reg[7] >> 4; |
| 123 | 139 | |
| 124 | 140 | /* scale to max and output */ |
| 125 | 141 | cursample = cursample * 32767 / 60; |
| r21519 | r21520 | |
| 136 | 152 | noise_clock -= 64; |
| 137 | 153 | |
| 138 | 154 | /* the same clock also controls the vibrato clock, which is a 13-bit counter */ |
| 139 | | chip->vibrato_clock++; |
| 155 | m_vibrato_clock++; |
| 140 | 156 | } |
| 141 | 157 | |
| 142 | 158 | /* clock the master oscillator; this is an 8-bit up counter */ |
| r21519 | r21520 | |
| 144 | 160 | if (master_count == 0) |
| 145 | 161 | { |
| 146 | 162 | /* reload based on mux value -- the value from the register is negative logic */ |
| 147 | | master_count = ~chip->reg[0]; |
| 163 | master_count = ~m_reg[0]; |
| 148 | 164 | |
| 149 | 165 | /* mux value 0 means reload based on the vibrato control */ |
| 150 | | if ((chip->reg[5] & 0x10) == 0) |
| 166 | if ((m_reg[5] & 0x10) == 0) |
| 151 | 167 | { |
| 152 | 168 | /* vibrato speed (register 4 bits 6-7) selects one of the top 4 bits */ |
| 153 | 169 | /* of the 13-bit vibrato clock to use (0=highest freq, 3=lowest) */ |
| 154 | | if (!((chip->vibrato_clock >> (chip->reg[4] >> 6)) & 0x0200)) |
| 170 | if (!((m_vibrato_clock >> (m_reg[4] >> 6)) & 0x0200)) |
| 155 | 171 | { |
| 156 | 172 | /* if the bit is clear, we add the vibrato volume to the counter */ |
| 157 | | master_count += chip->reg[4] & 0x3f; |
| 173 | master_count += m_reg[4] & 0x3f; |
| 158 | 174 | } |
| 159 | 175 | } |
| 160 | 176 | |
| r21519 | r21520 | |
| 163 | 179 | { |
| 164 | 180 | /* the top 8 bits of the noise LFSR are ANDed with the noise volume */ |
| 165 | 181 | /* register and added to the count */ |
| 166 | | master_count += chip->bitswap[(noise_state >> 7) & 0xff] & chip->reg[7]; |
| 182 | master_count += m_bitswap[(noise_state >> 7) & 0xff] & m_reg[7]; |
| 167 | 183 | } |
| 168 | 184 | |
| 169 | 185 | /* clock tone A */ |
| 170 | | if (++chip->a_count == 0) |
| 186 | if (++m_a_count == 0) |
| 171 | 187 | { |
| 172 | | chip->a_state ^= 1; |
| 173 | | chip->a_count = ~chip->reg[1]; |
| 188 | m_a_state ^= 1; |
| 189 | m_a_count = ~m_reg[1]; |
| 174 | 190 | } |
| 175 | 191 | |
| 176 | 192 | /* clock tone B */ |
| 177 | | if (++chip->b_count == 0) |
| 193 | if (++m_b_count == 0) |
| 178 | 194 | { |
| 179 | | chip->b_state ^= 1; |
| 180 | | chip->b_count = ~chip->reg[2]; |
| 195 | m_b_state ^= 1; |
| 196 | m_b_count = ~m_reg[2]; |
| 181 | 197 | } |
| 182 | 198 | |
| 183 | 199 | /* clock tone C */ |
| 184 | | if (++chip->c_count == 0) |
| 200 | if (++m_c_count == 0) |
| 185 | 201 | { |
| 186 | | chip->c_state ^= 1; |
| 187 | | chip->c_count = ~chip->reg[3]; |
| 202 | m_c_state ^= 1; |
| 203 | m_c_count = ~m_reg[3]; |
| 188 | 204 | } |
| 189 | 205 | } |
| 190 | 206 | } |
| 191 | 207 | |
| 192 | 208 | /* put back the locals */ |
| 193 | | chip->master_count = master_count; |
| 194 | | chip->noise_clock = noise_clock; |
| 195 | | chip->noise_state = noise_state; |
| 209 | m_master_count = master_count; |
| 210 | m_noise_clock = noise_clock; |
| 211 | m_noise_state = noise_state; |
| 196 | 212 | } |
| 197 | 213 | |
| 198 | 214 | |
| 215 | //------------------------------------------------- |
| 216 | // device_reset - device-specific reset |
| 217 | //------------------------------------------------- |
| 199 | 218 | |
| 200 | | /************************************* |
| 201 | | * |
| 202 | | * Chip reset |
| 203 | | * |
| 204 | | *************************************/ |
| 205 | | |
| 206 | | static DEVICE_RESET( astrocade ) |
| 219 | void astrocade_device::device_reset() |
| 207 | 220 | { |
| 208 | | astrocade_state *chip = get_safe_token(device); |
| 221 | memset(m_reg, 0, sizeof(m_reg)); |
| 209 | 222 | |
| 210 | | memset(chip->reg, 0, sizeof(chip->reg)); |
| 223 | m_master_count = 0; |
| 224 | m_vibrato_clock = 0; |
| 211 | 225 | |
| 212 | | chip->master_count = 0; |
| 213 | | chip->vibrato_clock = 0; |
| 226 | m_noise_clock = 0; |
| 227 | m_noise_state = 0; |
| 214 | 228 | |
| 215 | | chip->noise_clock = 0; |
| 216 | | chip->noise_state = 0; |
| 229 | m_a_count = 0; |
| 230 | m_a_state = 0; |
| 217 | 231 | |
| 218 | | chip->a_count = 0; |
| 219 | | chip->a_state = 0; |
| 232 | m_b_count = 0; |
| 233 | m_b_state = 0; |
| 220 | 234 | |
| 221 | | chip->b_count = 0; |
| 222 | | chip->b_state = 0; |
| 223 | | |
| 224 | | chip->c_count = 0; |
| 225 | | chip->c_state = 0; |
| 235 | m_c_count = 0; |
| 236 | m_c_state = 0; |
| 226 | 237 | } |
| 227 | 238 | |
| 228 | 239 | |
| 229 | | /************************************* |
| 230 | | * |
| 231 | | * Save state registration |
| 232 | | * |
| 233 | | *************************************/ |
| 240 | //------------------------------------------------- |
| 241 | // Save state registration |
| 242 | //------------------------------------------------- |
| 234 | 243 | |
| 235 | | static void astrocade_state_save_register(astrocade_state *chip, device_t *device) |
| 244 | void astrocade_device::state_save_register() |
| 236 | 245 | { |
| 237 | | device->save_item(NAME(chip->reg)); |
| 246 | save_item(NAME(m_reg)); |
| 238 | 247 | |
| 239 | | device->save_item(NAME(chip->master_count)); |
| 240 | | device->save_item(NAME(chip->vibrato_clock)); |
| 248 | save_item(NAME(m_master_count)); |
| 249 | save_item(NAME(m_vibrato_clock)); |
| 241 | 250 | |
| 242 | | device->save_item(NAME(chip->noise_clock)); |
| 243 | | device->save_item(NAME(chip->noise_state)); |
| 251 | save_item(NAME(m_noise_clock)); |
| 252 | save_item(NAME(m_noise_state)); |
| 244 | 253 | |
| 245 | | device->save_item(NAME(chip->a_count)); |
| 246 | | device->save_item(NAME(chip->a_state)); |
| 254 | save_item(NAME(m_a_count)); |
| 255 | save_item(NAME(m_a_state)); |
| 247 | 256 | |
| 248 | | device->save_item(NAME(chip->b_count)); |
| 249 | | device->save_item(NAME(chip->b_state)); |
| 257 | save_item(NAME(m_b_count)); |
| 258 | save_item(NAME(m_b_state)); |
| 250 | 259 | |
| 251 | | device->save_item(NAME(chip->c_count)); |
| 252 | | device->save_item(NAME(chip->c_state)); |
| 260 | save_item(NAME(m_c_count)); |
| 261 | save_item(NAME(m_c_state)); |
| 253 | 262 | } |
| 254 | 263 | |
| 255 | 264 | |
| 256 | | |
| 257 | 265 | /************************************* |
| 258 | 266 | * |
| 259 | | * Chip initialization |
| 260 | | * |
| 261 | | *************************************/ |
| 262 | | |
| 263 | | static DEVICE_START( astrocade ) |
| 264 | | { |
| 265 | | astrocade_state *chip = get_safe_token(device); |
| 266 | | int i; |
| 267 | | |
| 268 | | /* generate a bitswap table for the noise */ |
| 269 | | for (i = 0; i < 256; i++) |
| 270 | | chip->bitswap[i] = BITSWAP8(i, 0,1,2,3,4,5,6,7); |
| 271 | | |
| 272 | | /* allocate a stream for output */ |
| 273 | | chip->stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock(), chip, astrocade_update); |
| 274 | | |
| 275 | | /* reset state */ |
| 276 | | DEVICE_RESET_CALL(astrocade); |
| 277 | | astrocade_state_save_register(chip, device); |
| 278 | | } |
| 279 | | |
| 280 | | |
| 281 | | |
| 282 | | /************************************* |
| 283 | | * |
| 284 | 267 | * Sound write accessors |
| 285 | 268 | * |
| 286 | 269 | *************************************/ |
| 287 | 270 | |
| 288 | | WRITE8_DEVICE_HANDLER( astrocade_sound_w ) |
| 271 | WRITE8_MEMBER( astrocade_device::astrocade_sound_w ) |
| 289 | 272 | { |
| 290 | | astrocade_state *chip = get_safe_token(device); |
| 291 | | |
| 292 | 273 | if ((offset & 8) != 0) |
| 293 | 274 | offset = (offset >> 8) & 7; |
| 294 | 275 | else |
| 295 | 276 | offset &= 7; |
| 296 | 277 | |
| 297 | 278 | /* update */ |
| 298 | | chip->stream->update(); |
| 279 | m_stream->update(); |
| 299 | 280 | |
| 300 | 281 | /* stash the new register value */ |
| 301 | | chip->reg[offset & 7] = data; |
| 282 | m_reg[offset & 7] = data; |
| 302 | 283 | } |
| 303 | 284 | |
| 304 | | const device_type ASTROCADE = &device_creator<astrocade_device>; |
| 305 | | |
| 306 | | astrocade_device::astrocade_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 307 | | : device_t(mconfig, ASTROCADE, "Astrocade", tag, owner, clock), |
| 308 | | device_sound_interface(mconfig, *this) |
| 309 | | { |
| 310 | | m_token = global_alloc_clear(astrocade_state); |
| 311 | | } |
| 312 | | |
| 313 | | //------------------------------------------------- |
| 314 | | // device_config_complete - perform any |
| 315 | | // operations now that the configuration is |
| 316 | | // complete |
| 317 | | //------------------------------------------------- |
| 318 | | |
| 319 | | void astrocade_device::device_config_complete() |
| 320 | | { |
| 321 | | } |
| 322 | | |
| 323 | | //------------------------------------------------- |
| 324 | | // device_start - device-specific startup |
| 325 | | //------------------------------------------------- |
| 326 | | |
| 327 | | void astrocade_device::device_start() |
| 328 | | { |
| 329 | | DEVICE_START_NAME( astrocade )(this); |
| 330 | | } |
| 331 | | |
| 332 | | //------------------------------------------------- |
| 333 | | // device_reset - device-specific reset |
| 334 | | //------------------------------------------------- |
| 335 | | |
| 336 | | void astrocade_device::device_reset() |
| 337 | | { |
| 338 | | DEVICE_RESET_NAME( astrocade )(this); |
| 339 | | } |
| 340 | | |
| 341 | | //------------------------------------------------- |
| 342 | | // sound_stream_update - handle a stream update |
| 343 | | //------------------------------------------------- |
| 344 | | |
| 345 | | void astrocade_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 346 | | { |
| 347 | | // should never get here |
| 348 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 349 | | } |
trunk/src/emu/sound/st0016.c
| r21519 | r21520 | |
| 9 | 9 | #define VERBOSE (0) |
| 10 | 10 | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 11 | 11 | |
| 12 | | struct st0016_device_state |
| 13 | | { |
| 14 | | sound_stream * stream; |
| 15 | | UINT8 **sound_ram; |
| 16 | | int vpos[8], frac[8], lponce[8]; |
| 17 | | UINT8 regs[0x100]; |
| 18 | | }; |
| 19 | 12 | |
| 20 | | INLINE st0016_device_state *get_safe_token(device_t *device) |
| 21 | | { |
| 22 | | assert(device != NULL); |
| 23 | | assert(device->type() == ST0016); |
| 24 | | return (st0016_device_state *)downcast<st0016_device *>(device)->token(); |
| 25 | | } |
| 13 | // device type definition |
| 14 | const device_type ST0016 = &device_creator<st0016_device>; |
| 26 | 15 | |
| 27 | 16 | |
| 28 | | READ8_DEVICE_HANDLER( st0016_snd_r ) |
| 17 | //************************************************************************** |
| 18 | // LIVE DEVICE |
| 19 | //************************************************************************** |
| 20 | |
| 21 | //------------------------------------------------- |
| 22 | // st0016_device - constructor |
| 23 | //------------------------------------------------- |
| 24 | |
| 25 | st0016_device::st0016_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 26 | : device_t(mconfig, ST0016, "ST0016", tag, owner, clock), |
| 27 | device_sound_interface(mconfig, *this), |
| 28 | m_stream(NULL), |
| 29 | m_sound_ram(NULL) |
| 29 | 30 | { |
| 30 | | st0016_device_state *info = get_safe_token(device); |
| 31 | | return info->regs[offset]; |
| 31 | memset(m_vpos, 0, sizeof(int)*8); |
| 32 | memset(m_frac, 0, sizeof(int)*8); |
| 33 | memset(m_lponce, 0, sizeof(int)*8); |
| 34 | memset(m_regs, 0, sizeof(UINT8)*0x100); |
| 32 | 35 | } |
| 33 | 36 | |
| 34 | | WRITE8_DEVICE_HANDLER( st0016_snd_w ) |
| 35 | | { |
| 36 | | st0016_device_state *info = get_safe_token(device); |
| 37 | | int voice = offset/32; |
| 38 | | int reg = offset & 0x1f; |
| 39 | | int oldreg = info->regs[offset]; |
| 40 | | int vbase = offset & ~0x1f; |
| 41 | 37 | |
| 42 | | info->regs[offset] = data; |
| 38 | //------------------------------------------------- |
| 39 | // device_start - device-specific startup |
| 40 | //------------------------------------------------- |
| 43 | 41 | |
| 44 | | if ((voice < 8) && (data != oldreg)) |
| 45 | | { |
| 46 | | if ((reg == 0x16) && (data != 0)) |
| 47 | | { |
| 48 | | info->vpos[voice] = info->frac[voice] = info->lponce[voice] = 0; |
| 42 | void st0016_device::device_start() |
| 43 | { |
| 44 | const st0016_interface *intf = (const st0016_interface *)static_config(); |
| 49 | 45 | |
| 50 | | LOG(("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice, |
| 51 | | info->regs[vbase+2]<<16 | info->regs[vbase+1]<<8 | info->regs[vbase+2], |
| 52 | | info->regs[vbase+0xe]<<16 | info->regs[vbase+0xd]<<8 | info->regs[vbase+0xc], |
| 53 | | info->regs[vbase+6]<<16 | info->regs[vbase+5]<<8 | info->regs[vbase+4], |
| 54 | | info->regs[vbase+0xa]<<16 | info->regs[vbase+0x9]<<8 | info->regs[vbase+0x8], |
| 55 | | info->regs[vbase+0x11]<<8 | info->regs[vbase+0x10], |
| 56 | | info->regs[vbase+0x16])); |
| 57 | | } |
| 58 | | } |
| 46 | m_sound_ram = intf->p_soundram; |
| 47 | |
| 48 | m_stream = stream_alloc(0, 2, 44100); |
| 59 | 49 | } |
| 60 | 50 | |
| 61 | | static STREAM_UPDATE( st0016_update ) |
| 51 | |
| 52 | //------------------------------------------------- |
| 53 | // sound_stream_update - handle a stream update |
| 54 | //------------------------------------------------- |
| 55 | |
| 56 | void st0016_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 62 | 57 | { |
| 63 | | st0016_device_state *info = (st0016_device_state *)param; |
| 64 | | UINT8 *sound_ram = *info->sound_ram; |
| 58 | UINT8 *sound_ram = *m_sound_ram; |
| 65 | 59 | int v, i, snum; |
| 66 | 60 | unsigned char *slot; |
| 67 | 61 | INT32 mix[48000*2]; |
| r21519 | r21520 | |
| 73 | 67 | |
| 74 | 68 | for (v = 0; v < 8; v++) |
| 75 | 69 | { |
| 76 | | slot = (unsigned char *)&info->regs[v * 32]; |
| 70 | slot = (unsigned char *)&m_regs[v * 32]; |
| 77 | 71 | |
| 78 | 72 | if (slot[0x16] & 0x06) |
| 79 | 73 | { |
| r21519 | r21520 | |
| 87 | 81 | |
| 88 | 82 | for (snum = 0; snum < samples; snum++) |
| 89 | 83 | { |
| 90 | | sample = sound_ram[(sptr + info->vpos[v])&0x1fffff]<<8; |
| 84 | sample = sound_ram[(sptr + m_vpos[v])&0x1fffff]<<8; |
| 91 | 85 | |
| 92 | 86 | *mixp++ += (sample * (char)slot[0x14]) >> 8; |
| 93 | 87 | *mixp++ += (sample * (char)slot[0x15]) >> 8; |
| 94 | 88 | |
| 95 | | info->frac[v] += freq; |
| 96 | | info->vpos[v] += (info->frac[v]>>16); |
| 97 | | info->frac[v] &= 0xffff; |
| 89 | m_frac[v] += freq; |
| 90 | m_vpos[v] += (m_frac[v]>>16); |
| 91 | m_frac[v] &= 0xffff; |
| 98 | 92 | |
| 99 | 93 | // stop if we're at the end |
| 100 | | if (info->lponce[v]) |
| 94 | if (m_lponce[v]) |
| 101 | 95 | { |
| 102 | 96 | // we've looped once, check loop end rather than sample end |
| 103 | | if ((info->vpos[v] + sptr) >= leptr) |
| 97 | if ((m_vpos[v] + sptr) >= leptr) |
| 104 | 98 | { |
| 105 | | info->vpos[v] = (lsptr - sptr); |
| 99 | m_vpos[v] = (lsptr - sptr); |
| 106 | 100 | } |
| 107 | 101 | } |
| 108 | 102 | else |
| 109 | 103 | { |
| 110 | 104 | // not looped yet, check sample end |
| 111 | | if ((info->vpos[v] + sptr) >= eptr) |
| 105 | if ((m_vpos[v] + sptr) >= eptr) |
| 112 | 106 | { |
| 113 | 107 | if (slot[0x16] & 0x01) // loop? |
| 114 | 108 | { |
| 115 | | info->vpos[v] = (lsptr - sptr); |
| 116 | | info->lponce[v] = 1; |
| 109 | m_vpos[v] = (lsptr - sptr); |
| 110 | m_lponce[v] = 1; |
| 117 | 111 | } |
| 118 | 112 | else |
| 119 | 113 | { |
| 120 | 114 | slot[0x16] = 0; |
| 121 | | info->vpos[v] = info->frac[v] = 0; |
| 115 | m_vpos[v] = m_frac[v] = 0; |
| 122 | 116 | } |
| 123 | 117 | } |
| 124 | 118 | } |
| r21519 | r21520 | |
| 134 | 128 | } |
| 135 | 129 | } |
| 136 | 130 | |
| 137 | | static DEVICE_START( st0016 ) |
| 138 | | { |
| 139 | | const st0016_interface *intf = (const st0016_interface *)device->static_config(); |
| 140 | | st0016_device_state *info = get_safe_token(device); |
| 141 | 131 | |
| 142 | | info->sound_ram = intf->p_soundram; |
| 143 | | |
| 144 | | info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, st0016_update); |
| 145 | | } |
| 146 | | |
| 147 | | const device_type ST0016 = &device_creator<st0016_device>; |
| 148 | | |
| 149 | | st0016_device::st0016_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 150 | | : device_t(mconfig, ST0016, "ST0016", tag, owner, clock), |
| 151 | | device_sound_interface(mconfig, *this) |
| 132 | READ8_MEMBER( st0016_device::st0016_snd_r ) |
| 152 | 133 | { |
| 153 | | m_token = global_alloc_clear(st0016_device_state); |
| 134 | return m_regs[offset]; |
| 154 | 135 | } |
| 155 | 136 | |
| 156 | | //------------------------------------------------- |
| 157 | | // device_config_complete - perform any |
| 158 | | // operations now that the configuration is |
| 159 | | // complete |
| 160 | | //------------------------------------------------- |
| 161 | | |
| 162 | | void st0016_device::device_config_complete() |
| 137 | WRITE8_MEMBER( st0016_device::st0016_snd_w ) |
| 163 | 138 | { |
| 164 | | } |
| 139 | int voice = offset/32; |
| 140 | int reg = offset & 0x1f; |
| 141 | int oldreg = m_regs[offset]; |
| 142 | int vbase = offset & ~0x1f; |
| 165 | 143 | |
| 166 | | //------------------------------------------------- |
| 167 | | // device_start - device-specific startup |
| 168 | | //------------------------------------------------- |
| 144 | m_regs[offset] = data; |
| 169 | 145 | |
| 170 | | void st0016_device::device_start() |
| 171 | | { |
| 172 | | DEVICE_START_NAME( st0016 )(this); |
| 173 | | } |
| 146 | if ((voice < 8) && (data != oldreg)) |
| 147 | { |
| 148 | if ((reg == 0x16) && (data != 0)) |
| 149 | { |
| 150 | m_vpos[voice] = m_frac[voice] = m_lponce[voice] = 0; |
| 174 | 151 | |
| 175 | | //------------------------------------------------- |
| 176 | | // sound_stream_update - handle a stream update |
| 177 | | //------------------------------------------------- |
| 178 | | |
| 179 | | void st0016_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 180 | | { |
| 181 | | // should never get here |
| 182 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 152 | LOG(("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice, |
| 153 | m_regs[vbase+2]<<16 | m_regs[vbase+1]<<8 | m_regs[vbase+2], |
| 154 | m_regs[vbase+0xe]<<16 | m_regs[vbase+0xd]<<8 | m_regs[vbase+0xc], |
| 155 | m_regs[vbase+6]<<16 | m_regs[vbase+5]<<8 | m_regs[vbase+4], |
| 156 | m_regs[vbase+0xa]<<16 | m_regs[vbase+0x9]<<8 | m_regs[vbase+0x8], |
| 157 | m_regs[vbase+0x11]<<8 | m_regs[vbase+0x10], |
| 158 | m_regs[vbase+0x16])); |
| 159 | } |
| 160 | } |
| 183 | 161 | } |
| 162 | |
trunk/src/emu/sound/saa1099.c
| r21519 | r21520 | |
| 66 | 66 | #include "emu.h" |
| 67 | 67 | #include "saa1099.h" |
| 68 | 68 | |
| 69 | | |
| 70 | 69 | #define LEFT 0x00 |
| 71 | 70 | #define RIGHT 0x01 |
| 72 | 71 | |
| 73 | | /* this structure defines a channel */ |
| 74 | | struct saa1099_channel |
| 75 | | { |
| 76 | | int frequency; /* frequency (0x00..0xff) */ |
| 77 | | int freq_enable; /* frequency enable */ |
| 78 | | int noise_enable; /* noise enable */ |
| 79 | | int octave; /* octave (0x00..0x07) */ |
| 80 | | int amplitude[2]; /* amplitude (0x00..0x0f) */ |
| 81 | | int envelope[2]; /* envelope (0x00..0x0f or 0x10 == off) */ |
| 82 | | |
| 83 | | /* vars to simulate the square wave */ |
| 84 | | double counter; |
| 85 | | double freq; |
| 86 | | int level; |
| 87 | | }; |
| 88 | | |
| 89 | | /* this structure defines a noise channel */ |
| 90 | | struct saa1099_noise |
| 91 | | { |
| 92 | | /* vars to simulate the noise generator output */ |
| 93 | | double counter; |
| 94 | | double freq; |
| 95 | | int level; /* noise polynomal shifter */ |
| 96 | | }; |
| 97 | | |
| 98 | | /* this structure defines a SAA1099 chip */ |
| 99 | | struct saa1099_state |
| 100 | | { |
| 101 | | device_t *device; |
| 102 | | sound_stream * stream; /* our stream */ |
| 103 | | int noise_params[2]; /* noise generators parameters */ |
| 104 | | int env_enable[2]; /* envelope generators enable */ |
| 105 | | int env_reverse_right[2]; /* envelope reversed for right channel */ |
| 106 | | int env_mode[2]; /* envelope generators mode */ |
| 107 | | int env_bits[2]; /* non zero = 3 bits resolution */ |
| 108 | | int env_clock[2]; /* envelope clock mode (non-zero external) */ |
| 109 | | int env_step[2]; /* current envelope step */ |
| 110 | | int all_ch_enable; /* all channels enable */ |
| 111 | | int sync_state; /* sync all channels */ |
| 112 | | int selected_reg; /* selected register */ |
| 113 | | struct saa1099_channel channels[6]; /* channels */ |
| 114 | | struct saa1099_noise noise[2]; /* noise generators */ |
| 115 | | double sample_rate; |
| 116 | | }; |
| 117 | | |
| 118 | 72 | static const int amplitude_lookup[16] = { |
| 119 | 73 | 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16, |
| 120 | 74 | 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16, |
| r21519 | r21520 | |
| 166 | 120 | }; |
| 167 | 121 | |
| 168 | 122 | |
| 169 | | INLINE saa1099_state *get_safe_token(device_t *device) |
| 123 | // device type definition |
| 124 | const device_type SAA1099 = &device_creator<saa1099_device>; |
| 125 | |
| 126 | //************************************************************************** |
| 127 | // LIVE DEVICE |
| 128 | //************************************************************************** |
| 129 | |
| 130 | //------------------------------------------------- |
| 131 | // saa1099_device - constructor |
| 132 | //------------------------------------------------- |
| 133 | |
| 134 | saa1099_device::saa1099_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 135 | : device_t(mconfig, SAA1099, "SAA1099", tag, owner, clock), |
| 136 | device_sound_interface(mconfig, *this), |
| 137 | m_stream(NULL), |
| 138 | m_all_ch_enable(0), |
| 139 | m_sync_state(0), |
| 140 | m_selected_reg(0), |
| 141 | m_sample_rate(0.0) |
| 170 | 142 | { |
| 171 | | assert(device != NULL); |
| 172 | | assert(device->type() == SAA1099); |
| 173 | | return (saa1099_state *)downcast<saa1099_device *>(device)->token(); |
| 143 | memset(m_noise_params, 0, sizeof(int)*2); |
| 144 | memset(m_env_enable, 0, sizeof(int)*2); |
| 145 | memset(m_env_reverse_right, 0, sizeof(int)*2); |
| 146 | memset(m_env_mode, 0, sizeof(int)*2); |
| 147 | memset(m_env_bits, 0, sizeof(int)*2); |
| 148 | memset(m_env_clock, 0, sizeof(int)*2); |
| 149 | memset(m_env_step, 0, sizeof(int)*2); |
| 174 | 150 | } |
| 175 | 151 | |
| 176 | 152 | |
| 177 | | static void saa1099_envelope(saa1099_state *saa, int ch) |
| 153 | //------------------------------------------------- |
| 154 | // device_start - device-specific startup |
| 155 | //------------------------------------------------- |
| 156 | |
| 157 | void saa1099_device::device_start() |
| 178 | 158 | { |
| 179 | | if (saa->env_enable[ch]) |
| 180 | | { |
| 181 | | int step, mode, mask; |
| 182 | | mode = saa->env_mode[ch]; |
| 183 | | /* step from 0..63 and then loop in steps 32..63 */ |
| 184 | | step = saa->env_step[ch] = |
| 185 | | ((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20); |
| 159 | /* copy global parameters */ |
| 160 | m_sample_rate = clock() / 256; |
| 186 | 161 | |
| 187 | | mask = 15; |
| 188 | | if (saa->env_bits[ch]) |
| 189 | | mask &= ~1; /* 3 bit resolution, mask LSB */ |
| 190 | | |
| 191 | | saa->channels[ch*3+0].envelope[ LEFT] = |
| 192 | | saa->channels[ch*3+1].envelope[ LEFT] = |
| 193 | | saa->channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask; |
| 194 | | if (saa->env_reverse_right[ch] & 0x01) |
| 195 | | { |
| 196 | | saa->channels[ch*3+0].envelope[RIGHT] = |
| 197 | | saa->channels[ch*3+1].envelope[RIGHT] = |
| 198 | | saa->channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask; |
| 199 | | } |
| 200 | | else |
| 201 | | { |
| 202 | | saa->channels[ch*3+0].envelope[RIGHT] = |
| 203 | | saa->channels[ch*3+1].envelope[RIGHT] = |
| 204 | | saa->channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask; |
| 205 | | } |
| 206 | | } |
| 207 | | else |
| 208 | | { |
| 209 | | /* envelope mode off, set all envelope factors to 16 */ |
| 210 | | saa->channels[ch*3+0].envelope[ LEFT] = |
| 211 | | saa->channels[ch*3+1].envelope[ LEFT] = |
| 212 | | saa->channels[ch*3+2].envelope[ LEFT] = |
| 213 | | saa->channels[ch*3+0].envelope[RIGHT] = |
| 214 | | saa->channels[ch*3+1].envelope[RIGHT] = |
| 215 | | saa->channels[ch*3+2].envelope[RIGHT] = 16; |
| 216 | | } |
| 162 | /* for each chip allocate one stream */ |
| 163 | m_stream = stream_alloc(0, 2, m_sample_rate); |
| 217 | 164 | } |
| 218 | 165 | |
| 219 | 166 | |
| 220 | | static STREAM_UPDATE( saa1099_update ) |
| 167 | //------------------------------------------------- |
| 168 | // sound_stream_update - handle a stream update |
| 169 | //------------------------------------------------- |
| 170 | |
| 171 | void saa1099_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 221 | 172 | { |
| 222 | | saa1099_state *saa = (saa1099_state *)param; |
| 223 | 173 | int j, ch; |
| 224 | 174 | |
| 225 | 175 | /* if the channels are disabled we're done */ |
| 226 | | if (!saa->all_ch_enable) |
| 176 | if (!m_all_ch_enable) |
| 227 | 177 | { |
| 228 | 178 | /* init output data */ |
| 229 | 179 | memset(outputs[LEFT],0,samples*sizeof(*outputs[LEFT])); |
| r21519 | r21520 | |
| 233 | 183 | |
| 234 | 184 | for (ch = 0; ch < 2; ch++) |
| 235 | 185 | { |
| 236 | | switch (saa->noise_params[ch]) |
| 186 | switch (m_noise_params[ch]) |
| 237 | 187 | { |
| 238 | | case 0: saa->noise[ch].freq = 31250.0 * 2; break; |
| 239 | | case 1: saa->noise[ch].freq = 15625.0 * 2; break; |
| 240 | | case 2: saa->noise[ch].freq = 7812.5 * 2; break; |
| 241 | | case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; |
| 188 | case 0: m_noise[ch].freq = 31250.0 * 2; break; |
| 189 | case 1: m_noise[ch].freq = 15625.0 * 2; break; |
| 190 | case 2: m_noise[ch].freq = 7812.5 * 2; break; |
| 191 | case 3: m_noise[ch].freq = m_channels[ch * 3].freq; break; |
| 242 | 192 | } |
| 243 | 193 | } |
| 244 | 194 | |
| r21519 | r21520 | |
| 250 | 200 | /* for each channel */ |
| 251 | 201 | for (ch = 0; ch < 6; ch++) |
| 252 | 202 | { |
| 253 | | if (saa->channels[ch].freq == 0.0) |
| 254 | | saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / |
| 255 | | (511.0 - (double)saa->channels[ch].frequency); |
| 203 | if (m_channels[ch].freq == 0.0) |
| 204 | m_channels[ch].freq = (double)((2 * 15625) << m_channels[ch].octave) / |
| 205 | (511.0 - (double)m_channels[ch].frequency); |
| 256 | 206 | |
| 257 | 207 | /* check the actual position in the square wave */ |
| 258 | | saa->channels[ch].counter -= saa->channels[ch].freq; |
| 259 | | while (saa->channels[ch].counter < 0) |
| 208 | m_channels[ch].counter -= m_channels[ch].freq; |
| 209 | while (m_channels[ch].counter < 0) |
| 260 | 210 | { |
| 261 | 211 | /* calculate new frequency now after the half wave is updated */ |
| 262 | | saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / |
| 263 | | (511.0 - (double)saa->channels[ch].frequency); |
| 212 | m_channels[ch].freq = (double)((2 * 15625) << m_channels[ch].octave) / |
| 213 | (511.0 - (double)m_channels[ch].frequency); |
| 264 | 214 | |
| 265 | | saa->channels[ch].counter += saa->sample_rate; |
| 266 | | saa->channels[ch].level ^= 1; |
| 215 | m_channels[ch].counter += m_sample_rate; |
| 216 | m_channels[ch].level ^= 1; |
| 267 | 217 | |
| 268 | 218 | /* eventually clock the envelope counters */ |
| 269 | | if (ch == 1 && saa->env_clock[0] == 0) |
| 270 | | saa1099_envelope(saa, 0); |
| 271 | | if (ch == 4 && saa->env_clock[1] == 0) |
| 272 | | saa1099_envelope(saa, 1); |
| 219 | if (ch == 1 && m_env_clock[0] == 0) |
| 220 | saa1099_envelope(0); |
| 221 | if (ch == 4 && m_env_clock[1] == 0) |
| 222 | saa1099_envelope(1); |
| 273 | 223 | } |
| 274 | 224 | |
| 275 | 225 | /* if the noise is enabled */ |
| 276 | | if (saa->channels[ch].noise_enable) |
| 226 | if (m_channels[ch].noise_enable) |
| 277 | 227 | { |
| 278 | 228 | /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ |
| 279 | | if (saa->noise[ch/3].level & 1) |
| 229 | if (m_noise[ch/3].level & 1) |
| 280 | 230 | { |
| 281 | 231 | /* subtract to avoid overflows, also use only half amplitude */ |
| 282 | | output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; |
| 283 | | output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; |
| 232 | output_l -= m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16 / 2; |
| 233 | output_r -= m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16 / 2; |
| 284 | 234 | } |
| 285 | 235 | } |
| 286 | 236 | |
| 287 | 237 | /* if the square wave is enabled */ |
| 288 | | if (saa->channels[ch].freq_enable) |
| 238 | if (m_channels[ch].freq_enable) |
| 289 | 239 | { |
| 290 | 240 | /* if the channel level is high */ |
| 291 | | if (saa->channels[ch].level & 1) |
| 241 | if (m_channels[ch].level & 1) |
| 292 | 242 | { |
| 293 | | output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; |
| 294 | | output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; |
| 243 | output_l += m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16; |
| 244 | output_r += m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16; |
| 295 | 245 | } |
| 296 | 246 | } |
| 297 | 247 | } |
| r21519 | r21520 | |
| 299 | 249 | for (ch = 0; ch < 2; ch++) |
| 300 | 250 | { |
| 301 | 251 | /* check the actual position in noise generator */ |
| 302 | | saa->noise[ch].counter -= saa->noise[ch].freq; |
| 303 | | while (saa->noise[ch].counter < 0) |
| 252 | m_noise[ch].counter -= m_noise[ch].freq; |
| 253 | while (m_noise[ch].counter < 0) |
| 304 | 254 | { |
| 305 | | saa->noise[ch].counter += saa->sample_rate; |
| 306 | | if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) |
| 307 | | saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; |
| 255 | m_noise[ch].counter += m_sample_rate; |
| 256 | if( ((m_noise[ch].level & 0x4000) == 0) == ((m_noise[ch].level & 0x0040) == 0) ) |
| 257 | m_noise[ch].level = (m_noise[ch].level << 1) | 1; |
| 308 | 258 | else |
| 309 | | saa->noise[ch].level <<= 1; |
| 259 | m_noise[ch].level <<= 1; |
| 310 | 260 | } |
| 311 | 261 | } |
| 312 | 262 | /* write sound data to the buffer */ |
| r21519 | r21520 | |
| 316 | 266 | } |
| 317 | 267 | |
| 318 | 268 | |
| 319 | | |
| 320 | | static DEVICE_START( saa1099 ) |
| 269 | void saa1099_device::saa1099_envelope(int ch) |
| 321 | 270 | { |
| 322 | | saa1099_state *saa = get_safe_token(device); |
| 271 | if (m_env_enable[ch]) |
| 272 | { |
| 273 | int step, mode, mask; |
| 274 | mode = m_env_mode[ch]; |
| 275 | /* step from 0..63 and then loop in steps 32..63 */ |
| 276 | step = m_env_step[ch] = |
| 277 | ((m_env_step[ch] + 1) & 0x3f) | (m_env_step[ch] & 0x20); |
| 323 | 278 | |
| 324 | | /* copy global parameters */ |
| 325 | | saa->device = device; |
| 326 | | saa->sample_rate = device->clock() / 256; |
| 279 | mask = 15; |
| 280 | if (m_env_bits[ch]) |
| 281 | mask &= ~1; /* 3 bit resolution, mask LSB */ |
| 327 | 282 | |
| 328 | | /* for each chip allocate one stream */ |
| 329 | | saa->stream = device->machine().sound().stream_alloc(*device, 0, 2, saa->sample_rate, saa, saa1099_update); |
| 283 | m_channels[ch*3+0].envelope[ LEFT] = |
| 284 | m_channels[ch*3+1].envelope[ LEFT] = |
| 285 | m_channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask; |
| 286 | if (m_env_reverse_right[ch] & 0x01) |
| 287 | { |
| 288 | m_channels[ch*3+0].envelope[RIGHT] = |
| 289 | m_channels[ch*3+1].envelope[RIGHT] = |
| 290 | m_channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask; |
| 291 | } |
| 292 | else |
| 293 | { |
| 294 | m_channels[ch*3+0].envelope[RIGHT] = |
| 295 | m_channels[ch*3+1].envelope[RIGHT] = |
| 296 | m_channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask; |
| 297 | } |
| 298 | } |
| 299 | else |
| 300 | { |
| 301 | /* envelope mode off, set all envelope factors to 16 */ |
| 302 | m_channels[ch*3+0].envelope[ LEFT] = |
| 303 | m_channels[ch*3+1].envelope[ LEFT] = |
| 304 | m_channels[ch*3+2].envelope[ LEFT] = |
| 305 | m_channels[ch*3+0].envelope[RIGHT] = |
| 306 | m_channels[ch*3+1].envelope[RIGHT] = |
| 307 | m_channels[ch*3+2].envelope[RIGHT] = 16; |
| 308 | } |
| 330 | 309 | } |
| 331 | 310 | |
| 332 | | WRITE8_DEVICE_HANDLER( saa1099_control_w ) |
| 333 | | { |
| 334 | | saa1099_state *saa = get_safe_token(device); |
| 335 | 311 | |
| 312 | WRITE8_MEMBER( saa1099_device::saa1099_control_w ) |
| 313 | { |
| 336 | 314 | if ((data & 0xff) > 0x1c) |
| 337 | 315 | { |
| 338 | 316 | /* Error! */ |
| 339 | | logerror("%s: (SAA1099 '%s') Unknown register selected\n",device->machine().describe_context(), device->tag()); |
| 317 | logerror("%s: (SAA1099 '%s') Unknown register selected\n", machine().describe_context(), tag()); |
| 340 | 318 | } |
| 341 | 319 | |
| 342 | | saa->selected_reg = data & 0x1f; |
| 343 | | if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) |
| 320 | m_selected_reg = data & 0x1f; |
| 321 | if (m_selected_reg == 0x18 || m_selected_reg == 0x19) |
| 344 | 322 | { |
| 345 | 323 | /* clock the envelope channels */ |
| 346 | | if (saa->env_clock[0]) |
| 347 | | saa1099_envelope(saa,0); |
| 348 | | if (saa->env_clock[1]) |
| 349 | | saa1099_envelope(saa,1); |
| 324 | if (m_env_clock[0]) |
| 325 | saa1099_envelope(0); |
| 326 | if (m_env_clock[1]) |
| 327 | saa1099_envelope(1); |
| 350 | 328 | } |
| 351 | 329 | } |
| 352 | 330 | |
| 353 | 331 | |
| 354 | | WRITE8_DEVICE_HANDLER( saa1099_data_w ) |
| 332 | WRITE8_MEMBER( saa1099_device::saa1099_data_w ) |
| 355 | 333 | { |
| 356 | | saa1099_state *saa = get_safe_token(device); |
| 357 | | int reg = saa->selected_reg; |
| 334 | int reg = m_selected_reg; |
| 358 | 335 | int ch; |
| 359 | 336 | |
| 360 | 337 | /* first update the stream to this point in time */ |
| 361 | | saa->stream->update(); |
| 338 | m_stream->update(); |
| 362 | 339 | |
| 363 | 340 | switch (reg) |
| 364 | 341 | { |
| 365 | 342 | /* channel i amplitude */ |
| 366 | 343 | case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: |
| 367 | 344 | ch = reg & 7; |
| 368 | | saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; |
| 369 | | saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; |
| 345 | m_channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; |
| 346 | m_channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; |
| 370 | 347 | break; |
| 371 | 348 | /* channel i frequency */ |
| 372 | 349 | case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: |
| 373 | 350 | ch = reg & 7; |
| 374 | | saa->channels[ch].frequency = data & 0xff; |
| 351 | m_channels[ch].frequency = data & 0xff; |
| 375 | 352 | break; |
| 376 | 353 | /* channel i octave */ |
| 377 | 354 | case 0x10: case 0x11: case 0x12: |
| 378 | 355 | ch = (reg - 0x10) << 1; |
| 379 | | saa->channels[ch + 0].octave = data & 0x07; |
| 380 | | saa->channels[ch + 1].octave = (data >> 4) & 0x07; |
| 356 | m_channels[ch + 0].octave = data & 0x07; |
| 357 | m_channels[ch + 1].octave = (data >> 4) & 0x07; |
| 381 | 358 | break; |
| 382 | 359 | /* channel i frequency enable */ |
| 383 | 360 | case 0x14: |
| 384 | | saa->channels[0].freq_enable = data & 0x01; |
| 385 | | saa->channels[1].freq_enable = data & 0x02; |
| 386 | | saa->channels[2].freq_enable = data & 0x04; |
| 387 | | saa->channels[3].freq_enable = data & 0x08; |
| 388 | | saa->channels[4].freq_enable = data & 0x10; |
| 389 | | saa->channels[5].freq_enable = data & 0x20; |
| 361 | m_channels[0].freq_enable = data & 0x01; |
| 362 | m_channels[1].freq_enable = data & 0x02; |
| 363 | m_channels[2].freq_enable = data & 0x04; |
| 364 | m_channels[3].freq_enable = data & 0x08; |
| 365 | m_channels[4].freq_enable = data & 0x10; |
| 366 | m_channels[5].freq_enable = data & 0x20; |
| 390 | 367 | break; |
| 391 | 368 | /* channel i noise enable */ |
| 392 | 369 | case 0x15: |
| 393 | | saa->channels[0].noise_enable = data & 0x01; |
| 394 | | saa->channels[1].noise_enable = data & 0x02; |
| 395 | | saa->channels[2].noise_enable = data & 0x04; |
| 396 | | saa->channels[3].noise_enable = data & 0x08; |
| 397 | | saa->channels[4].noise_enable = data & 0x10; |
| 398 | | saa->channels[5].noise_enable = data & 0x20; |
| 370 | m_channels[0].noise_enable = data & 0x01; |
| 371 | m_channels[1].noise_enable = data & 0x02; |
| 372 | m_channels[2].noise_enable = data & 0x04; |
| 373 | m_channels[3].noise_enable = data & 0x08; |
| 374 | m_channels[4].noise_enable = data & 0x10; |
| 375 | m_channels[5].noise_enable = data & 0x20; |
| 399 | 376 | break; |
| 400 | 377 | /* noise generators parameters */ |
| 401 | 378 | case 0x16: |
| 402 | | saa->noise_params[0] = data & 0x03; |
| 403 | | saa->noise_params[1] = (data >> 4) & 0x03; |
| 379 | m_noise_params[0] = data & 0x03; |
| 380 | m_noise_params[1] = (data >> 4) & 0x03; |
| 404 | 381 | break; |
| 405 | 382 | /* envelope generators parameters */ |
| 406 | 383 | case 0x18: case 0x19: |
| 407 | 384 | ch = reg - 0x18; |
| 408 | | saa->env_reverse_right[ch] = data & 0x01; |
| 409 | | saa->env_mode[ch] = (data >> 1) & 0x07; |
| 410 | | saa->env_bits[ch] = data & 0x10; |
| 411 | | saa->env_clock[ch] = data & 0x20; |
| 412 | | saa->env_enable[ch] = data & 0x80; |
| 385 | m_env_reverse_right[ch] = data & 0x01; |
| 386 | m_env_mode[ch] = (data >> 1) & 0x07; |
| 387 | m_env_bits[ch] = data & 0x10; |
| 388 | m_env_clock[ch] = data & 0x20; |
| 389 | m_env_enable[ch] = data & 0x80; |
| 413 | 390 | /* reset the envelope */ |
| 414 | | saa->env_step[ch] = 0; |
| 391 | m_env_step[ch] = 0; |
| 415 | 392 | break; |
| 416 | 393 | /* channels enable & reset generators */ |
| 417 | 394 | case 0x1c: |
| 418 | | saa->all_ch_enable = data & 0x01; |
| 419 | | saa->sync_state = data & 0x02; |
| 395 | m_all_ch_enable = data & 0x01; |
| 396 | m_sync_state = data & 0x02; |
| 420 | 397 | if (data & 0x02) |
| 421 | 398 | { |
| 422 | 399 | int i; |
| 423 | 400 | |
| 424 | 401 | /* Synch & Reset generators */ |
| 425 | | logerror("%s: (SAA1099 '%s') -reg 0x1c- Chip reset\n",device->machine().describe_context(), device->tag()); |
| 402 | logerror("%s: (SAA1099 '%s') -reg 0x1c- Chip reset\n", machine().describe_context(), tag()); |
| 426 | 403 | for (i = 0; i < 6; i++) |
| 427 | 404 | { |
| 428 | | saa->channels[i].level = 0; |
| 429 | | saa->channels[i].counter = 0.0; |
| 405 | m_channels[i].level = 0; |
| 406 | m_channels[i].counter = 0.0; |
| 430 | 407 | } |
| 431 | 408 | } |
| 432 | 409 | break; |
| 433 | 410 | default: /* Error! */ |
| 434 | | logerror("%s: (SAA1099 '%s') Unknown operation (reg:%02x, data:%02x)\n",device->machine().describe_context(), device->tag(), reg, data); |
| 411 | logerror("%s: (SAA1099 '%s') Unknown operation (reg:%02x, data:%02x)\n", machine().describe_context(), tag(), reg, data); |
| 435 | 412 | } |
| 436 | 413 | } |
| 437 | | |
| 438 | | const device_type SAA1099 = &device_creator<saa1099_device>; |
| 439 | | |
| 440 | | saa1099_device::saa1099_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 441 | | : device_t(mconfig, SAA1099, "SAA1099", tag, owner, clock), |
| 442 | | device_sound_interface(mconfig, *this) |
| 443 | | { |
| 444 | | m_token = global_alloc_clear(saa1099_state); |
| 445 | | } |
| 446 | | |
| 447 | | //------------------------------------------------- |
| 448 | | // device_config_complete - perform any |
| 449 | | // operations now that the configuration is |
| 450 | | // complete |
| 451 | | //------------------------------------------------- |
| 452 | | |
| 453 | | void saa1099_device::device_config_complete() |
| 454 | | { |
| 455 | | } |
| 456 | | |
| 457 | | //------------------------------------------------- |
| 458 | | // device_start - device-specific startup |
| 459 | | //------------------------------------------------- |
| 460 | | |
| 461 | | void saa1099_device::device_start() |
| 462 | | { |
| 463 | | DEVICE_START_NAME( saa1099 )(this); |
| 464 | | } |
| 465 | | |
| 466 | | //------------------------------------------------- |
| 467 | | // sound_stream_update - handle a stream update |
| 468 | | //------------------------------------------------- |
| 469 | | |
| 470 | | void saa1099_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 471 | | { |
| 472 | | // should never get here |
| 473 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 474 | | } |