public void okim6295_write_rom(byte ChipID, int ROMSize, int DataStart, int DataLength, byte[] ROMData) { okim6295_state chip = OKIM6295Data[ChipID]; if (chip.ROMSize != ROMSize) { chip.ROM = new byte[ROMSize];// (byte*)realloc(chip.ROM, ROMSize); chip.ROMSize = (uint)ROMSize; //printf("OKIM6295: New ROM Size: 0x%05X\n", ROMSize); //memset(chip->ROM, 0xFF, ROMSize); for (int i = 0; i < ROMSize; i++) { chip.ROM[i] = 0xff; } } if (DataStart > ROMSize) return; if (DataStart + DataLength > ROMSize) DataLength = ROMSize - DataStart; //memcpy(chip->ROM + DataStart, ROMData, DataLength); for (int i = 0; i < DataLength; i++) { chip.ROM[i + DataStart] = ROMData[i]; } return; }
public void okim6295_write_rom2(byte ChipID, int ROMSize, int DataStart, int DataLength, byte[] ROMData,uint srcStartAddr) { //System.Console.Write("OKIM6295:okim6295_write_rom2: ChipID:{0} ROMSize:{1:X} DataStart:{2:X} DataLength:{3:X} srcStartAddr:{4:X}\n", ChipID, ROMSize, DataStart, DataLength, srcStartAddr); okim6295_state chip = OKIM6295Data[ChipID]; if (chip.ROMSize != ROMSize) { chip.ROM = new byte[ROMSize];// (byte*)realloc(chip.ROM, ROMSize); chip.ROMSize = (uint)ROMSize; //printf("OKIM6295: New ROM Size: 0x%05X\n", ROMSize); //memset(chip->ROM, 0xFF, ROMSize); for (int i = 0; i < ROMSize; i++) { chip.ROM[i] = 0xff; } } if (DataStart > ROMSize) return; if (DataStart + DataLength > ROMSize) DataLength = ROMSize - DataStart; //memcpy(chip->ROM + DataStart, ROMData, DataLength); for (int i = 0; i < DataLength; i++) { chip.ROM[i + DataStart] = ROMData[i + srcStartAddr]; //Console.Write("{0:X02} ", chip.ROM[i + DataStart]); } return; }
private static byte memory_raw_read_byte(okim6295_state chip, int offset) { int CurOfs; if (chip.nmk_mode==0) { CurOfs = chip.bank_offs | offset; } else { byte BankID; if (offset < NMK_TABLESIZE && (chip.nmk_mode & 0x80)!=0) { // pages sample table BankID = (byte)(offset >> (int)NMK_BNKTBLBITS); CurOfs = (int)(offset & NMK_TABLEMASK); // 0x3FF, not 0xFF } else { BankID = (byte)(offset >> (int)NMK_BANKBITS); CurOfs = (int)(offset & NMK_BANKMASK); } CurOfs |= (chip.nmk_bank[BankID & 0x03] << (int)NMK_BANKBITS); // I modified MAME to write a clean sample ROM. // (Usually it moves the data by NMK_ROMBASE.) //CurOfs += NMK_ROMBASE; } if (CurOfs < chip.ROMSize) return chip.ROM[CurOfs]; else return 0x00; }
/********************************************************************************************** DEVICE_RESET( okim6295 ) -- stop emulation of an OKIM6295-compatible chip ***********************************************************************************************/ //static DEVICE_RESET( okim6295 ) private void device_reset_okim6295(byte ChipID) { //okim6295_state *info = get_safe_token(device); okim6295_state info = OKIM6295Data[ChipID]; int voice; //stream_update(info->stream); info.command = -1; info.bank_offs = 0; info.nmk_mode = 0x00; //memset(info->nmk_bank, 0x00, 4 * sizeof(UINT8)); for (int i = 0; i < 4; i++) { info.nmk_bank[i] = 0x00; } info.master_clock = info.initial_clock & 0x7FFFFFFF; infos[ChipID].masterClock = info.master_clock; info.pin7_state = (byte)((info.initial_clock & 0x80000000) >> 31); infos[ChipID].pin7State = (byte)((info.initial_clock & 0x80000000) >> 31); for (voice = 0; voice < okim6295_state.OKIM6295_VOICES; voice++) { info.voice[voice].volume = 0; reset_adpcm(info.voice[voice].adpcm); info.voice[voice].playing = 0; } }
/********************************************************************************************** okim6295_set_pin7 -- adjust pin 7, which controls the internal clock division ***********************************************************************************************/ private static void okim6295_clock_changed(okim6295_state info) { int divisor; divisor = info.pin7_state != 0 ? 132 : 165; //stream_set_sample_rate(info->stream, info->master_clock/divisor); info.SmpRateFunc?.Invoke(info.SmpRateData, (int)info.master_clock / divisor); }
private void device_stop_okim6295(byte ChipID) { okim6295_state chip = OKIM6295Data[ChipID]; chip.ROM = null; chip.ROMSize = 0x00; return; }
//void okim6295_set_pin7(running_device *device, int pin7) private static void okim6295_set_pin7(okim6295_state info, int pin7) { //okim6295_state *info = get_safe_token(device); //int divisor = pin7 ? 132 : 165; info.pin7_state = (byte)pin7; //stream_set_sample_rate(info->stream, info->master_clock/divisor); okim6295_clock_changed(info); }
public void okim6295_set_srchg_cb(byte ChipID, dlgSRATE_CALLBACK CallbackFunc, MDSound.Chip DataPtr) { okim6295_state info = OKIM6295Data[ChipID]; // set Sample Rate Change Callback routine info.SmpRateFunc = CallbackFunc; info.SmpRateData = DataPtr; return; }
public void okim6295_set_mute_mask(byte ChipID, uint MuteMask) { okim6295_state chip = OKIM6295Data[ChipID]; byte CurChn; for (CurChn = 0; CurChn < okim6295_state.OKIM6295_VOICES; CurChn++) chip.voice[CurChn].Muted = (byte)((MuteMask >> CurChn) & 0x01); return; }
/********************************************************************************************** * * OKIM 6295 ADPCM chip: * * Command bytes are sent: * * 1xxx xxxx = start of 2-byte command sequence, xxxxxxx is the sample number to trigger * abcd vvvv = second half of command; one of the abcd bits is set to indicate which voice * the v bits seem to be volumed * * 0abc d000 = stop playing; one or more of the abcd bits is set to indicate which voice(s) * * Status is read: * * ???? abcd = one bit per voice, set to 0 if nothing is playing, or 1 if it is active * ***********************************************************************************************/ /********************************************************************************************** okim6295_update -- update the sound chip so that it is in sync with CPU execution ***********************************************************************************************/ //static STREAM_UPDATE( okim6295_update ) private void okim6295_update(byte ChipID, int[][] outputs, int samples) { //System.Console.Write("samples:{0}\n" , samples); //okim6295_state *chip = (okim6295_state *)param; okim6295_state chip = OKIM6295Data[ChipID]; int i; //memset(outputs[0], 0, samples * sizeof(*outputs[0])); for (i = 0; i < samples; i++) { outputs[0][i] = 0; } for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++) // for (i = 0; i < 1; i++) { ADPCMVoice voice = chip.voice[i]; infos[ChipID].chInfo[i].mask = voice.Muted == 0; if (voice.Muted == 0) { int[][] buffer = outputs; int ptrBuffer = 0; short[] sample_data = new short[MAX_SAMPLE_CHUNK]; int remaining = samples; /* loop while we have samples remaining */ while (remaining != 0) { int Samples = (remaining > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : remaining; int samp; generate_adpcm(chip, voice, sample_data, Samples); for (samp = 0; samp < Samples; samp++) { buffer[0][ptrBuffer++] += sample_data[samp]; //if (sample_data[samp] != 0) //{ // System.Console.WriteLine("ch:{0} sampledata[{1}]={2} count:{3} sample:{4}" // , i, samp, sample_data[samp] // , voice.count, voice.sample); //} } remaining -= samples; } } } //memcpy(outputs[1], outputs[0], samples * sizeof(*outputs[0])); for (i = 0; i < samples; i++) { outputs[1][i] = outputs[0][i]; } }
private void okim6295_w(byte ChipID, int offset, byte data) { okim6295_state chip = OKIM6295Data[ChipID]; switch (offset) { case 0x00: okim6295_write_command(chip, data); break; case 0x08: chip.master_clock &= ~((uint)0x000000FF); chip.master_clock |= (uint)(data << 0); break; case 0x09: chip.master_clock &= ~((uint)0x0000FF00); chip.master_clock |= (uint)(data << 8); break; case 0x0A: chip.master_clock &= ~((uint)0x00FF0000); chip.master_clock |= (uint)(data << 16); break; case 0x0B: data &= 0x7F; chip.master_clock &= ~((uint)0xFF000000); chip.master_clock |= (uint)(data << 24); okim6295_clock_changed(chip); break; case 0x0C: okim6295_set_pin7(chip, data); break; case 0x0E: // NMK112 bank switch enable chip.nmk_mode = data; break; case 0x0F: okim6295_set_bank_base(chip, data << 18); break; case 0x10: case 0x11: case 0x12: case 0x13: chip.nmk_bank[offset & 0x03] = data; break; } return; }
private void generate_adpcm(okim6295_state chip, ADPCMVoice voice, short[] buffer, int samples) { int ptrBuffer = 0; /* if this voice is active */ if (voice.playing != 0) { //System.Console.Write("base_offset[{0:X}] sample[{1:X}] count[{2:X}]\n", voice.base_offset, voice.sample, voice.count); int iBase = (int)voice.base_offset; int sample = (int)voice.sample; int count = (int)voice.count; /* loop while we still have samples to generate */ while (samples != 0) { /* compute the new amplitude and update the current step */ //int nibble = memory_raw_read_byte(chip->device->space(), base + sample / 2) >> (((sample & 1) << 2) ^ 4); //System.Console.Write("nibblecal1[{0:d}]2[{1:d}]\n", iBase + sample / 2, (((sample & 1) << 2) ^ 4)); byte nibble = (byte)(memory_raw_read_byte(chip, iBase + sample / 2) >> (((sample & 1) << 2) ^ 4)); //System.Console.Write( "nibble[{0:X}]\n", nibble); /* output to the buffer, scaling by the volume */ /* signal in range -2048..2047, volume in range 2..32 => signal * volume / 2 in range -32768..32767 */ buffer[ptrBuffer++] = (short)(clock_adpcm(voice.adpcm, nibble) * voice.volume / 2); //System.Console.Write("*buffer[{0}]\n", buffer[ptrBuffer-1]); samples--; /* next! */ if (++sample >= count) { voice.playing = 0; break; } } /* update the parameters */ voice.sample = (uint)sample; } /* fill the rest with silence */ while (samples-- != 0) { buffer[ptrBuffer++] = 0; } }
/********************************************************************************************** okim6295_status_r -- read the status port of an OKIM6295-compatible chip ***********************************************************************************************/ //READ8_DEVICE_HANDLER( okim6295_r ) private byte okim6295_r(byte ChipID, int offset) { //okim6295_state *info = get_safe_token(device); okim6295_state info = OKIM6295Data[ChipID]; int i, result; result = 0xf0; /* naname expects bits 4-7 to be 1 */ /* set the bit to 1 if something is playing on a given channel */ //stream_update(info->stream); for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++) { ADPCMVoice voice = info.voice[i]; /* set the bit if it's playing */ if (voice.playing != 0) result |= 1 << i; } return (byte)result; }
/********************************************************************************************** okim6295_set_bank_base -- set the base of the bank for a given voice on a given chip ***********************************************************************************************/ //void okim6295_set_bank_base(running_device *device, int base) private void okim6295_set_bank_base(okim6295_state info, int iBase) { //okim6295_state *info = get_safe_token(device); //stream_update(info->stream); /* if we are setting a non-zero base, and we have no bank, allocate one */ //if (info.bank_installed == 0 && iBase != 0) //{ /* override our memory map with a bank */ //memory_install_read_bank(device->space(), 0x00000, 0x3ffff, 0, 0, device->tag()); //info.bank_installed = 1;// TRUE; //} /* if we have a bank number, set the base pointer */ //if (info.bank_installed != 0) //{ //info.bank_offs = iBase; //memory_set_bankptr(device->machine, device->tag(), device->region->base.u8 + base); //} info.bank_offs = iBase; }
/********************************************************************************************** okim6295_data_w -- write to the data port of an OKIM6295-compatible chip ***********************************************************************************************/ //WRITE8_DEVICE_HANDLER( okim6295_w ) private void okim6295_write_command(okim6295_state info, byte data,okim6295Info Info) { //okim6295_state *info = get_safe_token(device); /* if a command is pending, process the second half */ if (info.command != -1) { int temp = data >> 4, i, start, stop; int iBase; /* the manual explicitly says that it's not possible to start multiple voices at the same time */ // if (temp != 0 && temp != 1 && temp != 2 && temp != 4 && temp != 8) // System.Console.Write("OKI6295 start %x contact MAMEDEV\n", temp); /* update the stream */ //stream_update(info->stream); /* determine which voice(s) (voice is set by a 1 bit in the upper 4 bits of the second byte) */ for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++, temp >>= 1) { if ((temp & 1) != 0) { ADPCMVoice voice = info.voice[i]; /* determine the start/stop positions */ iBase = info.command * 8; //start = memory_raw_read_byte(device->space(), base + 0) << 16; start = memory_raw_read_byte(info, iBase + 0) << 16; start |= memory_raw_read_byte(info, iBase + 1) << 8; start |= memory_raw_read_byte(info, iBase + 2) << 0; start &= 0x3ffff; Info.chInfo[i].stAdr = start; stop = memory_raw_read_byte(info, iBase + 3) << 16; stop |= memory_raw_read_byte(info, iBase + 4) << 8; stop |= memory_raw_read_byte(info, iBase + 5) << 0; stop &= 0x3ffff; Info.chInfo[i].edAdr = stop; /* set up the voice to play this sample */ if (start < stop) { if (voice.playing == 0) /* fixes Got-cha and Steel Force */ { voice.playing = 1; voice.base_offset = (uint)start; voice.sample = 0; voice.count = (uint)(2 * (stop - start + 1)); /* also reset the ADPCM parameters */ reset_adpcm(voice.adpcm); voice.volume = (uint)volume_table[data & 0x0f]; Info.keyon[i] = true; } else { //logerror("OKIM6295:'%s' requested to play sample %02x on non-stopped voice\n",device->tag(),info->command); // just displays warnings when seeking //logerror("OKIM6295: Voice %u requested to play sample %02x on non-stopped voice\n",i,info->command); } } /* invalid samples go here */ else { //logerror("OKIM6295:'%s' requested to play invalid sample %02x\n",device->tag(),info->command); //System.Console.Write("OKIM6295: Voice {0} requested to play invalid sample {1:X2} StartAddr {2:X} StopAdr {3:X} \n", i, info.command, start, stop); voice.playing = 0; } } } /* reset the command */ info.command = -1; } /* if this is the start of a command, remember the sample number for next time */ else if ((data & 0x80) != 0) { info.command = data & 0x7f; } /* otherwise, see if this is a silence command */ else { int temp = data >> 3, i; /* update the stream, then turn it off */ //stream_update(info->stream); /* determine which voice(s) (voice is set by a 1 bit in bits 3-6 of the command */ for (i = 0; i < okim6295_state.OKIM6295_VOICES; i++, temp >>= 1) { if ((temp & 1) != 0) { ADPCMVoice voice = info.voice[i]; voice.playing = 0; } } } }