public void k053260_write_rom(byte ChipID, Int32 ROMSize, Int32 DataStart, Int32 DataLength, byte[] ROMData, Int32 SrcStartAdr) { k053260_state info = K053260Data[ChipID]; if (info.rom_size != ROMSize) { info.rom = new byte[ROMSize];// (byte*)realloc(info.rom, ROMSize); info.rom_size = (UInt32)ROMSize; for (Int32 i = 0; i < ROMSize; i++) { info.rom[i] = 0xff; } //memset(info.rom, 0xFF, ROMSize); } if (DataStart > ROMSize) { return; } if (DataStart + DataLength > ROMSize) { DataLength = ROMSize - DataStart; } for (Int32 i = 0; i < DataLength; i++) { info.rom[i + DataStart] = ROMData[i + SrcStartAdr]; } //memcpy(info.rom + DataStart, ROMData, DataLength); return; }
}; //[MAX_CHIPS]; /*INLINE k053260_state *get_safe_token(device_t *device) * { * assert(device != NULL); * assert(device->type() == K053260); * return (k053260_state *)downcast<legacy_device_base *>(device)->token(); * }*/ private void InitDeltaTable(k053260_state ic, Int32 rate, Int32 clock) { Int32 i; double _base = (double)rate; double max = (double)(clock); /* Hz */ UInt32 val; for (i = 0; i < 0x1000; i++) { double v = (double)(0x1000 - i); double target = (max) / v; double _fixed = (double)(1 << BASE_SHIFT); if (target != 0 && _base != 0) { target = _fixed / (_base / target); val = (UInt32)target; if (val == 0) { val = 1; } } else { val = 1; } ic.delta_table[i] = val; } }
public void device_stop_k053260(byte ChipID) { k053260_state ic = K053260Data[ChipID]; //free(ic.delta_table); //free(ic.rom); ic.rom = null; return; }
public void k053260_set_mute_mask(byte ChipID, UInt32 MuteMask) { k053260_state info = K053260Data[ChipID]; byte CurChn; for (CurChn = 0; CurChn < 4; CurChn++) { info.channels[CurChn].Muted = (byte)((MuteMask >> CurChn) & 0x01); } return; }
//READ8_DEVICE_HANDLER( k053260_r ) public byte k053260_r(byte ChipID, Int32 offset) { //k053260_state *ic = get_safe_token(device); k053260_state ic = K053260Data[ChipID]; switch (offset) { case 0x29: /* channel status */ { Int32 i, status = 0; for (i = 0; i < 4; i++) { status |= ic.channels[i].play << i; } return((byte)status); } //break; case 0x2e: /* read ROM */ if ((ic.mode & 1) != 0) { UInt32 offs = ic.channels[0].start + (ic.channels[0].pos >> BASE_SHIFT) + (ic.channels[0].bank << 16); ic.channels[0].pos += (1 << 16); if (offs > ic.rom_size) { //logerror("%s: K53260: Attempting to read past ROM size in ROM Read Mode (offs = %06x, size = %06x).\n", device->machine().describe_context(),offs,ic.rom_size ); //logerror("K53260: Attempting to read past ROM size in ROM Read Mode (offs = %06x, size = %06x).\n", offs, ic.rom_size); return(0); } return(ic.rom[offs]); } break; } return((byte)ic.regs[offset]); }
//static DEVICE_RESET( k053260 ) public void device_reset_k053260(byte ChipID) { //k053260_state *ic = get_safe_token(device); k053260_state ic = K053260Data[ChipID]; Int32 i; for (i = 0; i < 4; i++) { ic.channels[i].rate = 0; ic.channels[i].size = 0; ic.channels[i].start = 0; ic.channels[i].bank = 0; ic.channels[i].volume = 0; ic.channels[i].play = 0; ic.channels[i].pan = 0; ic.channels[i].pos = 0; ic.channels[i].loop = 0; ic.channels[i].ppcm = 0; ic.channels[i].ppcm_data = 0; } }
private void check_bounds(k053260_state ic, Int32 channel) { Int32 channel_start = (Int32)((ic.channels[channel].bank << 16) + ic.channels[channel].start); Int32 channel_end = (Int32)(channel_start + ic.channels[channel].size - 1); if (channel_start > ic.rom_size) { //logerror("K53260: Attempting to start playing past the end of the ROM ( start = %06x, end = %06x ).\n", channel_start, channel_end); ic.channels[channel].play = 0; return; } if (channel_end > ic.rom_size) { //logerror("K53260: Attempting to play past the end of the ROM ( start = %06x, end = %06x ).\n", channel_start, channel_end); ic.channels[channel].size = (UInt32)(ic.rom_size - channel_start); } //if (LOG) logerror("K053260: Sample Start = %06x, Sample End = %06x, Sample rate = %04x, PPCM = %s\n", channel_start, channel_end, ic.channels[channel].rate, ic.channels[channel].ppcm ? "yes" : "no"); }
//WRITE8_DEVICE_HANDLER( k053260_w ) public void k053260_w(byte ChipID, Int32 offset, byte data) { Int32 i, t; Int32 r = offset; Int32 v = data; //k053260_state *ic = get_safe_token(device); k053260_state ic = K053260Data[ChipID]; if (r > 0x2f) { //logerror("K053260: Writing past registers\n"); return; } //ic.channel->update(); /* before we update the regs, we need to check for a latched reg */ if (r == 0x28) { t = ic.regs[r] ^ v; for (i = 0; i < 4; i++) { if ((t & (1 << i)) != 0) { if ((v & (1 << i)) != 0) { ic.channels[i].play = 1; ic.channels[i].pos = 0; ic.channels[i].ppcm_data = 0; check_bounds(ic, i); } else { ic.channels[i].play = 0; } } } ic.regs[r] = v; return; } /* update regs */ ic.regs[r] = v; /* communication registers */ if (r < 8) { return; } /* channel setup */ if (r < 0x28) { Int32 channel = (r - 8) / 8; switch ((r - 8) & 0x07) { case 0: /* sample rate low */ ic.channels[channel].rate &= 0x0f00; ic.channels[channel].rate |= (UInt32)v; break; case 1: /* sample rate high */ ic.channels[channel].rate &= 0x00ff; ic.channels[channel].rate |= (UInt32)((v & 0x0f) << 8); break; case 2: /* size low */ ic.channels[channel].size &= 0xff00; ic.channels[channel].size |= (UInt32)v; break; case 3: /* size high */ ic.channels[channel].size &= 0x00ff; ic.channels[channel].size |= (UInt32)(v << 8); break; case 4: /* start low */ ic.channels[channel].start &= 0xff00; ic.channels[channel].start |= (UInt32)v; break; case 5: /* start high */ ic.channels[channel].start &= 0x00ff; ic.channels[channel].start |= (UInt32)(v << 8); break; case 6: /* bank */ ic.channels[channel].bank = (UInt32)(v & 0xff); break; case 7: /* volume is 7 bits. Convert to 8 bits now. */ ic.channels[channel].volume = (UInt32)(((v & 0x7f) << 1) | (v & 1)); break; } return; } switch (r) { case 0x2a: /* loop, ppcm */ for (i = 0; i < 4; i++) { ic.channels[i].loop = (v & (1 << i)) != 0 ? 1 : 0; } for (i = 4; i < 8; i++) { ic.channels[i - 4].ppcm = (v & (1 << i)) != 0 ? 1 : 0; } break; case 0x2c: /* pan */ ic.channels[0].pan = (UInt32)(v & 7); ic.channels[1].pan = (UInt32)((v >> 3) & 7); break; case 0x2d: /* more pan */ ic.channels[2].pan = (UInt32)(v & 7); ic.channels[3].pan = (UInt32)((v >> 3) & 7); break; case 0x2f: /* control */ ic.mode = v & 7; /* bit 0 = read ROM */ /* bit 1 = enable sound output */ /* bit 2 = unknown */ break; } }
//static STREAM_UPDATE( k053260_update ) public void k053260_update(byte ChipID, Int32[][] outputs, Int32 samples) { //sbyte[] dpcmcnv = new sbyte[] { 0, 1, 2, 4, 8, 16, 32, 64, -128, -64, -32, -16, -8, -4, -2, -1 }; Int32 i, j; //Int32[] lvol = new Int32[4], rvol = new Int32[4], play = new Int32[4], loop = new Int32[4], ppcm = new Int32[4]; //byte[] rom = new byte[4]; //UInt32[] ptrRom = new UInt32[4]; //UInt32[] delta = new UInt32[4], end = new UInt32[4], pos = new UInt32[4]; //sbyte[] ppcm_data = new sbyte[4]; Int32 dataL, dataR; sbyte d; //k053260_state *ic = (k053260_state *)param; k053260_state ic = K053260Data[ChipID]; /* precache some values */ for (i = 0; i < 4; i++) { if (ic.channels[i].Muted != 0) { play[i] = 0; continue; } //rom[i] = ic.rom[ic.channels[i].start + (ic.channels[i].bank << 16)]; ptrRom[i] = ic.channels[i].start + (ic.channels[i].bank << 16); delta[i] = ic.delta_table[ic.channels[i].rate]; lvol[i] = (Int32)(ic.channels[i].volume * ic.channels[i].pan); rvol[i] = (Int32)(ic.channels[i].volume * (8 - ic.channels[i].pan)); end[i] = ic.channels[i].size; pos[i] = ic.channels[i].pos; play[i] = ic.channels[i].play; loop[i] = ic.channels[i].loop; ppcm[i] = ic.channels[i].ppcm; ppcm_data[i] = (sbyte)ic.channels[i].ppcm_data; if (ppcm[i] != 0) { delta[i] /= 2; } } for (j = 0; j < samples; j++) { dataL = dataR = 0; for (i = 0; i < 4; i++) { /* see if the voice is on */ if (play[i] != 0) { /* see if we're done */ if ((pos[i] >> BASE_SHIFT) >= end[i]) { ppcm_data[i] = 0; if (loop[i] != 0) { pos[i] = 0; } else { play[i] = 0; continue; } } if (ppcm[i] != 0) { /* Packed PCM */ /* we only update the signal if we're starting or a real sound sample has gone by */ /* this is all due to the dynamic sample rate conversion */ if (pos[i] == 0 || ((pos[i] ^ (pos[i] - delta[i])) & 0x8000) == 0x8000) { Int32 newdata; if ((pos[i] & 0x8000) != 0) { //newdata = ((rom[i][pos[i] >> BASE_SHIFT]) >> 4) & 0x0f; /*high nybble*/ newdata = ((ic.rom[ptrRom[i] + (pos[i] >> BASE_SHIFT)]) >> 4) & 0x0f; /*high nybble*/ } else { //newdata = ((rom[i][pos[i] >> BASE_SHIFT])) & 0x0f; /*low nybble*/ newdata = ((ic.rom[ptrRom[i] + (pos[i] >> BASE_SHIFT)])) & 0x0f; /*low nybble*/ } /*ppcm_data[i] = (( ( ppcm_data[i] * 62 ) >> 6 ) + dpcmcnv[newdata]); * * if ( ppcm_data[i] > 127 ) * ppcm_data[i] = 127; * else * if ( ppcm_data[i] < -128 ) * ppcm_data[i] = -128;*/ ppcm_data[i] += dpcmcnv[newdata]; } d = ppcm_data[i]; pos[i] += delta[i]; } else { /* PCM */ //d = rom[i][pos[i] >> BASE_SHIFT]; d = (sbyte)ic.rom[ptrRom[i] + (pos[i] >> BASE_SHIFT)]; pos[i] += delta[i]; } if ((ic.mode & 2) != 0) { dataL += (d * lvol[i]) >> 2; dataR += (d * rvol[i]) >> 2; } } } outputs[1][j] = limit(dataL, MAXOUT, MINOUT); outputs[0][j] = limit(dataR, MAXOUT, MINOUT); } /* update the regs now */ for (i = 0; i < 4; i++) { if (ic.channels[i].Muted != 0) { continue; } ic.channels[i].pos = pos[i]; ic.channels[i].play = play[i]; ic.channels[i].ppcm_data = ppcm_data[i]; } }