#ifdef __WIN32__ #include #else #define MessageBox(owner, text, caption, type) printf("%s: %s\n", caption, text) #endif #include "SDL.h" #include "SDL_thread.h" #include "shared.h" #include "sms_ntsc.h" #include "md_ntsc.h" #include "utils.h" #ifdef GCWZERO #include #include #include static int do_once = 1; static int gcw0_w = 320; static int gcw0_h = 240; static int gotomenu; static int show_lightgun; time_t current_time; const char *cursor[4]= { "./CLASSIC_01_RED.png", //doesn't flash (for epileptics it's default) "./CLASSIC_02.png", //square flashing red and white "./CLASSIC_01.png", "./SQUARE_02.png", }; #define JOY_DEADZONE 1000 #endif #ifdef GCWZERO #define SOUND_FREQUENCY 44100 #else #define SOUND_FREQUENCY 48000 #endif #define SOUND_SAMPLES_SIZE 2048 #define VIDEO_WIDTH 320 #define VIDEO_HEIGHT 240 int joynum = 0; int log_error = 0; int debug_on = 0; int turbo_mode = 0; int use_sound = 1; int fullscreen = 1; /* SDL_FULLSCREEN */ char rom_filename[256]; /* sound */ struct { char* current_pos; char* buffer; int current_emulated_samples; } sdl_sound; static uint8 brm_format[0x40] = { 0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x00,0x00,0x00,0x00,0x40, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x53,0x45,0x47,0x41,0x5f,0x43,0x44,0x5f,0x52,0x4f,0x4d,0x00,0x01,0x00,0x00,0x00, 0x52,0x41,0x4d,0x5f,0x43,0x41,0x52,0x54,0x52,0x49,0x44,0x47,0x45,0x5f,0x5f,0x5f }; static short soundframe[SOUND_SAMPLES_SIZE]; static void sdl_sound_callback(void *userdata, Uint8 *stream, int len) { if(sdl_sound.current_emulated_samples < len) { memset(stream, 0, len); } else { memcpy(stream, sdl_sound.buffer, len); /* loop to compensate desync */ do { sdl_sound.current_emulated_samples -= len; } while(sdl_sound.current_emulated_samples > 2 * len); memcpy(sdl_sound.buffer, sdl_sound.current_pos - sdl_sound.current_emulated_samples, sdl_sound.current_emulated_samples); sdl_sound.current_pos = sdl_sound.buffer + sdl_sound.current_emulated_samples; } } static int sdl_sound_init() { int n; SDL_AudioSpec as_desired, as_obtained; if(SDL_Init(SDL_INIT_AUDIO) < 0) { MessageBox(NULL, "SDL Audio initialization failed", "Error", 0); return 0; } as_desired.freq = SOUND_FREQUENCY; as_desired.format = AUDIO_S16LSB; as_desired.channels = 2; as_desired.samples = SOUND_SAMPLES_SIZE; as_desired.callback = sdl_sound_callback; if(SDL_OpenAudio(&as_desired, &as_obtained) == -1) { MessageBox(NULL, "SDL Audio open failed", "Error", 0); return 0; } if(as_desired.samples != as_obtained.samples) { MessageBox(NULL, "SDL Audio wrong setup", "Error", 0); return 0; } sdl_sound.current_emulated_samples = 0; n = SOUND_SAMPLES_SIZE * 2 * sizeof(short) * 20; sdl_sound.buffer = (char*)malloc(n); if(!sdl_sound.buffer) { MessageBox(NULL, "Can't allocate audio buffer", "Error", 0); return 0; } memset(sdl_sound.buffer, 0, n); sdl_sound.current_pos = sdl_sound.buffer; return 1; } static void sdl_sound_update(enabled) { int size = audio_update(soundframe) * 2; if (enabled) { int i; short *out; SDL_LockAudio(); out = (short*)sdl_sound.current_pos; for(i = 0; i < size; i++) { *out++ = soundframe[i]; } sdl_sound.current_pos = (char*)out; sdl_sound.current_emulated_samples += size * sizeof(short); SDL_UnlockAudio(); } } static void sdl_sound_close() { SDL_PauseAudio(1); SDL_CloseAudio(); if (sdl_sound.buffer) free(sdl_sound.buffer); } #ifdef GCWZERO //A-stick support static void sdl_joystick_init() { if(SDL_Init(SDL_INIT_JOYSTICK) < 0) { MessageBox(NULL, "SDL Joystick initialization failed", "Error", 0); return 0; } else MessageBox(NULL, "SDL Joystick initialisation successful", "Success", 0); return 1; } #endif /* video */ md_ntsc_t *md_ntsc; sms_ntsc_t *sms_ntsc; struct { SDL_Surface* surf_screen; SDL_Surface* surf_bitmap; SDL_Rect srect; SDL_Rect drect; Uint32 frames_rendered; } sdl_video; static int sdl_video_init() { if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { MessageBox(NULL, "SDL Video initialization failed", "Error", 0); return; } #ifdef GCWZERO sdl_video.surf_screen = SDL_SetVideoMode(VIDEO_WIDTH, VIDEO_HEIGHT, 16, SDL_HWSURFACE | #else sdl_video.surf_screen = SDL_SetVideoMode(VIDEO_WIDTH, VIDEO_HEIGHT, 16, SDL_HWSURFACE | fullscreen | #endif #ifdef SDL_TRIPLEBUF SDL_TRIPLEBUF #else SDL_DOUBLEBUF #endif ); sdl_video.surf_bitmap = SDL_CreateRGBSurface(SDL_HWSURFACE, 720, 576, 16, 0, 0, 0, 0); sdl_video.frames_rendered = 0; SDL_ShowCursor(0); return; } static void sdl_video_update() { static int test; if (system_hw == SYSTEM_MCD) { #ifdef GCWZERO if (test >= config.gcw0_frameskip) // >= in case frameskip has just been lowered { system_frame_scd(0); //render frame test = 0; } else { system_frame_scd(1); //skip frame render test ++; } #else system_frame_scd(0); #endif } else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) #ifdef GCWZERO { if (test >= config.gcw0_frameskip) { system_frame_gen(0); test = 0; } else { system_frame_gen(1); test ++; } #else system_frame_gen(0); #endif } else { #ifdef GCWZERO if (test >= config.gcw0_frameskip) { system_frame_sms(0); test = 0; } else { system_frame_sms(1); test ++; } #else system_frame_sms(0); #endif } /* viewport size changed */ if(bitmap.viewport.changed & 1) { bitmap.viewport.changed &= ~1; /* source bitmap */ #ifdef GCWZERO //remove left bar bug with SMS roms if ( (system_hw == SYSTEM_MARKIII) || (system_hw == SYSTEM_SMS) || (system_hw == SYSTEM_SMS2) || (system_hw == SYSTEM_PBC) ) { if (config.smsmaskleftbar) sdl_video.srect.x = 8; else sdl_video.srect.x = 0; } else { sdl_video.srect.x = 0; } #else sdl_video.srect.x = 0; #endif sdl_video.srect.y = 0; sdl_video.srect.w = bitmap.viewport.w+2*bitmap.viewport.x; sdl_video.srect.h = bitmap.viewport.h+2*bitmap.viewport.y; if (sdl_video.srect.w > VIDEO_WIDTH) { #ifdef GCWZERO if ( (system_hw == SYSTEM_MARKIII) || (system_hw == SYSTEM_SMS) || (system_hw == SYSTEM_SMS2) || (system_hw == SYSTEM_PBC) ) { if (config.smsmaskleftbar) sdl_video.srect.x = (sdl_video.srect.w - VIDEO_WIDTH) / 2 + 8; else sdl_video.srect.x = (sdl_video.srect.w - VIDEO_WIDTH) / 2; sdl_video.srect.w = VIDEO_WIDTH; } else { sdl_video.srect.x = (sdl_video.srect.w - VIDEO_WIDTH) / 2; sdl_video.srect.w = VIDEO_WIDTH; } #else sdl_video.srect.x = (sdl_video.srect.w - VIDEO_WIDTH) / 2; sdl_video.srect.w = VIDEO_WIDTH; #endif } if (sdl_video.srect.h > VIDEO_HEIGHT) { sdl_video.srect.y = (sdl_video.srect.h - VIDEO_HEIGHT) / 2; sdl_video.srect.h = VIDEO_HEIGHT; } /* destination bitmap */ sdl_video.drect.w = sdl_video.srect.w; sdl_video.drect.h = sdl_video.srect.h; sdl_video.drect.x = (VIDEO_WIDTH - sdl_video.drect.w) / 2; sdl_video.drect.y = (VIDEO_HEIGHT - sdl_video.drect.h) / 2; /* clear destination surface */ SDL_FillRect(sdl_video.surf_screen, 0, 0); #ifdef GCWZERO //triple buffering so stop flicker SDL_Flip(sdl_video.surf_screen); SDL_FillRect(sdl_video.surf_screen, 0, 0); SDL_Flip(sdl_video.surf_screen); SDL_FillRect(sdl_video.surf_screen, 0, 0); #endif #if 0 if (config.render && (interlaced || config.ntsc)) rect.h *= 2; if (config.ntsc) rect.w = (reg[12]&1) ? MD_NTSC_OUT_WIDTH(rect.w) : SMS_NTSC_OUT_WIDTH(rect.w); if (config.ntsc) { sms_ntsc = (sms_ntsc_t *)malloc(sizeof(sms_ntsc_t)); md_ntsc = (md_ntsc_t *)malloc(sizeof(md_ntsc_t)); switch (config.ntsc) { case 1: sms_ntsc_init(sms_ntsc, &sms_ntsc_composite); md_ntsc_init(md_ntsc, &md_ntsc_composite); break; case 2: sms_ntsc_init(sms_ntsc, &sms_ntsc_svideo); md_ntsc_init(md_ntsc, &md_ntsc_svideo); break; case 3: sms_ntsc_init(sms_ntsc, &sms_ntsc_rgb); md_ntsc_init(md_ntsc, &md_ntsc_rgb); break; } } else { if (sms_ntsc) { free(sms_ntsc); sms_ntsc = NULL; } if (md_ntsc) { free(md_ntsc); md_ntsc = NULL; } } #endif } //DK IPU scaling for gg/sms roms #ifdef GCWZERO if (config.gcw0_fullscreen) { if( (gcw0_w != sdl_video.drect.w) || (gcw0_h != sdl_video.drect.h) ) { if ( (system_hw == SYSTEM_MARKIII) || (system_hw == SYSTEM_SMS) || (system_hw == SYSTEM_SMS2) || (system_hw == SYSTEM_PBC) ) { if (config.smsmaskleftbar) { sdl_video.srect.w = sdl_video.srect.w - 8; sdl_video.drect.w = sdl_video.srect.w; sdl_video.drect.x = 4; } else { sdl_video.srect.w = sdl_video.srect.w ; sdl_video.drect.w = sdl_video.srect.w; sdl_video.drect.x = 0; } } else { sdl_video.drect.x = 0; sdl_video.drect.w = sdl_video.srect.w; } sdl_video.drect.h = sdl_video.srect.h; sdl_video.drect.y = 0; gcw0_w=sdl_video.drect.w; gcw0_h=sdl_video.drect.h; if ( (system_hw == SYSTEM_MARKIII) || (system_hw == SYSTEM_SMS) || (system_hw == SYSTEM_SMS2) || (system_hw == SYSTEM_PBC) ) { sdl_video.surf_screen = SDL_SetVideoMode(256,gcw0_h, 16, SDL_HWSURFACE | #ifdef SDL_TRIPLEBUF SDL_TRIPLEBUF); #else SDL_DOUBLEBUF); #endif } else { sdl_video.surf_screen = SDL_SetVideoMode(gcw0_w,gcw0_h, 16, SDL_HWSURFACE | #ifdef SDL_TRIPLEBUF SDL_TRIPLEBUF); #else SDL_DOUBLEBUF); #endif } } } if (show_lightgun && !config.gcw0_fullscreen) // hack to remove cursor corruption of over game screen edge { SDL_FillRect(sdl_video.surf_screen, 0, 0); } #endif SDL_BlitSurface(sdl_video.surf_bitmap, &sdl_video.srect, sdl_video.surf_screen, &sdl_video.drect); //SDL_UpdateRect(sdl_video.surf_screen, 0, 0, 0, 0); #ifdef GCWZERO // Add scanlines to Game Gear games if requested if ( (system_hw == SYSTEM_GG) && config.gg_scanlines) { SDL_Surface *scanlinesSurface; scanlinesSurface = IMG_Load("./scanlines.png"); SDL_BlitSurface(scanlinesSurface, NULL, sdl_video.surf_screen, &sdl_video.drect); SDL_FreeSurface(scanlinesSurface); } if (show_lightgun) { // Remove previous cursor from black bars if (config.gcw0_fullscreen) { if (config.smsmaskleftbar) { if(system_hw == SYSTEM_SMS2) { SDL_Rect srect; srect.x = 0; srect.y = 0; srect.w = 4; srect.h = 192; SDL_FillRect(sdl_video.surf_screen, &srect, SDL_MapRGB(sdl_video.surf_screen->format, 0, 0, 0)); srect.x = 252; SDL_FillRect(sdl_video.surf_screen, &srect, SDL_MapRGB(sdl_video.surf_screen->format, 0, 0, 0)); } } } /* get mouse coordinates (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); SDL_Rect lrect; lrect.x = x-7; lrect.y = y-7; lrect.w = 15; lrect.h = 15; SDL_Surface *lightgunSurface; lightgunSurface = IMG_Load(cursor[config.cursor]); static lightgun_af = 0; SDL_Rect srect; srect.y = 0; srect.w = 15; srect.h = 15; //only show cursor if movement occurred within 3 seconds. time_t current_time2; current_time2 = time(NULL); if (lightgun_af >= 10) { srect.x = 0; if((current_time2 - current_time) < 3) SDL_BlitSurface(lightgunSurface, &srect, sdl_video.surf_screen, &lrect); } else { if (config.cursor != 0) srect.x = 15; else srect.x = 0; if((current_time2 - current_time) < 3) SDL_BlitSurface(lightgunSurface, &srect, sdl_video.surf_screen, &lrect); } lightgun_af++; if (lightgun_af == 20) lightgun_af = 0; SDL_FreeSurface(lightgunSurface); } //show_lightgun #endif SDL_Flip(sdl_video.surf_screen); ++sdl_video.frames_rendered; } static void sdl_video_close() { if (sdl_video.surf_bitmap) SDL_FreeSurface(sdl_video.surf_bitmap); if (sdl_video.surf_screen) SDL_FreeSurface(sdl_video.surf_screen); } /* Timer Sync */ struct { SDL_sem* sem_sync; unsigned ticks; } sdl_sync; static Uint32 sdl_sync_timer_callback(Uint32 interval) { #ifdef GCWZERO if (!gotomenu) { SDL_SemPost(sdl_sync.sem_sync); sdl_sync.ticks++; } #else SDL_SemPost(sdl_sync.sem_sync); sdl_sync.ticks++; #endif if (sdl_sync.ticks == (vdp_pal ? 50 : 20)) { SDL_Event event; SDL_UserEvent userevent; userevent.type = SDL_USEREVENT; userevent.code = vdp_pal ? (sdl_video.frames_rendered / 3) : sdl_video.frames_rendered; userevent.data1 = NULL; userevent.data2 = NULL; sdl_sync.ticks = sdl_video.frames_rendered = 0; event.type = SDL_USEREVENT; event.user = userevent; SDL_PushEvent(&event); } return interval; } static int sdl_sync_init() { if(SDL_InitSubSystem(SDL_INIT_TIMER|SDL_INIT_EVENTTHREAD) < 0) { MessageBox(NULL, "SDL Timer initialization failed", "Error", 0); return 0; } sdl_sync.sem_sync = SDL_CreateSemaphore(0); sdl_sync.ticks = 0; return 1; } static void sdl_sync_close() { if(sdl_sync.sem_sync) SDL_DestroySemaphore(sdl_sync.sem_sync); } static const uint16 vc_table[4][2] = { /* NTSC, PAL */ {0xDA , 0xF2}, /* Mode 4 (192 lines) */ {0xEA , 0x102}, /* Mode 5 (224 lines) */ {0xDA , 0xF2}, /* Mode 4 (192 lines) */ {0x106, 0x10A} /* Mode 5 (240 lines) */ }; static int sdl_control_update(SDLKey keystate) { switch (keystate) { #ifndef GCWZERO case SDLK_TAB: { system_reset(); break; } #endif case SDLK_F1: { if (SDL_ShowCursor(-1)) SDL_ShowCursor(0); else SDL_ShowCursor(1); break; } case SDLK_F2: { if (fullscreen) fullscreen = 0; else fullscreen = SDL_FULLSCREEN; sdl_video.surf_screen = SDL_SetVideoMode(VIDEO_WIDTH, VIDEO_HEIGHT, 16, SDL_SWSURFACE | fullscreen); break; } case SDLK_F3: { if (config.bios == 0) config.bios = 3; else if (config.bios == 3) config.bios = 1; break; } case SDLK_F4: { if (!turbo_mode) use_sound ^= 1; break; } case SDLK_F5: { log_error ^= 1; break; } case SDLK_F6: { if (!use_sound) { turbo_mode ^=1; sdl_sync.ticks = 0; } break; } case SDLK_F7: { char save_state_file[256]; sprintf(save_state_file,"%s/%X.gp0", get_save_directory(), rominfo.realchecksum); FILE *f = fopen(save_state_file,"rb"); if (f) { uint8 buf[STATE_SIZE]; fread(&buf, STATE_SIZE, 1, f); state_load(buf); fclose(f); } break; } case SDLK_F8: { char save_state_file[256]; sprintf(save_state_file,"%s/%X.gp0", get_save_directory(), rominfo.realchecksum); FILE *f = fopen(save_state_file,"wb"); if (f) { uint8 buf[STATE_SIZE]; int len = state_save(buf); fwrite(&buf, len, 1, f); fclose(f); } break; } case SDLK_F9: { config.region_detect = (config.region_detect + 1) % 5; get_region(0); /* framerate has changed, reinitialize audio timings */ audio_init(snd.sample_rate, 0); /* system with region BIOS should be reinitialized */ if ((system_hw == SYSTEM_MCD) || ((system_hw & SYSTEM_SMS) && (config.bios & 1))) { system_init(); system_reset(); } else { /* reinitialize I/O region register */ if (system_hw == SYSTEM_MD) { io_reg[0x00] = 0x20 | region_code | (config.bios & 1); } else { io_reg[0x00] = 0x80 | (region_code >> 1); } /* reinitialize VDP */ if (vdp_pal) { status |= 1; lines_per_frame = 313; } else { status &= ~1; lines_per_frame = 262; } /* reinitialize VC max value */ switch (bitmap.viewport.h) { case 192: vc_max = vc_table[0][vdp_pal]; break; case 224: vc_max = vc_table[1][vdp_pal]; break; case 240: vc_max = vc_table[3][vdp_pal]; break; } } break; } case SDLK_F10: { gen_reset(0); break; } case SDLK_F11: { config.overscan = (config.overscan + 1) & 3; if ((system_hw == SYSTEM_GG) && !config.gg_extra) { bitmap.viewport.x = (config.overscan & 2) ? 14 : -48; } else { bitmap.viewport.x = (config.overscan & 2) * 7; } bitmap.viewport.changed = 3; break; } case SDLK_F12: { joynum = (joynum + 1) % MAX_DEVICES; while (input.dev[joynum] == NO_DEVICE) { joynum = (joynum + 1) % MAX_DEVICES; } break; } case SDLK_ESCAPE: { #ifndef GCWZERO /* exit */ return 0; #endif } default: break; } return 1; } static void shutdown() { FILE *fp; if (system_hw == SYSTEM_MCD) { /* save internal backup RAM (if formatted) */ char brm_file[256]; if (!memcmp(scd.bram + 0x2000 - 0x20, brm_format + 0x20, 0x20)) { sprintf(brm_file,"%s/", get_save_directory(), "scd.brm"); fp = fopen(brm_file, "wb"); if (fp!=NULL) { fwrite(scd.bram, 0x2000, 1, fp); fclose(fp); } } /* save cartridge backup RAM (if formatted) */ if (scd.cartridge.id) { if (!memcmp(scd.cartridge.area + scd.cartridge.mask + 1 - 0x20, brm_format + 0x20, 0x20)) { sprintf(brm_file,"%s/", get_save_directory(), "cart.brm"); fp = fopen(brm_file, "wb"); if (fp!=NULL) { fwrite(scd.cartridge.area, scd.cartridge.mask + 1, 1, fp); fclose(fp); } } } } if (sram.on) { /* save SRAM */ char save_file[256]; if (rom_filename[0] != '\0') { sprintf(save_file,"%s/%s.srm", get_save_directory(), rom_filename); fp = fopen(save_file, "wb"); if (fp!=NULL) { fwrite(sram.sram,0x10000,1, fp); fclose(fp); } } } audio_shutdown(); error_shutdown(); sdl_video_close(); sdl_sound_close(); sdl_sync_close(); SDL_Quit(); } #ifdef GCWZERO //menu! static int gcw0menu(void) { SDL_PauseAudio(1); /* display menu */ // change video mode sdl_video.surf_screen = SDL_SetVideoMode(320,240, 32, SDL_HWSURFACE | #ifdef SDL_TRIPLEBUF SDL_TRIPLEBUF); #else SDL_DOUBLEBUF); #endif // blank screen SDL_FillRect(sdl_video.surf_screen, 0, 0); enum {MAINMENU = 0, GRAPHICS_OPTIONS = 1, REMAP_OPTIONS = 2, SAVE_STATE = 3, LOAD_STATE = 4, MISC_OPTIONS = 5}; static int menustate = MAINMENU; // Menu text const char *gcw0menu_mainlist[9]= { "Resume game", "Save state", "Load state", "Graphics options", "Remap buttons", "Misc. Options", "", //spacer "Reset", "Quit" }; const char *gcw0menu_gfxlist[6]= { "Scaling", "Keep aspect ratio", "Scanlines (GG)", "Mask left bar (SMS)", "Frameskip", "Return to main menu", }; const char *gcw0menu_numericlist[4]= { "0", "1", "2", "3", }; const char *gcw0menu_onofflist[2]= { "Off", "On", }; const char *gcw0menu_remapoptionslist[9]= { "A", "B", "C", "X", "Y", "Z", "Start", "Mode", "Return to main menu", }; const char *gcw0menu_savestate[10]= { "Back to main menu", "Save state 1 (Quicksave)", "Save state 2", "Save state 3", "Save state 4", "Save state 5", "Save state 6", "Save state 7", "Save state 8", "Save state 9", }; const char *gcw0menu_loadstate[10]= { "Back to main menu", "Load state 1 (Quickload)", "Load state 2", "Load state 3", "Load state 4", "Load state 5", "Load state 6", "Load state 7", "Load state 8", "Load state 9", }; const char *gcw0menu_misc[7]= { "Back to main menu", "Resume on Save/Load", "A-stick", "Lock-on", "FM sound (SMS)", "Lightgun speed", "Lightgun Cursor", }; const char *lock_on_desc[4]= { " Off", " Game Genie", " Action Replay", "Sonic & Knuckles", }; // start menu loop bitmap.viewport.changed=1; //change screen res if required while(gotomenu) { // set up menu surface SDL_Surface *menuSurface = NULL; menuSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, 320, 240, 16, 0, 0, 0, 0); // identify system we are using to show correct background just cos we can :P if ( system_hw == SYSTEM_PICO) //Sega Pico { SDL_Surface *tempbgSurface; SDL_Surface *bgSurface; tempbgSurface = IMG_Load( "./PICO.png" ); bgSurface = SDL_DisplayFormat( tempbgSurface ); SDL_BlitSurface(bgSurface, NULL, menuSurface, NULL); SDL_FreeSurface(tempbgSurface); SDL_FreeSurface(bgSurface); } else if ( (system_hw == SYSTEM_SG)|| (system_hw == SYSTEM_SGII) || (system_hw == SYSTEM_SGII_RAM_EXT) ) //SG-1000 I&II { SDL_Surface *tempbgSurface; SDL_Surface *bgSurface; tempbgSurface = IMG_Load( "./SG1000.png" ); bgSurface = SDL_DisplayFormat( tempbgSurface ); SDL_BlitSurface(bgSurface, NULL, menuSurface, NULL); SDL_FreeSurface(tempbgSurface); SDL_FreeSurface(bgSurface); } else if ( (system_hw == SYSTEM_MARKIII) || (system_hw == SYSTEM_SMS) || ( system_hw == SYSTEM_GGMS) || (system_hw == SYSTEM_SMS2) || (system_hw == SYSTEM_PBC) ) //Mark III & Sega Master System I&II & Megadrive with power base converter { SDL_Surface *tempbgSurface; SDL_Surface *bgSurface; tempbgSurface = IMG_Load( "./SMS.png" ); bgSurface = SDL_DisplayFormat( tempbgSurface ); SDL_BlitSurface(bgSurface, NULL, menuSurface, NULL); SDL_FreeSurface(tempbgSurface); SDL_FreeSurface(bgSurface); } else if (system_hw == SYSTEM_GG) { SDL_Surface *tempbgSurface; SDL_Surface *bgSurface; tempbgSurface = IMG_Load( "./GG.png" ); bgSurface = SDL_DisplayFormat( tempbgSurface ); SDL_BlitSurface(bgSurface, NULL, menuSurface, NULL); SDL_FreeSurface(tempbgSurface); SDL_FreeSurface(bgSurface); } else if ( system_hw == SYSTEM_MD) //Megadrive { SDL_Surface *tempbgSurface; SDL_Surface *bgSurface; tempbgSurface = IMG_Load( "./MD.png" ); bgSurface = SDL_DisplayFormat( tempbgSurface ); SDL_BlitSurface(bgSurface, NULL, menuSurface, NULL); SDL_FreeSurface(tempbgSurface); SDL_FreeSurface(bgSurface); } else if ( system_hw == SYSTEM_MCD) //MegaCD { SDL_Surface *tempbgSurface; SDL_Surface *bgSurface; tempbgSurface = IMG_Load( "./MCD.png" ); bgSurface = SDL_DisplayFormat( tempbgSurface ); SDL_BlitSurface(bgSurface, NULL, menuSurface, NULL); SDL_FreeSurface(tempbgSurface); SDL_FreeSurface(bgSurface); } // show menu TTF_Init(); TTF_Font *ttffont = NULL; SDL_Color text_color = {180, 180, 180}; SDL_Color selected_text_color = {23, 86, 155}; //selected colour = Sega blue ;) SDL_Surface *textSurface; int i; static int selectedoption = 0; // Fill menu box SDL_Surface *MenuBackground; if (menustate == REMAP_OPTIONS) { MenuBackground = SDL_CreateRGBSurface(SDL_HWSURFACE, 320, 185, 16, 0, 0, 0, 0); SDL_Rect rect; rect.x = 0; rect.y = 35; rect.w = 320; rect.h = 185; SDL_FillRect(MenuBackground, 0, 0); SDL_SetAlpha(MenuBackground, SDL_SRCALPHA, 50); SDL_BlitSurface(MenuBackground, NULL, menuSurface, &rect); SDL_FreeSurface(MenuBackground); } else { MenuBackground = SDL_CreateRGBSurface(SDL_HWSURFACE, 180, 185, 16, 0, 0, 0, 0); SDL_Rect rect; rect.x = 60; rect.y = 35; rect.w = 180; rect.h = 185; SDL_FillRect(MenuBackground, 0, 0); SDL_SetAlpha(MenuBackground, SDL_SRCALPHA, 50); SDL_BlitSurface(MenuBackground, NULL, menuSurface, &rect); SDL_FreeSurface(MenuBackground); } // Show title ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); SDL_Rect destination; destination.x = 80; destination.y = 40; destination.w = 100; destination.h = 50; textSurface = TTF_RenderText_Solid(ttffont, "Genesis Plus GX", text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); TTF_CloseFont (ttffont); if (menustate == MAINMENU) { //there's no need to open/close font each cycle :P ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); for(i=0; i<9; i++) { SDL_Rect destination; destination.x = 80; destination.y = 70+(15*i); destination.w = 100; destination.h = 50; if (i == selectedoption) textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_mainlist[i], selected_text_color); else textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_mainlist[i], text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); } TTF_CloseFont (ttffont); } else if (menustate == GRAPHICS_OPTIONS) { ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); for(i=0; i<6; i++) { SDL_Rect destination; destination.x = 80; destination.y = 70+(15*i); destination.w = 100; destination.h = 50; if ((i+10) == selectedoption) textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_gfxlist[i], selected_text_color); else textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_gfxlist[i], text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); } /* Display On/Off */ SDL_Rect destination; destination.x = 220; destination.w = 100; destination.h = 50; // Scaling destination.y = 70+(15*0); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.gcw0_fullscreen], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // Aspect ratio destination.y = 70+(15*1); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.keepaspectratio], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // Scanlines destination.y = 70+(15*2); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.gg_scanlines], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // Mask left bar destination.y = 70+(15*3); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.smsmaskleftbar], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // Frameskip destination.y = 70+(15*4); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_numericlist[config.gcw0_frameskip], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); TTF_CloseFont (ttffont); } else if (menustate == REMAP_OPTIONS) { char* remap_text[256]; ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); sprintf(remap_text, "%s%25s", "GenPlus", "GCW-Zero"); SDL_Rect destination = {30, 60, 100, 50}; textSurface = TTF_RenderText_Solid(ttffont, remap_text, text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); for(i=0; i < 9; i++) { if (i < 8) { sprintf(remap_text, "%-5s %-7s", gcw0menu_remapoptionslist[i], gcw0_get_key_name(config.buttons[i])); } else { sprintf(remap_text, gcw0menu_remapoptionslist[i]); // for return option } SDL_Rect destination = {30, 80 + (15 * i), 100, 50}; if ((i+20) == selectedoption) { textSurface = TTF_RenderText_Solid(ttffont, remap_text, selected_text_color); } else { textSurface = TTF_RenderText_Solid(ttffont, remap_text, text_color); } SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); } TTF_CloseFont (ttffont); } else if (menustate == SAVE_STATE) { //Show saved BMP as background if available SDL_Surface* screenshot; char load_state_screenshot[256]; sprintf(load_state_screenshot,"%s/%s.%d.bmp", get_save_directory(), rom_filename, selectedoption-30); screenshot = SDL_LoadBMP(load_state_screenshot); if (screenshot) { SDL_Rect destination; destination.x = (320 - screenshot->w) / 2; destination.y = (240 - screenshot->h) / 2; destination.w = 320; destination.h = 240; SDL_BlitSurface(screenshot, NULL, menuSurface, &destination); // Fill menu box SDL_Surface *MenuBackground = SDL_CreateRGBSurface(SDL_HWSURFACE, 180, 185, 16, 0, 0, 0, 0); SDL_Rect rect; rect.x = 60; rect.y = 35; rect.w = 180; rect.h = 185; SDL_FillRect(MenuBackground, 0, 0); SDL_SetAlpha(MenuBackground, SDL_SRCALPHA, 180); SDL_BlitSurface(MenuBackground, NULL, menuSurface, &rect); SDL_FreeSurface(MenuBackground); } SDL_FreeSurface(screenshot); // Show title ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); SDL_Rect destination; destination.x = 80; destination.y = 40; destination.w = 100; destination.h = 50; textSurface = TTF_RenderText_Solid(ttffont, "Genesis Plus GX", text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); TTF_CloseFont (ttffont); ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); for(i=0; i<10; i++) { SDL_Rect destination; destination.x = 80; destination.y = 70+(15*i); destination.w = 100; destination.h = 50; if ((i+30) == selectedoption) textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_savestate[i], selected_text_color); else textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_savestate[i], text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); } TTF_CloseFont (ttffont); } else if (menustate == LOAD_STATE) { //Show saved BMP as background if available SDL_Surface* screenshot; char load_state_screenshot[256]; sprintf(load_state_screenshot,"%s/%s.%d.bmp", get_save_directory(), rom_filename, selectedoption-40); screenshot = SDL_LoadBMP(load_state_screenshot); if (screenshot) { SDL_Rect destination; destination.x = (320 - screenshot->w) / 2; destination.y = (240 - screenshot->h) / 2; destination.w = 320; destination.h = 240; SDL_BlitSurface(screenshot, NULL, menuSurface, &destination); // Fill menu box SDL_Surface *MenuBackground = SDL_CreateRGBSurface(SDL_HWSURFACE, 180, 185, 16, 0, 0, 0, 0); SDL_Rect rect; rect.x = 60; rect.y = 35; rect.w = 180; rect.h = 185; SDL_FillRect(MenuBackground, 0, 0); SDL_SetAlpha(MenuBackground, SDL_SRCALPHA, 180); SDL_BlitSurface(MenuBackground, NULL, menuSurface, &rect); SDL_FreeSurface(MenuBackground); } SDL_FreeSurface(screenshot); // Show title ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); SDL_Rect destination; destination.x = 80; destination.y = 40; destination.w = 100; destination.h = 50; textSurface = TTF_RenderText_Solid(ttffont, "Genesis Plus GX", text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); TTF_CloseFont (ttffont); ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); for(i=0; i<10; i++) { SDL_Rect destination; destination.x = 80; destination.y = 70+(15*i); destination.w = 100; destination.h = 50; if ((i+40) == selectedoption) textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_loadstate[i], selected_text_color); else textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_loadstate[i], text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); } TTF_CloseFont (ttffont); } else if (menustate == MISC_OPTIONS) { ttffont = TTF_OpenFont("./ProggyTiny.ttf", 16); for(i=0; i<7; i++) { SDL_Rect destination; destination.x = 80; destination.y = 70+(15*i); destination.w = 100; destination.h = 50; if ((i+50) == selectedoption) textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_misc[i], selected_text_color); else textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_misc[i], text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); } /* Display On/Off */ SDL_Rect destination; destination.x = 220; destination.w = 100; destination.h = 50; // Save/load autoresume destination.y = 70+(15*1); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.sl_autoresume], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // A-stick destination.y = 70+(15*2); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.a_stick], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); /* Display Lock-on Types */ destination.x = 142; destination.y = 70+(15*3); textSurface = TTF_RenderText_Solid(ttffont, lock_on_desc[config.lock_on], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // FM sound(SMS) destination.x = 220; destination.y = 70+(15*4); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_onofflist[config.ym2413], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // Lightgun speed destination.x = 220; destination.y = 70+(15*5); textSurface = TTF_RenderText_Solid(ttffont, gcw0menu_numericlist[config.lightgun_speed], selected_text_color); SDL_BlitSurface(textSurface, NULL, menuSurface, &destination); SDL_FreeSurface(textSurface); // Lightgun Cursor destination.y = 70+(15*6); SDL_Surface *lightgunSurface; lightgunSurface = IMG_Load(cursor[config.cursor]); static lightgun_af_demo = 0; SDL_Rect srect; srect.x = 0; srect.y = 0; srect.w = 15; srect.h = 15; if (lightgun_af_demo >= 10 && config.cursor != 0) { srect.x = 15; } lightgun_af_demo++; if (lightgun_af_demo == 20) lightgun_af_demo = 0; SDL_BlitSurface(lightgunSurface, &srect, menuSurface, &destination); SDL_FreeSurface(lightgunSurface); TTF_CloseFont (ttffont); } //TODO other menu's go here /* Update display */ SDL_Rect dest; dest.w = 320; dest.h = 240; dest.x = 0; dest.y = 0; SDL_BlitSurface(menuSurface, NULL, sdl_video.surf_screen, &dest); SDL_FreeSurface(menuSurface); SDL_Flip(sdl_video.surf_screen); /* Check for user input */ SDL_EnableKeyRepeat(0,0); static int keyheld=0; SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: sdl_control_update(event.key.keysym.sym); break; case SDL_KEYUP: keyheld = 0; break; default: break; } } if (event.type == SDL_KEYDOWN && !keyheld) { keyheld++; uint8 *keystate2; keystate2 = SDL_GetKeyState(NULL); if(keystate2[SDLK_DOWN]) { if (selectedoption > 9 && selectedoption < 20) //graphics menu { selectedoption++; if (selectedoption == 16) selectedoption = 10; } else if (selectedoption > 19 && selectedoption < 30) //remap menu { selectedoption++; if (selectedoption == 29) selectedoption = 20; } else if (selectedoption > 29 && selectedoption < 40) //save menu { selectedoption++; if (selectedoption == 40) selectedoption = 30; } else if (selectedoption > 39 && selectedoption < 50) //load menu { selectedoption++; if (selectedoption == 50) selectedoption = 40; } else if (selectedoption > 49 && selectedoption < 60) //misc menu { selectedoption++; if (selectedoption == 57) selectedoption = 50; } else //main menu { selectedoption++; if (selectedoption == 6) selectedoption = 7; if (selectedoption > 8) selectedoption=0; } SDL_Delay(100); } else if(keystate2[SDLK_UP]) { if (selectedoption > 9 && selectedoption < 20) //graphics menu { selectedoption--; if (selectedoption == 9) selectedoption = 15; } else if (selectedoption > 19 && selectedoption < 30) //remap menu { selectedoption--; if (selectedoption == 19) selectedoption = 28; } else if (selectedoption > 29 && selectedoption < 40) //save menu { selectedoption--; if (selectedoption == 29) selectedoption = 39; } else if (selectedoption > 39 && selectedoption < 50) //load menu { selectedoption--; if (selectedoption == 39) selectedoption = 49; } else if (selectedoption > 49 && selectedoption < 60) //misc menu { selectedoption--; if (selectedoption == 49) selectedoption = 56; } else { //main menu if (!selectedoption) selectedoption = 8; else selectedoption--; if (selectedoption == 6) selectedoption = 5; } SDL_Delay(100); } else if(keystate2[SDLK_LALT] && menustate != REMAP_OPTIONS) //back to last menu or quit menu { if (menustate == GRAPHICS_OPTIONS) { menustate = MAINMENU; selectedoption = 3; SDL_Delay(130); } else if (menustate == SAVE_STATE) { menustate = MAINMENU; selectedoption = 1; SDL_Delay(130); } else if (menustate == LOAD_STATE) { menustate = MAINMENU; selectedoption = 2; SDL_Delay(130); } else if (menustate == MISC_OPTIONS) { menustate = MAINMENU; selectedoption = 5; SDL_Delay(130); } else if (menustate == MAINMENU) { gotomenu=0; selectedoption=0; SDL_Delay(130); break; } } else if(keystate2[SDLK_LCTRL] && menustate != REMAP_OPTIONS) { if (selectedoption == 0) { //Resume gotomenu=0; selectedoption=0; SDL_Delay(130); break; } else if (selectedoption == 1) //Save { menustate = SAVE_STATE; selectedoption = 30; SDL_Delay(130); } else if (selectedoption == 2) //Load { menustate = LOAD_STATE; selectedoption = 40; SDL_Delay(130); } else if (selectedoption == 3) //Graphics { menustate = GRAPHICS_OPTIONS; selectedoption = 10; SDL_Delay(200); } else if (selectedoption == 4) //Remap { menustate = REMAP_OPTIONS; selectedoption=20; SDL_Delay(200); } else if (selectedoption == 5) //Misc. { menustate = MISC_OPTIONS; selectedoption=50; SDL_Delay(200); } else if (selectedoption == 7) //Reset { gotomenu = 0; selectedoption=0; system_reset(); SDL_Delay(130); break; } else if (selectedoption == 8) //Quit { exit(0); SDL_Delay(130); break; } else if (selectedoption == 10) { //Scaling config.gcw0_fullscreen = !config.gcw0_fullscreen; SDL_Delay(130); config_save(); } else if (selectedoption == 11) { //Keep aspect ratio SDL_Delay(130); config.keepaspectratio = !config.keepaspectratio; config_save(); do_once = 1; } else if (selectedoption == 12) { //Scanlines (GG) SDL_Delay(130); config.gg_scanlines = !config.gg_scanlines; config_save(); } else if (selectedoption == 13) { //Mask left bar SDL_Delay(130); config.smsmaskleftbar = !config.smsmaskleftbar; config_save(); } else if (selectedoption == 14) { //Frameskip SDL_Delay(130); config.gcw0_frameskip ++; if (config.gcw0_frameskip == 4) config.gcw0_frameskip = 0; config_save(); } else if (selectedoption == 15) { //Back to main menu menustate = MAINMENU; selectedoption = 3; SDL_Delay(130); } else if (selectedoption == 30) { //Return to main menu menustate = MAINMENU; selectedoption = 1; SDL_Delay(130); } else if (selectedoption > 30 && selectedoption < 40) { //save to selected savestate char save_state_file[256]; sprintf(save_state_file,"%s/%s.gp%d", get_save_directory(), rom_filename, selectedoption-30); FILE *f = fopen(save_state_file,"wb"); if (f) { uint8 buf[STATE_SIZE]; int len = state_save(buf); fwrite(&buf, len, 1, f); fclose(f); } //Save BMP screenshot char save_state_screenshot[256]; sprintf(save_state_screenshot,"%s/%s.%d.bmp", get_save_directory(), rom_filename, selectedoption-30); SDL_Surface* screenshot; if (!config.gcw0_fullscreen) { screenshot = SDL_CreateRGBSurface(SDL_HWSURFACE, sdl_video.srect.w, sdl_video.srect.h, 16, 0, 0, 0, 0); SDL_Rect temp; temp.x = 0; temp.y = 0; temp.w = sdl_video.srect.w; temp.h = sdl_video.srect.h; SDL_BlitSurface(sdl_video.surf_bitmap, &temp, screenshot, &temp); SDL_SaveBMP(screenshot, save_state_screenshot); SDL_FreeSurface(screenshot); } else { screenshot = SDL_CreateRGBSurface(SDL_HWSURFACE, gcw0_w, gcw0_h, 16, 0, 0, 0, 0); SDL_Rect temp; temp.x = 0; temp.y = 0; temp.w = gcw0_w; temp.h = gcw0_h; SDL_BlitSurface(sdl_video.surf_bitmap, &temp, screenshot, &temp); SDL_SaveBMP(screenshot, save_state_screenshot); SDL_FreeSurface(screenshot); } SDL_Delay(250); if (config.sl_autoresume) { menustate = MAINMENU; selectedoption = 0; gotomenu = 0; break; } } else if (selectedoption == 40) { //return to main menu menustate = MAINMENU; selectedoption = 2; SDL_Delay(130); } else if (selectedoption > 40 && selectedoption < 50) { //load selected loadstate char save_state_file[256]; sprintf(save_state_file,"%s/%s.gp%d", get_save_directory(), rom_filename, selectedoption-40 ); FILE *f = fopen(save_state_file,"rb"); if (f) { uint8 buf[STATE_SIZE]; fread(&buf, STATE_SIZE, 1, f); state_load(buf); fclose(f); } if (config.sl_autoresume) { gotomenu = 0; menustate = MAINMENU; selectedoption = 0; SDL_Delay(250); break; } } else if (selectedoption == 50) { //return to main menu menustate = MAINMENU; selectedoption = 5; SDL_Delay(130); } else if (selectedoption == 51) { //toggle auto resume when save/loading config.sl_autoresume=!config.sl_autoresume; config_save(); SDL_Delay(130); } else if (selectedoption == 52) { //toggle A-Stick config.a_stick=!config.a_stick; config_save(); SDL_Delay(130); } else if (selectedoption == 53) { config.lock_on = (++config.lock_on == 4)? 0 : config.lock_on; config_save(); SDL_Delay(130); } else if (selectedoption == 54) { config.ym2413 = !config.ym2413; config_save(); SDL_Delay(130); } else if (selectedoption == 55) { config.lightgun_speed++; if (config.lightgun_speed == 4) config.lightgun_speed = 1; config_save(); SDL_Delay(130); } else if (selectedoption == 56) { config.cursor++; if (config.cursor == 4) config.cursor = 0; config_save(); SDL_Delay(130); } } else if(menustate == REMAP_OPTIONS) {// REMAP_OPTIONS needs to capture all input SDLKey pressed_key = 0; if (keystate2[SDLK_RETURN]) pressed_key = SDLK_RETURN; else if (keystate2[SDLK_LCTRL]) pressed_key = SDLK_LCTRL; else if (keystate2[SDLK_LALT]) pressed_key = SDLK_LALT; else if (keystate2[SDLK_LSHIFT]) pressed_key = SDLK_LSHIFT; else if (keystate2[SDLK_SPACE]) pressed_key = SDLK_SPACE; else if (keystate2[SDLK_TAB]) pressed_key = SDLK_TAB; else if (keystate2[SDLK_BACKSPACE]) pressed_key = SDLK_BACKSPACE; else if (keystate2[SDLK_ESCAPE]) pressed_key = SDLK_ESCAPE; if (pressed_key) { if (selectedoption == 20) { //button a remap config.buttons[A] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 21) { //button b remap config.buttons[B] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 22) { //button c remap config.buttons[C] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 23) { //button x remap config.buttons[X] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 24) { //button y remap config.buttons[Y] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 25) { //button z remap config.buttons[Z] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 26) { //button start remap config.buttons[START] = (pressed_key==SDLK_ESCAPE)? 0: pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 27) { //button mode remap config.buttons[MODE] = pressed_key; config_save(); SDL_Delay(130); selectedoption++; } else if (selectedoption == 28) { //return to main menu menustate = MAINMENU; selectedoption = 4; SDL_Delay(130); } } } } }//menu loop SDL_PauseAudio(0); if(config.gcw0_fullscreen) { if ( (system_hw == SYSTEM_MARKIII) || (system_hw == SYSTEM_SMS) || (system_hw == SYSTEM_SMS2) || (system_hw == SYSTEM_PBC) ) { gcw0_w=sdl_video.drect.w; gcw0_h=sdl_video.drect.h; sdl_video.surf_screen = SDL_SetVideoMode(256,gcw0_h, 16, SDL_HWSURFACE | #ifdef SDL_TRIPLEBUF SDL_TRIPLEBUF); #else SDL_DOUBLEBUF); #endif } else { sdl_video.drect.w = sdl_video.srect.w; sdl_video.drect.h = sdl_video.srect.h; sdl_video.drect.x = 0; sdl_video.drect.y = 0; gcw0_w=sdl_video.drect.w; gcw0_h=sdl_video.drect.h; sdl_video.surf_screen = SDL_SetVideoMode(gcw0_w,gcw0_h, 16, SDL_HWSURFACE | #ifdef SDL_TRIPLEBUF SDL_TRIPLEBUF); #else SDL_DOUBLEBUF); #endif } } else { SDL_FillRect(sdl_video.surf_screen, 0, 0); SDL_Flip(sdl_video.surf_screen); SDL_FillRect(sdl_video.surf_screen, 0, 0); SDL_Flip(sdl_video.surf_screen); SDL_FillRect(sdl_video.surf_screen, 0, 0); SDL_Flip(sdl_video.surf_screen); } return 1; } #endif int sdl_input_update(void) { uint8 *keystate = SDL_GetKeyState(NULL); /* reset input */ input.pad[joynum] = 0; if(show_lightgun) input.pad[4] = 0; //player2: switch (input.dev[4]) { case DEVICE_LIGHTGUN: show_lightgun = 1; /* get mouse coordinates (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); if (config.gcw0_fullscreen) { input.analog[4][0] = x; input.analog[4][1] = y; } else { input.analog[4][0] = x - (VIDEO_WIDTH-bitmap.viewport.w)/2; input.analog[4][1] = y - (VIDEO_HEIGHT-bitmap.viewport.h)/2; } if (config.smsmaskleftbar) x += 8; /* TRIGGER, B, C (Menacer only), START (Menacer & Justifier only) */ if(keystate[SDLK_ESCAPE]) input.pad[4] |= INPUT_START; default: break; } switch (input.dev[joynum]) { case DEVICE_LIGHTGUN: { #ifdef GCWZERO show_lightgun = 2; /* get mouse coordinates (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); if (config.gcw0_fullscreen) { input.analog[0][0] = x; input.analog[0][1] = y; } else { input.analog[0][0] = x - (VIDEO_WIDTH-bitmap.viewport.w)/2; input.analog[0][1] = y - (VIDEO_HEIGHT-bitmap.viewport.h)/2; } if (config.smsmaskleftbar) x += 8; /* TRIGGER, B, C (Menacer only), START (Menacer & Justifier only) */ if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_A; if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_B; if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_C; if(keystate[SDLK_ESCAPE]) input.pad[0] |= INPUT_START; #else /* get mouse coordinates (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); /* X axis */ input.analog[joynum][0] = x - (VIDEO_WIDTH-bitmap.viewport.w)/2; /* Y axis */ input.analog[joynum][1] = y - (VIDEO_HEIGHT-bitmap.viewport.h)/2; /* TRIGGER, B, C (Menacer only), START (Menacer & Justifier only) */ if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_A; if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_B; if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_C; if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START; break; #endif } #ifndef GCWZERO case DEVICE_PADDLE: { /* get mouse (absolute values) */ int x; int state = SDL_GetMouseState(&x, NULL); /* Range is [0;256], 128 being middle position */ input.analog[joynum][0] = x * 256 /VIDEO_WIDTH; /* Button I -> 0 0 0 0 0 0 0 I*/ if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B; break; } case DEVICE_SPORTSPAD: { /* get mouse (relative values) */ int x,y; int state = SDL_GetRelativeMouseState(&x,&y); /* Range is [0;256] */ input.analog[joynum][0] = (unsigned char)(-x & 0xFF); input.analog[joynum][1] = (unsigned char)(-y & 0xFF); /* Buttons I & II -> 0 0 0 0 0 0 II I*/ if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B; if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_C; break; } case DEVICE_MOUSE: { SDL_ShowCursor(1); /* get mouse (relative values) */ int x,y; int state = SDL_GetRelativeMouseState(&x,&y); /* Sega Mouse range is [-256;+256] */ input.analog[joynum][0] = x * 2; input.analog[joynum][1] = y * 2; /* Vertical movement is upsidedown */ if (!config.invert_mouse) input.analog[joynum][1] = 0 - input.analog[joynum][1]; /* Start,Left,Right,Middle buttons -> 0 0 0 0 START MIDDLE RIGHT LEFT */ if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B; if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_C; if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_A; if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START; break; } case DEVICE_XE_1AP: { /* A,B,C,D,Select,START,E1,E2 buttons -> E1(?) E2(?) START SELECT(?) A B C D */ if(keystate[SDLK_a]) input.pad[joynum] |= INPUT_START; if(keystate[SDLK_s]) input.pad[joynum] |= INPUT_A; if(keystate[SDLK_d]) input.pad[joynum] |= INPUT_C; if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_Y; if(keystate[SDLK_z]) input.pad[joynum] |= INPUT_B; if(keystate[SDLK_x]) input.pad[joynum] |= INPUT_X; if(keystate[SDLK_c]) input.pad[joynum] |= INPUT_MODE; if(keystate[SDLK_v]) input.pad[joynum] |= INPUT_Z; /* Left Analog Stick (bidirectional) */ if(keystate[SDLK_UP]) input.analog[joynum][1]-=2; else if(keystate[SDLK_DOWN]) input.analog[joynum][1]+=2; else input.analog[joynum][1] = 128; if(keystate[SDLK_LEFT]) input.analog[joynum][0]-=2; else if(keystate[SDLK_RIGHT]) input.analog[joynum][0]+=2; else input.analog[joynum][0] = 128; /* Right Analog Stick (unidirectional) */ if(keystate[SDLK_KP8]) input.analog[joynum+1][0]-=2; else if(keystate[SDLK_KP2]) input.analog[joynum+1][0]+=2; else if(keystate[SDLK_KP4]) input.analog[joynum+1][0]-=2; else if(keystate[SDLK_KP6]) input.analog[joynum+1][0]+=2; else input.analog[joynum+1][0] = 128; /* Limiters */ if (input.analog[joynum][0] > 0xFF) input.analog[joynum][0] = 0xFF; else if (input.analog[joynum][0] < 0) input.analog[joynum][0] = 0; if (input.analog[joynum][1] > 0xFF) input.analog[joynum][1] = 0xFF; else if (input.analog[joynum][1] < 0) input.analog[joynum][1] = 0; if (input.analog[joynum+1][0] > 0xFF) input.analog[joynum+1][0] = 0xFF; else if (input.analog[joynum+1][0] < 0) input.analog[joynum+1][0] = 0; if (input.analog[joynum+1][1] > 0xFF) input.analog[joynum+1][1] = 0xFF; else if (input.analog[joynum+1][1] < 0) input.analog[joynum+1][1] = 0; break; } case DEVICE_PICO: { /* get mouse (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); /* Calculate X Y axis values */ input.analog[0][0] = 0x3c + (x * (0x17c-0x03c+1)) / VIDEO_WIDTH; input.analog[0][1] = 0x1fc + (y * (0x2f7-0x1fc+1)) / VIDEO_HEIGHT; /* Map mouse buttons to player #1 inputs */ if(state & SDL_BUTTON_MMASK) pico_current = (pico_current + 1) & 7; if(state & SDL_BUTTON_RMASK) input.pad[0] |= INPUT_PICO_RED; if(state & SDL_BUTTON_LMASK) input.pad[0] |= INPUT_PICO_PEN; break; } case DEVICE_TEREBI: { /* get mouse (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); /* Calculate X Y axis values */ input.analog[0][0] = (x * 250) / VIDEO_WIDTH; input.analog[0][1] = (y * 250) / VIDEO_HEIGHT; /* Map mouse buttons to player #1 inputs */ if(state & SDL_BUTTON_RMASK) input.pad[0] |= INPUT_B; break; } case DEVICE_GRAPHIC_BOARD: { /* get mouse (absolute values) */ int x,y; int state = SDL_GetMouseState(&x,&y); /* Calculate X Y axis values */ input.analog[0][0] = (x * 255) / VIDEO_WIDTH; input.analog[0][1] = (y * 255) / VIDEO_HEIGHT; /* Map mouse buttons to player #1 inputs */ if(state & SDL_BUTTON_LMASK) input.pad[0] |= INPUT_GRAPHIC_PEN; if(state & SDL_BUTTON_RMASK) input.pad[0] |= INPUT_GRAPHIC_MENU; if(state & SDL_BUTTON_MMASK) input.pad[0] |= INPUT_GRAPHIC_DO; break; } case DEVICE_ACTIVATOR: { if(keystate[SDLK_g]) input.pad[joynum] |= INPUT_ACTIVATOR_7L; if(keystate[SDLK_h]) input.pad[joynum] |= INPUT_ACTIVATOR_7U; if(keystate[SDLK_j]) input.pad[joynum] |= INPUT_ACTIVATOR_8L; if(keystate[SDLK_k]) input.pad[joynum] |= INPUT_ACTIVATOR_8U; } #endif default: { #ifdef GCWZERO if(keystate[config.buttons[A]]) input.pad[joynum] |= INPUT_A; if(keystate[config.buttons[B]]) input.pad[joynum] |= INPUT_B; if(keystate[config.buttons[C]]) input.pad[joynum] |= INPUT_C; if(keystate[config.buttons[START]]) input.pad[joynum] |= INPUT_START; if (show_lightgun == 1) { if(keystate[config.buttons[X]]) input.pad[4] |= INPUT_A; //player 2 if(keystate[config.buttons[Y]]) input.pad[4] |= INPUT_B; //player 2 if(keystate[config.buttons[Z]]) input.pad[4] |= INPUT_C; //player 2 } else if (show_lightgun == 2) { if(keystate[config.buttons[X]]) input.pad[4] |= INPUT_A; //player 2 if(keystate[config.buttons[Y]]) input.pad[4] |= INPUT_B; //player 2 if(keystate[config.buttons[Z]]) input.pad[4] |= INPUT_C; //player 2 } else { if(keystate[config.buttons[X]]) input.pad[joynum] |= INPUT_X; if(keystate[config.buttons[Y]]) input.pad[joynum] |= INPUT_Y; if(keystate[config.buttons[Z]]) input.pad[joynum] |= INPUT_Z; } if(keystate[config.buttons[MODE]]) input.pad[joynum] |= INPUT_MODE; if (keystate[SDLK_ESCAPE] && keystate[SDLK_RETURN]) { gotomenu=1; } if (keystate[SDLK_ESCAPE] && keystate[SDLK_TAB]) { //save to quicksave slot char save_state_file[256]; sprintf(save_state_file,"%s/%s.gp1", get_save_directory(), rom_filename); FILE *f = fopen(save_state_file,"wb"); if (f) { uint8 buf[STATE_SIZE]; int len = state_save(buf); fwrite(&buf, len, 1, f); fclose(f); } //Save BMP screenshot char save_state_screenshot[256]; sprintf(save_state_screenshot,"%s/%s.1.bmp", get_save_directory(), rom_filename); SDL_Surface* screenshot; if (!config.gcw0_fullscreen) { screenshot = SDL_CreateRGBSurface(SDL_HWSURFACE, sdl_video.srect.w, sdl_video.srect.h, 16, 0, 0, 0, 0); SDL_Rect temp; temp.x = 0; temp.y = 0; temp.w = sdl_video.srect.w; temp.h = sdl_video.srect.h; SDL_BlitSurface(sdl_video.surf_bitmap, &temp, screenshot, &temp); SDL_SaveBMP(screenshot, save_state_screenshot); SDL_FreeSurface(screenshot); } else { screenshot = SDL_CreateRGBSurface(SDL_HWSURFACE, gcw0_w, gcw0_h, 16, 0, 0, 0, 0); SDL_Rect temp; temp.x = 0; temp.y = 0; temp.w = gcw0_w; temp.h = gcw0_h; SDL_BlitSurface(sdl_video.surf_bitmap, &temp, screenshot, &temp); SDL_SaveBMP(screenshot, save_state_screenshot); SDL_FreeSurface(screenshot); } SDL_Delay(250); } if (keystate[SDLK_ESCAPE] && keystate[SDLK_BACKSPACE]) { //load quicksave slot char save_state_file[256]; sprintf(save_state_file,"%s/%s.gp1", get_save_directory(), rom_filename ); FILE *f = fopen(save_state_file,"rb"); if (f) { uint8 buf[STATE_SIZE]; fread(&buf, STATE_SIZE, 1, f); state_load(buf); fclose(f); } SDL_Delay(250); } #else if(keystate[SDLK_a]) input.pad[joynum] |= INPUT_A; if(keystate[SDLK_s]) input.pad[joynum] |= INPUT_B; if(keystate[SDLK_d]) input.pad[joynum] |= INPUT_C; if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START; if(keystate[SDLK_z]) input.pad[joynum] |= INPUT_X; if(keystate[SDLK_x]) input.pad[joynum] |= INPUT_Y; if(keystate[SDLK_c]) input.pad[joynum] |= INPUT_Z; if(keystate[SDLK_v]) input.pad[joynum] |= INPUT_MODE; #endif #ifdef GCWZERO //A-stick support static int MoveLeft = 0; static int MoveRight = 0; static int MoveUp = 0; static int MoveDown = 0; Sint16 x_move = 0; Sint16 y_move = 0; static int lg_left = 0; static int lg_right = 0; static int lg_up = 0; static int lg_down = 0; SDL_Joystick* joy; if(SDL_NumJoysticks() > 0) { joy = SDL_JoystickOpen(0); x_move = SDL_JoystickGetAxis(joy, 0); y_move = SDL_JoystickGetAxis(joy, 1); } // Control lightgun with A-stick if activated if (show_lightgun) { lg_left = 0; lg_right = 0; lg_up = 0; lg_down = 0; if (x_move < -1000 || x_move > 1000) { if (x_move < -1000 ) lg_left = 1; if (x_move < -20000) lg_left = 3; if (x_move > 1000 ) lg_right = 1; if (x_move > 20000) lg_right = 3; current_time = time(NULL); //cursor disappears after 3 seconds... } if (y_move < -1000 || y_move > 1000) { if (y_move < -1000 ) lg_up = 1; if (y_move < -20000) lg_up = 3; if (y_move > 1000 ) lg_down = 1; if (y_move > 20000) lg_down = 3; current_time = time(NULL); } // Keep mouse within screen, wrap around! int x,y; int state = SDL_GetMouseState(&x,&y); if (!config.gcw0_fullscreen) { if ((x - lg_left ) < sdl_video.drect.x ) x = VIDEO_WIDTH - sdl_video.drect.x; if ((y - lg_up ) < sdl_video.drect.y ) y = VIDEO_HEIGHT - sdl_video.drect.y; // if ((x + lg_right) > 288) x = 288; // if ((y + lg_down ) > 216) y = 216; // if ((x + lg_right) > 320) x = 320; // if ((y + lg_down ) > 240) y = 240; if ((x + lg_right) > VIDEO_WIDTH - sdl_video.drect.x) x = sdl_video.drect.x; if ((y + lg_down ) > VIDEO_HEIGHT - sdl_video.drect.y) y = sdl_video.drect.y; // sdl_video.drect.x = (VIDEO_WIDTH - sdl_video.drect.w) / 2; // sdl_video.drect.y = (VIDEO_HEIGHT - sdl_video.drect.h) / 2; } else //scaling on { if ((x - lg_left) < 0) x = gcw0_w; if ((y - lg_up ) < 0) y = gcw0_h; if ((x + lg_right) > gcw0_w) x = 0; if ((y + lg_down ) > gcw0_h) y = 0; } SDL_WarpMouse( ( x+ ( ( lg_right - lg_left ) * config.lightgun_speed ) ) , ( y+ ( ( lg_down - lg_up ) * config.lightgun_speed ) ) ); } else // otherwise it's just mirroring the D-pad controls if (config.a_stick) { MoveLeft = 0; MoveRight = 0; MoveUp = 0; MoveDown = 0; if (x_move < -1000 || x_move > 1000) { if (x_move < -1000) MoveLeft = 1; if (x_move > 1000) MoveRight = 1; } if (y_move < -1000 || y_move > 1000) { if (y_move < -1000) MoveUp = 1; if (y_move > 1000) MoveDown = 1; } } if(show_lightgun == 1) //Genesis/MD D-pad controls player 2 { if(MoveUp == 1) input.pad[4] |= INPUT_UP; if(MoveDown == 1) input.pad[4] |= INPUT_DOWN; if(MoveLeft == 1) input.pad[4] |= INPUT_LEFT; if(MoveRight == 1) input.pad[4] |= INPUT_RIGHT; if(keystate[SDLK_UP] == 1) input.pad[joynum] |= INPUT_UP; if(keystate[SDLK_DOWN] == 1) input.pad[joynum] |= INPUT_DOWN; if(keystate[SDLK_LEFT] == 1) input.pad[joynum] |= INPUT_LEFT; if(keystate[SDLK_RIGHT]== 1) input.pad[joynum] |= INPUT_RIGHT; } else if(show_lightgun == 2) //SMS D-pad controls player 2 { if(MoveUp == 1) input.pad[joynum] |= INPUT_UP; if(MoveDown == 1) input.pad[joynum] |= INPUT_DOWN; if(MoveLeft == 1) input.pad[joynum] |= INPUT_LEFT; if(MoveRight == 1) input.pad[joynum] |= INPUT_RIGHT; if(keystate[SDLK_UP] == 1) input.pad[4] |= INPUT_UP; if(keystate[SDLK_DOWN] == 1) input.pad[4] |= INPUT_DOWN; if(keystate[SDLK_LEFT] == 1) input.pad[4] |= INPUT_LEFT; if(keystate[SDLK_RIGHT]== 1) input.pad[4] |= INPUT_RIGHT; } else { if (keystate[SDLK_UP] || MoveUp == 1) input.pad[joynum] |= INPUT_UP; else if(keystate[SDLK_DOWN] || MoveDown == 1) input.pad[joynum] |= INPUT_DOWN; if (keystate[SDLK_LEFT] || MoveLeft == 1) input.pad[joynum] |= INPUT_LEFT; else if(keystate[SDLK_RIGHT] || MoveRight == 1) input.pad[joynum] |= INPUT_RIGHT; } #else if (keystate[SDLK_UP] ) input.pad[joynum] |= INPUT_UP; else if(keystate[SDLK_DOWN] ) input.pad[joynum] |= INPUT_DOWN; if (keystate[SDLK_LEFT] ) input.pad[joynum] |= INPUT_LEFT; else if(keystate[SDLK_RIGHT]) input.pad[joynum] |= INPUT_RIGHT; #endif } } return 1; } int main (int argc, char **argv) { FILE *fp; int running = 1; atexit(shutdown); /* Print help if no game specified */ if(argc < 2) { char caption[256]; sprintf(caption, "Genesis Plus GX\\SDL\nusage: %s gamename\n", argv[0]); MessageBox(NULL, caption, "Information", 0); exit(1); } error_init(); create_default_directories(); /* set default config */ set_config_defaults(); /* using rom file name instead of crc code to save files */ sprintf(rom_filename, "%s", get_file_name(argv[1])); /* mark all BIOS as unloaded */ system_bios = 0; /* Genesis BOOT ROM support (2KB max) */ memset(boot_rom, 0xFF, 0x800); fp = fopen(MD_BIOS, "rb"); if (fp != NULL) { int i; /* read BOOT ROM */ fread(boot_rom, 1, 0x800, fp); fclose(fp); /* check BOOT ROM */ if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) { /* mark Genesis BIOS as loaded */ system_bios = SYSTEM_MD; } /* Byteswap ROM */ for (i=0; i<0x800; i+=2) { uint8 temp = boot_rom[i]; boot_rom[i] = boot_rom[i+1]; boot_rom[i+1] = temp; } } /* initialize SDL */ if(SDL_Init(0) < 0) { char caption[256]; sprintf(caption, "SDL initialization failed"); MessageBox(NULL, caption, "Error", 0); exit(1); } #ifdef GCWZERO sdl_joystick_init(); #endif sdl_video_init(); if (use_sound) sdl_sound_init(); sdl_sync_init(); /* initialize Genesis virtual system */ SDL_LockSurface(sdl_video.surf_bitmap); memset(&bitmap, 0, sizeof(t_bitmap)); bitmap.width = 720; bitmap.height = 576; #if defined(USE_8BPP_RENDERING) bitmap.pitch = (bitmap.width * 1); #elif defined(USE_15BPP_RENDERING) bitmap.pitch = (bitmap.width * 2); #elif defined(USE_16BPP_RENDERING) bitmap.pitch = (bitmap.width * 2); #elif defined(USE_32BPP_RENDERING) bitmap.pitch = (bitmap.width * 4); #endif bitmap.data = sdl_video.surf_bitmap->pixels; SDL_UnlockSurface(sdl_video.surf_bitmap); bitmap.viewport.changed = 3; /* Load game file */ if(!load_rom(argv[1])) { char caption[256]; sprintf(caption, "Error loading file `%s'.", argv[1]); MessageBox(NULL, caption, "Error", 0); exit(1); } /* initialize system hardware */ //NOTE gcw0 second value determines framerate audio_init(SOUND_FREQUENCY, 0); system_init(); /* Mega CD specific */ char brm_file[256]; if (system_hw == SYSTEM_MCD) { /* load internal backup RAM */ sprintf(brm_file,"%s/", get_save_directory(), "scd.brm"); fp = fopen(brm_file, "rb"); if (fp!=NULL) { fread(scd.bram, 0x2000, 1, fp); fclose(fp); } /* check if internal backup RAM is formatted */ if (memcmp(scd.bram + 0x2000 - 0x20, brm_format + 0x20, 0x20)) { /* clear internal backup RAM */ memset(scd.bram, 0x00, 0x200); /* Internal Backup RAM size fields */ brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00; brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (sizeof(scd.bram) / 64) - 3; /* format internal backup RAM */ memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40); } /* load cartridge backup RAM */ if (scd.cartridge.id) { sprintf(brm_file,"%s/", get_save_directory(), "cart.brm"); fp = fopen(brm_file, "rb"); if (fp!=NULL) { fread(scd.cartridge.area, scd.cartridge.mask + 1, 1, fp); fclose(fp); } /* check if cartridge backup RAM is formatted */ if (memcmp(scd.cartridge.area + scd.cartridge.mask + 1 - 0x20, brm_format + 0x20, 0x20)) { /* clear cartridge backup RAM */ memset(scd.cartridge.area, 0x00, scd.cartridge.mask + 1); /* Cartridge Backup RAM size fields */ brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = (((scd.cartridge.mask + 1) / 64) - 3) >> 8; brm_format[0x11] = brm_format[0x13] = brm_format[0x15] = brm_format[0x17] = (((scd.cartridge.mask + 1) / 64) - 3) & 0xff; /* format cartridge backup RAM */ memcpy(scd.cartridge.area + scd.cartridge.mask + 1 - sizeof(brm_format), brm_format, sizeof(brm_format)); } } } if (sram.on) { /* load SRAM */ char save_file[256]; sprintf(save_file,"%s/%s.srm", get_save_directory(), rom_filename); fp = fopen(save_file, "rb"); if (fp!=NULL) { fread(sram.sram,0x10000,1, fp); fclose(fp); } } /* reset system hardware */ system_reset(); if(use_sound) SDL_PauseAudio(0); /* 3 frames = 50 ms (60hz) or 60 ms (50hz) */ if(sdl_sync.sem_sync) SDL_SetTimer(vdp_pal ? 60 : 50, sdl_sync_timer_callback); /* emulation loop */ while(running) { SDL_Event event; if (SDL_PollEvent(&event)) { switch(event.type) { case SDL_USEREVENT: { char caption[100]; sprintf(caption,"Genesis Plus GX - %d fps - %s)", event.user.code, (rominfo.international[0] != 0x20) ? rominfo.international : rominfo.domestic); SDL_WM_SetCaption(caption, NULL); break; } case SDL_QUIT: { running = 0; break; } case SDL_KEYDOWN: { running = sdl_control_update(event.key.keysym.sym); break; } } } #ifdef GCWZERO if (do_once) { do_once--; //don't waste write cycles! if (config.keepaspectratio) { FILE* aspect_ratio_file = fopen("/sys/devices/platform/jz-lcd.0/keep_aspect_ratio", "w"); if (aspect_ratio_file) { fwrite("Y", 1, 1, aspect_ratio_file); fclose(aspect_ratio_file); } } if (!config.keepaspectratio) { FILE* aspect_ratio_file = fopen("/sys/devices/platform/jz-lcd.0/keep_aspect_ratio", "w"); if (aspect_ratio_file) { fwrite("N", 1, 1, aspect_ratio_file); fclose(aspect_ratio_file); } } } #endif sdl_video_update(); sdl_sound_update(use_sound); if(!turbo_mode && sdl_sync.sem_sync && sdl_video.frames_rendered % 3 == 0) { if (!config.gcw0_frameskip || (config.gcw0_frameskip && (system_hw != SYSTEM_MCD))) //we really only need this for fmv sequences if(!gotomenu) SDL_SemWait(sdl_sync.sem_sync); #ifdef GCWZERO } else { if (gotomenu) gcw0menu(); #endif } } return 0; }