From c9937400800cf241da0f0638768c4e464ca2e150 Mon Sep 17 00:00:00 2001 From: "fabio.olimpieri" Date: Tue, 14 Aug 2012 21:31:45 +0000 Subject: [PATCH] Support for ABC stereo, fixed bug in SNA format --- src/cargador.c | 12 ++-- src/computer.c | 5 +- src/computer.h | 3 +- src/emulator.c | 13 ++-- src/gui_sdl.c | 136 ++++++++++++++++++++++++-------------- src/menus.c | 2 +- src/sound.c | 8 +-- src/spk_ay.c | 174 ++++++++++++++++++++++++++++--------------------- 8 files changed, 212 insertions(+), 141 deletions(-) diff --git a/src/cargador.c b/src/cargador.c index 75e8f14..34b9ac7 100644 --- a/src/cargador.c +++ b/src/cargador.c @@ -506,15 +506,11 @@ int load_sna(char *filename) { snap->IY=((word)tempo[15])+256*((word)tempo[16]); snap->IX=((word)tempo[17])+256*((word)tempo[18]); - if (tempo[19]&0x01) { + if (tempo[19]&0x04) { snap->IFF1=1; - } else { - snap->IFF1=0; - } - - if (tempo[19]&0x02) { snap->IFF2=1; } else { + snap->IFF1=0; snap->IFF2=0; } @@ -525,7 +521,7 @@ int load_sna(char *filename) { snap->Imode=tempo[25]; snap->border=tempo[26]; - if (type==0) { + if (type==0) { //48k v1=tempo[23]; v2=tempo[24]; @@ -547,7 +543,7 @@ int load_sna(char *filename) { memcpy(snap->page[0],tempo+27,16384); memcpy(snap->page[1],tempo+16411,16384); memcpy(snap->page[2],tempo+32795,16384); - } else { + } else { //128k snap->PC=((word)tempo2[0])+256*((word)tempo2[1]); memcpy(snap->page[5],tempo+27,16384); memcpy(snap->page[2],tempo+16411,16384); diff --git a/src/computer.c b/src/computer.c index 261784a..3266468 100644 --- a/src/computer.c +++ b/src/computer.c @@ -172,6 +172,7 @@ void computer_init () { //Called only on start-up ordenador.last_selected_poke_file[0]='\0'; ordenador.npixels=4; ordenador.progressive=0; + ordenador.audio_mode=2; //ACB } void computer_set_palete() { @@ -460,7 +461,7 @@ void register_screen (SDL_Surface * pantalla) { ordenador.current_buffer = sound[0]; ordenador.num_buff = 0; // first buffer ordenador.sound_cuantity = 0; - ordenador.sound_current_value = 0; + //ordenador.sound_current_value = 0; update_npixels(); } @@ -1553,6 +1554,8 @@ void ResetComputer () { ordenador.last_selected_poke_file[0]='\0'; + ordenador.tst_sample=ordenador.cpufreq/ordenador.freq; + microdrive_reset(); } diff --git a/src/computer.h b/src/computer.h index cbbd095..e911c77 100644 --- a/src/computer.h +++ b/src/computer.h @@ -129,13 +129,14 @@ struct computer { unsigned int aych_a,aych_b,aych_c,aych_n,aych_envel; // counters for AY emulation unsigned char ayval_a,ayval_b,ayval_c,ayval_n; unsigned char ay_emul; // 0: no AY emulation; 1: AY emulation + unsigned char audio_mode; //mono, ABC, ACB, BAC unsigned char vol_a,vol_b,vol_c; unsigned int tst_ay; unsigned int tst_ay2; unsigned int ay_latch; signed char ay_envel_value; unsigned char ay_envel_way; - unsigned char sound_current_value; + //unsigned char sound_current_value; unsigned int wr; unsigned int r_fetch; unsigned int io; diff --git a/src/emulator.c b/src/emulator.c index 7488352..63ff09c 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -486,7 +486,6 @@ int bucle, bucle2,ret2; ordenador.increment=ordenador.channels; for(bucle2=0;bucle2joystick[0],10); fprintf(fconfig,"joystick2=%c%c",48+object->joystick[1],10); fprintf(fconfig,"ay_sound=%c%c",48+object->ay_emul,10); + fprintf(fconfig,"audio_mode=%c%c",48+object->audio_mode,10); fprintf(fconfig,"interface1=%c%c",48+object->mdr_active,10); fprintf(fconfig,"doublescan=%c%c",48+object->dblscan,10); fprintf(fconfig,"framerate=%c%c",48+jump_frames,10); @@ -699,7 +697,7 @@ int load_config(struct computer *object, char *filename) { int pos, key_sdl=0; FILE *fconfig; unsigned char volume=255,mode128k=255,issue=255,ntsc=255, joystick1=255,joystick2=255,ay_emul=255,mdr_active=255, - dblscan=255,framerate =255, screen =255, text=255, precision=255, bw=255, tap_fast=255, + dblscan=255,framerate =255, screen =255, text=255, precision=255, bw=255, tap_fast=255, audio_mode=255, joypad1=255, joypad2=255, rumble1=255, rumble2=255, joy_n=255, key_n=255, port=255, autoconf=255; if (filename) strcpy(config_path,filename); @@ -758,6 +756,10 @@ int load_config(struct computer *object, char *filename) { ay_emul=line[9]-'0'; continue; } + if (!strncmp(line,"audio_mode=",11)) { + audio_mode=line[11]-'0'; + continue; + } if (!strncmp(line,"interface1=",11)) { mdr_active=line[11]-'0'; continue; @@ -844,6 +846,9 @@ int load_config(struct computer *object, char *filename) { if (ay_emul<2) { object->ay_emul=ay_emul; } + if (audio_mode<4) { + object->audio_mode=audio_mode; + } if (mdr_active<2) { object->mdr_active=mdr_active; } diff --git a/src/gui_sdl.c b/src/gui_sdl.c index 1221999..be75e25 100644 --- a/src/gui_sdl.c +++ b/src/gui_sdl.c @@ -67,11 +67,11 @@ static const char *main_menu_messages[] = { /*06*/ "^|Wiimote1|Wiimote2", /*07*/ "Emulation settings", /*08*/ "Screen settings", - /*09*/ "Confs files", - /*10*/ "Microdrive", - /*11*/ "Tools", - /*12*/ "Reset", - /*13*/ "Help", + /*09*/ "Audio settings", + /*10*/ "Config files", + /*11*/ "Microdrive", + /*12*/ "Tools", + /*13*/ "Reset", /*14*/ "Quit", NULL }; @@ -79,18 +79,27 @@ static const char *main_menu_messages[] = { static const char *emulation_messages[] = { /*00*/ "Emulated machine", /*01*/ "^|48k_2|48K_3|128k|+2|+2A/+3|128K_Sp|NTSC", - /*02*/ "Volume", - /*03*/ "^|0|1|2|3|4|5|6|7|max", - /*04*/ "Frame rate", - /*05*/ "^|100%|50%|33%|25%|20%", - /*06*/ "Tap fast speed", - /*07*/ "^|on|off", - /*08*/ "Turbo mode", - /*09*/ "^|off|speed|ultraspeed", - /*10*/ "Precision", - /*11*/ "^|on|off", - /*12*/ "AY-3-8912 Emulation", - /*13*/ "^|on|off", + /*02*/ "Frame rate", + /*03*/ "^|100%|50%|33%|25%|20%", + /*04*/ "Tap fast speed", + /*05*/ "^|on|off", + /*06*/ "Turbo mode", + /*07*/ "^|off|speed|ultraspeed", + /*08*/ "Precision", + /*09*/ "^|on|off", + NULL +}; + +static const char *audio_messages[] = { + /*00*/ "Volume", + /*01*/ "^|0|1|2|3|4|5|6|7|max", + /*02*/ " ", + /*03*/ "AY-3-8912 Emulation", + /*04*/ "^|on|off", + /*05*/ " ", + /*06*/ "Audio mode", + /*07*/ "^|mono|ABC|ACB|BAC", + NULL }; @@ -152,6 +161,8 @@ static const char *tools_messages[] = { /*09*/ " ", /*10*/ "Port", /*11*/ "^|sd|usb|smb", + /*12*/ " ", + /*13*/ "Help", NULL }; @@ -480,21 +491,20 @@ static void set_machine_model(int which) static void emulation_settings(void) { - unsigned int submenus[7],submenus_old[7]; + unsigned int submenus[5],submenus_old[5]; int opt, i; unsigned char old_mode, old_videosystem; memset(submenus, 0, sizeof(submenus)); submenus[0] = get_machine_model(); - submenus[1] = ordenador.volume/2; - submenus[2] = jump_frames; - submenus[3] = !ordenador.tape_fast_load; - submenus[4] = ordenador.turbo; - submenus[5] = !ordenador.precision; - submenus[6] = !ordenador.ay_emul; + submenus[1] = jump_frames; + submenus[2] = !ordenador.tape_fast_load; + submenus[3] = ordenador.turbo; + submenus[4] = !ordenador.precision; + - for (i=0; i<7; i++) submenus_old[i] = submenus[i]; + for (i=0; i<5; i++) submenus_old[i] = submenus[i]; old_mode=ordenador.mode128k; old_videosystem = ordenador.videosystem; @@ -504,16 +514,14 @@ static void emulation_settings(void) return; set_machine_model(submenus[0]); - if ((old_mode!=ordenador.mode128k)||(old_videosystem!=ordenador.videosystem)) ResetComputer(); else - ordenador.ay_emul = !submenus[6]; + if ((old_mode!=ordenador.mode128k)||(old_videosystem!=ordenador.videosystem)) ResetComputer(); - ordenador.volume = submenus[1]*2; //I should use set_volume() ? - jump_frames = submenus[2]; - ordenador.tape_fast_load = !submenus[3]; - ordenador.turbo = submenus[4]; + jump_frames = submenus[1]; + ordenador.tape_fast_load = !submenus[2]; + ordenador.turbo = submenus[3]; curr_frames=0; - if (submenus[4] != submenus_old[4]) + if (submenus[3] != submenus_old[3]) { switch(ordenador.turbo) { @@ -536,7 +544,34 @@ static void emulation_settings(void) } } - if (ordenador.turbo==0) ordenador.precision = !submenus[5]; + if (ordenador.turbo==0) ordenador.precision = !submenus[4]; +} + +static void audio_settings(void) +{ + unsigned int submenus[3]; + int opt; + + + memset(submenus, 0, sizeof(submenus)); + + + submenus[0] = ordenador.volume/2; + submenus[1] = !ordenador.ay_emul; + submenus[2] = ordenador.audio_mode; + + + opt = menu_select_title("Audio settings menu", + audio_messages, submenus); + if (opt < 0) + return; + + + ordenador.volume = submenus[0]*2; + ordenador.ay_emul = !submenus[1]; + ordenador.audio_mode = submenus[2]; + + } static void save_load_general_configurations(int); @@ -1251,6 +1286,11 @@ void load_poke_file() } +static void help(void) +{ + menu_select_title("FBZX-WII help", + help_messages, NULL); +} static void tools() { @@ -1268,6 +1308,8 @@ static void tools() set_port(submenus[0]); + do + { switch(opt) { case 0: // Show keyboard @@ -1284,10 +1326,14 @@ static void tools() break; case 8: // Load poke file load_poke_file(); - break; + break; + case 10: + help(); + break; default: break; - } + } + } while (opt == 10); } @@ -1548,12 +1594,6 @@ static void manage_configurations() } } - -static void help(void) -{ - menu_select_title("FBZX-WII help", - help_messages, NULL); -} void main_menu() { @@ -1586,15 +1626,18 @@ void main_menu() screen_settings(); break; case 9: + audio_settings(); + break; + case 10: manage_configurations(); break; - case 10: + case 11: microdrive(); break; - case 11: + case 12: tools(); break; - case 12: + case 13: ResetComputer (); ordenador.pause = 1; if (ordenador.tap_file != NULL) { @@ -1602,9 +1645,6 @@ void main_menu() rewind_tape (ordenador.tap_file,1); } break; - case 13: - help(); - break; case 14: if (msgYesNo("Are you sure to quit?", 0, FULL_DISPLAY_X /2-138/RATIO, FULL_DISPLAY_Y /2-48/RATIO)) {salir = 0;} @@ -1612,7 +1652,7 @@ void main_menu() default: break; } - } while (opt == 5 || opt == 7 || opt == 10 || opt == 13); + } while (opt == 4 || opt == 7 || opt == 11); clean_screen(); diff --git a/src/menus.c b/src/menus.c index 22e9ca8..e2bde8d 100644 --- a/src/menus.c +++ b/src/menus.c @@ -2002,9 +2002,9 @@ if (freq == 0) if (ordenador.videosystem==0) ordenador.cpufreq = 3500000; else ordenador.cpufreq = 3527500; break; - case 3: // +2A/+3 case 1: // 128K case 2: // +2 + case 3: // +2A/+3 case 4: // spanish 128K ordenador.cpufreq = 3546900; break; diff --git a/src/sound.c b/src/sound.c index 8baf60e..500609a 100644 --- a/src/sound.c +++ b/src/sound.c @@ -183,7 +183,7 @@ int sound_init_asnd() { ASND_Pause(0); ordenador.sign=0; ordenador.format=0; //8 bit - ordenador.channels=1; //mono + ordenador.channels=2; //stereo ordenador.freq=48000; ordenador.buffer_len=4096; started_sound_asnd = 0; @@ -495,17 +495,17 @@ void sound_play() { #ifdef GEKKO case SOUND_ASND: // ASND if (!started_sound_asnd) { - ASND_SetVoice(1,VOICE_MONO_8BIT_U,48000,0,sound[0],ordenador.buffer_len, + ASND_SetVoice(1,VOICE_STEREO_8BIT_U,ordenador.freq,0,sound[0],ordenador.buffer_len*ordenador.increment, MID_VOLUME, MID_VOLUME, callback); started_sound_asnd = 1; } //Double buffer while (!ASND_TestVoiceBufferReady(1)){}; //Wait for one buffer to be free if (!ASND_TestPointer (1, sound[0])) - {ASND_AddVoice(1,sound[0],ordenador.buffer_len); + {ASND_AddVoice(1,sound[0],ordenador.buffer_len*ordenador.increment); ordenador.current_buffer = sound[0]; } else - {ASND_AddVoice(1,sound[1],ordenador.buffer_len); + {ASND_AddVoice(1,sound[1],ordenador.buffer_len*ordenador.increment); ordenador.current_buffer = sound[1]; } return; diff --git a/src/spk_ay.c b/src/spk_ay.c index 206c4f7..2842633 100644 --- a/src/spk_ay.c +++ b/src/spk_ay.c @@ -187,8 +187,8 @@ inline void play_ay (unsigned int tstados) { if (!noise_period) noise_period = 1; - if (tone_period_a*ordenador.freq<110841) //Freq_camp > cpufreq/(2*16*tone_period) - ordenador.aych_a =1; + if (tone_period_a<6) //max 20KHz + ordenador.ayval_a =1; else { if (ordenador.aych_a cpufreq/(2*16*tone_period) - ordenador.aych_b =1; + if (tone_period_b<6) //max 20KHz + ordenador.ayval_b =1; else { if (ordenador.aych_b cpufreq/(2*16*tone_period) - ordenador.aych_c =1; + if (tone_period_c<6) //max 20KHz + ordenador.ayval_c =1; else { if (ordenador.aych_c>= 1 ; ordenador.aych_n =0; + + } - // Volume - //Each channel max 51 - - if (ordenador.ay_registers[8] & 0x10) - ordenador.vol_a = - (unsigned char) (levels[ordenador.ay_envel_value]*(unsigned int) ordenador.volume/80); - else - ordenador.vol_a = - (unsigned char) (levels[ordenador.ay_registers[8] &0x0F]*(unsigned int) ordenador.volume/80); - - if (ordenador.ay_registers[10] & 0x10) - ordenador.vol_c = - (unsigned char) (levels[ordenador.ay_envel_value] *(unsigned int) ordenador.volume/80); - else - ordenador.vol_c = - (unsigned char) (levels[ordenador.ay_registers[10] & 0x0F] *(unsigned int) ordenador.volume/80); - - if (ordenador.ay_registers[9] & 0x10) - ordenador.vol_b = - (unsigned char) (levels[ordenador.ay_envel_value] *(unsigned int) ordenador.volume/80); - else - ordenador.vol_b = - (unsigned char)(levels[ordenador.ay_registers[9] &0x0F] *(unsigned int) ordenador.volume/80); - - - } -} - - -/* Creates the sound buffer during the TSTADOS tstate that the Z80 used to - execute last instruction */ - -inline void play_sound (unsigned int tstados) { - - int bucle; - int value; - unsigned char sample_v; - - ordenador.tstados_counter_sound += tstados; - - while (ordenador.tstados_counter_sound >= ordenador.tst_sample) { - - ordenador.tstados_counter_sound -= ordenador.tst_sample; - if (sound_type!=1) //!SOUND_OSS - for (bucle = 0; bucle < ordenador.increment; bucle++) { - sample_v = ordenador.sample1b[bucle]; - if (ordenador.sound_bit && sample_v) - //Sound bit volume max 96 - ordenador.sound_current_value=ordenador.volume*6; - else ordenador.sound_current_value=0; - value = ordenador.sound_current_value; - - //Mixer + //Mixer // The 8912 has three outputs, each output is the mix of one of the three // tone generators and of the (single) noise generator. The two are mixed @@ -330,23 +280,99 @@ inline void play_sound (unsigned int tstados) { // Setting the output to 1 is necessary because a disabled channel is locked // into the ON state (see above); and it has no effect if the volume is 0. // If the volume is 0, increase the counter, but don't touch the output. - - if (ordenador.ay_emul) { // if emulation is ON, emulate it - //ordenador.ayval_n = 1; - if (sample_v &&((ordenador.ayval_a || (ordenador.ay_registers[7] & 0x01))&&(ordenador.ayval_n || (ordenador.ay_registers[7] & 0x08)))) - value += (int) ordenador.vol_a; - if (sample_v &&((ordenador.ayval_b || (ordenador.ay_registers[7] & 0x02))&&(ordenador.ayval_n || (ordenador.ay_registers[7] & 0x10)))) - value += (int) ordenador.vol_b; - if (sample_v &&((ordenador.ayval_c || (ordenador.ay_registers[7] & 0x04))&&(ordenador.ayval_n || (ordenador.ay_registers[7] & 0x20)))) - value += (int) ordenador.vol_c; + + if ((ordenador.ayval_a || (ordenador.ay_registers[7] & 0x01))&&(ordenador.ayval_n || (ordenador.ay_registers[7] & 0x08))) + { + if (ordenador.ay_registers[8] & 0x10) + ordenador.vol_a = levels[ordenador.ay_envel_value]; + else + ordenador.vol_a = levels[ordenador.ay_registers[8] &0x0F]; + } + else ordenador.vol_a = 0; + + + if ((ordenador.ayval_b || (ordenador.ay_registers[7] & 0x02))&&(ordenador.ayval_n || (ordenador.ay_registers[7] & 0x10))) + { + if (ordenador.ay_registers[9] & 0x10) + ordenador.vol_b = levels[ordenador.ay_envel_value]; + else + ordenador.vol_b = levels[ordenador.ay_registers[9] &0x0F]; + } + else ordenador.vol_b = 0; - } - if (value > 255) - value = 255; - sample_v = (unsigned char)(value - (unsigned int)ordenador.sign); - *ordenador.current_buffer = sample_v; - ordenador.current_buffer++; + if ((ordenador.ayval_c || (ordenador.ay_registers[7] & 0x04))&&(ordenador.ayval_n || (ordenador.ay_registers[7] & 0x20))) + { + if (ordenador.ay_registers[10] & 0x10) + ordenador.vol_c = levels[ordenador.ay_envel_value]; + else + ordenador.vol_c = levels[ordenador.ay_registers[10] & 0x0F]; + } + else ordenador.vol_c = 0; + } +} + + +/* Creates the sound buffer during the TSTADOS tstate that the Z80 used to + execute last instruction */ + +inline void play_sound (unsigned int tstados) { + + int value, lvalue, rvalue; + + + ordenador.tstados_counter_sound += tstados; + + while (ordenador.tstados_counter_sound >= ordenador.tst_sample) { + + ordenador.tstados_counter_sound -= ordenador.tst_sample; + + if (ordenador.sound_bit) value=ordenador.volume*6; //Sound bit volume max 96 + else value=0; + + //Each channel max 51 + + if (ordenador.ay_emul) + { + switch (ordenador.audio_mode) + { + case 0: //Mono + lvalue = value + (ordenador.vol_a + ordenador.vol_b +ordenador.vol_c)*ordenador.volume/80; + rvalue = value + (ordenador.vol_a + ordenador.vol_b +ordenador.vol_c)*ordenador.volume/80; + break; + case 1: //ABC + lvalue = value + (ordenador.vol_a*2 + ordenador.vol_b)*ordenador.volume/80; + rvalue = value + (ordenador.vol_b + ordenador.vol_c*2)*ordenador.volume/80; + break; + case 2: //ACB + lvalue = value + (ordenador.vol_a*2 + ordenador.vol_c)*ordenador.volume/80; + rvalue = value + (ordenador.vol_c + ordenador.vol_b*2)*ordenador.volume/80; + break; + case 3: //BAC + lvalue = value + (ordenador.vol_b*2 + ordenador.vol_a)*ordenador.volume/80; + rvalue = value + (ordenador.vol_a + ordenador.vol_c*2)*ordenador.volume/80; + break; + default: //No emulation + rvalue = value; + lvalue = value; + break; } + } + else + { + rvalue = value; + lvalue = value; + } + + /* + if (rvalue > 255) rvalue = 255; + if (lvalue > 255) lvalue = 255; + */ + + *ordenador.current_buffer = (unsigned char)(rvalue - (unsigned int)ordenador.sign); + ordenador.current_buffer++; + *ordenador.current_buffer = (unsigned char)(lvalue - (unsigned int)ordenador.sign); + ordenador.current_buffer++; + ordenador.sound_cuantity++; if (ordenador.sound_cuantity == ordenador.buffer_len) { // buffer filled