diff --git a/src/gui_sdl.c b/src/gui_sdl.c index 327b2a1..e8aeb2b 100644 --- a/src/gui_sdl.c +++ b/src/gui_sdl.c @@ -38,6 +38,7 @@ #include "spk_ay.h" #include "sound.h" #include "rzx_lib/rzx.h" +#include "rzx_init.h" #define ID_BUTTON_OFFSET 0 @@ -192,27 +193,27 @@ static const char *microdrive_messages[] = { }; static const char *tools_messages[] = { - /*00*/ "Screen shot", - /*01*/ "^|Save1|Save2|Load|Delete", - /*02*/ "Files source", + /*00*/ "Recording (RZX)", + /*01*/ "^|Record|Play|Stop|Bookmark|Browser", + /*02*/ "Screen shot", + /*03*/ "^|Save1|Save2|Load|Delete", + /*04*/ "Files source", #ifdef HW_RVL - /*03*/ "^|default|sd|usb|smb|wos", + /*05*/ "^|default|sd|usb|smb|wos", #else //HW_DOL - Wii - /*03*/ "^|default", + /*05*/ "^|default", #endif - /*04*/ "Manage files", - /*05*/ "^|Paste|Copy|Delete", + /*06*/ "Manage files", + /*07*/ "^|Paste|Copy|Delete", #ifdef HW_DOL - /*06*/ "Unused", - /*07*/ "^|----", + /*08*/ "Unused", + /*09*/ "^|----", #else //HW_RVL - Wii - /*06*/ "Auto virtual keyboard", - /*07*/ "^|on|off", -#endif - /*08*/ "Keyboard rumble", + /*08*/ "Auto virtual keyboard", /*09*/ "^|on|off", - /*10*/ "Recording (RZX)", - /*11*/ "^|Record|Play|Stop|Bookmark", +#endif + /*10*/ "Keyboard rumble", + /*11*/ "^|on|off", /*12*/ "Load poke file", /*13*/ "Insert poke", /*14*/ "Help", @@ -1926,6 +1927,37 @@ static int save_rzx() return 0; } +static void rzx_browser() +{ + unsigned int rzx_position, block_n_int; + const char *row_selected; + char block_n[5]; + + if (rzx_browser_list[0].position==0) {msgInfo("No RZX snapshot",3000,NULL);return;} + + row_selected = menu_select_browser_rzx(); + + if (row_selected==NULL) // Aborted + return; + + if (row_selected[0]==']') strncpy(block_n, row_selected+1,4); + else strncpy(block_n, row_selected,4); + + block_n[4]=0; + + block_n_int=atoi(block_n); + + if (block_n_int >(MAX_RZX_BROWSER_ITEM-1)) return; + + rzx_position=rzx_browser_list[block_n_int].position; + + ordenador.frames_count_rzx=rzx_browser_list[block_n_int].frames_count; + + set_rzxfile_position(rzx_position); + + free((void*)row_selected); +} + static int do_rzx(int which) { int retorno = 0; //Stay in the menu as default @@ -1975,6 +2007,11 @@ static int do_rzx(int which) unlink("temp.z80"); retorno = -2; break; + case 4: //browser + if (!ordenador.playing_rzx) break; + rzx_browser(); + retorno = -2; + break; default: break; } @@ -1992,9 +2029,9 @@ static int tools() do { retorno=-1; //Exit from menu as default - submenus[1] = ordenador.port; - submenus[3] = !ordenador.vk_auto; - submenus[4] = !ordenador.vk_rumble; + submenus[2] = ordenador.port; + submenus[4] = !ordenador.vk_auto; + submenus[5] = !ordenador.vk_rumble; old_port=ordenador.port; @@ -2003,22 +2040,22 @@ static int tools() if (opt < 0) return 0; - if (old_port!= submenus[1]) {set_port(submenus[1]);retorno=0;} + if (old_port!= submenus[2]) {set_port(submenus[2]);retorno=0;} #ifndef HW_DOL - ordenador.vk_auto = !submenus[3]; + ordenador.vk_auto = !submenus[4]; #endif - ordenador.vk_rumble = !submenus[4]; + ordenador.vk_rumble = !submenus[5]; switch(opt) { case 0: - retorno = manage_scr(submenus[0]); + retorno = do_rzx(submenus[0]); break; - case 4: - retorno = manage_file(submenus[2]); + case 2: + retorno = manage_scr(submenus[1]); break; - case 10: - retorno = do_rzx(submenus[5]); + case 6: + retorno = manage_file(submenus[3]); break; case 12: // Load poke file retorno = load_poke_file(); diff --git a/src/menu_sdl.c b/src/menu_sdl.c index 4649537..baa1634 100644 --- a/src/menu_sdl.c +++ b/src/menu_sdl.c @@ -45,6 +45,8 @@ #include "tape_browser.h" #include "cargador.h" #include "sound.h" +#include "rzx_lib/rzx.h" +#include "rzx_init.h" #if defined(HW_RVL) @@ -1240,7 +1242,7 @@ static int menu_select_internal(SDL_Surface *screen, SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 255, 0)); SDL_FillRect(screen, &r_int, SDL_MapRGB(screen->format, 0, 0, 0)); - if (strcmp(p_menu->title, "Select block")&&strcmp(p_menu->title, "Select program") + if (strcmp(p_menu->title, "Select block")&&strcmp(p_menu->title, "Select program")&&strcmp(p_menu->title, "Select snapshot") &&strncmp(p_menu->title, "Selected file:",14)&&strcmp(p_menu->title, "Select file")) { SDL_Rect dst_rect = {410/RATIO, 70/RATIO, 0, 0}; @@ -1485,6 +1487,29 @@ const char **get_file_list_browser(unsigned int tape_pos, unsigned int *block_po return (const char **) browser_list_menu; } +const char **get_file_list_browser_rzx() +{ + unsigned int loop; + char **browser_list_menu; + + + browser_list_menu = (char**)malloc((MAX_RZX_BROWSER_ITEM+1) * sizeof(char*)); + browser_list_menu[0] = NULL; + + for(loop=0;rzx_browser_list[loop].position!=0;loop++) + { + browser_list_menu[loop]=malloc(48); + if (rzx_browser_list[loop].position==last_snapshot_position) + { + sprintf(browser_list_menu[loop],"]%04d Frames: %u",loop, rzx_browser_list[loop].frames_count); + } + else + sprintf(browser_list_menu[loop],"%04d Frames: %u",loop, rzx_browser_list[loop].frames_count); + } + browser_list_menu[loop]=NULL; + return (const char **) browser_list_menu; +} + const char **get_file_list_select_block() { unsigned int loop; @@ -1519,6 +1544,7 @@ static const char *menu_select_file_internal(char *dir_path, block_pos = 0; if (!strcmp(dir_path,"browser")) file_list = get_file_list_browser(tape_pos, &block_pos); + else if (!strcmp(dir_path,"browser_rzx")) file_list = get_file_list_browser_rzx(); else if (!strcmp(dir_path,"select_block")) file_list = get_file_list_select_block(); else file_list = get_file_list(dir_path); @@ -1526,6 +1552,7 @@ static const char *menu_select_file_internal(char *dir_path, return NULL; if (!strcmp(dir_path,"browser")) opt = menu_select_sized("Select block", file_list, NULL, block_pos, x, y, x2, y2, NULL, NULL ,FONT_ALT, 0); + else if (!strcmp(dir_path,"browser_rzx")) opt = menu_select_sized("Select snapshot", file_list, NULL, 0, x, y, x2, y2, NULL, NULL ,FONT_ALT, 1); else if (!strcmp(dir_path,"select_block")) opt = menu_select_sized("Select program", file_list, NULL, 0, x, y, x2, y2, NULL, NULL ,FONT_ALT, 0); else if (selected_file) { @@ -1552,7 +1579,7 @@ static const char *menu_select_file_internal(char *dir_path, if (!sel) return NULL; - if (!strcmp(dir_path,"browser")||!strcmp(dir_path,"select_block")) return sel; + if (!strcmp(dir_path,"browser")||!strcmp(dir_path,"select_block")||!strcmp(dir_path,"browser_rzx")) return sel; if (!strcmp(sel,"[..]")) //selected "[..]" { @@ -1625,6 +1652,12 @@ const char *menu_select_browser(unsigned int tape_pos) 0, 18/RATIO, FULL_DISPLAY_X, FULL_DISPLAY_Y - 18/RATIO, NULL, 0, tape_pos); } +const char *menu_select_browser_rzx() +{ + return menu_select_file_internal("browser_rzx", + 0, 18/RATIO, FULL_DISPLAY_X, FULL_DISPLAY_Y - 18/RATIO, NULL, 1, 0); +} + const char *menu_select_tape_block() { SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0)); diff --git a/src/menu_sdl.h b/src/menu_sdl.h index 8b81481..2470929 100644 --- a/src/menu_sdl.h +++ b/src/menu_sdl.h @@ -56,6 +56,7 @@ int menu_select_title(const char *title, const char **pp_msgs, int *p_submenus); int menu_select(const char **pp_msgs, int *p_submenus); const char *menu_select_file(char *dir_path,const char *selected_file, int draw_scr); const char *menu_select_browser(unsigned int tape_pos); +const char *menu_select_browser_rzx(); uint32_t menu_wait_key_press(); diff --git a/src/rzx_init.c b/src/rzx_init.c index eb3a56c..5ae31f6 100644 --- a/src/rzx_init.c +++ b/src/rzx_init.c @@ -24,6 +24,7 @@ #include "cargador.h" #include "menu_sdl.h" #include "computer.h" +#include "rzx_init.h" #ifdef DEBUG extern FILE *fdebug; @@ -39,6 +40,8 @@ extern FILE *fdebug; RZX_EMULINFO emul_info; rzx_u32 tstates; +int snapshot_counter; +RZX_browser rzx_browser_list[MAX_RZX_BROWSER_ITEM+1]; void find_name (char *name, char *filename) { @@ -64,6 +67,14 @@ rzx_u32 rzx_callback(int msg, void *par) switch(msg) { case RZXMSG_LOADSNAP: + if(rzx.mode==RZX_SCAN) + { + if (snapshot_counter>=MAX_RZX_BROWSER_ITEM) break; + if (!(((RZX_SNAPINFO*)par)->options&RZX_EXTERNAL)) rzx_browser_list[snapshot_counter++].position=((RZX_SNAPINFO*)par)->position; //Embedded snapshot - Position at beginning + rzx_browser_list[snapshot_counter].position=0; + } + else + { retorno=0; printf("> LOADSNAP: '%s' (%i bytes), %s, %s\n", ((RZX_SNAPINFO*)par)->filename, @@ -83,6 +94,7 @@ rzx_u32 rzx_callback(int msg, void *par) printf("> Load snapshot error %d\n", retorno); return RZX_INVALID; } + } break; case RZXMSG_CREATOR: printf("> CREATOR: '%s %d.%d'\n", @@ -90,7 +102,9 @@ rzx_u32 rzx_callback(int msg, void *par) (int)((RZX_EMULINFO*)par)->ver_major, (int)((RZX_EMULINFO*)par)->ver_minor); if ((int)((RZX_EMULINFO*)par)->length>0) - printf("%s \n", (const char *)((RZX_EMULINFO*)par)->data); + printf("%s \n", (const char *)((RZX_EMULINFO*)par)->data); + snapshot_counter=0; + rzx_browser_list[0].position=0; break; case RZXMSG_IRBNOTIFY: if(rzx.mode==RZX_PLAYBACK) @@ -115,7 +129,8 @@ rzx_u32 rzx_callback(int msg, void *par) } else if(rzx.mode==RZX_SCAN) { - ordenador.total_frames_rzx += ((RZX_IRBINFO*)par)->framecount; + if ((snapshot_counter>0)&&(snapshot_counterframecount; printf("> IRB notify: Total frames to play %d\n", ordenador.total_frames_rzx); } break; diff --git a/src/rzx_init.h b/src/rzx_init.h new file mode 100644 index 0000000..0296b3a --- /dev/null +++ b/src/rzx_init.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 Fabio Olimpieri + * This file is part of FBZX Wii + * + * FBZX Wii is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * FBZX Wii is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#define MAX_RZX_BROWSER_ITEM 63 + + +typedef struct +{ + unsigned int position; + unsigned int frames_count; +} RZX_browser; + + +extern RZX_browser rzx_browser_list[MAX_RZX_BROWSER_ITEM+1]; \ No newline at end of file diff --git a/src/rzx_lib/rzx.c b/src/rzx_lib/rzx.c index 659f6a9..96be9d0 100644 --- a/src/rzx_lib/rzx.c +++ b/src/rzx_lib/rzx.c @@ -86,6 +86,7 @@ static rzx_u8 *zbuf=0; static int zmode=0; static rzx_u32 packed_bytes=0; +unsigned int last_snapshot_position; int rzx_pwrite(rzx_u8 *buffer, int len) { @@ -200,6 +201,9 @@ int rzx_scan() { long fpos=10; memset(&file_emul,0,sizeof(RZX_EMULINFO)); + memset(&rzx_irb,0,sizeof(RZX_IRBINFO)); + memset(&rzx_snap,0,sizeof(RZX_SNAPINFO)); + int ret=0; do { fseek(rzxfile,fpos,SEEK_SET); @@ -225,6 +229,7 @@ int rzx_scan() fread(file_emul.data,file_emul.length,1,rzxfile); } else file_emul.data=0; + ret = emul_handler(RZXMSG_CREATOR,&file_emul); break; case RZXBLK_SECURITY: /* signal that the RZX contains at least one encrypted block */ @@ -246,6 +251,11 @@ int rzx_scan() emul_handler(RZXMSG_SEC_SIG,NULL); break; case RZXBLK_SNAP: + rzx_snap.position=fpos; + fread(block.buff,1,1,rzxfile); + rzx_snap.options=0x00; + if((block.buff[0]&0x01)) rzx_snap.options|=RZX_EXTERNAL; + emul_handler(RZXMSG_LOADSNAP,&rzx_snap); break; default: emul_handler(RZXMSG_UNKNOWN,NULL); @@ -258,9 +268,75 @@ int rzx_scan() block.start=10; block.length=0; block.type=0; - return emul_handler(RZXMSG_CREATOR,&file_emul); + return ret; } +void set_rzxfile_position(unsigned int rzx_position) +{ + + block.start = rzx_position; + rzx_status&=~RZX_IRB; + #ifdef RZX_USE_COMPRESSION + rzx_pclose(); + #endif +} + +int extract_snapshot(int position) +{ +int done=0; +long old_position, fpos; +FILE *snapfile; + +old_position=ftell(rzxfile); + + fseek(rzxfile,position,SEEK_SET); + fread(block.buff,12,1,rzxfile); + strcpy(rzx_snap.filename,""); + rzx_snap.options=0x00; + if(!(block.buff[0]&0x01)) + { + /* embedded snap */ + #ifdef RZX_USE_COMPRESSION + if(block.buff[0]&0x02) rzx_snap.options|=RZX_COMPRESSED; + fpos=ftell(rzxfile); + rzx_popen(fpos,"rb"); + #endif + strcpy(rzx_snap.filename,"rzxtemp."); + strcat(rzx_snap.filename,&block.buff[4]); + #ifndef RZX_BIG_ENDIAN + rzx_snap.length=*((rzx_u32*)&block.buff[8]); + #else + rzx_snap.length=block.buff[8]+256*block.buff[9]+65536*block.buff[10]+16777216*block.buff[11]; + #endif + /* extract to tempfile */ + snapfile=fopen(rzx_snap.filename,"wb"); + /* if you can't, skip to next block */ + if(snapfile==NULL) return -1; + /* ok */ + //rzx_snap.options|=RZX_REMOVE; + fpos=rzx_snap.length; + while(fpos>0) + { + done=(fpos>RZXBLKBUF)?RZXBLKBUF:fpos; + #ifdef RZX_USE_COMPRESSION + if(rzx_snap.options&RZX_COMPRESSED) rzx_pread(block.buff,done); + else fread(block.buff,done,1,rzxfile); + #else + fread(block.buff,done,1,rzxfile); + #endif + fwrite(block.buff,done,1,snapfile); + fpos-=done; + } + #ifdef RZX_USE_COMPRESSION + rzx_pclose(); + #endif + fclose(snapfile); + done=0; + } + + fseek(rzxfile,old_position,SEEK_SET); + return 0; +} void rzx_close_irb() { @@ -317,7 +393,8 @@ int rzx_seek_irb() switch(block.type) { case RZXBLK_SNAP: - fread(block.buff,12,1,rzxfile); + last_snapshot_position = ftell(rzxfile)-5; + fread(block.buff,12,1,rzxfile); strcpy(rzx_snap.filename,""); rzx_snap.options=0x00; if(!(block.buff[0]&0x01)) diff --git a/src/rzx_lib/rzx.h b/src/rzx_lib/rzx.h index 9d4f15c..e17da5e 100644 --- a/src/rzx_lib/rzx.h +++ b/src/rzx_lib/rzx.h @@ -109,6 +109,7 @@ typedef struct { char filename[260]; rzx_u32 length; + rzx_u32 position; rzx_u32 options; } RZX_SNAPINFO; @@ -122,6 +123,7 @@ typedef struct /* RZX public data structures */ extern RZX_INFO rzx; +extern unsigned int last_snapshot_position; /* RZX functions API */ @@ -136,6 +138,7 @@ int rzx_get_input(rzx_u8 *input); int rzx_add_snapshot(const char *filename, const rzx_u32 flags); int rzx_add_comment(const char *text, const rzx_u32 flags); +void set_rzxfile_position(unsigned int rzx_position); #ifdef RZX_DEBUG extern rzx_u16 INcount;