#ifdef HAVE_CONFIG_H #include #endif #include "SDL.h" #include "SDL_endian.h" #include #include #include #include "memory.h" #include "state.h" #include "fileio.h" #include "screen.h" static ST_REG *reglist; static ST_MODULE st_mod[ST_MODULE_END]; static SDL_Rect buf_rect = {24, 16, 304, 224}; static SDL_Rect screen_rect = { 0, 0, 304, 224}; SDL_Surface *state_img_tmp; void create_state_register(ST_MODULE_TYPE module,char *reg_name, Uint8 num,void *data,int size,ST_DATA_TYPE type) { ST_REG *t=(ST_REG*)calloc(1,sizeof(ST_REG)); t->next=st_mod[module].reglist; st_mod[module].reglist=t; t->reg_name=reg_name; t->data=data; t->size=size; t->type=type; t->num=num; } void set_pre_save_function(ST_MODULE_TYPE module,void (*func)(void)) { st_mod[module].pre_save_state=func; } void set_post_load_function(ST_MODULE_TYPE module,void (*func)(void)) { st_mod[module].post_load_state=func; } static void *find_data_by_name(ST_MODULE_TYPE module,Uint8 num,char *name) { ST_REG *t=st_mod[module].reglist; while(t) { if ((!strcmp(name,t->reg_name)) && (t->num==num)) { /* *len=t->size; *type=t->type; */ return t->data; } t=t->next; } return NULL; } static int sizeof_st_type(ST_DATA_TYPE type) { switch (type) { case REG_UINT8: case REG_INT8: return 1; case REG_UINT16: case REG_INT16: return 2; case REG_UINT32: case REG_INT32: return 4; } return 0; /* never go here */ } void swap_buf16_if_need(Uint8 src_endian,Uint16* buf,Uint32 size) { int i; #ifdef WORDS_BIGENDIAN Uint8 my_endian=1; #else Uint8 my_endian=0; #endif if (my_endian!=src_endian) { for (i=0;ipixels,304*224*2); gzclose(gzf); return state_img_tmp; } SDL_bool load_state(char *game,int slot) { char *st_name; // char *st_name_len; #ifdef GP2X char *gngeo_dir="save/"; #else char *gngeo_dir=get_gngeo_dir(); #endif #ifdef WORDS_BIGENDIAN Uint8 my_endian=1; #else Uint8 my_endian=0; #endif int i; gzFile *gzf; char string[20]; Uint8 a,num; ST_DATA_TYPE type; void *data; Uint32 len; Uint8 endian; Uint32 rate; st_name=(char*)alloca(strlen(gngeo_dir)+strlen(game)+5); sprintf(st_name,"%s%s.%03d",gngeo_dir,game,slot); if ((gzf=gzopen(st_name,"rb"))==NULL) { printf("%s not found\n",st_name); return SDL_FALSE; } memset(string,0,20); gzread(gzf,string,6); if (strcmp(string,"GNGST1")) { printf("%s is not a valid gngeo st file\n",st_name); gzclose(gzf); return SDL_FALSE; } gzread(gzf,&endian,1); if (my_endian!=endian) { printf("This save state comme from a different endian architecture.\n" "This is not currently supported :(\n"); return SDL_FALSE; } gzread(gzf,&rate,4); swap_buf32_if_need(endian,&rate,1); #ifdef GP2X if (rate==0 && conf.sound) { gn_popup_error("Failed!", "This save state is incompatible " "because you have sound enabled " "and this save state don't have sound data"); return SDL_FALSE; } if (rate!=0 && conf.sound==0) { gn_popup_error("Failed!", "This save state is incompatible " "because you don't have sound enabled " "and this save state need it"); return SDL_FALSE; } else if (rate!=conf.sample_rate && conf.sound) { conf.sample_rate=rate; close_sdl_audio(); init_sdl_audio(); } #else if (rate==0 && conf.sound) { /* disable sound */ conf.sound=0; SDL_PauseAudio(1); close_sdl_audio(); } else if (rate!=0 && conf.sound==0) { /* enable sound */ conf.sound=1; conf.sample_rate=rate; if (!conf.snd_st_reg_create) { cpu_z80_init(); init_sdl_audio(); streams_sh_start(); YM2610_sh_start(); conf.snd_st_reg_create=1; } else init_sdl_audio(); SDL_PauseAudio(0); } else if (rate!=conf.sample_rate && conf.sound) { conf.sample_rate=rate; close_sdl_audio(); init_sdl_audio(); } #endif gzread(gzf,state_img->pixels,304*224*2); swap_buf16_if_need(endian,state_img->pixels,304*224); while(!gzeof(gzf)) { gzread(gzf,&a,1); /* name size */ memset(string,0,20); gzread(gzf,string,a); /* regname */ gzread(gzf,&num,1); /* regname num */ gzread(gzf,&a,1); /* module id */ gzread(gzf,&len,4); gzread(gzf,&type,1); data=find_data_by_name(a,num,string); if (data) { gzread(gzf,data,len); switch(type) { case REG_UINT16: case REG_INT16: swap_buf16_if_need(endian,data,len>>1); break; case REG_UINT32: case REG_INT32: swap_buf32_if_need(endian,data,len>>2); break; case REG_INT8: case REG_UINT8: /* nothing */ break; } } else { /* unknow reg, ignore it*/ printf("skeeping unknow reg %s\n",string); gzseek(gzf,len,SEEK_CUR); } // /*if (a==ST_68k)*/ printf("LO %02d %20s %02x %08x \n",a,string,num,len/*,*(Uint32*)data*/); } gzclose(gzf); for(i=0;ipixels,304*224*2); for(i=0;ireg_name,t->num,t->size/*,*(Uint32*)t->data*/); a=strlen(t->reg_name); gzwrite(gzf,&a,1); /* strlen(regname) */ gzwrite(gzf,t->reg_name,strlen(t->reg_name)); /* regname */ gzwrite(gzf,&t->num,1); /* regname num */ gzwrite(gzf,&i,1); /* module id */ gzwrite(gzf,&t->size,4); gzwrite(gzf,&t->type,1); gzwrite(gzf,t->data,t->size); t=t->next; } } gzclose(gzf); return SDL_TRUE; } /* neogeo state register */ static Uint8 st_current_pal,st_current_fix; static void neogeo_pre_save_state(void) { st_current_pal=(current_pal==memory.pal1?0:1); st_current_fix=(current_fix==memory.sfix_board?0:1); } static void neogeo_post_load_state(void) { current_pal=(st_current_pal==0?memory.pal1:memory.pal2); current_pc_pal=(st_current_pal==0?memory.pal_pc1:memory.pal_pc2); current_fix=(st_current_fix==0?memory.sfix_board:memory.sfix_game); update_all_pal(); } void clear_state_reg(void) { int i; ST_REG *t,*s; for(i=0;inext; free(s); } st_mod[i].reglist=NULL; } } void neogeo_init_save_state(void) { int i; ST_REG *t,*s; if (!state_img) state_img=SDL_CreateRGBSurface(SDL_SWSURFACE,304, 224, 16, 0xF800, 0x7E0, 0x1F, 0); state_img_tmp=SDL_CreateRGBSurface(SDL_SWSURFACE,304, 224, 16, 0xF800, 0x7E0, 0x1F, 0); /* for(i=0;inext; free(s); } st_mod[i].reglist=NULL; } */ create_state_register(ST_NEOGEO,"vptr",1,(void *)&vptr,sizeof(Sint32),REG_INT32); create_state_register(ST_NEOGEO,"modulo",1,(void *)&modulo,sizeof(Sint16),REG_INT16); create_state_register(ST_NEOGEO,"current_pal",1,(void *)&st_current_pal,sizeof(Uint8),REG_UINT8); create_state_register(ST_NEOGEO,"current_fix",1,(void *)&st_current_fix,sizeof(Uint8),REG_UINT8); create_state_register(ST_NEOGEO,"sram_lock",1,(void *)&sram_lock,sizeof(Uint8),REG_UINT8); create_state_register(ST_NEOGEO,"sound_code",1,(void *)&sound_code,sizeof(Uint8),REG_UINT8); create_state_register(ST_NEOGEO,"pending_command",1,(void *)&pending_command,sizeof(Uint8),REG_UINT8); create_state_register(ST_NEOGEO,"result_code",1,(void *)&result_code,sizeof(Uint8),REG_UINT8); create_state_register(ST_NEOGEO,"sram",1,(void *)memory.sram,0x10000,REG_UINT8); create_state_register(ST_NEOGEO,"pal1",1,(void *)memory.pal1,0x2000,REG_UINT8); create_state_register(ST_NEOGEO,"pal2",1,(void *)memory.pal2,0x2000,REG_UINT8); create_state_register(ST_NEOGEO,"video",1,(void *)memory.video,0x20000,REG_UINT8); create_state_register(ST_NEOGEO,"irq2enable",1,(void *)&irq2enable,sizeof(Uint16),REG_UINT16); create_state_register(ST_NEOGEO,"irq2start",1,(void *)&irq2start,sizeof(Uint16),REG_UINT16); create_state_register(ST_NEOGEO,"irq2repeat",1,(void *)&irq2repeat,sizeof(Uint16),REG_UINT16); create_state_register(ST_NEOGEO,"irq2control",1,(void *)&irq2control,sizeof(Uint16),REG_UINT16); create_state_register(ST_NEOGEO,"lastirq2line",1,(void *)&lastirq2line,sizeof(Uint16),REG_UINT16); create_state_register(ST_NEOGEO,"fc_speed",1,(void *)&neogeo_frame_counter_speed,sizeof(Sint32),REG_INT32); create_state_register(ST_NEOGEO,"fc",1,(void *)&neogeo_frame_counter,sizeof(Sint32),REG_INT32); set_post_load_function(ST_NEOGEO,neogeo_post_load_state); set_pre_save_function(ST_NEOGEO,neogeo_pre_save_state); }