Added poke file management, improved speed emulation

This commit is contained in:
fabio.olimpieri 2012-08-11 08:31:00 +00:00
parent d3a4f5c805
commit 22f91ace59
10 changed files with 376 additions and 73 deletions

View File

@ -119,6 +119,7 @@ dist: $(BUILD)
mkdir -p $@/fbzx-wii/microdrives
mkdir -p $@/fbzx-wii/scr
mkdir -p $@/fbzx-wii/configurations
mkdir -p $@/fbzx-wii/poke
mkdir -p $@/apps/fbzx-wii/doc
cp fbzx.dol $@/apps/fbzx-wii/boot.dol
cp meta.xml $@/apps/fbzx-wii/meta.xml
@ -134,6 +135,7 @@ dist: $(BUILD)
touch $@/fbzx-wii/microdrives/dummy
touch $@/fbzx-wii/scr/dummy
touch $@/fbzx-wii/configurations/dummy
touch $@/fbzx-wii/poke/dummy
cd $@ && tar -czf ../fbzx-wii-vx-bin.tar.gz *
distsource:

View File

@ -579,6 +579,7 @@ void load_snap(struct z80snapshot *snap) {
int bucle;
printf("Loading SnapShot\n");
ordenador.last_selected_poke_file[0]='\0';
switch(snap->type) {
case 0: // 48k

View File

@ -48,6 +48,14 @@ extern FILE *fdebug;
#endif
#endif
void update_npixels()
{
ordenador.npixels= 1;
if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3))
{if (ordenador.dblscan) ordenador.npixels= 4; else ordenador.npixels= 2;}
}
/* Returns the bus value when reading a port without a periferial */
@ -87,7 +95,7 @@ inline void emulate (int tstados) {
}
}
void computer_init () {
void computer_init () { //Called only on start-up
int bucle;
@ -161,6 +169,8 @@ void computer_init () {
ordenador.cpufreq = 3500000; // values for 48K mode
ordenador.fetch_state =0;
ordenador.last_selected_poke_file[0]='\0';
ordenador.npixels=4;
}
void computer_set_palete() {
@ -377,7 +387,7 @@ void register_screen (SDL_Surface * pantalla) {
ordenador.screen = pantalla;
ordenador.border = 0;
ordenador.border_p = 0;
ordenador.border_sampled = 0;
ordenador.currline = 0;
ordenador.currpix = 0;
ordenador.flash = 0;
@ -450,6 +460,8 @@ void register_screen (SDL_Surface * pantalla) {
ordenador.num_buff = 0; // first buffer
ordenador.sound_cuantity = 0;
ordenador.sound_current_value = 0;
update_npixels();
}
void set_memory_pointers () {
@ -562,9 +574,9 @@ inline void show_screen (int tstados) {
// is border
if (ordenador.ulaplus) {
paint_pixels (255, ordenador.border+24, 0, 8); // paint 8 pixels with BORDER color
paint_pixels (255, ordenador.border+24, 0); // paint 8 pixels with BORDER color
} else {
paint_pixels (255, ordenador.border, 0, 8); // paint 8 pixels with BORDER color
paint_pixels (255, ordenador.border, 0); // paint 8 pixels with BORDER color
}
ordenador.bus_value = 255;
@ -602,9 +614,9 @@ inline void show_screen (int tstados) {
ordenador.p_translt2++;
if ((fflash) && (ordenador.flash))
paint_pixels (temporal3, paper, ink, 8); // if FLASH, invert PAPER and INK
paint_pixels (temporal3, paper, ink); // if FLASH, invert PAPER and INK
else
paint_pixels (temporal3, ink, paper, 8);
paint_pixels (temporal3, ink, paper);
}
}
@ -695,7 +707,7 @@ inline void show_screen_precision (int tstados) {
ordenador.pixels_word = ordenador.currpix%16;
ordenador.pixels_octect = ordenador.currpix%8;
ordenador.pixels_octect = ordenador.pixels_word&0x7;
// test if current pixel is for border or for user area
@ -704,12 +716,12 @@ inline void show_screen_precision (int tstados) {
// is border
if (ordenador.pixels_octect==0) ordenador.border_p = ordenador.border;
if (ordenador.pixels_octect==0) ordenador.border_sampled = ordenador.border;
if (ordenador.ulaplus) {
paint_pixels (255, ordenador.border_p+24, 0, 2); // paint 2 pixels with BORDER color
paint_pixels_precision (255, ordenador.border_sampled+24, 0); // paint 2 pixels with BORDER color
} else {
paint_pixels (255, ordenador.border_p, 0, 2); // paint 2 pixels with BORDER color
paint_pixels_precision (255, ordenador.border_sampled, 0); // paint 2 pixels with BORDER color
}
ordenador.bus_value = 255;
@ -757,8 +769,43 @@ inline void show_screen_precision (int tstados) {
temporal3 = temporal2; // bitmap
//Floating bus
if ((ordenador.currpix < 295) && (ordenador.mode128k != 3)) //no floating bus and snow effect in +3
{
// attributes first byte
ordenador.bus_value = temporal;
}
break;
case 2:
//Floating bus
if ((ordenador.currpix < 295) && (ordenador.mode128k != 3)) //no floating bus and snow effect in +3
{
// Snow Effect
if((ordenador.fetch_state==2)&&((procesador.I & 0xC0) == 0x40)) {
temporal2_1 = ordenador.memoria[((*(ordenador.p_translt-1) + ordenador.video_offset)&0xFFFFFF80)+(((*(ordenador.p_translt-2)) + ordenador.video_offset)&0x7F)]; // bitmap with snow second byte
temporal_1 = ordenador.memoria[((*(ordenador.p_translt2-1) + ordenador.video_offset)&0xFFFFFF80)+(((*(ordenador.p_translt2-2)) + ordenador.video_offset)&0x7F)]; // attributes with snow second byte
}
// bitmap second byte
ordenador.bus_value = temporal2_1;
}
break;
case 4:
//Floating bus
if ((ordenador.currpix < 295) && (ordenador.mode128k != 3)) //no floating bus and snow effect in +3
{
// attributes second byte
ordenador.bus_value = temporal_1;
}
break;
case 6:
ordenador.bus_value = 255;
break;
case 8: //start of second byte
@ -786,51 +833,29 @@ inline void show_screen_precision (int tstados) {
temporal_1 = ordenador.memoria[(*(ordenador.p_translt2+1)) + ordenador.video_offset]; // attributes second byte
temporal2_1 = ordenador.memoria[(*(ordenador.p_translt+1)) + ordenador.video_offset]; // bitmap second byte
//Floating bus
if ((ordenador.currpix < 295) && (ordenador.mode128k != 3)) //no floating bus and snow effect in +3
{
// Snow Effect
if((ordenador.fetch_state==2)&&((procesador.I & 0xC0) == 0x40)) {
temporal2 = ordenador.memoria[(((*(ordenador.p_translt)) + (ordenador.video_offset))&0xFFFFFF80)+(procesador.R&0x7F)]; // bitmap with snow first byte
temporal = ordenador.memoria[(((*(ordenador.p_translt2)) + (ordenador.video_offset))&0xFFFFFF80)+(procesador.R&0x7F)]; // attributes with snow first byte
}
// bitmap first byte
ordenador.bus_value = temporal2;
}
ordenador.p_translt+=2;
ordenador.p_translt2+=2;
break;
}
//Floating bus
if ((ordenador.currpix < 295) && (ordenador.mode128k != 3)) //no floating bus and snow effect in +3
switch (ordenador.pixels_word)
{
case 14:
// Snow Effect
if((ordenador.fetch_state==2)&&((procesador.I & 0xC0) == 0x40)) {
temporal2 = ordenador.memoria[(((*(ordenador.p_translt-2)) + (ordenador.video_offset))&0xFFFFFF80)+(procesador.R&0x7F)]; // bitmap with snow first byte
temporal = ordenador.memoria[(((*(ordenador.p_translt2-2)) + (ordenador.video_offset))&0xFFFFFF80)+(procesador.R&0x7F)]; // attributes with snow first byte
}
// bitmap first byte
ordenador.bus_value = temporal2;
break;
case 0:
// attributes first byte
ordenador.bus_value = temporal;
break;
case 2:
// Snow Effect
if((ordenador.fetch_state==2)&&((procesador.I & 0xC0) == 0x40)) {
temporal2_1 = ordenador.memoria[((*(ordenador.p_translt-1) + ordenador.video_offset)&0xFFFFFF80)+(((*(ordenador.p_translt-2)) + ordenador.video_offset)&0x7F)]; // bitmap with snow second byte
temporal_1 = ordenador.memoria[((*(ordenador.p_translt2-1) + ordenador.video_offset)&0xFFFFFF80)+(((*(ordenador.p_translt2-2)) + ordenador.video_offset)&0x7F)]; // attributes with snow second byte
}
// bitmap second byte
ordenador.bus_value = temporal2_1;
break;
case 4:
// attributes second byte
ordenador.bus_value = temporal_1;
break;
default:
ordenador.bus_value = 255;
break;
}
if ((fflash) && (ordenador.flash))
paint_pixels (temporal3, paper, ink, 2); // if FLASH, invert PAPER and INK
paint_pixels_precision (temporal3, paper, ink); // if FLASH, invert PAPER and INK
else
paint_pixels (temporal3, ink, paper ,2);
paint_pixels_precision (temporal3, ink, paper);
}
}
@ -895,36 +920,86 @@ inline void show_screen_precision (int tstados) {
}
}
/* PAINT_PIXELS paints bits with INK color for 1 bits and PAPER color
for 0 bits, and increment acordingly the pointer PIXEL */
inline void paint_pixels (unsigned char octet,unsigned char ink, unsigned char paper, unsigned char bit) {
inline void paint_pixels (unsigned char octet,unsigned char ink, unsigned char paper) {
static int bucle,valor,*p;
static unsigned char mask;
if (ordenador.pixels_octect==0 ||bit == 8) mask = 0x80;
mask = 0x80;
for (bucle = 0; bucle < bit; bucle++) {
for (bucle = 0; bucle < 8; bucle++) {
valor = (octet & mask) ? (int) ink : (int) paper;
p=(colors+valor);
paint_one_pixel((unsigned char *)p,ordenador.pixel);
if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3)&&(ordenador.dblscan)) {
paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline);
}
switch (ordenador.npixels)
{
case 2:
ordenador.pixel+=ordenador.next_pixel;
if ((ordenador.zaurus_mini!=1)&&(ordenador.zaurus_mini!=3)) {
paint_one_pixel((unsigned char *)p,ordenador.pixel);
if (ordenador.dblscan) {
break;
case 4:
paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline);
}
ordenador.pixel+=ordenador.next_pixel;
paint_one_pixel((unsigned char *)p,ordenador.pixel);
paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline);
break;
default:
break;
}
ordenador.pixel+=ordenador.next_pixel;
mask = ((mask >> 1) & 0x7F);
}
}
inline void paint_pixels_precision (unsigned char octet,unsigned char ink, unsigned char paper) {
static int bucle,valor,*p;
static unsigned char mask;
if (ordenador.pixels_octect==0) mask = 0x80;
for (bucle = 0; bucle < 2; bucle++) {
valor = (octet & mask) ? (int) ink : (int) paper;
p=(colors+valor);
paint_one_pixel((unsigned char *)p,ordenador.pixel);
switch (ordenador.npixels)
{
case 2:
ordenador.pixel+=ordenador.next_pixel;
paint_one_pixel((unsigned char *)p,ordenador.pixel);
break;
case 4:
paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline);
ordenador.pixel+=ordenador.next_pixel;
paint_one_pixel((unsigned char *)p,ordenador.pixel);
paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline);
break;
default:
break;
}
ordenador.pixel+=ordenador.next_pixel;
mask = ((mask >> 1) & 0x7F);
}
}
#ifdef GEKKO
inline void paint_one_pixel(unsigned char *colour,unsigned char *address)
{
*(address++)=*(colour+2);
*(address++)=*(colour+3);
}
#else
inline void paint_one_pixel(unsigned char *colour,unsigned char *address) {
#if BYTE_ORDER == LITTLE_ENDIAN
@ -960,6 +1035,8 @@ inline void paint_one_pixel(unsigned char *colour,unsigned char *address) {
#endif
}
#endif
// Read the keyboard and stores the flags
@ -1473,6 +1550,8 @@ void ResetComputer () {
break;
}
ordenador.last_selected_poke_file[0]='\0';
microdrive_reset();
}

View File

@ -37,6 +37,7 @@ int countdown;
struct computer {
unsigned char precision; //If set 1 emulate with more precision
unsigned char npixels; //1, 2 or 4 depending on dblscan and zaurus_mini
unsigned int temporal_io;
// screen private global variables
@ -49,11 +50,12 @@ struct computer {
unsigned char dblscan;
unsigned char bw;
int contador_flash;
unsigned int *p_translt,*p_translt2;
unsigned char *pixel; // current address
char border,flash, border_p;
char border,flash, border_sampled;
int currline,currpix;
int tstados_counter; // counts tstates leaved to the next call
@ -166,6 +168,7 @@ struct computer {
unsigned char tape_fast_load; // 0 normal load; 1 fast load
unsigned char current_tap[2049];
unsigned char last_selected_file[2049];
unsigned char last_selected_poke_file[2049];
unsigned char tape_current_bit;
unsigned int tape_block_level;
@ -238,7 +241,8 @@ void computer_init();
void register_screen(SDL_Surface *);
inline void show_screen(int);
inline void show_screen_precision(int);
inline void paint_pixels(unsigned char, unsigned char, unsigned char, unsigned char);
inline void paint_pixels(unsigned char, unsigned char, unsigned char);
inline void paint_pixels_precision(unsigned char, unsigned char, unsigned char);
inline void read_keyboard();
void fill_audio(void *udata,Uint8 *,int);
void set_volume(unsigned char);
@ -253,5 +257,6 @@ inline void paint_one_pixel(unsigned char *colour,unsigned char *address);
void computer_set_palete();
void set_palete_entry(unsigned char entry, byte Value);
void restart_video();
void update_npixels();
#endif

View File

@ -68,6 +68,7 @@ char path_taps[2049];
char path_mdrs[2049];
char path_scr[2049];
char path_confs[2049];
char path_poke[2049];
unsigned int colors[80];
unsigned int jump_frames,curr_frames;
char *filenames[5];
@ -1087,11 +1088,13 @@ int main(int argc,char *argv[]) {
strcpy(path_mdrs,path_snaps);
strcpy(path_scr,path_snaps);
strcpy(path_confs,path_snaps);
strcpy(path_poke,path_snaps);
strcat(path_snaps,"snapshots");
strcat(path_taps,"tapes");
strcat(path_mdrs,"microdrives");
strcat(path_scr,"scr");
strcat(path_confs,"configurations");
strcat(path_poke,"poke");
#ifdef GEKKO
if ((ordenador.port==1)&&usbismount) {

View File

@ -37,6 +37,7 @@ extern char path_taps[2049];
extern char path_mdrs[2049];
extern char path_scr[2049];
extern char path_confs[2049];
extern char path_poke[2049];
extern unsigned int colors[80];
extern unsigned int jump_frames,curr_frames;

View File

@ -50,6 +50,9 @@ extern FILE *fdebug;
#endif
#endif
#define MAX_POKE 20
#define MAX_TRAINER 40
extern int countdown;
void clean_screen();
@ -142,8 +145,10 @@ static const char *tools_messages[] = {
/*05*/ " ",
/*06*/ "Insert poke",
/*07*/ " ",
/*08*/ "Port",
/*09*/ "^|sd|usb|smb",
/*08*/ "Load poke file",
/*09*/ " ",
/*10*/ "Port",
/*11*/ "^|sd|usb|smb",
NULL
};
@ -555,12 +560,16 @@ static void screen_settings(void)
ordenador.dblscan = !submenus[0];
ordenador.bw = submenus[1];
if (submenus[0] != submenus_old[0]) update_npixels();
if (submenus[1]!=submenus_old[1]) computer_set_palete();
if (submenus[2] != submenus_old[2])
{
if (submenus[2]==0) {ordenador.zaurus_mini = 0; ordenador.text_mini=0;}
else {ordenador.zaurus_mini = 3; ordenador.text_mini=1;}
update_npixels();
restart_video();
}
}
@ -990,7 +999,6 @@ void do_poke_sdl() {
while(1) {
print_string(videomem,"Type address to POKE",-1,32,15,0,ancho);
//print_string(videomem,"(ESC to exit)",-1,52,12,0,ancho);
retorno=ask_value_sdl(&address,84,65535);
@ -1027,7 +1035,6 @@ void do_poke_sdl() {
}
print_string(videomem,"Type new value to POKE",-1,32,15,0,ancho);
//print_string(videomem,"(ESC to cancel)",-1,52,12,0,ancho);
sprintf(string,"Address: %d; old value: %d\n",address,old_value);
print_string(videomem,string,-1,130,14,0,ancho);
@ -1065,6 +1072,168 @@ void do_poke_sdl() {
}
}
int parse_poke (const char *filename)
{
static unsigned char old_poke[MAX_TRAINER][MAX_POKE]; //Max 19 Pokes per trainer and max 40 trainer
FILE* fpoke;
unsigned char title[128], flag, newfile, restore, old_mport1;
int bank, address, value, original_value, ritorno,y,k, trainer, poke;
SDL_Rect src;
src.x=0;
src.y=0;
src.w=640/RATIO;
src.h=20/RATIO;
y=60/RATIO;
if (strcmp(ordenador.last_selected_poke_file,filename)) newfile=1; else newfile=0;
trainer=0;
fpoke = fopen(filename,"r");
if (fpoke==NULL)
{
msgInfo("Can not access the file",3000,NULL);
return (0);
}
clean_screen();
print_font(screen, 0xd0, 0xd0, 0xd0,0, 30/RATIO, "Press 1 to deselect, 2 to select", 16);
ritorno=0;
do
{
if (trainer==MAX_TRAINER) {ritorno=2;break;}
poke=1;
restore=0;
if (!fgets(title,128,fpoke)) {ritorno=1;break;}
if (title[0]=='Y') break;
if (title[0]!='N') {ritorno=1;break;}
if (strlen(title)>1) title[strlen(title)-2]='\0'; //cancel new line and line feed
if (y>450/RATIO) {clean_screen();y=40/RATIO;}
if (newfile) print_font(screen, 0x80, 0x80, 0x80,0, y, title+1, 16);
else {if (old_poke[trainer][0]==0) print_font(screen, 0xd0, 0, 0,0, y, title+1, 16); //In row 0 information on trainer selection
else print_font(screen, 0, 0xd0, 0,0, y, title+1, 16);}
SDL_Flip(screen);
k=0;
while (!((k & KEY_ESCAPE)||(k & KEY_SELECT)))
{k = menu_wait_key_press();}
src.y=y;
SDL_FillRect(screen, &src, SDL_MapRGB(screen->format, 0, 0, 0));
if (k & KEY_SELECT)
{
print_font(screen, 0, 0x80, 0,0, y, title+1, 16);
old_poke[trainer][0]=1;
}
else
{
if ((!newfile)&&(old_poke[trainer][0]==1)) restore=1;
print_font(screen, 0x80, 0, 0,0, y, title+1, 16);
old_poke[trainer][0]=0;
}
SDL_Flip(screen);
y+=20/RATIO;
do
{
if (poke==MAX_POKE) old_poke[trainer][0]=0; //in order not to restore the old_value
fscanf(fpoke, "%1s %d %d %d %d", &flag, &bank, &address, &value, &original_value);
if (((flag!='M')&&(flag!='Z'))||(bank>8)||(bank<0)||(address>0xFFFF)||(address<0x4000)||(value>256)||(value<0)||(original_value>255)||(original_value<0)) {ritorno=1;break;}
if (feof(fpoke)) {ritorno=1;break;}
if ((!(bank&0x8))&&((ordenador.mode128k==1)||(ordenador.mode128k==2)||(ordenador.mode128k==4))) //+3?
{
old_mport1 = ordenador.mport1;
ordenador.mport1 = (unsigned char) (bank&0x7);
set_memory_pointers (); // set the pointers
if (poke<MAX_POKE)
{
if(newfile)
{if (original_value) old_poke[trainer][poke]=(unsigned char) original_value; else old_poke[trainer][poke]= Z80free_Rd_fake ((word) address);}
if (restore) value = (int) old_poke[trainer][poke];
}
if (((value < 256) && (k & KEY_SELECT))||(restore)) Z80free_Wr_fake ((word)address, (unsigned char) value);
ordenador.mport1 = old_mport1;
set_memory_pointers (); // set the pointers
}
else
{
if (poke<MAX_POKE)
{
if(newfile)
{if (original_value) old_poke[trainer][poke]=(unsigned char) original_value; else old_poke[trainer][poke]= Z80free_Rd_fake ((word) address);}
if (restore) value = (int) old_poke[trainer][poke];
}
if (((value < 256) && (k & KEY_SELECT))||(restore)) Z80free_Wr_fake ((word)address, (unsigned char) value);
}
poke++;
}
while (flag!='Z');
trainer++;
if (!fgets(title,128,fpoke)) {ritorno=1;break;} //line feed reading
}
while (ritorno==0);
k=0;
while (!(k & KEY_ESCAPE))
{k = menu_wait_key_press();}
fclose(fpoke);
if (ritorno==0) strcpy(ordenador.last_selected_poke_file,filename);
return (ritorno);
}
void load_poke_file()
{
const char *dir = path_poke;
int ritorno;
ritorno=0;
const char *filename = menu_select_file(dir, NULL,-1);
if (!filename) return;
if (ext_matches(filename, ".pok")|ext_matches(filename, ".POK"))
ritorno = parse_poke(filename);
switch(ritorno)
{
case 1:
msgInfo("Not compatible file",3000,NULL);
break;
case 2:
msgInfo("Too many trainers",3000,NULL);
break;
}
free((void*)filename);
}
static void tools()
{
int opt ;
@ -1093,9 +1262,10 @@ static void tools()
load_scr();
break;
case 6: // Insert poke
// Insert poke ;
do_poke_sdl();
//msgInfo("Not yet implemented",3000,NULL);
break;
case 8: // Load poke file
load_poke_file();
break;
default:
break;

View File

@ -282,7 +282,7 @@ static const char **get_file_list(const char *base_dir)
{
char buf[255];
const char *exts[] = {".tap", ".TAP", ".tzx", ".TZX", ".z80",".Z80",".sna", ".SNA",
".mdr", ".MDR", ".scr", ".SCR", ".conf", ".CONF",NULL};
".mdr", ".MDR", ".scr", ".SCR", ".conf", ".CONF",".pok", ".POK", NULL};
struct stat st;
snprintf(buf, 255, "%s/%s", base_dir, de->d_name);
@ -386,6 +386,46 @@ void menu_print_font(SDL_Surface *screen, int r, int g, int b,
SDL_FreeSurface(font_surf);
}
void print_font(SDL_Surface *screen, int r, int g, int b,
int x, int y, const char *msg, int font_size)
{
#define _MAX_STRING 64
SDL_Surface *font_surf;
SDL_Rect dst = {x, y, 0, 0};
SDL_Color color = {r, g, b};
char buf[255];
memset(buf, 0, sizeof(buf));
strncpy(buf, msg, 254);
if (strlen(buf)>_MAX_STRING)
{
buf[_MAX_STRING] = '\0';
}
if (FULL_DISPLAY_X == 640)
{
if (font_size == 16) font_surf = TTF_RenderUTF8_Blended(menu_font16, buf, color);
else font_surf = TTF_RenderUTF8_Blended(menu_font20, buf, color);
}
else
{
if (font_size == 16) font_surf = TTF_RenderUTF8_Blended(menu_font8, buf, color);
else font_surf = TTF_RenderUTF8_Blended(menu_font10, buf, color);
}
if (!font_surf)
{
fprintf(stderr, "%s\n", TTF_GetError());
exit(1);
}
SDL_BlitSurface(font_surf, NULL, screen, &dst);
SDL_FreeSurface(font_surf);
}
static void menu_draw(SDL_Surface *screen, menu_t *p_menu, int sel, int font_size)
{

View File

@ -46,6 +46,7 @@ int RATIO;
void menu_print_font(SDL_Surface *screen, int r, int g, int b, int x, int y, const char *msg, int font_size);
void print_font(SDL_Surface *screen, int r, int g, int b, int x, int y, const char *msg, int font_size);
/* Various option selects */
int menu_select_title(const char *title, const char **pp_msgs, int *p_submenus);

View File

@ -277,6 +277,7 @@ void settings_menu() {
break;
case SDLK_d:
ordenador.dblscan=1-ordenador.dblscan;
update_npixels();
break;
case SDLK_a:
ordenador.ay_emul=1-ordenador.ay_emul;