diff --git a/Makefile b/Makefile index 35729c2..d24aec1 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/src/cargador.c b/src/cargador.c index 46a3604..75e8f14 100644 --- a/src/cargador.c +++ b/src/cargador.c @@ -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 diff --git a/src/computer.c b/src/computer.c index a396a09..3019021 100644 --- a/src/computer.c +++ b/src/computer.c @@ -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; @@ -741,8 +753,8 @@ inline void show_screen_precision (int tstados) { { case 0: //start of first byte - ink = temporal & 0x07; // ink colour - paper = (temporal >> 3) & 0x07; // paper colour + ink = temporal & 0x07; // ink colour + paper = (temporal >> 3) & 0x07; // paper colour if (ordenador.ulaplus) { tmp2=0x10+((temporal>>2)&0x30); ink+=tmp2; @@ -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) { - paint_one_pixel((unsigned char *)p,ordenador.pixel+ordenador.next_scanline); - } - 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); } } + +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(); } diff --git a/src/computer.h b/src/computer.h index ac03bfb..5a9e076 100644 --- a/src/computer.h +++ b/src/computer.h @@ -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 @@ -48,12 +49,13 @@ struct computer { unsigned char text_mini; 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 diff --git a/src/emulator.c b/src/emulator.c index 56c006c..e065754 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -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) { diff --git a/src/emulator.h b/src/emulator.h index 16d363b..d363888 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -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; diff --git a/src/gui_sdl.c b/src/gui_sdl.c index 4711602..93184ef 100644 --- a/src/gui_sdl.c +++ b/src/gui_sdl.c @@ -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 (poked_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) { diff --git a/src/menu_sdl.h b/src/menu_sdl.h index 04cd0ca..a13e99c 100644 --- a/src/menu_sdl.h +++ b/src/menu_sdl.h @@ -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); diff --git a/src/menus.c b/src/menus.c index dca3b09..22e9ca8 100644 --- a/src/menus.c +++ b/src/menus.c @@ -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;