From: Shamus Hammons Date: Sat, 19 Apr 2014 20:28:01 +0000 (-0500) Subject: Emulator working with YM2151 and V63701 emus in place. X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=thunder;a=commitdiff_plain;h=be67039a7ed493081dd1503f94cdfae4dd4d965e Emulator working with YM2151 and V63701 emus in place. --- diff --git a/src/sound.cpp b/src/sound.cpp index 930de35..744eafa 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -14,6 +14,7 @@ #include "sound.h" #include #include "resource.h" +#include "ym2151.h" // Function prototypes void SoundFunc(void *, Uint8 *, int); @@ -22,7 +23,7 @@ void SoundFunc(void *, Uint8 *, int); extern uint8_t voice_rom[]; // PCM data pointer static bool soundInitialized = false; -const float sampleBase = 22050.0/6000.0; // Btwn 5512.5 and 6000 +const float sampleBase = 44010.0/6000.0; // Btwn 5512.5 and 6000 bool snd_go = false; bool chan1_go = false, chan2_go = false, chan3_go = false; bool chan4_go = false, chan5_go = false, chan6_go = false; @@ -47,9 +48,17 @@ uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen }; void InitSound(void) { + // params 1, 4 & 5 are useless +// if (YMInit(1, 3579580, 22050, 16, 512))//, (SAMPLE **)sbp)) + if (YMInit(1, 3579580, 44100, 16, 512)) + { + printf("SOUND: Could not init YM2151 emulator!\n"); + return;// -1; + } + SDL_AudioSpec desired, obtained; - desired.freq = 22050; - desired.format = AUDIO_U8; + desired.freq = 44100; + desired.format = AUDIO_S16; desired.channels = 1; desired.samples = 1024; desired.callback = SoundFunc; @@ -58,7 +67,7 @@ void InitSound(void) if (SDL_OpenAudio(&desired, &obtained) < 0) { soundInitialized = false; - printf("Couldn't open audio: %s\n", SDL_GetError()); + printf("SOUND: Couldn't open audio: %s\n", SDL_GetError()); return; } @@ -145,6 +154,7 @@ void SpawnSound(int type, int snd, int channel/* = 0*/) chan4_go = false; // No sound loaded, so don't do it! } } +#if 0 else if (type == FMSOUND) { spos5 = 0; @@ -155,6 +165,7 @@ void SpawnSound(int type, int snd, int channel/* = 0*/) if (spos5 == end_pos5) chan5_go = false; // No sound loaded, so don't do it! } +#endif else if (type == USERSOUND) { spos6 = 0; @@ -167,6 +178,13 @@ void SpawnSound(int type, int snd, int channel/* = 0*/) void SoundFunc(void * userdata, Uint8 * buff, int num) { + static bool psg1go = false, psg2go = false; + // Length / 2 is because it's set up for 16-bit samples +// YM2151UpdateOne(buffer, length / 2); + // Have to go into ym2151.cpp and change this manually back to 8 bit + YM2151UpdateOne(buff, num / 2); +// return; + // 0-22 different sounds... uint16_t cnt = 0, sample; uint8_t start_samp1, end_samp1, start_samp2, end_samp2; @@ -174,123 +192,127 @@ void SoundFunc(void * userdata, Uint8 * buff, int num) samp4 = 128, samp5 = 128, samp6 = 128; // Zero samples... // Kill sound... - memset(buff, 128, num); +// memset(buff, 128, num); + + if (!(chan1_go || chan2_go || chan3_go || chan4_go /*|| chan5_go*/ || chan6_go)) + return; - if (chan1_go || chan2_go || chan3_go || chan4_go || chan5_go || chan6_go) + while (cnt != (num / 2)) { - while (cnt != num) + if (chan1_go) { - if (chan1_go) + if (sample1 < 1) { - if (sample1 < 1) + samp1 = voice_rom[spos1++]; + + // Kill channel 1 if done... + if (samp1 == 0xFF) { - samp1 = voice_rom[spos1++]; - - // Kill channel 1 if done... - if (samp1 == 0xFF) - { - chan1_go = false; - samp1 = 128; - } - // RLE compression... - else if (samp1 == 0x00) - { - // # of repeats - sample1 += (float)voice_rom[spos1++] * sampleBase; - // Get last good sample - samp1 = prevSamp1; - } - else - // Keep fractional part intact - sample1 += sampleBase; + chan1_go = false; + samp1 = 128; } - - prevSamp1 = samp1; // Save last sample value - sample1 -= 1.0; // Decrement repeat counter + // RLE compression... + else if (samp1 == 0x00) + { + // # of repeats + sample1 += (float)voice_rom[spos1++] * sampleBase; + // Get last good sample + samp1 = prevSamp1; + } + else + // Keep fractional part intact + sample1 += sampleBase; } + prevSamp1 = samp1; // Save last sample value + sample1 -= 1.0; // Decrement repeat counter + } + // Stretching 5KHz samples to 22KHz: // numRepeats = 4; // 6KHz -> 22KHz: 22/6 repeats... - if (chan2_go) + if (chan2_go) + { + if (sample2 < 1) { - if (sample2 < 1) + samp2 = voice_rom[spos2++]; + + if (samp2 == 0xFF) { - samp2 = voice_rom[spos2++]; - - if (samp2 == 0xFF) - { - chan2_go = false; - samp2 = 128; // Kill channel 2 if done... - } - else if (samp2 == 0x00) // RLE compression... - { - sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats - samp2 = prevSamp2; - } - else - sample2 += sampleBase; + chan2_go = false; + samp2 = 128; // Kill channel 2 if done... } + else if (samp2 == 0x00) // RLE compression... + { + sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats + samp2 = prevSamp2; + } + else + sample2 += sampleBase; + } // Delta-X values were making the samples sound like crap... // start_samp2 += delta_x2; - prevSamp2 = samp2; - sample2 -= 1.0; - } + prevSamp2 = samp2; + sample2 -= 1.0; + } - if (chan3_go) - { - samp3 = sndp3[spos3++]; + if (chan3_go) + { + samp3 = (psg1go ? sndp3[spos3++] : sndp3[spos3]); + psg1go = !psg1go; - if (spos3 == end_pos3) - { - chan3_go = false; - samp3 = 128; // Kill channel 3 if done... - } + if (spos3 == end_pos3) + { + chan3_go = false; + samp3 = 128; // Kill channel 3 if done... } + } - if (chan4_go) - { - samp4 = sndp4[spos4++]; + if (chan4_go) + { + samp4 = (psg2go ? sndp4[spos4++] : sndp4[spos4]); + psg2go = !psg2go; - if (spos4 == end_pos4) - { - chan4_go = false; - samp4 = 128; // Kill channel 4 if done... - } + if (spos4 == end_pos4) + { + chan4_go = false; + samp4 = 128; // Kill channel 4 if done... } + } +#if 0 + if (chan5_go) + { + samp5 = sndp5[spos5++]; - if (chan5_go) + if (spos5 == end_pos5) { - samp5 = sndp5[spos5++]; - - if (spos5 == end_pos5) - { - chan5_go = false; - samp5 = 128; // Kill channel 5 if done... - } + chan5_go = false; + samp5 = 128; // Kill channel 5 if done... } + } +#endif + if (chan6_go) + { + samp6 = sndp6[spos6++]; - if (chan6_go) + if (spos6 == end_pos6) { - samp6 = sndp6[spos6++]; - - if (spos6 == end_pos6) - { - chan6_go = false; - samp6 = 128; // Kill channel 6... - } + chan6_go = false; + samp6 = 128; // Kill channel 6... } + } - // Mix 'em... - sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640; + // Mix 'em... +// sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640; + sample = samp1 + samp2 + samp3 + samp4 + samp6 - (5 * 128); - // If it overflowed, clip it - if (sample & 0xFF00) - sample = (sample & 0x8000 ? 0x00 : 0xFF); + // If it overflowed, clip it + if (sample & 0xFF00) +// sample = (sample & 0x8000 ? 0x00 : 0xFF); + sample = (sample & 0x8000 ? 0x0000 : 0xFFFF); - buff[cnt++] = sample; - } + ((uint16_t *)buff)[cnt++] += sample << 7; } } diff --git a/src/thunder.cpp b/src/thunder.cpp index 5219805..d1ebfde 100644 --- a/src/thunder.cpp +++ b/src/thunder.cpp @@ -33,6 +33,8 @@ #include "v63701.h" #include "v6809.h" #include "video.h" +#include "ym2151.h" + using namespace std; @@ -98,8 +100,10 @@ uint8_t * psg_adrs[16]; //uint32_t voc_lens[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //uint8_t * voc_adrs[32]; -uint32_t fm_lens[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -uint8_t * fm_adrs[14]; +//uint32_t fm_lens[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +//uint8_t * fm_adrs[14]; + +Byte input1, input2, input3, input4, input5; fstream tr; // Tracelog hook uint16_t pcx; // Where we at? @@ -167,7 +171,10 @@ if (((addr >= 0x4180) && (addr <= 0x4191)) || (addr == 0x4380)) } #endif // if (addr < 0x423D || addr > 0x425C) // Protect writes to DSWs - +//if (addr == 0x4191) +//{ +// printf("V6809: Writing %02X to $4191...\n", b); +//} // Memory shared with MCU (CPU #1 only! CPU #2 does not) if ((addr >= 0x4000) && (addr <= 0x43FF)) mcuMem[addr - 0x3000] = b; @@ -279,34 +286,42 @@ if (((addr >= 0x0180) && (addr <= 0x0191)) || (addr == 0x0380)) uint8_t MCUReadMemory(uint16_t address) { -#if 1 if (address < 0x20) { // printf("V63701 read $%02X from $%02X...\n", memory[address], address); return InternalRegisterRead(address); } -#endif - -#if 0 - // Translate local reads @ $1000-$13FF to $4000-$43FF in shared RAM - if ((address >= 0x1000) && (address <= 0x13FF)) - return gram1[0x3000 + address]; - else -#endif - if ((address >= 0x2000) && (address <= 0x2001)) + else if ((address >= 0x2000) && (address <= 0x2001)) + { +// return 0; //for now + return YMReadReg(0); + } + // Various joystick + buttons; all are active low. + else if (address == 0x2020) + { +//printf("MCURead: Returning $%02X from $2020...\n", input1.byte); + return input1.byte; + } + else if (address == 0x2021) { - return 0; //for now -// return YMReadReg(0); +//extern bool V63701LogGo; +//if (input2.byte == 0xDF) +// V63701LogGo = true; + +//printf("MCURead: Returning $%02X from $2021...\n", input2.byte); + return input2.byte; } -// else if (address == 0x2020) -// return input_port_0_r(0); -// else if (address == 0x2021) -// return input_port_1_r(0); // This is DSW1 & 2. All switch settings are active low. else if (address == 0x2030) - return 0xFF; + { +//printf("MCURead: Returning $%02X from $2030...\n", input4.byte); + return input4.byte; + } else if (address == 0x2031) - return 0xFF; + { +//printf("MCURead: Returning $%02X from $2031...\n", input5.byte); + return input5.byte; + } return mcuMem[address]; } @@ -325,6 +340,10 @@ void MCUWriteMemory(uint16_t address, uint8_t data) } #endif +//if (address == 0x1191) +//{ +// printf("V63701: Writing $%02X to $1191...\n", data); +//} #if 0 // Translate local reads @ $1000-$13FF to $4000-$43FF in shared RAM if ((address >= 0x1000) && (address <= 0x13FF)) @@ -345,7 +364,7 @@ void MCUWriteMemory(uint16_t address, uint8_t data) else if (address == 0x2001) { //printf("Writing $%02X to YM2151 register $%02X...\n", data, ymRegister); -// YMWriteReg(0, ymRegister, data); + YMWriteReg(0, ymRegister, data); return; } @@ -354,6 +373,31 @@ void MCUWriteMemory(uint16_t address, uint8_t data) } +uint8_t V63701ReadPort1(void) +{ +// printf("V63701ReadPort1: Read $%02X...\n", input3.byte); + return input3.byte; +} + + +uint8_t V63701ReadPort2(void) +{ + return 0xFF; +} + + +void V63701WritePort1(uint8_t data) +{ +// printf("V63701WritePort1: Wrote $%02X...\n", data); +} + + +void V63701WritePort2(uint8_t data) +{ +// printf("V63701WritePort2: Wrote $%02X...\n", data); +} + + // // Generic Load file into image space // (No error checking performed! Responsibility of caller!) @@ -584,6 +628,7 @@ void LoadPSGs(void) } +#if 0 // // Load FM samples from disk // @@ -622,6 +667,7 @@ void LoadFMs(void) fp.close(); } } +#endif // @@ -743,7 +789,7 @@ extern bool disasm; // From 'V6809.CPP' // Load samples if they're there... LoadPSGs(); - LoadFMs(); +// LoadFMs(); // Set up V6809 execution contexts @@ -767,6 +813,10 @@ extern bool disasm; // From 'V6809.CPP' trace1 = false; SetRefreshRate(refresh2); // Tell GUI our refresh rate + // Set all inputs to inactive... + input1.byte = input2.byte = input3.byte = input4.byte = input5.byte = 0xFF; +// mcu.port1 = 0xFF; +// mcu.port2 = 0xFF; #if 0 // This is data that is supposed to come from the MCU... So that's why it hangs gram1[0x4182] = 0xA6; // Temp kludge @@ -860,53 +910,135 @@ WriteLog("About to enter main loop...\n"); SavePCXSnapshot(); // debounce = 10; } - else if (event.key.keysym.sym == SDLK_F10) - gram1[0x41A5]++; // Coin? (F10) - else if (event.key.keysym.sym == SDLK_c) - gram1[0x418C]++; // ? (C) Start +#if 1 + else if (event.key.keysym.sym == SDLK_5) + input1.bit.b5 = 0; + else if (event.key.keysym.sym == SDLK_1) + input1.bit.b6 = 0; else if (event.key.keysym.sym == SDLK_RIGHT) - { - // Disallow opposite directions @ same time - if (gram1[0x4281] == 0) - gram1[0x427F] = 1; // Stick right - } + input3.bit.b5 = 0; else if (event.key.keysym.sym == SDLK_LEFT) - { - // Disallow opposite directions@same time - if (gram1[0x427F] == 0) - gram1[0x4281] = 1; // Stick left - } + input3.bit.b4 = 0; else if (event.key.keysym.sym == SDLK_UP) - { - // Disallow opposite directions@same time - if (gram1[0x427D] == 0) - gram1[0x427B] = 1; // Stick up - } + input2.bit.b2 = 0; else if (event.key.keysym.sym == SDLK_DOWN) - { - // Disallow opposite directions@same time - if (gram1[0x427B] == 0) - gram1[0x427D] = 1; // Stick down - } - else if (event.key.keysym.sym == SDLK_q) - gram1[0x4276] = 1; // (Q) Jump + input1.bit.b2 = 0; + else if (event.key.keysym.sym == SDLK_q) // (Q) Jump + input1.bit.b1 = 0; else if (event.key.keysym.sym == SDLK_e) // (E) Fire - gram1[0x4278] = 1; + input3.bit.b3 = 0; +#else + else if (event.key.keysym.sym == SDLK_1) + input1.bit.b0 = 0; + else if (event.key.keysym.sym == SDLK_2) + input1.bit.b1 = 0; + else if (event.key.keysym.sym == SDLK_3) + input1.bit.b2 = 0; + else if (event.key.keysym.sym == SDLK_4) + input1.bit.b3 = 0; + else if (event.key.keysym.sym == SDLK_5) + input1.bit.b4 = 0; + else if (event.key.keysym.sym == SDLK_6) + input1.bit.b5 = 0; + else if (event.key.keysym.sym == SDLK_7) + input1.bit.b6 = 0; + else if (event.key.keysym.sym == SDLK_8) + input1.bit.b7 = 0; + + else if (event.key.keysym.sym == SDLK_q) + input2.bit.b0 = 0; + else if (event.key.keysym.sym == SDLK_w) + input2.bit.b1 = 0; + else if (event.key.keysym.sym == SDLK_e) + input2.bit.b2 = 0; + else if (event.key.keysym.sym == SDLK_r) + input2.bit.b3 = 0; + else if (event.key.keysym.sym == SDLK_t) + input2.bit.b4 = 0; + else if (event.key.keysym.sym == SDLK_y) + input2.bit.b5 = 0; + else if (event.key.keysym.sym == SDLK_u) + input2.bit.b6 = 0; + else if (event.key.keysym.sym == SDLK_i) + input2.bit.b7 = 0; + + else if (event.key.keysym.sym == SDLK_a) + input3.bit.b0 = 0; + else if (event.key.keysym.sym == SDLK_s) + input3.bit.b1 = 0; + else if (event.key.keysym.sym == SDLK_d) + input3.bit.b2 = 0; + else if (event.key.keysym.sym == SDLK_f) + input3.bit.b3 = 0; + else if (event.key.keysym.sym == SDLK_g) + input3.bit.b4 = 0; +#endif break; case SDL_KEYUP: - if (event.key.keysym.sym == SDLK_RIGHT) - gram1[0x427F] = 0; +#if 1 + if (event.key.keysym.sym == SDLK_5) + input1.bit.b5 = 1; + else if (event.key.keysym.sym == SDLK_1) + input1.bit.b6 = 1; + else if (event.key.keysym.sym == SDLK_RIGHT) + input3.bit.b5 = 1; else if (event.key.keysym.sym == SDLK_LEFT) - gram1[0x4281] = 0; + input3.bit.b4 = 1; else if (event.key.keysym.sym == SDLK_UP) - gram1[0x427B] = 0; + input2.bit.b2 = 1; else if (event.key.keysym.sym == SDLK_DOWN) - gram1[0x427D] = 0; - else if (event.key.keysym.sym == SDLK_q) - gram1[0x4276] = 0; // (Q) Jump + input1.bit.b2 = 1; + else if (event.key.keysym.sym == SDLK_q) // (Q) Jump + input1.bit.b1 = 1; else if (event.key.keysym.sym == SDLK_e) // (E) Fire - gram1[0x4278] = 0; + input3.bit.b3 = 1; +#else + if (event.key.keysym.sym == SDLK_1) + input1.bit.b0 = 1; + else if (event.key.keysym.sym == SDLK_2) + input1.bit.b1 = 1; + else if (event.key.keysym.sym == SDLK_3) + input1.bit.b2 = 1; + else if (event.key.keysym.sym == SDLK_4) + input1.bit.b3 = 1; + else if (event.key.keysym.sym == SDLK_5) + input1.bit.b4 = 1; + else if (event.key.keysym.sym == SDLK_6) + input1.bit.b5 = 1; + else if (event.key.keysym.sym == SDLK_7) + input1.bit.b6 = 1; + else if (event.key.keysym.sym == SDLK_8) + input1.bit.b7 = 1; + + else if (event.key.keysym.sym == SDLK_q) + input2.bit.b0 = 1; + else if (event.key.keysym.sym == SDLK_w) + input2.bit.b1 = 1; + else if (event.key.keysym.sym == SDLK_e) + input2.bit.b2 = 1; + else if (event.key.keysym.sym == SDLK_r) + input2.bit.b3 = 1; + else if (event.key.keysym.sym == SDLK_t) + input2.bit.b4 = 1; + else if (event.key.keysym.sym == SDLK_y) + input2.bit.b5 = 1; + else if (event.key.keysym.sym == SDLK_u) + input2.bit.b6 = 1; + else if (event.key.keysym.sym == SDLK_i) + input2.bit.b7 = 1; + + else if (event.key.keysym.sym == SDLK_a) + input3.bit.b0 = 1; + else if (event.key.keysym.sym == SDLK_s) + input3.bit.b1 = 1; + else if (event.key.keysym.sym == SDLK_d) + input3.bit.b2 = 1; + else if (event.key.keysym.sym == SDLK_f) + input3.bit.b3 = 1; + else if (event.key.keysym.sym == SDLK_g) + input3.bit.b4 = 1; +#endif break; } @@ -1131,6 +1263,7 @@ WriteLog("About to enter main loop...\n"); // We can do this here because we're not executing the cores yet. cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ; cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ; + mcu.cpuFlags |= V63701_ASSERT_LINE_IRQ; // while (cpu1.clock < 25000) // 1.538 MHz = 25633.333... cycles per frame (1/60 s) // 25600 cycles/frame @@ -1170,9 +1303,11 @@ WriteLog("About to enter main loop...\n"); if (psg_adrs[i]) delete[] psg_adrs[i]; +#if 0 for(int i=0; i<14; i++) if (fm_adrs[i]) delete[] fm_adrs[i]; +#endif LogDone(); diff --git a/src/v63701.cpp b/src/v63701.cpp index b76063f..ea225bd 100644 --- a/src/v63701.cpp +++ b/src/v63701.cpp @@ -37,7 +37,7 @@ // conversion to macro style opcodes is completed. :-) // [DONE--remain to be seen if there is any performance increase] -//#define __DEBUG__ +#define __DEBUG__ #define TEST_DONT_BRANCH_OPTIMIZATION #include "v63701.h" @@ -46,6 +46,7 @@ #ifdef __DEBUG__ #include "dis63701.h" //#include "log.h" +#include // for printf() #define WriteLog printf #endif @@ -94,10 +95,12 @@ #define WRITE_BACK(d) regs.WrMem(addr, (d)) -#define PULL regs.RdMem(regs.s++) -#define PUSH(r) regs.WrMem(--regs.s, (r)) -#define PULL16 RdMemW(regs.s); regs.s += 2 -#define PUSH16(r) regs.WrMem(--regs.s, (r) & 0xFF); regs.WrMem(--regs.s, (r) >> 8) +// This is correct; PUSH writes the location *then* decrements the stack +// pointer, and PULL does the opposite. Verified from the data sheet. +#define PULL regs.RdMem(++regs.s) +#define PUSH(r) regs.WrMem(regs.s--, (r)) +#define PULL16 RdMemW(++regs.s); ++regs.s; +#define PUSH16(r) regs.WrMem(regs.s--, (r) & 0xFF); regs.WrMem(regs.s--, (r) >> 8) #define PACK_FLAGS ((regs.cc & 0xC0) | (flagH << 5) | (flagI << 4) | (flagN << 3) | (flagZ << 2) | (flagV << 1) | flagC) #define UNPACK_FLAGS flagH = (regs.cc & FLAG_H) >> 5; \ @@ -110,7 +113,9 @@ // Private global variables static V63701REGS regs; +//V63701REGS regs; static V63701REGS * regsPointer; +//V63701REGS * regsPointer; static uint8_t flagH, flagI, flagN, flagZ, flagV, flagC; static uint8_t CPUCycles[256] = { @@ -2591,10 +2596,11 @@ static void myMemcpy(void * dst, void * src, uint32_t size) #ifdef __DEBUG__ //int instCount[256]; -//static bool logGo = false; -static bool logGo = true; +bool V63701LogGo = false; +//static bool V63701LogGo = true; char instBuf[256]; -extern uint8_t memory[]; +extern uint8_t mcuMem[]; +uint8_t * memory = mcuMem; #endif // // Function to execute 63701 for "cycles" cycles @@ -2618,8 +2624,14 @@ void Execute63701(V63701REGS * context, uint32_t cycles) while (regs.clock < endCycles) #endif { +#if 0 +if (regs.pc == 0x8236) +{ + printf("V63701: $8236 called by $%04X...\n", RdMemW(regs.s)); +} +#endif #ifdef __DEBUG__ -if (logGo) +if (V63701LogGo) { Decode63701(memory, regs.pc, instBuf); WriteLog("%s\n", instBuf); @@ -2674,7 +2686,7 @@ if (logGo) } } #ifdef __DEBUG__ -if (logGo) +if (V63701LogGo) // WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%s%s%s%s%s%s%s%s]\n", regs.pc, regs.s, regs.x, regs.d.acc.a, regs.d.acc.b, (regs.cc & FLAG_E ? "E" : " "), (regs.cc & FLAG_F ? "F" : " "), (regs.cc & FLAG_H ? "H" : " "), (regs.cc & FLAG_I ? "I" : " "), (regs.cc & FLAG_N ? "N" : " "), (regs.cc & FLAG_Z ? "Z" : " "), (regs.cc & FLAG_V ? "V" : " "), (regs.cc & FLAG_C ? "C" : " ")); WriteLog(" [PC=%04X S=%04X X=%04X A=%02X B=%02X CC=%s%s%s%s%s%s TCSR=%s%s%s%s%s%s%s%s CT=%04X OC=%04X]\n", regs.pc, regs.s, regs.x, regs.d.acc.a, regs.d.acc.b, (flagH ? "H" : "."), (flagI ? "I" : "."), (flagN ? "N" : "."), (flagZ ? "Z" : "."), (flagV ? "V" : "."), (flagC ? "C" : "."), (regs.tcsr.bit.icf ? "I" :"."), (regs.tcsr.bit.ocf ? "O" :"."), (regs.tcsr.bit.tof ? "T" :"."), (regs.tcsr.bit.eici ? "i" :"."), (regs.tcsr.bit.eoci ? "o" :"."), (regs.tcsr.bit.etoi ? "t" :"."), (regs.tcsr.bit.iedg ? "E" :"."), (regs.tcsr.bit.olvl ? "O" :"."), regs.counter.word, regs.outputCompare.word); #endif @@ -2683,7 +2695,8 @@ if (logGo) if (regs.cpuFlags & V63701_ASSERT_LINE_RESET) { #ifdef __DEBUG__ -WriteLog("*** RESET LINE ASSERTED ***\n"); +if (V63701LogGo) + WriteLog("*** RESET LINE ASSERTED ***\n"); #endif regs.tcsr.byte = 0; regs.tcsrWasRead = false; @@ -2697,21 +2710,24 @@ WriteLog("*** RESET LINE ASSERTED ***\n"); else if (regs.cpuFlags & V63701_ASSERT_LINE_NMI) { #ifdef __DEBUG__ -WriteLog("*** NMI LINE ASSERTED ***\n"); +if (V63701LogGo) + WriteLog("*** NMI LINE ASSERTED ***\n"); #endif HandleInterrupt(0xFFFC, V63701_ASSERT_LINE_NMI); } else if (regs.cpuFlags & V63701_ASSERT_LINE_IRQ) { #ifdef __DEBUG__ -WriteLog("*** IRQ LINE ASSERTED ***\n"); +if (V63701LogGo) + WriteLog("*** IRQ LINE ASSERTED ***\n"); #endif // if (!(regs.cc & FLAG_I)) // Process an interrupt (I=0)? if (!flagI) // Process an interrupt (I=0)? { #ifdef __DEBUG__ -WriteLog(" IRQ TAKEN!\n"); -logGo = true; +if (V63701LogGo) + WriteLog(" IRQ TAKEN!\n"); +//V63701LogGo = true; #endif HandleInterrupt(0xFFF8, V63701_ASSERT_LINE_IRQ); } @@ -2719,14 +2735,16 @@ logGo = true; else if (regs.cpuFlags & V63701_ASSERT_INPUT_CAPTURE) { #ifdef __DEBUG__ -WriteLog("*** INPUT CAPTURE ASSERTED ***\n"); +if (V63701LogGo) + WriteLog("*** INPUT CAPTURE ASSERTED ***\n"); #endif // Process interrupt if no I inhibit set, & enable in TCSR is set if (!flagI && regs.tcsr.bit.eici) { #ifdef __DEBUG__ -WriteLog(" IC TAKEN!\n"); -logGo = true; +if (V63701LogGo) + WriteLog(" IC TAKEN!\n"); +//V63701LogGo = true; #endif HandleInterrupt(0xFFF6, V63701_ASSERT_INPUT_CAPTURE); } @@ -2734,14 +2752,16 @@ logGo = true; else if (regs.cpuFlags & V63701_ASSERT_OUTPUT_COMPARE) { #ifdef __DEBUG__ -WriteLog("*** OUTPUT COMPARE ASSERTED ***\n"); +if (V63701LogGo) + WriteLog("*** OUTPUT COMPARE ASSERTED ***\n"); #endif // Process interrupt if no I inhibit set, & enable in TCSR is set if (!flagI && regs.tcsr.bit.eoci) { #ifdef __DEBUG__ -WriteLog(" OC TAKEN!\n"); -logGo = true; +if (V63701LogGo) + WriteLog(" OC TAKEN!\n"); +//V63701LogGo = true; #endif HandleInterrupt(0xFFF4, V63701_ASSERT_OUTPUT_COMPARE); } @@ -2749,14 +2769,16 @@ logGo = true; else if (regs.cpuFlags & V63701_ASSERT_TIMER_OVERFLOW) { #ifdef __DEBUG__ -WriteLog("*** TIMER OVER ASSERTED ***\n"); +if (V63701LogGo) + WriteLog("*** TIMER OVER ASSERTED ***\n"); #endif // Process interrupt if no I inhibit set, & enable in TCSR is set if (!flagI && regs.tcsr.bit.etoi) { #ifdef __DEBUG__ -WriteLog(" TO TAKEN!\n"); -logGo = true; +if (V63701LogGo) + WriteLog(" TO TAKEN!\n"); +//V63701LogGo = true; #endif HandleInterrupt(0xFFF2, V63701_ASSERT_TIMER_OVERFLOW); } @@ -2813,8 +2835,15 @@ uint8_t InternalRegisterRead(uint16_t address) { case 0x00: return regs.ddr1; + case 0x01: + return regs.ddr2; case 0x02: - return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port1 & regs.ddr1); + return (V63701ReadPort1() & ~regs.ddr1) | (regs.port1data & regs.ddr1); +// return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port1r & ~regs.ddr1); + case 0x03: + // Top 3 bits are MCU mode bits. + return (V63701ReadPort2() & ~regs.ddr2) | (regs.port2data & regs.ddr2); +// return /*(regs.port1read & ~regs.ddr1) |*/ (regs.port2r & ~regs.ddr2 & 0x1F); // Timer Control and Status Register case 0x08: regs.tcsrWasRead = true; @@ -2855,6 +2884,8 @@ uint8_t InternalRegisterRead(uint16_t address) void InternalRegisterWrite(uint16_t address, uint8_t data) { + uint8_t writeData; + switch (address & 0x1F) { case 0x00: @@ -2864,10 +2895,13 @@ void InternalRegisterWrite(uint16_t address, uint8_t data) regs.ddr2 = data; break; case 0x02: - regs.port1 = data; + regs.port1data = data; + writeData = (V63701ReadPort1() & ~regs.ddr1) | (data & regs.ddr1); + V63701WritePort1(writeData); break; case 0x03: - regs.port2 = data; + // Port 2 only has 5 bits of output, top 3 are the MCU mode bits + regs.port2data = ((regs.port2data & ~regs.ddr2) | (data & regs.ddr2)) & 0x1F; break; // case 0x05: // Timer Control and Status Register diff --git a/src/v63701.h b/src/v63701.h index 47c5b18..2e711dc 100644 --- a/src/v63701.h +++ b/src/v63701.h @@ -105,8 +105,8 @@ struct V63701REGS Word outputCompare; // 63701 Output Compare register uint8_t ddr1; uint8_t ddr2; - uint8_t port1; - uint8_t port2; + uint8_t port1data; + uint8_t port2data; uint8_t ramCtrl; uint8_t cWriteLatch; // Counter write latch uint8_t cReadLatch; // Counter read latch @@ -128,5 +128,11 @@ uint64_t GetCurrentV63701Clock(void); // Get the clock of the currently executi uint8_t InternalRegisterRead(uint16_t); void InternalRegisterWrite(uint16_t, uint8_t); +// These functions must be implemented by the user... +extern uint8_t V63701ReadPort1(void); +extern uint8_t V63701ReadPort2(void); +extern void V63701WritePort1(uint8_t); +extern void V63701WritePort2(uint8_t); + #endif // __V63701_H__ diff --git a/src/ym2151.c b/src/ym2151.c deleted file mode 100644 index a69a281..0000000 --- a/src/ym2151.c +++ /dev/null @@ -1,1450 +0,0 @@ -// -// Jarek Burczynski's YM2151 emulator -// -// Cleaned of most MAMEisms & cleaned up in general by James Hammons -// (this is mostly a placeholder until I write my own) -// - -#include "ym2151.h" - -#include -#include -#include -#include -#include - - -// Missing shit (from M.A.M.E.) - -#if 1 -#define PI 3.1415629535897932338 -static FILE * errorlog = 0; -//int cpu_scalebyfcount(int); -//void timer_remove(void *); -//void * timer_set(int, int, void (*)(int)); - -// Bogus M.A.M.E. shite -int cpu_scalebyfcount(int f) { return f; } -void timer_remove(void * foo) { printf("STUB: timer_remove()\n"); } -void * timer_set(int foo, int bar, void (* baz)(int)) { printf("STUB: timer_set()\n"); return 0; } - -#endif - - -/* -** some globals ... -*/ - -/* -** Shifts below are subject to change if sampling frequency changes... -*/ -#define FREQ_SH 16 /* 16.16 fixed point for frequency calculations */ -#define LFO_SH 24 /* 8.24 fixed point for LFO frequency calculations */ -#define ENV_SH 16 /* 16.16 fixed point for envelope calculations */ -#define TIMER_SH 16 /* 16.16 fixed point for timers calculations */ - -#define ENV_BITS 10 -#define ENV_RES ((int)1< 16 bit sample, 0 -> 8 bit */ - -static int YMBufSize; /* size of sound buffer, in samples */ -static int YMNumChips; /* total # of YM's emulated */ - -static int TimerA[1024]; -static int TimerB[256]; - -/* ASG 980324: added */ -static double TimerATime[1024]; -static double TimerBTime[256]; - -static YM2151 * YMPSG = NULL; /* array of YM's */ - -signed int * BuffTemp = NULL; /*temporary buffer for speedup purposes*/ - -static void (* envelope_calc[5])(OscilRec *); -static void (* register_writes[256])(uint8_t, uint8_t, uint8_t); - -//save output as raw 16-bit sample - just in case you would like to listen to it offline ;-) -//#define SAVE_SAMPLE -//#define SAVE_SEPARATE_CHANNELS - -#ifdef SAVE_SAMPLE -#ifdef SAVE_SEPARATE_CHANNELS -FILE * sample1; -FILE * sample2; -FILE * sample3; -FILE * sample4; -FILE * sample5; -FILE * sample6; -#endif -FILE * samplesum; -#endif - -int PMTab[8]; /*8 channels */ -/* this table is used for PM setup of LFO */ - -int AMTab[8]; /*8 channels */ -/* this table is used for AM setup of LFO */ - -static int decib45[16]; -/*decibel table to convert from D1L values to index in lookup table*/ - -static int attack_curve[ENV_RES]; - -unsigned int divia[64]; //Attack dividers -unsigned int divid[64]; //Decay dividers -static unsigned int A_DELTAS[64+31]; //Attack deltas (64 keycodes + 31 RKS's = 95) -static unsigned int D_DELTAS[64+31]; //Decay deltas (64 keycodes + 31 RKS's = 95) - -float DT1Tab[32][4]={ /* 8 octaves * 4 key codes, 4 DT1 values */ -/* - * Table defines offset in Hertz from base frequency depending on KC and DT1 - * User's Manual page 21 -*/ -/*OCT NOTE DT1=0 DT1=1 DT1=2 DT1=3*/ -/* 0 0*/{0, 0, 0.053, 0.107}, -/* 0 1*/{0, 0, 0.053, 0.107}, -/* 0 2*/{0, 0, 0.053, 0.107}, -/* 0 3*/{0, 0, 0.053, 0.107}, -/* 1 0*/{0, 0.053, 0.107, 0.107}, -/* 1 1*/{0, 0.053, 0.107, 0.160}, -/* 1 2*/{0, 0.053, 0.107, 0.160}, -/* 1 3*/{0, 0.053, 0.107, 0.160}, -/* 2 0*/{0, 0.053, 0.107, 0.213}, -/* 2 1*/{0, 0.053, 0.160, 0.213}, -/* 2 2*/{0, 0.053, 0.160, 0.213}, -/* 2 3*/{0, 0.053, 0.160, 0.267}, -/* 3 0*/{0, 0.107, 0.213, 0.267}, -/* 3 1*/{0, 0.107, 0.213, 0.320}, -/* 3 2*/{0, 0.107, 0.213, 0.320}, -/* 3 3*/{0, 0.107, 0.267, 0.373}, -/* 4 0*/{0, 0.107, 0.267, 0.427}, -/* 4 1*/{0, 0.160, 0.320, 0.427}, -/* 4 2*/{0, 0.160, 0.320, 0.480}, -/* 4 3*/{0, 0.160, 0.373, 0.533}, -/* 5 0*/{0, 0.213, 0.427, 0.587}, -/* 5 1*/{0, 0.213, 0.427, 0.640}, -/* 5 2*/{0, 0.213, 0.480, 0.693}, -/* 5 3*/{0, 0.267, 0.533, 0.747}, -/* 6 0*/{0, 0.267, 0.587, 0.853}, -/* 6 1*/{0, 0.320, 0.640, 0.907}, -/* 6 2*/{0, 0.320, 0.693, 1.013}, -/* 6 3*/{0, 0.373, 0.747, 1.067}, -/* 7 0*/{0, 0.427, 0.853, 1.173}, -/* 7 1*/{0, 0.427, 0.907, 1.173}, -/* 7 2*/{0, 0.480, 1.013, 1.173}, -/* 7 3*/{0, 0.533, 1.067, 1.173} -}; - -static uint16_t DT2Tab[4]={ /* 4 DT2 values */ -/* - * DT2 defines offset in cents from base note - * - * The table below defines offset in deltas table... - * User's Manual page 22 - * Values below were calculated using formula: value = orig.val / 1.5625 - * - * DT2=0 DT2=1 DT2=2 DT2=3 - * 0 600 781 950 - */ - 0, 384, 500, 608 -}; - -static uint16_t KC_TO_INDEX[16*8]; /*16 note codes * 8 octaves */ -/*translate key code KC (OCT2 OCT1 OCT0 N3 N2 N1 N0) into index in deltas table*/ - -static signed int DT1deltas[32][8]; - -static signed int deltas[9*12*64];/*9 octaves, 12 semitones, 64 'cents' */ -/*deltas in sintable (fixed point) to get the closest frequency possible */ -/*there're 9 octaves because of DT2 (max 950 cents over base frequency) */ - -static signed int LFOdeltas[256]; /*frequency deltas for LFO*/ - - -void sin_init(void) -{ - int x, i; - float m; - - for(i=0; i -0.0001)) /*is m very close to zero ?*/ - m = ENV_RES - 1; - else - { - if (m > 0.0) - { - m = 20 * log10(1.0 / m); /* and how many decibels is it? */ - m = m / ENV_STEP; - } - else - { - m = 20 * log10(-1.0 / m); /* and how many decibels is it? */ - m = (m / ENV_STEP) + TL_TAB_LEN / 2; - } - } - - sin_tab[i] = &TL_TAB[(unsigned int)m]; /**/ - //if (errorlog) fprintf(errorlog,"sin %i = %i\n",i,sin_tab[i] ); - } - - for(x=0; x> 1; //oct 3 - deltas[i + oct * 2] = deltas[oct * 4 + i] >> 2; //oct 2 - deltas[i + oct * 1] = deltas[oct * 4 + i] >> 3; //oct 1 - deltas[i + oct * 0] = deltas[oct * 4 + i] >> 4; //oct 0 - - //if (errorlog) fprintf(errorlog,"deltas[%04i] = %08x\n",i,deltas[i]); - } - - for(j=0; j<4; j++) - { - for(i=0; i<32; i++) - { - pom = scaler * DT1Tab[i][j]; - //calculate phase increment for above precounted Hertz value - DT1deltas[i][j] = ((pom * SIN_LEN) / (float)YM2151_SAMPFREQ) * mult; /*fixed point*/ - DT1deltas[i][j + 4] = -DT1deltas[i][j]; - } - } - - mult = (long int)1 << LFO_SH; - m = (float)YM2151_CLOCK; - - for(i=0; i<256; i++) - { - j = i & 0x0F; - pom = scaler * fabs((m / 65536 / (1 << (i / 16))) - (m / 65536 / 32 / (1 << (i / 16)) * (j + 1))); - - /*calculate phase increment for above precounted Hertz value*/ - pom2 = ((pom * SIN_LEN) / (float)YM2151_SAMPFREQ) * mult; /*fixed point*/ - LFOdeltas[0xFF - i] = pom2; - //if (errorlog) fprintf(errorlog, "LFO[%02x] = %08x\n",0xff-i, LFOdeltas[0xff-i]); - } - - /* calculate KC to index table */ - j=0; - for(i=0; i<16*8; i++) - { - KC_TO_INDEX[i] = (i >> 4) * 12 * 64 + j * 64 ; - - if ((i & 3) != 3) - j++; /* change note code */ - - if ((i & 15) == 15) - j = 0; /* new octave */ - - //if (errorlog) fprintf(errorlog,"NOTE[%i] = %i\n",i,KC_TO_INDEX[i]); - } - - /* precalculate envelope times */ - for(i=0; i<64; i++) - { - pom = (16 << (i >> 2)) + (4 << (i >> 2)) * (i & 0x03); - - if ((i >> 2) == 0) - pom = 1; //infinity - - if ((i >> 2) == 15) - pom = 524288; //const - - divid[i] = pom; - } - - for(i=0; i<64; i++) - { - pom = ((128+64+32)<<(i>>2))+((32+16+8)<<(i>>2))*(i&0x03); - - if ((i>>2)==0) pom=1; //infinity - - if ((i>>2)==15) - { - if ((i & 0x03) == 3) - pom = 153293300; //zero attack time - else - pom = 6422528; //const attack time - } - - divia[i] = pom; - } - - mult = (long int)1 << ENV_SH; - - for(i=0; i<64; i++) - { - if (divid[i] == 1) - pom = 0; //infinity - else - pom = (scaler * ENV_RES * mult) / ((float)YM2151_SAMPFREQ * ((float)YM2151_CLOCK / 1000.0 / (float)divid[i])); - //if (errorlog) fprintf(errorlog,"i=%03i div=%i time=%f delta=%f\n",i,divid[i], - // (float)YM2151_CLOCK/1000.0/(float)divid[i], pom ); - D_DELTAS[i] = pom; - } - - for (i=0; i<64; i++) - { - if (divia[i] == 1) - pom = 0; //infinity - else - pom = (scaler * ENV_RES * mult) / ((float)YM2151_SAMPFREQ * ((float)YM2151_CLOCK / 1000.0 / (float)divia[i])); - - //if (errorlog) fprintf(errorlog,"i=%03i div=%i time=%f delta=%f\n",i,divia[i], - // (float)YM2151_CLOCK/1000.0/(float)divia[i], pom ); - A_DELTAS[i] = pom; - } - - // This is only for speedup purposes -> to avoid testing if (keycode+RKS is - // over 63) - for(i=0; i<32; i++) - { - D_DELTAS[64 + i] = D_DELTAS[63]; - A_DELTAS[64 + i] = A_DELTAS[63]; - } - - /* precalculate timers deltas */ - /* User's Manual pages 15,16 */ - mult = (int)1 << TIMER_SH; - - for(i=0; i<1024; i++) - { - /* ASG 980324: changed to compute both TimerA and TimerATime */ - pom = (64.0 * (1024.0 - i) / YM2151_CLOCK); - TimerATime[i] = pom; - TimerA[i] = pom * YM2151_SAMPFREQ * mult; /*number of samples that timer period should last (fixed point) */ - } - - for(i=0; i<256; i++) - { - /* ASG 980324: changed to compute both TimerB and TimerBTime */ - pom = (1024.0 * (256.0 - i) / YM2151_CLOCK); - TimerBTime[i] = pom; - TimerB[i] = pom * YM2151_SAMPFREQ * mult; /*number of samples that timer period should last (fixed point) */ - } -} - - -void envelope_attack(OscilRec * op) -{ - if ((op->attack_volume -= op->delta_AR) < MIN_VOLUME_INDEX) //is volume index min already ? - { - op->volume = MIN_VOLUME_INDEX; - op->state++; - } - else - op->volume = attack_curve[op->attack_volume>>ENV_SH]; -} - - -void envelope_decay(OscilRec * op) -{ - if ((op->volume += op->delta_D1R) > op->D1L) - { - //op->volume = op->D1L; - op->state++; - } -} - - -void envelope_sustain(OscilRec * op) -{ - if ((op->volume += op->delta_D2R) > MAX_VOLUME_INDEX) - { - op->state = 4; - op->volume = VOLUME_OFF; - } -} - - -void envelope_release(OscilRec * op) -{ - if ((op->volume += op->delta_RR) > MAX_VOLUME_INDEX) - { - op->state = 4; - op->volume = VOLUME_OFF; - } -} - - -void envelope_nothing(OscilRec *op) -{ -} - - -inline void envelope_KOFF(OscilRec * op) -{ - op->state = 3; /*release*/ -} - - -inline void envelope_KON(OscilRec * op) -{ - /*this is to remove the gap time if TL>0*/ - op->volume = VOLUME_OFF; //(ENV_RES - op->TL)<attack_volume = op->volume; - op->phase = 0; - op->state = 0; /*KEY ON = attack*/ - op->OscilFB = 0; /*Clear feedback after key on */ -} - - -void refresh_chip(YM2151 * PSG) -{ - uint16_t kc_index_oscil, kc_index_channel, mul; - uint8_t op,v,kc; - signed char k,chan; - OscilRec * osc; - - for(chan=7; chan>=0; chan--) - { - kc = PSG->KC[chan]; - kc_index_channel = KC_TO_INDEX[kc] + PSG->KF[chan]; - kc >>=2; - - for(k=24; k>=0; k-=8) - { - op = chan + k; - osc = &PSG->Oscils[op]; - -/*calc freq begin*/ - v = (PSG->Regs[YM_DT2_D2R_BASE + op] >> 6) & 0x03; //DT2 value - kc_index_oscil = kc_index_channel + DT2Tab[v]; //DT2 offset - v = PSG->Regs[YM_DT1_MUL_BASE + op]; - mul = (v & 0x0F) << 1; - - if (mul) - osc->freq = deltas[kc_index_oscil] * mul; - else - osc->freq = deltas[kc_index_oscil]; - - osc->freq += DT1deltas[kc][(v >> 4) & 0x07]; //DT1 value -/*calc freq end*/ - -/*calc envelopes begin*/ - v = kc >> PSG->KS[op]; - osc->delta_AR = A_DELTAS[ osc->AR + v]; /* 2*RR + RKS =max 95*/ - osc->delta_D1R = D_DELTAS[osc->D1R + v]; /* 2*RR + RKS =max 95*/ - osc->delta_D2R = D_DELTAS[osc->D2R + v]; /* 2*RR + RKS =max 95*/ - osc->delta_RR = D_DELTAS[ osc->RR + v]; /* 2*RR + RKS =max 95*/ -/*calc envelopes end*/ - } - } -} - - -void write_YM_NON_EMULATED(uint8_t n, uint8_t r, uint8_t v) -{ - if (errorlog) - fprintf(errorlog, "Write to non emulated register %02x value %02x\n", r, v); -} - - -void write_YM_KON(uint8_t n, uint8_t r, uint8_t v) -{ - uint8_t chan; - YM2151 * PSG = &(YMPSG[n]); - - chan = v & 0x07; - - if (v & 0x08) - envelope_KON(&PSG->Oscils[chan]); - else - envelope_KOFF(&PSG->Oscils[chan]); - - if (v & 0x10) - envelope_KON(&PSG->Oscils[chan + 16]); - else - envelope_KOFF(&PSG->Oscils[chan + 16]); - - if (v & 0x20) - envelope_KON(&PSG->Oscils[chan + 8]); - else - envelope_KOFF(&PSG->Oscils[chan + 8]); - - if (v & 0x40) - envelope_KON(&PSG->Oscils[chan + 24]); - else - envelope_KOFF(&PSG->Oscils[chan + 24]); -} - - -void write_YM_CLOCKA1(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].Regs[r] = v; -} - - -void write_YM_CLOCKA2(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].Regs[r] = v & 0x03; -} - - -void write_YM_CLOCKB(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].Regs[r] = v; -} - - -static void timer_callback_a(int n) -{ - YM2151 * PSG = &YMPSG[n]; -// YM2151UpdateOne(n, cpu_scalebyfcount(YMBufSize)); - - if (PSG->handler) - (*PSG->handler)(); - - PSG->TimA = 0; - PSG->TimIRQ |= 1; - PSG->TimATimer = 0; -} - - -static void timer_callback_b(int n) -{ - YM2151 * PSG = &YMPSG[n]; -// YM2151UpdateOne(n, cpu_scalebyfcount(YMBufSize)); - - if (PSG->handler) - (*PSG->handler)(); - - PSG->TimB = 0; - PSG->TimIRQ |= 2; - PSG->TimBTimer = 0; -} - - -void write_YM_CLOCKSET(uint8_t n, uint8_t r, uint8_t v) -{ - YM2151 * PSG = &(YMPSG[n]); - - v &= 0xBF; - //PSG->Regs[r]=v; -// if (errorlog) fprintf(errorlog,"CSM= %01x FRESET=%02x, IRQEN=%02x, LOAD=%02x\n",v>>7,(v>>4)&0x03,(v>>2)&0x03,v&0x03 ); - - if (v & 0x80) //CSM - {} - - /* ASG 980324: remove the timers if they exist */ - if (PSG->TimATimer) - timer_remove(PSG->TimATimer); - - if (PSG->TimBTimer) - timer_remove(PSG->TimBTimer); - - PSG->TimATimer = 0; - PSG->TimBTimer = 0; - - if (v & 0x01) //LOAD A - { - PSG->TimA = 1; - PSG->TimAVal = TimerA[(PSG->Regs[YM_CLOCKA1] << 2) | PSG->Regs[YM_CLOCKA2]]; - /* ASG 980324: added a real timer if we have a handler */ - - if (PSG->handler) - PSG->TimATimer = timer_set(TimerATime[(PSG->Regs[YM_CLOCKA1] << 2) | PSG->Regs[YM_CLOCKA2]], n, timer_callback_a); - } - else - PSG->TimA = 0; - - if (v & 0x02) //load B - { - PSG->TimB = 1; - PSG->TimBVal = TimerB[PSG->Regs[YM_CLOCKB]]; - - /* ASG 980324: added a real timer if we have a handler */ - if (PSG->handler) - PSG->TimBTimer = timer_set (TimerBTime[PSG->Regs[YM_CLOCKB]], n, timer_callback_b); - } - else - PSG->TimB = 0; - - if (v & 0x04) //IRQEN A - {} - - if (v & 0x08) //IRQEN B - {} - - if (v & 0x10) //FRESET A - { - PSG->TimIRQ &= 0xFE; - } - - if (v & 0x20) //FRESET B - { - PSG->TimIRQ &= 0xFD; - } -} - - -void write_YM_CT1_CT2_W(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].Regs[r] = v; -} - - -void write_YM_CONNECT_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - // NOTE: L/R Channel enables are ignored! This emu is mono! - YM2151 * PSG = &(YMPSG[n]); - - //PSG->Regs[r] = v; - uint8_t chan = r - YM_CONNECT_BASE; - - PSG->ConnectTab[chan] = v & 7; /*connection number*/ - PSG->FeedBack[chan] = FEED[(v >> 3) & 7]; -} - - -void write_YM_KC_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].KC[r - YM_KC_BASE] = v; - //freq_calc(chan,PSG); -} - - -void write_YM_KF_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].KF[r - YM_KF_BASE] = v >> 2; - //freq_calc(chan,PSG); -} - - -void write_YM_PMS_AMS_BASE(uint8_t n, uint8_t r, uint8_t v) -{ -// uint8_t chan, i; - YM2151 * PSG = &(YMPSG[n]); - PSG->Regs[r] = v; - uint8_t chan = r - YM_PMS_AMS_BASE; - - PMTab[chan] = v >> 4; //PMS; - -// if (i && errorlog) -// fprintf(errorlog,"PMS CHN %02x =%02x\n", chan, i); - - AMTab[chan] = v & 0x03; //AMS; - -// if (i && errorlog) -// fprintf(errorlog,"AMS CHN %02x =%02x\n", chan, i); - -} - - -void write_YM_DT1_MUL_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - YMPSG[n].Regs[r] = v; - //freq_calc(chan,PSG); -} - - -void write_YM_TL_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - v &= 0x7F; - YMPSG[n].Oscils[r - YM_TL_BASE].TL = v << (ENV_BITS - 7); /*7bit TL*/ -} - - -void write_YM_KS_AR_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - uint8_t op; - YM2151 * PSG; - - op = r - YM_KS_AR_BASE; - PSG = &(YMPSG[n]); - - PSG->KS[op] = 3 - (v >> 6); - PSG->Oscils[op].AR = (v & 0x1F) << 1; -} - - -void write_YM_AMS_D1R_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - uint8_t op = r - YM_AMS_D1R_BASE; - - if ((v & 0x80) && errorlog) - fprintf(errorlog,"AMS ON oper%02x\n", op); - - //HERE something to do with AMS; - - YMPSG[n].Oscils[op].D1R = (v & 0x1F) << 1; -} - - -void write_YM_DT2_D2R_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - YM2151 * PSG = &(YMPSG[n]); - OscilRec * osc = &PSG->Oscils[r - YM_DT2_D2R_BASE]; - PSG->Regs[r] = v; - - osc->D2R = (v & 0x1F) << 1; - //freq_calc(chan,PSG); -} - - -void write_YM_D1L_RR_BASE(uint8_t n, uint8_t r, uint8_t v) -{ - OscilRec * osc = &YMPSG[n].Oscils[r - YM_D1L_RR_BASE]; - - osc->D1L = decib45[(v >> 4) & 0x0F]; - osc->RR = ((v & 0x0F) << 2) | 0x02; -} - - -/* -** Initialize YM2151 emulator(s). -** -** 'num' is the number of virtual YM2151's to allocate -** 'clock' is the chip clock -** 'rate' is sampling rate and 'bufsiz' is the size of the -** buffer that should be updated at each interval -*/ -int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE ** buffer) -{ - int i; - - if (YMPSG) - return (-1); /* duplicate init. */ - - YMNumChips = num; - YM2151_SAMPFREQ = rate; - -#if 0 - if (sample_bits == 16) - sample_16bit = 1; - else - sample_16bit = 0; -#endif - - YM2151_CLOCK = clock; - YMBufSize = bufsiz; - - envelope_calc[0] = envelope_attack; - envelope_calc[1] = envelope_decay; - envelope_calc[2] = envelope_sustain; - envelope_calc[3] = envelope_release; - envelope_calc[4] = envelope_nothing; - - for(i=0; i<256; i++) - register_writes[i] = write_YM_NON_EMULATED; - - register_writes[YM_KON] = write_YM_KON; - register_writes[YM_CLOCKA1] = write_YM_CLOCKA1; - register_writes[YM_CLOCKA2] = write_YM_CLOCKA2; - register_writes[YM_CLOCKB] = write_YM_CLOCKB; - register_writes[YM_CLOCKSET] = write_YM_CLOCKSET; - register_writes[YM_CT1_CT2_W] = write_YM_CT1_CT2_W; - - for(i=YM_CONNECT_BASE; iBuf, '\0', YMBufSize); - - /* ASG 980324 -- reset the timers before writing to the registers */ - PSG->TimATimer = 0; - PSG->TimBTimer = 0; - - /* initialize hardware registers */ - for(i=0; i<256; i++) - PSG->Regs[i] = 0; - - for(i=0; i<32; i++) - { - memset(&PSG->Oscils[i], '\0', sizeof(OscilRec)); - PSG->Oscils[i].volume = VOLUME_OFF; - PSG->Oscils[i].state = 4; //envelope off - } - - for(i=0; i<8; i++) - { - PSG->ConnectTab[i] = 0; - PSG->FeedBack[i] = 0; - } - - PSG->TimA = 0; - PSG->TimB = 0; - PSG->TimAVal = 0; - PSG->TimBVal = 0; - PSG->TimIRQ = 0; -} - - -static inline signed int op_calc(OscilRec * OP, signed int pm) -{ - return sin_tab[(((OP->phase += OP->freq) >> FREQ_SH) + (pm)) & SIN_MASK] - [OP->TL + (OP->volume >> ENV_SH)]; -} - - -//void YM2151UpdateOne(int num, int endp) -void YM2151UpdateOne(void * BUF, int endp) -{ -// YM2151 * PSG = &(YMPSG[num]); - YM2151 * PSG = &(YMPSG[0]); - PSG->bufp = 0; -// SAMPLE * BUF; - signed int * PSGBUF; - OscilRec * OP0, * OP1, * OP2, * OP3; - uint16_t i; - signed int k, wy; -#ifdef SAVE_SEPARATE_CHANNELS - signed int pom; -#endif - - refresh_chip(PSG); - - //calculate timers... - if (PSG->TimA) - { - PSG->TimAVal -= ((endp - PSG->bufp) << TIMER_SH); - - if (PSG->TimAVal <= 0) - { - PSG->TimA = 0; - PSG->TimIRQ |= 1; - /* ASG 980324 - handled by real timers now - if (PSG->handler !=0) PSG->handler();*/ - } - } - - if (PSG->TimB) - { - PSG->TimBVal -= ((endp - PSG->bufp) << TIMER_SH); - - if (PSG->TimBVal <= 0) - { - PSG->TimB = 0; - PSG->TimIRQ |= 2; - /* ASG 980324 - handled by real timers now - if (PSG->handler !=0) PSG->handler();*/ - } - } - - OP0 = &PSG->Oscils[0 ]; - OP1 = &PSG->Oscils[0 + 8]; - OP2 = &PSG->Oscils[0 + 16]; - OP3 = &PSG->Oscils[0 + 24]; - - for(PSGBUF=&BuffTemp[PSG->bufp]; PSGBUF<&BuffTemp[endp]; PSGBUF++) - { - //chan0 - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - - if (PSG->FeedBack[0]) - OP0->OscilFB = wy >> PSG->FeedBack[0]; - else - OP0->OscilFB = 0; - - switch(PSG->ConnectTab[0]) - { - case 0: *(PSGBUF) = op_calc(OP3, op_calc(OP1, op_calc(OP2, wy))); break; - case 1: *(PSGBUF) = op_calc(OP3, op_calc(OP1, op_calc(OP2, 0) + wy)); break; - case 2: *(PSGBUF) = op_calc(OP3, op_calc(OP1, op_calc(OP2, 0)) + wy); break; - case 3: *(PSGBUF) = op_calc(OP3, op_calc(OP2, wy) + op_calc(OP1, 0)); break; - case 4: *(PSGBUF) = op_calc(OP2, wy) + op_calc(OP3, op_calc(OP1, 0)); break; - case 5: *(PSGBUF) = op_calc(OP2, wy) + op_calc(OP1, wy) + op_calc(OP3, wy); break; - case 6: *(PSGBUF) = op_calc(OP2, wy) + op_calc(OP1, 0) + op_calc(OP3, 0); break; - default: *(PSGBUF) = wy + op_calc(OP2, 0) + op_calc(OP1, 0) + op_calc(OP3, 0); break; - } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)(*PSGBUF) & 0xFF, sample1); -fputc(((uint16_t)(*PSGBUF) >> 8) & 0xFF, sample1); -#endif - } - - //chan1 - OP0 = &PSG->Oscils[1 ]; - OP1 = &PSG->Oscils[1 + 8]; - OP2 = &PSG->Oscils[1 + 16]; - OP3 = &PSG->Oscils[1 + 24]; - - for(PSGBUF=&BuffTemp[PSG->bufp]; PSGBUF<&BuffTemp[endp]; PSGBUF++) - { - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - - if (PSG->FeedBack[1]) - OP0->OscilFB = wy >> PSG->FeedBack[1]; - else - OP0->OscilFB = 0; - -#ifdef SAVE_SEPARATE_CHANNELS -pom = *(PSGBUF); -#endif - switch(PSG->ConnectTab[1]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default: *(PSGBUF) += wy + op_calc(OP2, 0) + op_calc(OP1, 0) + op_calc(OP3, 0); break; - } - -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample2); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample2); -#endif - } - -//chan2 - OP0 = &PSG->Oscils[2 ]; - OP1 = &PSG->Oscils[2 + 8]; - OP2 = &PSG->Oscils[2 + 16]; - OP3 = &PSG->Oscils[2 + 24]; - -for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) -{ - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - if (PSG->FeedBack[2]) - OP0->OscilFB = wy >> PSG->FeedBack[2]; - else - OP0->OscilFB = 0; - -#ifdef SAVE_SEPARATE_CHANNELS - pom=*(PSGBUF); -#endif - switch(PSG->ConnectTab[2]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; - } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample3); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample3); -#endif -} - -//chan3 - OP0 = &PSG->Oscils[3 ]; - OP1 = &PSG->Oscils[3 + 8]; - OP2 = &PSG->Oscils[3 + 16]; - OP3 = &PSG->Oscils[3 + 24]; - -for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) -{ - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - if (PSG->FeedBack[3]) - OP0->OscilFB = wy >> PSG->FeedBack[3]; - else - OP0->OscilFB = 0; - -#ifdef SAVE_SEPARATE_CHANNELS - pom=*(PSGBUF); -#endif - switch(PSG->ConnectTab[3]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; - } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample4); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample4); -#endif -} - - //chan4 - OP0 = &PSG->Oscils[4 ]; - OP1 = &PSG->Oscils[4 + 8]; - OP2 = &PSG->Oscils[4 + 16]; - OP3 = &PSG->Oscils[4 + 24]; - - for(PSGBUF=&BuffTemp[PSG->bufp]; PSGBUF<&BuffTemp[endp]; PSGBUF++) - { - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - - if (PSG->FeedBack[4]) - OP0->OscilFB = wy >> PSG->FeedBack[4]; - else - OP0->OscilFB = 0; - - #ifdef SAVE_SEPARATE_CHANNELS - pom = *(PSGBUF); - #endif - - switch(PSG->ConnectTab[4]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; - } - -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample5); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample5); -#endif - } - - //chan5 - OP0 = &PSG->Oscils[5 ]; - OP1 = &PSG->Oscils[5 + 8]; - OP2 = &PSG->Oscils[5 + 16]; - OP3 = &PSG->Oscils[5 + 24]; - -for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) -{ - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - if (PSG->FeedBack[5]) - OP0->OscilFB = wy >> PSG->FeedBack[5]; - else - OP0->OscilFB = 0; - -#ifdef SAVE_SEPARATE_CHANNELS - pom=*(PSGBUF); -#endif - switch(PSG->ConnectTab[5]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; - } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample6); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample6); -#endif -} - -//chan6 - OP0 = &PSG->Oscils[6 ]; - OP1 = &PSG->Oscils[6 + 8]; - OP2 = &PSG->Oscils[6 + 16]; - OP3 = &PSG->Oscils[6 + 24]; - -for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) -{ - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - if (PSG->FeedBack[6]) - OP0->OscilFB = wy >> PSG->FeedBack[6]; - else - OP0->OscilFB = 0; - - switch(PSG->ConnectTab[6]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; - } -} - - //chan7 - OP0 = &PSG->Oscils[7 ]; - OP1 = &PSG->Oscils[7 + 8]; - OP2 = &PSG->Oscils[7 + 16]; - OP3 = &PSG->Oscils[7 + 24]; - - for(PSGBUF=&BuffTemp[PSG->bufp]; PSGBUF<&BuffTemp[endp]; PSGBUF++) - { - envelope_calc[OP0->state](OP0); - envelope_calc[OP1->state](OP1); - envelope_calc[OP2->state](OP2); - envelope_calc[OP3->state](OP3); - - wy = op_calc(OP0, OP0->OscilFB); - - if (PSG->FeedBack[7]) - OP0->OscilFB = wy >> PSG->FeedBack[7]; - else - OP0->OscilFB = 0; - - switch(PSG->ConnectTab[7]) - { - case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; - case 1: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)+wy ) ); break; - case 2: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,0)) +wy ); break; - case 3: *(PSGBUF) += op_calc(OP3, op_calc(OP2, wy)+op_calc(OP1,0) ); break; - case 4: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP3, op_calc(OP1,0)); break; - case 5: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1, wy) + op_calc(OP3,wy); break; - case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; - default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; - } - } - -// BUF = PSG->Buf; - PSGBUF = &BuffTemp[PSG->bufp]; - - for(i=PSG->bufp; i> 8) & 0xFF, samplesum); -#endif - -// if (sample_16bit) - { - /*16 bit mode*/ - k >>= FINAL_SH16; //AUDIO_CONV - k <<= 2; - - if (k > 32767) - k = 32767; - else if (k < -32768) - k = -32768; - - ((uint16_t *)BUF)[i] = (uint16_t)k; - } -#if 0 - else - { - /*8 bit mode*/ - k >>= FINAL_SH8; //AUDIO_CONV - - if (k > 127) - k = 127; - else if (k < -128) - k = -128; - - ((uint8_t *)BUF)[i] = (uint8_t)k; - } -#endif - } - - PSG->bufp = endp; -} - - -/* -** called to update all chips -*/ -void YM2151Update(void) -{ - int i; - for(i=0; i