void ai_miserys_bubble(Object *o) { Object *target; switch(o->state) { case 0: { // find the Toroko object we are to home in on target = mbubble_find_target(); if (!target) { o->state = 9999; return; } o->xmark = target->x - (6 << CSF); o->ymark = target->y - (6 << CSF); ThrowObject(o, o->xmark, o->ymark, 0, (2 << CSF)); o->state = 1; // correct values: 0x3F0, 0xAE NX_LOG("Computed toss values xi: 0x%x, 0x%x\n", o->xinertia, o->yinertia); NX_LOG("Target x/y: 0x%x, 0x%x\n", target->x, target->y); } case 1: ANIMATE(1, 0, 1); if (abs(o->x - o->xmark) <= (3 << CSF) && \ abs(o->y - o->ymark) <= (3 << CSF)) { o->state = 2; o->frame = 2; sound(SND_BUBBLE); if ((target = mbubble_find_target())) target->invisible = true; } break; case 2: { ANIMATE(1, 2, 3); o->xinertia -= 0x20; o->yinertia -= 0x20; LIMITX(0x5FF); LIMITY(0x5FF); if (o->y < -1000) o->Delete(); } break; } }
void ai_boulder(Object *o) { switch(o->state) { // shaking case 10: { NX_LOG("ai_boulder - state 10.\n"); o->state = 11; o->timer = 0; o->xmark = o->x; } case 11: { NX_LOG("ai_boulder - state 11.\n"); if ((++o->timer % 3) != 0) o->x = o->xmark + (1 << CSF); else o->x = o->xmark; } break; // thrown away by Balrog case 20: { NX_LOG("ai_boulder - state 20.\n"); o->yinertia = -0x400; o->xinertia = 0x100; sound(SND_FUNNY_EXPLODE); o->state = 21; o->timer = 0; } case 21: { NX_LOG("ai_boulder - state 21.\n"); o->yinertia += 0x10; if (o->blockd && o->yinertia >= 0) { sound(SND_EXPLOSION1); game.quaketime = 40; o->xinertia = 0; o->yinertia = 0; o->state = 0; } } break; } }
static bool tryload(Settings *setfile) { char setfilename_tmp[1024]; RFILE *fp = NULL; retro_create_path_string(setfilename_tmp, sizeof(setfilename_tmp), g_dir, setfilename); fp = filestream_open(setfilename_tmp, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fp) { NX_ERR("Couldn't open file %s.\n", setfilename_tmp); return 1; } NX_LOG("Loading settings...\n"); setfile->version = 0; filestream_read(fp, setfile, sizeof(Settings)); if (setfile->version != SETTINGS_VERSION) { NX_ERR("Wrong settings version %04x.\n", setfile->version); return 1; } filestream_close(fp); return 0; }
bool settings_save(Settings *setfile) { char setfilename_tmp[1024]; RFILE *fp = NULL; if (!setfile) setfile = &normal_settings; retro_create_path_string(setfilename_tmp, sizeof(setfilename_tmp), g_dir, setfilename); fp = filestream_open(setfilename_tmp, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fp) { NX_ERR("Couldn't open file %s.\n", setfilename_tmp); return 1; } NX_LOG("Writing settings...\n"); for(int i=0;i<INPUT_COUNT;i++) setfile->input_mappings[i] = input_get_mapping(i); setfile->version = SETTINGS_VERSION; filestream_write(fp, setfile, sizeof(Settings)); filestream_close(fp); return 0; }
void InitNewGame(bool with_intro) { NX_LOG("= Beginning new game =\n"); memset(game.flags, 0, sizeof(game.flags)); memset(game.skipflags, 0, sizeof(game.skipflags)); textbox.StageSelect.ClearSlots(); game.quaketime = game.megaquaketime = 0; game.showmapnametime = 0; game.debug.god = 0; game.running = true; game.frozen = false; // fully re-init the player object Objects::DestroyAll(true); game.createplayer(); player->maxHealth = 3; player->hp = player->maxHealth; game.switchstage.mapno = STAGE_START_POINT; game.switchstage.playerx = 10; game.switchstage.playery = 8; game.switchstage.eventonentry = (with_intro) ? 200 : 91; fade.set_full(FADE_OUT); }
bool retro_load_game(const struct retro_game_info *game) { struct retro_input_descriptor desc[] = { { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Jump" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Fire" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Show/Hide Map" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Previous Weapon" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Next Weapon" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Settings" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Inventory" }, { 0 }, }; environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); extract_directory(g_dir, game->path, sizeof(g_dir)); NX_LOG("g_dir: %s\n", g_dir); if (pre_main()) return 0; return 1; }
static void init_pitch(void) { NX_LOG("Calculating pitch scale...\n"); for(int i=0;i<NUM_NOTES;i++) { pitch[i] = (int)(441.0*(pow(2.0,((i-19.0)/12.0)))); } }
bool retro_load_game(const struct retro_game_info *game) { extract_directory(g_dir, game->path, sizeof(g_dir)); NX_LOG("g_dir: %s\n", g_dir); if (pre_main()) return 0; else return 1; }
static bool load_drumtable(FILE *fp) // pxt_path = the path where drum pxt files can be found { NX_LOG("load_drumtable: cache gone; rebuilding drums...\n"); pxt_initsynth(); for (int d = 0; d < NUM_DRUMS; d++) { if (drum_pxt[d]) if (load_drum_pxt(fp, drum_pxt[d], d)) return 1; } return 0; }
static bool check_data_exists() { char fname[1024]; retro_create_subpath_string(fname, sizeof(fname), g_dir, data_dir, "npc.tbl"); NX_LOG("check_data_exists: %s\n", fname); if (file_exists(fname)) return 0; NX_ERR("Fatal Error\n"); NX_ERR("Missing \"%s\" directory.\n", data_dir); NX_ERR("Please copy it over from a Doukutsu installation.\n"); return 1; }
// load the surface from a .pbm or bitmap file bool NXSurface::LoadImage(const char *pbm_name, bool use_colorkey, int use_display_format) { SDL_Surface *image; Free(); char filename[1024]; NX_LOG("filename: %s\n", pbm_name); image = SDL_LoadBMP(pbm_name); if (!image) { NX_ERR("NXSurface::LoadImage: load failed of '%s'!\n", filename); return 1; } fSurface = Scale(image, SCALE, use_colorkey, true, use_display_format); return (fSurface == NULL); }
bool SIFLoader::LoadHeader(const char *filename) { CFILE *fp; uint32_t magick; ClearIndex(); if (fFP) cclose(fFP); fp = fFP = copen(filename, "rb"); if (!fp) { NX_ERR("SIFLoader::LoadHeader: failed to open file '%s'\n", filename); return 1; } if ((magick = cgetl(fp)) != SIF_MAGICK) { NX_ERR("SIFLoader::LoadHeader: magick check failed--this isn't a SIF file or is wrong version?\n"); NX_ERR(" (expected %08x, got %08x)\n", SIF_MAGICK, magick); return 1; } int nsections = cgetc(fp); NX_LOG("SIFLoader::LoadHeader: read index of %d sections\n", nsections); for(int i=0;i<nsections;i++) { SIFIndexEntry *entry = new SIFIndexEntry; entry->type = cgetc(fp); // section type entry->foffset = cgetl(fp); // absolute offset in file entry->length = cgetl(fp); // length of section data entry->data = NULL; // we won't load it until asked fIndex.AddItem(entry); //NX_LOG(" - Sect%02d @ %04x\n", entry->type, entry->foffset); } // ..leave file handle open, its ok return 0; }
bool settings_load(Settings *setfile) { if (!setfile) setfile = &normal_settings; if (tryload(settings)) { NX_LOG("No saved settings; using defaults.\n"); memset(setfile, 0, sizeof(Settings)); setfile->resolution = 2; // 640x480 Windowed, should be safe value setfile->last_save_slot = 0; setfile->multisave = true; setfile->enable_debug_keys = false; setfile->sound_enabled = true; setfile->music_enabled = 1; // both Boss and Regular music setfile->instant_quit = false; setfile->emulate_bugs = false; setfile->no_quake_in_hell = false; setfile->inhibit_fullscreen = false; setfile->files_extracted = false; // I found that 8bpp->32bpp blits are actually noticably faster // than 32bpp->32bpp blits on several systems I tested. Not sure why // but calling SDL_DisplayFormat seems to actually be slowing things // down. This goes against established wisdom so if you want it back on, // run "displayformat 1" in the console and restart. setfile->displayformat = false; return 1; } else { input_set_mappings(settings->input_mappings); } return 0; }
// load into memory and return a pointer to the section of type 'type', // or NULL if the file doesn't have a section of that type. uint8_t *SIFLoader::FindSection(int type, int *length_out) { // try and find the section in the index for(int i=0;;i++) { SIFIndexEntry *entry = (SIFIndexEntry *)fIndex.ItemAt(i); if (!entry) break; if (entry->type == type) { // got it! // haven't loaded it yet? need to fetch it from file? if (!entry->data) { if (!fFP) { NX_ERR("SIFLoader::FindSection: entry found and need to load it, but file handle closed\n"); if (length_out) *length_out = 0; return NULL; } NX_LOG("Loading SIF section %d from address %04x\n", type, entry->foffset); entry->data = (uint8_t *)malloc(entry->length); cseek(fFP, entry->foffset, SEEK_SET); cread(entry->data, entry->length, 1, fFP); } if (length_out) *length_out = entry->length; return entry->data; } } if (length_out) *length_out = 0; return NULL; }
bool SIFSpritesSect::LoadFrame(SIFFrame *frame, int ndirs, \ const uint8_t **data, const uint8_t *data_end) { // sets defaults for un-specified/default fields memset(frame, 0, sizeof(SIFFrame)); for(int d=0;d<ndirs;d++) { SIFDir *dir = &frame->dir[d]; LoadPoint(&dir->sheet_offset, data, data_end); int t; for(;;) { t = read_U8(data, data_end); if (t == S_DIR_END) break; switch(t) { case S_DIR_DRAW_POINT: LoadPoint(&dir->drawpoint, data, data_end); break; case S_DIR_ACTION_POINT: LoadPoint(&dir->actionpoint, data, data_end); break; case S_DIR_ACTION_POINT_2: LoadPoint(&dir->actionpoint2, data, data_end); break; case S_DIR_PF_BBOX: LoadRect(&dir->pf_bbox, data, data_end); break; default: NX_LOG("SIFSpriteSect::LoadFrame: encountered unknown optional field type %d\n", t); return 1; } } } return 0; }
void ai_block_movev(Object *o) { int py = player->CenterY(); int objy = o->CenterY(); switch(o->state) { case 0: NX_LOG("ai_block_movev - state 0.\n"); o->flags |= FLAG_SOLID_BRICK; o->smushdamage = 100; o->dir = (o->dir == LEFT) ? UP : DOWN; o->state = (o->dir == DOWN) ? 10 : 20; break; case 10: // at top edge, ready to travel down NX_LOG("ai_block_movev - state 10.\n"); if (((py > objy) && (py - objy) < 0x32000) || \ ((py < objy) && (objy - py) < 0x3200)) { if (pdistlx(0x3200)) { o->state = 30; o->timer = 0; } } break; case 20: // at bottom edge, ready to travel up NX_LOG("ai_block_movev - state 20.\n"); if (((py > objy) && (py - objy) < 0x3200) || \ ((py < objy) && (objy - py) < 0x32000)) { if (pdistlx(0x3200)) { o->state = 30; o->timer = 0; } } break; case 30: // traveling NX_LOG("ai_block_movev - state 30.\n"); { YACCEL(0x20); LIMITY(0x200); // hit edge if ((o->dir == DOWN && o->blockd) || (o->dir == UP && o->blocku)) { SmokeSide(o, 4, o->dir); quake(10); o->yinertia = 0; o->dir ^= 1; o->state = (o->dir==DOWN) ? 10 : 20; } if ((++o->timer % 10) == 6) sound(SND_BLOCK_MOVE); } break; } }
void ai_block_moveh(Object *o) { int px = player->CenterX(); int objx = o->CenterX(); switch(o->state) { case 0: NX_LOG("ai_block_moveh - state 0.\n"); o->flags |= FLAG_SOLID_BRICK; o->smushdamage = 100; o->state = (o->dir == LEFT) ? 10:20; break; case 10: // at right edge, ready to travel left NX_LOG("ai_block_moveh - state 10.\n"); if (((px > objx) && (px - objx) < 0x3200) || \ ((px < objx) && (objx - px) < 0x32000)) { if (pdistly(0x3200)) { o->state = 30; o->timer = 0; } } break; case 20: // at left edge, ready to travel right NX_LOG("ai_block_moveh - state 20.\n"); if (((px > objx) && (px - objx) < 0x32000) || \ ((px < objx) && (objx - px) < 0x3200)) { if (pdistly(0x3200)) { o->state = 30; o->timer = 0; } } break; case 30: // traveling { NX_LOG("ai_block_moveh - state 30.\n"); XACCEL(0x20); LIMITX(0x200); // hit edge if ((o->dir == RIGHT && o->blockr) || (o->dir == LEFT && o->blockl)) { SmokeSide(o, 4, o->dir); quake(10); o->xinertia = 0; o->dir ^= 1; o->state = (o->dir==LEFT) ? 10 : 20; } if ((++o->timer % 10) == 6) sound(SND_BLOCK_MOVE); } break; } }
void pre_main(void) { #ifdef DEBUG_LOG char debug_fname[1024]; retro_create_path_string(debug_fname, sizeof(debug_fname), g_dir, "debug.txt"); SetLogFilename(debug_fname); #endif // start up inputs first thing because settings_load may remap them input_init(); // load settings, or at least get the defaults, // so we know the initial screen resolution. settings_load(); char filename[1024]; FILE *fp; NX_LOG("= Extracting Files =\n"); retro_create_path_string(filename, sizeof(filename), g_dir, "Doukutsu.exe"); fp = fopen(filename, "rb"); extract_files(fp); if (sound_init()) { fatal("Failed to initialize sound."); error = 1; return; } extract_stages(fp); fclose(fp); settings->files_extracted = true; settings_save(); if (Graphics::init(settings->resolution)) { NX_ERR("Failed to initialize graphics.\n"); error = 1; return; } if (font_init()) { NX_ERR("Failed to load font.\n"); error = 1; return; } //return; if (check_data_exists()) { error = 1; return; } //Graphics::ShowLoadingScreen(); if (trig_init()) { fatal("Failed trig module init."); error = 1; return; } if (tsc_init()) { fatal("Failed to initialize script engine."); error = 1; return; } if (textbox.Init()) { fatal("Failed to initialize textboxes."); error = 1; return; } if (Carets::init()) { fatal("Failed to initialize carets."); error = 1; return; } if (game.init()) { error = 1; return; } game.setmode(GM_NORMAL); // set null stage just to have something to do while we go to intro game.switchstage.mapno = 0; //#define REPLAY #ifdef REPLAY game.switchstage.mapno = START_REPLAY; //Replay::set_ffwd(6000); //Replay::set_stopat(3500); game.switchstage.param = 1; #else //game.switchstage.mapno = LOAD_GAME; //game.pause(GP_OPTIONS); if (settings->skip_intro && file_exists(GetProfileName(settings->last_save_slot))) game.switchstage.mapno = LOAD_GAME; else game.setmode(GM_INTRO); #endif // for debug if (game.paused) { game.switchstage.mapno = 0; game.switchstage.eventonentry = 0; } if (game.switchstage.mapno == LOAD_GAME) inhibit_loadfade = true; game.running = true; freshstart = true; NX_LOG("Entering main loop...\n"); //return; }
bool extract_pxt(FILE *fp) { struct { union { int intvalue; double fpvalue; } values[50]; } chan[4]; int s, c, i; char slash; #ifdef _WIN32 slash = '\\'; #else slash = '/'; #endif for(s=0;;s++) { if (!snd[s].id) break; char outfilename[MAXPATHLEN]; char outpath[MAXPATHLEN]; snprintf(outfilename, sizeof(outfilename), "%s%cpxt%cfx%02x.pxt", g_dir, slash, slash, snd[s].id); snprintf(outpath, sizeof(outpath), "%s%cpxt", g_dir, slash); NX_LOG("[ %s ]\n", outfilename); #if defined(_WIN32) _mkdir(outpath); #else mkdir(outpath, 0755); #endif FILE *fpo = fopen(outfilename, "wb"); if (!fpo) { NX_ERR("failed to open %s\n", outfilename); return 1; } fseek(fp, snd[s].offset, SEEK_SET); memset(chan, 0, sizeof(chan)); // load data for(c=0;c<snd[s].nchanl;c++) { for(i=0;fields[i].name;i++) { if (fields[i].is_integer) { chan[c].values[i].intvalue = fgetl(fp); } else { chan[c].values[i].fpvalue = fgetfloat(fp); } } // skip padding between sections if (fgetl(fp) != 0) { NX_ERR("PXT out of sync\n"); return 1; } } // write human-readable section for(c=0;c<4;c++) { for(i=0;fields[i].name;i++) { if (fields[i].is_integer) fprintf(fpo, "%s:%d\r\n", fields[i].name, chan[c].values[i].intvalue); else fprintf(fpo, "%s:%.2f\r\n", fields[i].name, chan[c].values[i].fpvalue); } fprintf(fpo, "\r\n"); } // write machine-readable section for(c=0;c<4;c++) { fprintf(fpo, "{"); for(i=0;fields[i].name;i++) { const char *suffix = (fields[i+1].name == NULL) ? "},\r\n" : ","; if (fields[i].is_integer) fprintf(fpo, "%d%s", chan[c].values[i].intvalue, suffix); else fprintf(fpo, "%.2f%s", chan[c].values[i].fpvalue, suffix); } } fclose(fpo); } return 0; }
bool SIFSpritesSect::Decode(const uint8_t *data, int datalen, \ SIFSprite *sprites, int *nsprites_out, int maxsprites) { const uint8_t *data_end = data + (datalen - 1); int i, f, nsprites; nsprites = read_U16(&data, data_end); if (nsprites_out) *nsprites_out = nsprites; if (nsprites >= maxsprites) { NX_ERR("SIFSpritesSect::Decode: too many sprites in file (nsprites=%d, maxsprites=%d)\n", nsprites, maxsprites); return 1; } NX_LOG("SIFSpritesSect: loading %d sprites\n", nsprites); for(i=0;i<nsprites;i++) { if (data > data_end) { NX_ERR("SIFSpritesSect::Decode: section corrupt: overran end of data\n"); return 1; } // read sprite-level fields sprites[i].w = read_U8(&data, data_end); sprites[i].h = read_U8(&data, data_end); sprites[i].spritesheet = read_U8(&data, data_end); sprites[i].nframes = read_U8(&data, data_end); sprites[i].ndirs = read_U8(&data, data_end); if (sprites[i].ndirs > SIF_MAX_DIRS) { NX_ERR("SIFSpritesSect::Decode: SIF_MAX_DIRS exceeded on sprite %d (ndirs=%d)\n", i, sprites[i].ndirs); return 1; } LoadRect(&sprites[i].bbox, &data, data_end); LoadRect(&sprites[i].solidbox, &data, data_end); LoadPoint(&sprites[i].spawn_point, &data, data_end); LoadPointList(&sprites[i].block_l, &data, data_end); LoadPointList(&sprites[i].block_r, &data, data_end); LoadPointList(&sprites[i].block_u, &data, data_end); LoadPointList(&sprites[i].block_d, &data, data_end); // malloc enough space to hold the specified number // of apple fritters, i mean, frames. sprites[i].frame = (SIFFrame *)malloc(sizeof(SIFFrame) * sprites[i].nframes); // then load all frames for(f=0;f<sprites[i].nframes;f++) { if (LoadFrame(&sprites[i].frame[f], sprites[i].ndirs, &data, data_end)) return 1; } } return 0; }
char org_load(int songno) { static const char *magic = "Org-02"; char buf[8]; char *f; char **fp; int i, j; f = org_data[songno]; fp = &f; if (!fp) { NX_WARN("org_load: no such file: '%d'\n", songno); return 1; } for(i=0;i<6;i++) { buf[i] = mgetc(fp); } buf[i] = 0; if (strcmp(buf, magic)) { NX_WARN("org-load: not an org file (got '%s')\n", buf); //fclose(fp); return 1; } NX_LOG("%d: %s detected\n", songno, magic); //fseek(fp, 0x06, SEEK_SET); song.ms_per_beat = mgeti(fp); song.steps_per_bar = mgetc(fp); song.beats_per_step = mgetc(fp); song.loop_start = mgetl(fp); song.loop_end = mgetl(fp); //song.ms_per_beat = 500; //song.loop_start = 64; if (song.loop_end < song.loop_start) { visible_warning("org_load: loop end is before loop start"); //fclose(fp); return 1; } // compute how long the last beat of a note should be (it should not use up the whole beat) song.ms_of_last_beat_of_note = song.ms_per_beat - (int)((double)song.ms_per_beat * 0.1); // not actually used in this module, but the larger program might want to know this song.beats_per_bar = (song.beats_per_step * song.steps_per_bar); /*lprintf("tempo: %d ms/beat\n", song.ms_per_beat); lprintf("beats_per_step: %d\n", song.beats_per_step); lprintf("steps_per_bar: %d\n", song.steps_per_bar); lprintf("loop begins on beat %d\n", song.loop_start); lprintf("loop ends on beat %d\n", song.loop_end);*/ for(i=0;i<16;i++) { song.instrument[i].pitch = mgeti(fp); song.instrument[i].wave = mgetc(fp); song.instrument[i].pi = mgetc(fp); song.instrument[i].nnotes = mgeti(fp); if (song.instrument[i].nnotes >= MAX_SONG_LENGTH) { visible_warning(" * org_load: instrument %d has too many notes! (has %d, max %d)", i, song.instrument[i].nnotes, MAX_SONG_LENGTH); //fclose(fp); return 1; } /*if (song.instrument[i].nnotes) { lprintf("Instrument %d: ", i); lprintf(" Pitch: %d, ", song.instrument[i].pitch); lprintf(" Wave: %d, ", song.instrument[i].wave); lprintf(" Pi: %d, ", song.instrument[i].pi); lprintf(" Nnotes: %d\n", song.instrument[i].nnotes); }*/ // substitute unavailable drums // credits track for one, has Per02 set which CS didn't actually have, I don't think if (i >= 8) { switch(song.instrument[i].wave) { case 9: song.instrument[i].wave = 8; break; } } } for(i=0;i<16;i++) { for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].beat = mgetl(fp); for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].note = mgetc(fp); for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].length = mgetc(fp); for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].volume = mgetc(fp); for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].panning = mgetc(fp); } //fclose(fp); return init_buffers(); }
void org_fade(void) { NX_LOG("org_fade\n"); song.fading = true; song.last_fade_time = 0; }
bool run_main(void) { if (in_gameloop) goto loop; // SSS/SPS persists across stage transitions until explicitly // stopped, or you die & reload. It seems a bit risky to me, // but that's the spec. if (game.switchstage.mapno >= MAPNO_SPECIALS) { StopLoopSounds(); } // enter next stage, whatever it may be if (game.switchstage.mapno == LOAD_GAME || \ game.switchstage.mapno == LOAD_GAME_FROM_MENU) { if (game.switchstage.mapno == LOAD_GAME_FROM_MENU) freshstart = true; NX_LOG("= Loading game =\n"); if (game_load(settings->last_save_slot)) { fatal("savefile error"); game.running = false; error = 1; return false; } Replay::OnGameStarting(); if (!inhibit_loadfade) fade.Start(FADE_IN, FADE_CENTER); else inhibit_loadfade = false; } else if (game.switchstage.mapno == START_REPLAY) { NX_LOG(">> beginning replay '%s'\n", GetReplayName(game.switchstage.param)); StopScripts(); if (Replay::begin_playback(GetReplayName(game.switchstage.param))) { fatal("error starting playback"); game.running = false; error = 1; return false; } } else { if (game.switchstage.mapno == NEW_GAME || \ game.switchstage.mapno == NEW_GAME_FROM_MENU) { static bool show_intro = (game.switchstage.mapno == NEW_GAME_FROM_MENU); InitNewGame(show_intro); } // slide weapon bar on first intro to Start Point if (game.switchstage.mapno == STAGE_START_POINT && \ game.switchstage.eventonentry == 91) { freshstart = true; } // switch maps if (load_stage(game.switchstage.mapno)) { game.running = false; error = 1; return false; } player->x = (game.switchstage.playerx * TILE_W) << CSF; player->y = (game.switchstage.playery * TILE_H) << CSF; } // start the level if (game.initlevel()) { game.running = false; error = 1; return false; } if (freshstart) weapon_introslide(); game.switchstage.mapno = -1; loop: in_gameloop = true; if (gameloop()) return true; in_gameloop = false; game.stageboss.OnMapExit(); freshstart = false; }
bool extract_files(FILE *exefp) { uint8_t *buffer; uint8_t *file; uint32_t length; uint32_t crc; bool check_crc = true; bool first_crc_failure = true; buffer = (uint8_t *)malloc(MAX_FILE_SIZE); crc_init(); for(int i=0;;i++) { if (!files[i].filename) break; char outfilename[1024]; retro_create_path_string(outfilename, sizeof(outfilename), g_dir, files[i].filename); NX_LOG("[ %s ]\n", outfilename); // initialize header if any file = buffer; length = files[i].length; if (files[i].header) { memcpy(buffer, files[i].header, HEADER_LEN); file += HEADER_LEN; length += HEADER_LEN; } // read data from exe fseek(exefp, files[i].offset, SEEK_SET); fread(file, files[i].length, 1, exefp); if (check_crc) { crc = crc_calc(file, files[i].length); if (crc != files[i].crc) { NX_ERR("File '%s' failed CRC check.\n", outfilename); NX_ERR("\n"); NX_ERR("[I]gnore\n"); NX_ERR("Ignore [A]ll\n"); NX_ERR("[S]top\n"); #define IGNORE_BTN SDLK_i #define IGNORE_ALL_BTN SDLK_a #define STOP_BTN SDLK_s first_crc_failure = false; } } // write out the file createdir(outfilename); FILE *fp = fopen(outfilename, "wb"); if (!fp) { NX_ERR("Failed to open '%s' for writing.\n", outfilename); free(buffer); return 1; } fwrite(buffer, length, 1, fp); fclose(fp); } free(buffer); return 0; }