Support for ABC stereo, fixed bug in SNA format

This commit is contained in:
fabio.olimpieri 2012-08-14 21:31:45 +00:00
parent acc37ba021
commit c993740080
8 changed files with 212 additions and 141 deletions

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -486,7 +486,6 @@ int bucle, bucle2,ret2;
ordenador.increment=ordenador.channels;
for(bucle2=0;bucle2<NUM_SNDBUF;bucle2++) {
//sound[bucle2]=(unsigned char *)malloc(ordenador.buffer_len*ordenador.increment+8);
//ASND Required alligned memory with padding
sound[bucle2]=(unsigned char *)memalign(32,ordenador.buffer_len*ordenador.increment+32);
for(bucle=0;bucle<ordenador.buffer_len*ordenador.increment+4;bucle++)
@ -495,8 +494,6 @@ int bucle, bucle2,ret2;
printf("Init sound 2\n");
ordenador.tst_sample=ordenador.cpufreq/ordenador.freq;
//printf("Set volume\n");
//set_volume(70);
}
void end_system() {
@ -564,6 +561,7 @@ int save_config(struct computer *object, char *filename) {
fprintf(fconfig,"joystick1=%c%c",48+object->joystick[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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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<tone_period_a)
@ -200,8 +200,8 @@ inline void play_ay (unsigned int tstados) {
}
}
if (tone_period_b*ordenador.freq<110841) //Freq_camp > 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<tone_period_b)
@ -213,8 +213,8 @@ inline void play_ay (unsigned int tstados) {
}
}
if (tone_period_c*ordenador.freq<110841) //Freq_camp > 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<tone_period_c)
@ -262,61 +262,11 @@ inline void play_ay (unsigned int tstados) {
noise >>= 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