trunk/src/mame/drivers/srmp6.c
| r19924 | r19925 | |
| 563 | 563 | //AM_RANGE(0x5fff00, 0x5fffff) AM_WRITE_LEGACY(dma_w) AM_SHARE("dmaram") |
| 564 | 564 | |
| 565 | 565 | AM_RANGE(0x4c0000, 0x4c006f) AM_READWRITE(video_regs_r, video_regs_w) AM_SHARE("video_regs") // ? gfx regs ST-0026 NiLe |
| 566 | | AM_RANGE(0x4e0000, 0x4e00ff) AM_DEVREADWRITE_LEGACY("nile", nile_snd_r, nile_snd_w) |
| 567 | | AM_RANGE(0x4e0100, 0x4e0101) AM_DEVREADWRITE_LEGACY("nile", nile_sndctrl_r, nile_sndctrl_w) |
| 566 | AM_RANGE(0x4e0000, 0x4e00ff) AM_DEVREADWRITE("nile", nile_device, nile_snd_r, nile_snd_w) |
| 567 | AM_RANGE(0x4e0100, 0x4e0101) AM_DEVREADWRITE("nile", nile_device, nile_sndctrl_r, nile_sndctrl_w) |
| 568 | 568 | //AM_RANGE(0x4e0110, 0x4e0111) AM_NOP // ? accessed once ($268dc, written $b.w) |
| 569 | 569 | //AM_RANGE(0x5fff00, 0x5fff1f) AM_RAM // ? see routine $5ca8, video_regs related ??? |
| 570 | 570 | |
| r19924 | r19925 | |
| 689 | 689 | /* sound hardware */ |
| 690 | 690 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 691 | 691 | |
| 692 | | MCFG_SOUND_ADD("nile", NILE, 0) |
| 692 | MCFG_NILE_ADD("nile", 0) |
| 693 | 693 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 694 | 694 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
| 695 | 695 | MACHINE_CONFIG_END |
trunk/src/emu/sound/nile.c
| r19924 | r19925 | |
| 27 | 27 | #include "emu.h" |
| 28 | 28 | #include "nile.h" |
| 29 | 29 | |
| 30 | | #define NILE_VOICES 8 |
| 31 | | |
| 32 | 30 | enum |
| 33 | 31 | { |
| 34 | 32 | NILE_REG_UNK0=0, |
| r19924 | r19925 | |
| 50 | 48 | }; |
| 51 | 49 | |
| 52 | 50 | |
| 51 | const device_type NILE = &device_creator<nile_device>; |
| 53 | 52 | |
| 54 | | struct nile_state |
| 53 | nile_device::nile_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 54 | : device_t(mconfig, NILE, "NiLe", tag, owner, clock), |
| 55 | device_sound_interface(mconfig, *this), |
| 56 | m_stream(NULL), |
| 57 | m_sound_ram(NULL), |
| 58 | m_ctrl(0) |
| 55 | 59 | { |
| 56 | | sound_stream * stream; |
| 57 | | UINT8 *sound_ram; |
| 58 | | UINT16 sound_regs[0x80]; |
| 59 | | int vpos[NILE_VOICES], frac[NILE_VOICES], lponce[NILE_VOICES]; |
| 60 | | UINT16 ctrl; |
| 61 | | }; |
| 62 | | |
| 63 | | INLINE nile_state *get_safe_token(device_t *device) |
| 64 | | { |
| 65 | | assert(device != NULL); |
| 66 | | assert(device->type() == NILE); |
| 67 | | return (nile_state *)downcast<nile_device *>(device)->token(); |
| 68 | 60 | } |
| 69 | 61 | |
| 70 | 62 | |
| 71 | | WRITE16_DEVICE_HANDLER( nile_sndctrl_w ) |
| 72 | | { |
| 73 | | nile_state *info = get_safe_token(device); |
| 74 | | UINT16 ctrl=info->ctrl; |
| 63 | //------------------------------------------------- |
| 64 | // device_start - device-specific startup |
| 65 | //------------------------------------------------- |
| 75 | 66 | |
| 76 | | info->stream->update(); |
| 77 | | |
| 78 | | COMBINE_DATA(&info->ctrl); |
| 79 | | |
| 80 | | // printf("CTRL: %04x -> %04x (PC=%x)\n", ctrl, info->ctrl, space.device().safe_pc()); |
| 81 | | |
| 82 | | ctrl^=info->ctrl; |
| 83 | | } |
| 84 | | |
| 85 | | READ16_DEVICE_HANDLER( nile_sndctrl_r ) |
| 67 | void nile_device::device_start() |
| 86 | 68 | { |
| 87 | | nile_state *info = get_safe_token(device); |
| 88 | | |
| 89 | | info->stream->update(); |
| 90 | | |
| 91 | | return info->ctrl; |
| 69 | m_sound_ram = *region(); |
| 70 | m_stream = stream_alloc(0, 2, 44100); |
| 92 | 71 | } |
| 93 | 72 | |
| 94 | | READ16_DEVICE_HANDLER( nile_snd_r ) |
| 95 | | { |
| 96 | | nile_state *info = get_safe_token(device); |
| 97 | | int reg=offset&0xf; |
| 98 | 73 | |
| 99 | | info->stream->update(); |
| 74 | //------------------------------------------------- |
| 75 | // sound_stream_update - handle update requests |
| 76 | // for our sound stream |
| 77 | //------------------------------------------------- |
| 100 | 78 | |
| 101 | | if(reg==2 || reg==3) |
| 102 | | { |
| 103 | | int slot=offset/16; |
| 104 | | int sptr = ((info->sound_regs[slot*16+3]<<16)|info->sound_regs[slot*16+2])+info->vpos[slot]; |
| 105 | | |
| 106 | | if(reg==2) |
| 107 | | { |
| 108 | | return sptr&0xffff; |
| 109 | | } |
| 110 | | else |
| 111 | | { |
| 112 | | return sptr>>16; |
| 113 | | } |
| 114 | | } |
| 115 | | return info->sound_regs[offset]; |
| 116 | | } |
| 117 | | |
| 118 | | WRITE16_DEVICE_HANDLER( nile_snd_w ) |
| 79 | void nile_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 119 | 80 | { |
| 120 | | nile_state *info = get_safe_token(device); |
| 121 | | int v, r; |
| 122 | | |
| 123 | | info->stream->update(); |
| 124 | | |
| 125 | | COMBINE_DATA(&info->sound_regs[offset]); |
| 126 | | |
| 127 | | v = offset / 16; |
| 128 | | r = offset % 16; |
| 129 | | |
| 130 | | if ((r == 2) || (r == 3)) |
| 131 | | { |
| 132 | | info->vpos[v] = info->frac[v] = info->lponce[v] = 0; |
| 133 | | } |
| 134 | | |
| 135 | | //printf("v%02d: %04x to reg %02d (PC=%x)\n", v, info->sound_regs[offset], r, space.device().safe_pc()); |
| 136 | | } |
| 137 | | |
| 138 | | static STREAM_UPDATE( nile_update ) |
| 139 | | { |
| 140 | | nile_state *info = (nile_state *)param; |
| 141 | | UINT8 *sound_ram = info->sound_ram; |
| 81 | UINT8 *sound_ram = m_sound_ram; |
| 142 | 82 | int v, i, snum; |
| 143 | 83 | UINT16 *slot; |
| 144 | 84 | INT32 mix[48000*2]; |
| r19924 | r19925 | |
| 152 | 92 | |
| 153 | 93 | for (v = 0; v < NILE_VOICES; v++) |
| 154 | 94 | { |
| 155 | | slot = &info->sound_regs[v * 16]; |
| 95 | slot = &m_sound_regs[v * 16]; |
| 156 | 96 | |
| 157 | | if (info->ctrl&(1<<v)) |
| 97 | if (m_ctrl&(1<<v)) |
| 158 | 98 | { |
| 159 | 99 | mixp = &mix[0]; |
| 160 | 100 | |
| r19924 | r19925 | |
| 167 | 107 | |
| 168 | 108 | for (snum = 0; snum < samples; snum++) |
| 169 | 109 | { |
| 170 | | sample = sound_ram[sptr + info->vpos[v]]<<8; |
| 110 | sample = sound_ram[sptr + m_vpos[v]]<<8; |
| 171 | 111 | |
| 172 | 112 | *mixp++ += (sample * (INT32)slot[NILE_REG_VOL_R]) >> 16; |
| 173 | 113 | *mixp++ += (sample * (INT32)slot[NILE_REG_VOL_L]) >> 16; |
| 174 | 114 | |
| 175 | | info->frac[v] += freq; |
| 176 | | info->vpos[v] += info->frac[v]>>16; |
| 177 | | info->frac[v] &= 0xffff; |
| 115 | m_frac[v] += freq; |
| 116 | m_vpos[v] += m_frac[v]>>16; |
| 117 | m_frac[v] &= 0xffff; |
| 178 | 118 | |
| 179 | 119 | // stop if we're at the end |
| 180 | | if (info->lponce[v]) |
| 120 | if (m_lponce[v]) |
| 181 | 121 | { |
| 182 | 122 | // we've looped once, check loop end rather than sample end |
| 183 | | if ((info->vpos[v] + sptr) >= leptr) |
| 123 | if ((m_vpos[v] + sptr) >= leptr) |
| 184 | 124 | { |
| 185 | | info->vpos[v] = (lsptr - sptr); |
| 125 | m_vpos[v] = (lsptr - sptr); |
| 186 | 126 | } |
| 187 | 127 | } |
| 188 | 128 | else |
| 189 | 129 | { |
| 190 | 130 | // not looped yet, check sample end |
| 191 | | if ((info->vpos[v] + sptr) >= eptr) |
| 131 | if ((m_vpos[v] + sptr) >= eptr) |
| 192 | 132 | { |
| 193 | 133 | // code at 11d8c: |
| 194 | 134 | // if bit 2 (0x4) is set, check if loop start = loop end. |
| r19924 | r19925 | |
| 197 | 137 | // the loop start/end registers in the NiLe. |
| 198 | 138 | if ((slot[NILE_REG_FLAGS] & 0x5) == 0x5) |
| 199 | 139 | { |
| 200 | | info->vpos[v] = (lsptr - sptr); |
| 201 | | info->lponce[v] = 1; |
| 140 | m_vpos[v] = (lsptr - sptr); |
| 141 | m_lponce[v] = 1; |
| 202 | 142 | } |
| 203 | 143 | else |
| 204 | 144 | { |
| 205 | | info->ctrl &= ~(1<<v); |
| 206 | | info->vpos[v] = (eptr - sptr); |
| 207 | | info->frac[v] = 0; |
| 145 | m_ctrl &= ~(1<<v); |
| 146 | m_vpos[v] = (eptr - sptr); |
| 147 | m_frac[v] = 0; |
| 208 | 148 | } |
| 209 | 149 | |
| 210 | 150 | } |
| r19924 | r19925 | |
| 220 | 160 | } |
| 221 | 161 | } |
| 222 | 162 | |
| 223 | | static DEVICE_START( nile ) |
| 163 | |
| 164 | WRITE16_MEMBER( nile_device::nile_sndctrl_w ) |
| 224 | 165 | { |
| 225 | | nile_state *info = get_safe_token(device); |
| 166 | UINT16 ctrl=m_ctrl; |
| 226 | 167 | |
| 227 | | info->sound_ram = *device->region(); |
| 168 | m_stream->update(); |
| 228 | 169 | |
| 229 | | info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, nile_update); |
| 230 | | } |
| 170 | COMBINE_DATA(&m_ctrl); |
| 231 | 171 | |
| 232 | | const device_type NILE = &device_creator<nile_device>; |
| 172 | // printf("CTRL: %04x -> %04x (PC=%x)\n", ctrl, m_ctrl, space.device().safe_pc()); |
| 233 | 173 | |
| 234 | | nile_device::nile_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 235 | | : device_t(mconfig, NILE, "NiLe", tag, owner, clock), |
| 236 | | device_sound_interface(mconfig, *this) |
| 237 | | { |
| 238 | | m_token = global_alloc_clear(nile_state); |
| 174 | ctrl^=m_ctrl; |
| 239 | 175 | } |
| 240 | 176 | |
| 241 | | //------------------------------------------------- |
| 242 | | // device_config_complete - perform any |
| 243 | | // operations now that the configuration is |
| 244 | | // complete |
| 245 | | //------------------------------------------------- |
| 246 | 177 | |
| 247 | | void nile_device::device_config_complete() |
| 178 | READ16_MEMBER( nile_device::nile_sndctrl_r ) |
| 248 | 179 | { |
| 180 | m_stream->update(); |
| 181 | return m_ctrl; |
| 249 | 182 | } |
| 250 | 183 | |
| 251 | | //------------------------------------------------- |
| 252 | | // device_start - device-specific startup |
| 253 | | //------------------------------------------------- |
| 254 | 184 | |
| 255 | | void nile_device::device_start() |
| 185 | READ16_MEMBER( nile_device::nile_snd_r ) |
| 256 | 186 | { |
| 257 | | DEVICE_START_NAME( nile )(this); |
| 187 | int reg=offset&0xf; |
| 188 | |
| 189 | m_stream->update(); |
| 190 | |
| 191 | if(reg==2 || reg==3) |
| 192 | { |
| 193 | int slot=offset/16; |
| 194 | int sptr = ((m_sound_regs[slot*16+3]<<16)|m_sound_regs[slot*16+2])+m_vpos[slot]; |
| 195 | |
| 196 | if(reg==2) |
| 197 | { |
| 198 | return sptr&0xffff; |
| 199 | } |
| 200 | else |
| 201 | { |
| 202 | return sptr>>16; |
| 203 | } |
| 204 | } |
| 205 | return m_sound_regs[offset]; |
| 258 | 206 | } |
| 259 | 207 | |
| 260 | | //------------------------------------------------- |
| 261 | | // sound_stream_update - handle a stream update |
| 262 | | //------------------------------------------------- |
| 263 | 208 | |
| 264 | | void nile_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 209 | WRITE16_MEMBER( nile_device::nile_snd_w ) |
| 265 | 210 | { |
| 266 | | // should never get here |
| 267 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 268 | | } |
| 211 | int v, r; |
| 269 | 212 | |
| 213 | m_stream->update(); |
| 270 | 214 | |
| 215 | COMBINE_DATA(&m_sound_regs[offset]); |
| 216 | |
| 217 | v = offset / 16; |
| 218 | r = offset % 16; |
| 219 | |
| 220 | if ((r == 2) || (r == 3)) |
| 221 | { |
| 222 | m_vpos[v] = m_frac[v] = m_lponce[v] = 0; |
| 223 | } |
| 224 | |
| 225 | //printf("v%02d: %04x to reg %02d (PC=%x)\n", v, m_sound_regs[offset], r, space.device().safe_pc()); |
| 226 | } |
trunk/src/emu/sound/nile.h
| r19924 | r19925 | |
| 3 | 3 | #ifndef __NILE_H__ |
| 4 | 4 | #define __NILE_H__ |
| 5 | 5 | |
| 6 | | #include "devlegcy.h" |
| 7 | 6 | |
| 8 | | DECLARE_WRITE16_DEVICE_HANDLER( nile_snd_w ); |
| 9 | | DECLARE_READ16_DEVICE_HANDLER( nile_snd_r ); |
| 10 | | DECLARE_WRITE16_DEVICE_HANDLER( nile_sndctrl_w ); |
| 11 | | DECLARE_READ16_DEVICE_HANDLER( nile_sndctrl_r ); |
| 7 | //************************************************************************** |
| 8 | // INTERFACE CONFIGURATION MACROS |
| 9 | //************************************************************************** |
| 12 | 10 | |
| 11 | #define MCFG_NILE_ADD(_tag, _clock) \ |
| 12 | MCFG_DEVICE_ADD(_tag, NILE, _clock) \ |
| 13 | |
| 14 | #define MCFG_NILE_REPLACE(_tag, _clock) \ |
| 15 | MCFG_DEVICE_REPLACE(_tag, NILE, _clock) \ |
| 16 | |
| 17 | |
| 18 | |
| 19 | //************************************************************************** |
| 20 | // TYPE DEFINITIONS |
| 21 | //************************************************************************** |
| 22 | |
| 23 | #define NILE_VOICES 8 |
| 24 | |
| 25 | // ======================> nile_device |
| 26 | |
| 13 | 27 | class nile_device : public device_t, |
| 14 | | public device_sound_interface |
| 28 | public device_sound_interface |
| 15 | 29 | { |
| 16 | 30 | public: |
| 17 | 31 | nile_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 18 | | ~nile_device() { global_free(m_token); } |
| 32 | ~nile_device() { } |
| 19 | 33 | |
| 20 | | // access to legacy token |
| 21 | | void *token() const { assert(m_token != NULL); return m_token; } |
| 22 | 34 | protected: |
| 23 | 35 | // device-level overrides |
| 24 | | virtual void device_config_complete(); |
| 25 | 36 | virtual void device_start(); |
| 26 | 37 | |
| 27 | 38 | // sound stream update overrides |
| 28 | 39 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 40 | |
| 41 | public: |
| 42 | DECLARE_WRITE16_MEMBER( nile_snd_w ); |
| 43 | DECLARE_READ16_MEMBER( nile_snd_r ); |
| 44 | DECLARE_WRITE16_MEMBER( nile_sndctrl_w ); |
| 45 | DECLARE_READ16_MEMBER( nile_sndctrl_r ); |
| 46 | |
| 29 | 47 | private: |
| 30 | | // internal state |
| 31 | | void *m_token; |
| 48 | sound_stream *m_stream; |
| 49 | UINT8 *m_sound_ram; |
| 50 | UINT16 m_sound_regs[0x80]; |
| 51 | int m_vpos[NILE_VOICES]; |
| 52 | int m_frac[NILE_VOICES]; |
| 53 | int m_lponce[NILE_VOICES]; |
| 54 | UINT16 m_ctrl; |
| 32 | 55 | }; |
| 33 | 56 | |
| 34 | 57 | extern const device_type NILE; |