diff options
Diffstat (limited to 'src/game.c')
-rw-r--r-- | src/game.c | 1678 |
1 files changed, 1678 insertions, 0 deletions
diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..4234f50 --- /dev/null +++ b/src/game.c @@ -0,0 +1,1678 @@ +#include "game.h" +#include "hero.h" +#include "PHL.h" +#include "qda.h" +#include "ini.h" +#include "titlescreen.h" +#include "options.h" +#include "inventory.h" +#include "object.h" +#include "effect.h" +#include "text.h" +#include "stagedata.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int gameStep(); +void gameDraw(char doDrawHud); + +void freeArrays(); +void drawHud(); +int getTileType(int valx, int valy); + +void loadUncommonImages(); + +char forceGameExit = 0; + +int drawhp; +int NumOfSounds = 43; +int NumOfImages = 14; + +char autoSave = 1; +int levelStartFlag = 0; + +char tilesetStrings[9][12] = {"stage01.bmp", + "stage02.bmp", + "stage02.bmp", + "stage03.bmp", + "stage04.bmp", + "stage03.bmp", + "stage02.bmp", + "stage05.bmp", + "stage08.bmp" }; + +char musicStrings[9][14] = { "midi/main01", + "midi/main02", + "midi/main02", + "midi/main05", + "midi/main03", + "midi/main05", + "midi/main02", + "midi/main04", + "midi/main06" }; + + + +double cutInTimer = 240; +int transitionTimer = 0; +int level = 0; +int screenX = 5, + screenY = 2; + +#ifdef _SDL +char savename[4096]; +#else +#define savename "data/save.tmp" +#endif + +void game() +{ +#ifdef _SDL + const char* home = getenv("HOME"); + if(home) + { + strcpy(savename, home); + strcat(savename, "/.hydracastlelabyrinth/"); + strcat(savename, "save.tmp"); + } else { + strcpy(savename, "data/save.tmp"); + } +#endif + //Setup services + PHL_Init(); + initQDA(); + textInit(); + iniInit(); + + //Load Resources + loadText(); + loadResources(); + + while (PHL_MainLoop()) + { + //Titlescreen + int titleScreenResult = titleScreen(); + + //Exit game + if (titleScreenResult == 2) { + PHL_GameQuit(); + } + + //Game Start + else{ + //Reset game state + gameSetup(); + + //Load Game + if (titleScreenResult == 1) + { + if (fileExists(savename) == 1) { + loadSave(savename); + }else if (fileExists("map/018.map") == 1) { + loadSave("map/018.map"); + } + } + + //Update resources, depending on level + loadUncommonImages(); + + /*printf("\nTiles are "); + if (images[imgTiles].pxdata == NULL) { + printf("not loaded."); + }else{ + printf("loaded."); + }*/ + PHL_FreeSurface(images[imgTiles]); + images[imgTiles] = PHL_LoadQDA(tilesetStrings[level]); + + PHL_FreeMusic(bgmMusic); + bgmMusic = PHL_LoadMusic(musicStrings[level], 1); + + loadScreen(); + + //In game main loop + char gameLoop = 1; + + while (PHL_MainLoop() == 1 && gameLoop == 1) { + PHL_ScanInput(); + + int gameResult = gameStep(); + + if (gameResult != -1) { + gameLoop = 0; + } + + if (gameLoop == 1) { + PHL_StartDrawing(); + gameDraw(1); + PHL_EndDrawing(); + } + } + + //Game end (return to titlescreen) + roomDarkness = 0; + freeArrays(); + + //Erase temp save if it exists + if (fileExists(savename)) + { + #ifdef _SDL + remove(savename); + #else + char fullPath[128]; + strcpy(fullPath, ""); + #ifdef _3DS + strcat(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/"); + #endif + strcat(fullPath, savename); + remove(fullPath); + #endif + } + } + } + + //Free Resources + textFree(); + freeResources(); + + //Deinit services + PHL_Deinit(); +} + +void loadResources() +{ + //Loading Images + images[imgTiles] = PHL_LoadQDA(tilesetStrings[level]); + images[imgEnemies] = PHL_LoadQDA("ene01.bmp"); + images[imgHud] = PHL_LoadQDA("status.bmp"); + images[imgMisc20] = PHL_LoadQDA("chr20.BMP"); + images[imgMisc32] = PHL_LoadQDA("chr32.BMP"); + images[imgHero] = PHL_LoadQDA("mychr.bmp"); + images[imgItems] = PHL_LoadQDA("items.bmp"); + images[imgExplosion] = PHL_LoadQDA("chr64.BMP"); + images[imgBoss] = PHL_LoadQDA("boss01.bmp"); + //images[imgMisc2040] = PHL_LoadQDA("chr20x40.BMP"); + images[imgFontKana] = PHL_LoadQDA("font8x8-kana.bmp"); + images[imgBoldFont] = PHL_LoadQDA("font8x8-01.bmp"); + //images[imgDark] = PHL_LoadQDA("dark.bmp"); + //images[imgMisc6020] = PHL_LoadQDA("chr60x20.bmp"); + //images[imgHud].colorKey = PHL_NewRGB(0, 0, 0); + //PHL_SetColorKey(images[imgHud], 0, 0, 0); + images[imgTitle01] = PHL_LoadQDA("title01.BMP"); + + //Load Sounds + sounds[sndBee01] = PHL_LoadSound("wav/bee01.wav"); + sounds[sndBell01] = PHL_LoadSound("wav/bell01.wav"); + sounds[sndBom01] = PHL_LoadSound("wav/bom01.wav"); + sounds[sndBom02] = PHL_LoadSound("wav/bom02.wav"); + sounds[sndBom03] = PHL_LoadSound("wav/bom03.wav"); + sounds[sndDoor00] = PHL_LoadSound("wav/door00.wav"); + sounds[sndFire01] = PHL_LoadSound("wav/fire01.wav"); + sounds[sndGas01] = PHL_LoadSound("wav/gas01.wav"); + sounds[sndGet01] = PHL_LoadSound("wav/get01.wav"); + sounds[sndGet02] = PHL_LoadSound("wav/get02.wav"); + sounds[sndHit01] = PHL_LoadSound("wav/hit01.wav"); + sounds[sndHit02] = PHL_LoadSound("wav/hit02.wav"); + sounds[sndHit03] = PHL_LoadSound("wav/hit03.wav"); + sounds[sndHit04] = PHL_LoadSound("wav/hit04.wav"); + sounds[sndHit05] = PHL_LoadSound("wav/hit05.wav"); + sounds[sndHit06] = PHL_LoadSound("wav/hit06.wav"); + sounds[sndHit07] = PHL_LoadSound("wav/hit07.wav"); + sounds[sndJump01] = PHL_LoadSound("wav/jump01.wav"); + sounds[sndJump02] = PHL_LoadSound("wav/jump02.wav"); + sounds[sndNg] = PHL_LoadSound("wav/ng.wav"); + sounds[sndOk] = PHL_LoadSound("wav/ok.wav"); + sounds[sndPi01] = PHL_LoadSound("wav/pi01.wav"); + sounds[sndPi02] = PHL_LoadSound("wav/pi02.wav"); + sounds[sndPi03] = PHL_LoadSound("wav/pi03.wav"); + sounds[sndPi04] = PHL_LoadSound("wav/pi04.wav"); + sounds[sndPi05] = PHL_LoadSound("wav/pi05.wav"); + sounds[sndPi06] = PHL_LoadSound("wav/pi06.wav"); + sounds[sndPi07] = PHL_LoadSound("wav/pi07.wav"); + sounds[sndPi08] = PHL_LoadSound("wav/pi08.wav"); + sounds[sndPi09] = PHL_LoadSound("wav/pi09.wav"); + sounds[sndPi10] = PHL_LoadSound("wav/pi10.wav"); + sounds[sndPower01] = PHL_LoadSound("wav/power01.wav"); + sounds[sndPower02] = PHL_LoadSound("wav/power02.wav"); + sounds[sndShot01] = PHL_LoadSound("wav/shot01.wav"); + sounds[sndShot02] = PHL_LoadSound("wav/shot02.wav"); + sounds[sndShot03] = PHL_LoadSound("wav/shot03.wav"); + sounds[sndShot04] = PHL_LoadSound("wav/shot04.wav"); + sounds[sndShot05] = PHL_LoadSound("wav/shot05.wav"); + sounds[sndShot06] = PHL_LoadSound("wav/shot06.wav"); + sounds[sndShot07] = PHL_LoadSound("wav/shot07.wav"); + sounds[sndStep01] = PHL_LoadSound("wav/step01.wav"); + sounds[sndWater01] = PHL_LoadSound("wav/water01.wav"); + sounds[sndWolf01] = PHL_LoadSound("wav/wolf01.wav"); + + //Load Music + bgmSecret = PHL_LoadMusic("midi/nazo", 0); + bgmGameover = PHL_LoadMusic("midi/gameover", 0); +} + +void freeResources() +{ + //Free sounds + int i; + for (i = 0; i < NumOfSounds; i++) { + PHL_FreeSound(sounds[i]); + } + + //Free Music + PHL_FreeMusic(bgmMusic); + PHL_FreeMusic(bgmGameover); + PHL_FreeMusic(bgmSecret); + + //Free graphics + for (i = 0; i < NumOfImages; i++) { + PHL_FreeSurface(images[i]); + } +} + +void gameSetup() +{ + //Reset Flags + { + quakeTimer = 0; + secretTimer = 0; + roomDarkness = 0; + + bellFlag = 0; + bossFlag = 0; + bossDefeatedFlag = 0; + + int i; + for (i = 0; i < 60; i++) { + flags[i] = 0; + } + } + + //Save Data + { + playTime = 0; + + //Inventory + int i; + for (i = 0; i < 5; i++) { + hasWeapon[i] = 0; + } + + for (i = 0; i < 28; i++) { + hasItem[i] = 0; + } + + for (i = 0; i< 8; i++) { + hasKey[i] = 0; + } + } + + //Room Data + { + roomSecret = 0; + level = 0; + screenX = 5; + screenY = 2; + } + + //Hero Setup + { + heroSetup(); + drawhp = herohp; + } + + //Reset object arrays + freeArrays(); + + //Setup screen transition + cutInTimer = 240; +} + +int gameStep() +{ + //Manage Timers + { + playTime += 1; + + secretCountdown(); + + if (quakeTimer > 0) { + quakeTimer -= 1; + } + + if (cutInTimer > 0) { + cutInTimer -= 5; + + //Play music when the transition ends + if (cutInTimer <= 0 && bossDefeatedFlag == 0 && bossFlag == 0) { + PHL_PlayMusic(bgmMusic); + } + } + } + + //Hero step + { + //End game if hero died + if (heroStep() == 1) { + return 0; + } + } + + //Menu button presses + { + if (getHeroState() <= 5 && cutInTimer <= 0) { + if (btnSelect.pressed == 1) + { + int optionsResult = options(); + + //Reset Game + if (optionsResult == 1) { + return 0; + } + //Exit Game + if (optionsResult == 3) { + PHL_GameQuit(); + return 1; + } + }else if (btnStart.pressed == 1) { + inventory(); + } + } + } + + //Objects steps + { + int i; + for (i = 0; i < MAX_PLATFORMS; i++) { + if (platforms[i] != NULL) { + platformStep(platforms[i]); + } + } + + for (i = 0; i < MAX_OBJECTS; i++) { + if (objects[i] != NULL) { + objects[i]->objectStep(objects[i]->data); + } + } + + for (i = 0; i < MAX_WEAPONS; i++) { + if (weapons[i] != NULL) { + weaponStep(weapons[i]); + } + } + + for (i = 0; i < MAX_EFFECTS; i++) { + if (effects[i] != NULL) { + effectStep(effects[i]); + } + } + + for (i = 0; i < MAX_ENEMIES; i++) { + if (enemies[i] != NULL) { + enemies[i]->enemyStep(enemies[i]->data); + } + } + } + + if (forceGameExit == 1) { + forceGameExit = 0; + return 0; + } + + return -1; +} + +void gameDraw(char doDrawHud) +{ + PHL_DrawBackground(background, foreground); + + int i; + //Draw water/lava top effects + for (i = 0; i < MAX_EFFECTS; i++) { + if (effects[i] != NULL) { + if (effects[i]->depth == -1) { + effectDraw(effects[i]); + } + } + } + + for (i = 0; i < MAX_PLATFORMS; i++) { + if (platforms[i] != NULL) { + platformDraw(platforms[i]); + } + } + + for (i = 0; i < MAX_OBJECTS; i++) { + if (objects[i] != NULL) { + objects[i]->objectDraw(objects[i]->data); + } + } + + for (i = 0; i < MAX_WEAPONS; i++) { + if (weapons[i] != NULL) { + weaponDraw(weapons[i]); + } + } + + //Draw effects under + for (i = 0; i < MAX_EFFECTS; i++) { + if (effects[i] != NULL) { + if (effects[i]->depth == 0) { + effectDraw(effects[i]); + } + } + } + + //Draw enemies backwards, so bullets and such are underneath their spawners + //for (i = MAX_ENEMIES - 1; i >= 0; i--) { + for (i = 0; i < MAX_ENEMIES; i++) { + if (enemies[i] != NULL) { + enemies[i]->enemyDraw(enemies[i]->data); + } + } + + //Not Death, draw death later + if (getHeroState() != 8) { + heroDraw(); + } + + //Draw effects over + for (i = 0; i < MAX_EFFECTS; i++) { + if (effects[i] != NULL) { + if (effects[i]->depth == 1) { + effectDraw(effects[i]); + } + } + } + + //Draw Darkness + if (roomDarkness == 1) { + int cornerX = herox - 160, + cornerY = heroy + 20 - 160; + + PHL_DrawSurfacePart(cornerX, cornerY, 320 * hasItem[18], 0, 320, 320, images[imgDark]); + + //Top darkness rectangle + if (cornerY > 0) { + PHL_DrawRect(0, 0, 640, cornerY, PHL_NewRGB(10, 0, 0)); + } + //Bottom darkness rectangle + if (cornerY + 320 < 480) { + PHL_DrawRect(0, cornerY + 320, 640, 480, PHL_NewRGB(10, 0, 0)); + } + + //Left rectangle + if (cornerX > 0) { + PHL_DrawRect(0, cornerY, cornerX, 320, PHL_NewRGB(10, 0, 0)); + } + //Right rectangle + if (cornerX + 320 < 640) { + PHL_DrawRect(cornerX + 320, cornerY, 640 - cornerX + 320, 320, PHL_NewRGB(10, 0, 0)); + } + } + + //Draw death over darkness + if (getHeroState() == 8) { + heroDraw(); + } + + if (doDrawHud == 1) { + drawHud(); + } + + //cut-in transition + { + if (cutInTimer > 0) { + PHL_DrawRect(0, 0, 640, cutInTimer, PHL_NewRGB(0, 0, 0)); + PHL_DrawRect(0, 240 + (240 - cutInTimer), 640, 480, PHL_NewRGB(0, 0, 0)); + } + } + +} + +void getItem(int itemNum) +{ + setHeroState(6); + setHeroImageIndex(0); + + char getItemTimer = 0; + char loop = 1; + + while (PHL_MainLoop() && loop == 1) + { + secretCountdown(); + //Get Item Step + if (getItemTimer == 0) { + setHeroImageIndex(getHeroImageIndex() + 0.3); + if (getHeroImageIndex() > 3) { + getItemTimer = 1; + } + }else if (getItemTimer == 1) { + //Wait for input + PHL_ScanInput(); + + if (btnAccept.pressed == 1 || btnFaceDown.pressed == 1 || btnFaceRight.pressed == 1 || + btnFaceUp.pressed == 1 || btnFaceLeft.pressed == 1 || btnStart.pressed == 1) { + getItemTimer = 2; + } + }else if (getItemTimer == 2) { + setHeroImageIndex(getHeroImageIndex() + 0.3); + if (getHeroImageIndex() >= 7) { + loop = 0; + + setHeroState(0); + setHeroImageIndex(0); + } + } + + //Get Item Draw + { + PHL_StartDrawing(); + + gameDraw(1); + + if (getHeroImageIndex() >= 3) { + char tempDarkness = roomDarkness; + roomDarkness = 0; + + PHL_DrawRect(140, 208, 360, 64, PHL_NewRGB(255, 255, 255)); + PHL_DrawRect(142, 210, 356, 60, PHL_NewRGB(0, 20, 0)); + + PHL_DrawRect(148, 216, 48, 48, PHL_NewRGB(255, 255, 255)); + PHL_DrawRect(152, 220, 40, 40, PHL_NewRGB(119, 166, 219)); + //Image + PHL_DrawSurfacePart(152, 220, itemGotX, itemGotY, 40, 40, images[imgItems]); + //Text + { + int drawX = 196, drawY = 216; + int twoLayers = 0; + if (itemName[itemNum]->length + found->length + 2 > 17) { + twoLayers = 1; + drawY -= 8; + } + drawX = drawCharacter(17, 2, drawX, drawY); + drawX = drawText(itemName[itemNum], drawX, drawY); + drawX = drawCharacter(18, 2, drawX, drawY); + if (twoLayers == 1) { + drawX = 204; + drawY += 24; + } + drawText(found, drawX, drawY); + } + + roomDarkness = tempDarkness; + } + + PHL_EndDrawing(); + } + } +} + +void saveScreen() +{ + PHL_PlaySound(sounds[sndPower02], CHN_SOUND); + herohp = maxhp; + setHeroHsp(0); + + int saveTimer = 60; + char loop = 1; + + while (PHL_MainLoop() && loop == 1) + { + PHL_StartDrawing(); + + gameDraw(1); + + PHL_DrawRect(140, 208, 360, 64, PHL_NewRGB(255, 255, 255)); + PHL_DrawRect(142, 210, 356, 60, PHL_NewRGB(0, 0, 255)); + drawTextCentered(saving, 320, 216); + + saveTimer -= 1; + if (saveTimer <= 0) { + loop = 0; + } + + PHL_EndDrawing(); + } + + if (writeSave("map/018.map") == 1) + { + if (fileExists(savename)) + { + char fullPath[128]; + strcpy(fullPath, ""); + #ifdef _3DS + strcat(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/"); + #endif + strcat(fullPath, savename); + remove(fullPath); + } + } +} + +//Result screen and credits +void gameEnding() +{ + int timer = 0; + char exitLoop = 0; + + //Result screen + { + PHL_StopMusic(); + PHL_FreeMusic(bgmMusic); + bgmMusic = PHL_LoadMusic("midi/allclear", 0); + PHL_PlayMusic(bgmMusic); + + //Calculate completion percentage + char treasureString[10]; + { + int itemCount = 0; + int ALLITEMS = 41; + + int i; + for (i = 0; i < 5; i++) { + itemCount += hasWeapon[i]; + } + + for (i = 0; i < 28; i++) { + itemCount += hasItem[i]; + } + + for (i = 0; i < 8; i++) { + itemCount += hasKey[i]; + } + + sprintf(treasureString, "%d%%", itemCount * 100 / ALLITEMS); + } + + //Calculate time + char timeString[9]; + { + int hours = playTime / 216000; + int minutes = (playTime % 216000) / 3600; + int seconds = ((playTime % 216000) % 3600) / 60; + + sprintf(timeString, "%02d:%02d:%02d", hours, minutes, seconds); + } + + int transTimer = 0; + + while (PHL_MainLoop() && exitLoop == 0) + { + timer += 1; + if (timer >= 500) { + transTimer += 8; + } + + if (transTimer >= 360) { + exitLoop = 1; + } + + //Animate Effects + int i; + for (i = 0; i < MAX_EFFECTS; i++) { + if (effects[i] != NULL) { + effectStep(effects[i]); + } + } + + PHL_StartDrawing(); + + gameDraw(0); + + PHL_DrawTextBoldCentered("--- ALL CLEAR! ---", 320, 64, YELLOW); + + PHL_DrawTextBoldCentered("TIME", 320, 128, YELLOW); + PHL_DrawTextBoldCentered(timeString, 320, 144, WHITE); + + PHL_DrawTextBoldCentered("TREASURE", 320, 192, YELLOW); + PHL_DrawTextBoldCentered(treasureString, 320, 208, WHITE); + + //transition + if (transTimer > 0) { + PHL_DrawRect(0, 0, 640, transTimer, PHL_NewRGB(0, 0, 0)); + PHL_DrawRect(0, 240 + (240 - transTimer), 640, 480, PHL_NewRGB(0, 0, 0)); + } + + PHL_EndDrawing(); + } + } + + //Credits + { + timer = 0; + exitLoop = 0; + + PHL_StopMusic(); + PHL_FreeMusic(bgmMusic); + bgmMusic = PHL_LoadMusic("midi/ending", 0); + PHL_PlayMusic(bgmMusic); + + int timer = 0; + double viewY = 0; + int maxViewY = 2200; + double imageIndex = 0; + + while (PHL_MainLoop() && exitLoop == 0) + { + timer += 1; + if (timer >= 2220) { + exitLoop = 1; + } + + viewY += 1; + if (viewY >= maxViewY - 480) { + viewY = maxViewY - 480; + } + + imageIndex += 0.1; + if (imageIndex >= 2) { + imageIndex -= 2; + } + + PHL_StartDrawing(); + + PHL_DrawRect(0, 0, 640, 480, PHL_NewRGB(0, 0, 0)); + + if (exitLoop == 0) { + PHL_DrawTextBoldCentered("- STAFF -", 320, 480 - viewY, YELLOW); + + PHL_DrawTextBoldCentered("SPRITES", 320, 560 - viewY, YELLOW); + PHL_DrawTextBoldCentered("BUSTER", 320, 576 - viewY, WHITE); + + PHL_DrawTextBoldCentered("PROGRAM", 320, 640 - viewY, YELLOW); + PHL_DrawTextBoldCentered("BUSTER", 320, 656 - viewY, WHITE); + + PHL_DrawTextBoldCentered("MUSIC", 320, 720 - viewY, YELLOW); + PHL_DrawTextBoldCentered("MATAJUUROU", 320, 736 - viewY, WHITE); + + PHL_DrawTextBoldCentered("TEST PLAYER", 320, 800 - viewY, YELLOW); + PHL_DrawTextBoldCentered("ZAC", 320, 816 - viewY, WHITE); + + PHL_DrawTextBoldCentered("- SPECIAL THANKS -", 320, 912 - viewY, YELLOW); + + PHL_DrawTextBoldCentered("QUADRUPLE D", 320, 992 - viewY, YELLOW); + PHL_DrawTextBoldCentered("SANDMAN", 320, 1008 - viewY, WHITE); + + PHL_DrawTextBoldCentered("KBGM", 320, 1072 - viewY, YELLOW); + PHL_DrawTextBoldCentered("KR.SHIN", 320, 1088 - viewY, WHITE); + + PHL_DrawTextBoldCentered("KBGMPLAYER", 320, 1152 - viewY, YELLOW); + PHL_DrawTextBoldCentered("NARUTO", 320, 1168 - viewY, WHITE); + + PHL_DrawTextBoldCentered("SOUND EFFECT", 320, 1232 - viewY, YELLOW); + PHL_DrawTextBoldCentered("OSABISHIYUUKI", 320, 1248 - viewY, WHITE); + + PHL_DrawTextBoldCentered("EDGE", 320, 1312 - viewY, YELLOW); + PHL_DrawTextBoldCentered("TAKABO", 320, 1328 - viewY, WHITE); + + PHL_DrawTextBoldCentered("THE END", 320, maxViewY - 284 - viewY, YELLOW); + PHL_DrawSurfacePart(300, maxViewY - 256 - viewY, (int)imageIndex * 40, 280, 40, 80, images[imgHero]); + } + + PHL_EndDrawing(); + } + + } + + forceGameExit = 1; + +} + +//Black screen between screens +void screenTransition() +{ + char timer = 15; + + while (PHL_MainLoop() && timer > 0) + { + PHL_StartDrawing(); + + PHL_DrawRect(0, 0, 640, 480, PHL_NewRGB(0, 0, 0)); + timer -= 1; + + PHL_EndDrawing(); + } + + if (autoSave == 1) { + writeSave(savename); + } +} + +void enterDoor() +{ + //Is not leaving boss room prematurely + bossFlag = 0; + + level = lastDoor->warplevel; + + screenX = lastDoor->warpcoords % 12; + screenY = lastDoor->warpcoords / 12; + + herox = lastDoor->warpx; + heroy = lastDoor->warpy; + + PHL_StopMusic(); + PHL_FreeMusic(bgmMusic); + + if (level == 0) { + //Free uncommon images + PHL_FreeSurface(images[imgMisc2040]); + PHL_FreeSurface(images[imgMisc6020]); + PHL_FreeSurface(images[imgDark]); + }else{ + bgmMusic = PHL_LoadMusic("midi/start", 0); + PHL_PlayMusic(bgmMusic); + + int timer = 125; + while (PHL_MainLoop() && timer > 0) + { + timer -= 1; + + PHL_StartDrawing(); + + PHL_DrawRect(0, 0, 640, 480, PHL_NewRGB(0, 0, 0)); + drawTextCentered(dungeon[level - 1], 320, 216); + + PHL_EndDrawing(); + } + + PHL_StopMusic(); + PHL_FreeMusic(bgmMusic); + + loadUncommonImages(); + } + + //Reload tileset + PHL_FreeSurface(images[imgTiles]); + images[imgTiles] = PHL_LoadQDA(tilesetStrings[level]); + + bgmMusic = PHL_LoadMusic(musicStrings[level], 1); + + changeScreen(0, 0); + + PHL_PlayMusic(bgmMusic); +} + +void loadScreen() +{ + //Stop music if you leave a boss room early + if (bossFlag == 1) { + PHL_StopMusic(); + PHL_FreeMusic(bgmMusic); + + bgmMusic = PHL_LoadMusic(musicStrings[level], 1); + PHL_PlayMusic(bgmMusic); + } + + bossDefeatedFlag = bossFlag = 0; + roomDarkness = 0; + + screenTransition(); + + int fileNum = stage[level][(screenY * 12) + screenX]; + + //Cycle through this process twice. Once for the backgroud, and one for the foreground + int cycle = 0; + for (cycle = 0; cycle < 2; cycle++) + { + //Build file string + char toChar[4]; + sprintf(toChar, "%03d", fileNum); + + char dest[80]; + strcpy(dest, ""); + #ifdef _3DS + strcat(dest, "romfs:/map/"); + #elif defined(_SDL) + strcat(dest, "data/map/"); + #else + strcat(dest, "romfs/map/"); + #endif + strcat(dest, toChar); + + //load background on first pass + if (cycle == 0) { + strcat(dest, "a"); + } + strcat(dest, ".map"); + + //Read file + FILE* file; + if ((file = fopen(dest, "rb"))) + { + char* memblock; + int size; + + fseek(file, 0, SEEK_END); + size = ftell(file); + memblock = (char*)malloc(size); + fseek(file, 0, SEEK_SET); + fread(memblock, 1, size, file); + fclose(file); + + //Load data + int count = 162; //Level data starts 118 + int xx, yy; + int valx = 0, valy = 0; + int raw; + for (yy = 0; yy < 12; yy++) { + for (xx = 0; xx < 16; xx++) { + raw = (unsigned)memblock[count]; + valx = raw & 0x0F; + valy = raw & 0xF0; + valy >>= 4; + + if (cycle == 0) { + background.tileX[xx][yy] = valx; + background.tileY[xx][yy] = valy; + }else if (cycle == 1) { + foreground.tileX[xx][yy] = valx; + foreground.tileY[xx][yy] = valy; + + collisionTiles[xx][yy] = getTileType(valx, valy); + //Breakable blocks + if (valy == 11 && (valx == 0 || valx == 1 || valx == 2)) { + int secret = 0; + if (valx == 2) { + secret = 1; + } + createDestroyable(xx * 40, yy * 40, secret); + } + + //Lava + if (valx == 2 && valy == 1) { + createEffect(10, xx * 40, yy * 40); + foreground.tileX[xx][yy] = 0; + foreground.tileY[xx][yy] = 0; + } + + //Water + if (valx == 6 && valy == 1) { + createEffect(11, xx * 40, yy * 40); + foreground.tileX[xx][yy] = 0; + foreground.tileY[xx][yy] = 0; + } + } + + count += 2; + } + count += 12; + } + + free(memblock); + + }else{ + PHL_ErrorScreen("Map file was not found"); + } + } + PHL_UpdateBackground(background, foreground); + + //Load file + //Build file string + char toChar[4]; + sprintf(toChar, "%03d", fileNum); + + char dest[30]; + #ifdef _3DS + strcpy(dest, "romfs:/obj/"); + #elif defined(_SDL) + strcpy(dest, "data/obj/"); + #else + strcpy(dest, "romfs/obj/"); + #endif + + + //Add a 0 if needed + /* + if (fileNum < 100) { + strcat(dest, "0"); + } + */ + strcat(dest, toChar); + strcat(dest, ".dat"); + + FILE* file; + if ((file = fopen(dest, "rb"))) { + unsigned char* memblock; + int size; + + fseek(file, 0, SEEK_END); + size = ftell(file); + memblock = (unsigned char*)malloc(size); + fseek(file, 0, SEEK_SET); + fread(memblock, 1, size, file); + + int count = 0; + while (count < size) { + int type = memblock[count]; + + if (type <= 10) + { + if (type == 0 || type == 9) { //Blue/Red Slime + createSlime(memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count + 4]); + } + else if (type == 1) { //Bat (grey/red) + createBat(memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3]); + } + else if (type == 2) { //Slug + createSlug(memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3]); + } + else if (type == 3) { //Knight + createKnight(memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3]); + } + else if (type == 4) { //Rhyno head + createHead(0, memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count+4], memblock[count+5]); + } + else if (type == 5) { //Dragon head + createHead(2, memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count+4], memblock[count+5]); + } + else if (type == 6) { //Goblin/medusa head + createHead(1, memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count+4], memblock[count+5]); + } + else if (type == 7) { //Demon head + createHead(3, memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count+4], memblock[count+5]); + } + else if (type == 10) { //Fireball head + createHead(4, memblock[count+1] * 20, memblock[count+2] * 20, 1, memblock[count+3], memblock[count+4]); + } + } + + else if (type <= 20) + { + if (type == 11) { //Poison Gas + createGas(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 12) { //Flying skull + createSkull(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 13) { //Fish + createFish(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 14) { //Water Jumper + createWaterJumper(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3], memblock[count+4], memblock[count+5]); + } + else if (type == 15) { //Podoboo + createPodoboo(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3], memblock[count+4]); + } + else if (type == 16) { //Thwomp + createThwomp(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3], memblock[count+4], memblock[count+5], memblock[count+6]); + } + else if (type == 17) { //Skeleton + createSkeleton(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 18) { //Ghoul + createGhoul(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 19) { //Seal + createSeal(memblock[count+1]*20, memblock[count+2]*20); + } + else if (type == 20) { //Jellyfish + createJellyfish(memblock[count+1]*20, memblock[count+2]*20); + } + } + + else if (type <= 30) + { + if (type == 21) { //Wizard + createWizard(memblock[count+1]*20, memblock[count+2]*20); + } + else if (type == 22) { //Pendulum + createPendulum(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 24) { //Bee + createBee(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 25) { //Air Jar + //createJar(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3], memblock[count+4]); + createHead(5, memblock[count + 1] * 20, memblock[count + 2] * 20, 0, memblock[count+3], memblock[count+4]); + } + else if (type == 26) { //Boar + createBoar(memblock[count+1]*20, memblock[count+2]*20); + } + else if (type == 27) { //Fire Wheel + createFirewheel(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 28) { //Rock Golem + createGolem(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 29) { //Poison Knight + createPoisonknight(memblock[count+1]*20, memblock[count+2]*20); + } + else if (type == 30) { //Electricity doggy + createDog(memblock[count+1]*20, memblock[count+2]*20); + } + } + + else if (type < 40) + { + if (type == 31) { + createBoomknight(memblock[count+1]*20, memblock[count+2]*20); + } + else if (type == 32) { + createPumpkinenemy(memblock[count+1]*20, memblock[count+2]*20); + } + } + + else if (type < 50) + { + //Bosses + if (type == 40) { + createDodo(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 41) { + createBatboss(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 42) { + createCrab(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 43) { + createGyra(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 44) { + createLolidra(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 45) { + createDevil(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 46) { + createGarm(memblock[count+1] * 20, memblock[count+2] * 20); + } + else if (type == 47) { + createHydra(memblock[count+1] * 20); + } + } + + else if (type <= 60) + { + //Objects + if (type == 50) { //Moving platforms + createPlatform(0, memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3] * 20, memblock[count + 4] * 20, memblock[count + 5], memblock[count+6]); + } + else if (type == 51) { //Loose block + createPlatform(1, memblock[count + 1] * 20, memblock[count + 2] * 20, 0, 0, 0, memblock[count+3]); + } + else if (type == 52) { //Locked Block + createLockBlock(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 53) { //Gate + createGate(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 54) { //Statue + createStatue(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 55) { //Megaman block + createPlatform(2, memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count + 4], 0, 0); + } + else if (type == 56) { //Electric gate + createShockgate(memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3]); + } + else if (type == 57) { //Hydra platform + createPlatform(3, memblock[count + 1] * 20, memblock[count + 2] * 20, 0, 0, 0, 0); + } + } + + else if (type < 70) + { + + } + + else/* if (type <= 80)*/ + { + if (type == 70) { //Breakable Block + createDestroyable(memblock[count+1] * 20, memblock[count+2] * 20, 1); + } + else if (type == 71) { //Secret Trigger + createSecretTrigger(memblock[count+1], memblock[count+2], memblock[count+3]); + } + else if (type == 73) { //Chests + createChest(memblock[count + 1] * 20, memblock[count + 2] * 20, memblock[count + 3], memblock[count + 4]); + } + else if (type == 74) { //Save Points + createSavePoint(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 75) { //door + createDoor(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3], memblock[count+4], memblock[count+5] * 20, memblock[count+6] * 20, memblock[count+7]); + } + else if (type == 76) { //Light Switch + createSwitch(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 77) { //Floor Button + createFloorPad(memblock[count+1]*20, memblock[count+2]*20, memblock[count+3]); + } + else if (type == 78) { + roomDarkness = 1; + } + else if (type == 79) { //Ladder Spawner + createLadder(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 80) { //Generator + createGenerator(memblock[count+1] * 20, memblock[count+2] * 20, memblock[count+3]); + } + else if (type == 81) { //Crown + createCrown(memblock[count+1] * 20, memblock[count+2] * 20); + } + } + count += 16; + } + + free(memblock); + fclose(file); + } + +} + +void drawHud() +{ + //Repress certain screen altering variables + int tempDark = roomDarkness; + roomDarkness = 0; + + int tempQuake = quakeTimer; + quakeTimer = 0; + + //Change HUD position + int drawy = 8; + { + if (heroy <= 100) { + drawy = 400; + } + } + + //Move scrolling health bar + { + if (drawhp > herohp) { + drawhp -= 1; + } + if (drawhp < herohp) { + drawhp += 1; + } + } + + //Main image + { + PHL_DrawSurfacePart(8, drawy, 0, 0, 368, 64, images[imgHud]); + } + + //Health bar + { + PHL_RGB hpbarc = PHL_NewRGB(128, 255, 0); + if (getHeroPoisoned() > 0) { + hpbarc = PHL_NewRGB(255, 128, 255); + } + + PHL_DrawRect(76, drawy + 8, maxhp * 2, 6, PHL_NewRGB(255, 0, 0)); + PHL_DrawRect(76, drawy + 8, drawhp * 2, 6, hpbarc); + } + + //Ammo counter + { + char c[10]; + sprintf(c, "%02d", heroAmmo); + PHL_DrawTextBold(c, 74, drawy + 36, WHITE); + } + + //Draw weapon icon + { + int wx = 32 * (heroWeapon + 1); + if (hasWeapon[heroWeapon] == 0) { + wx = 0; + } + PHL_DrawSurfacePart(24, drawy + 16, wx, 64, 32, 32, images[imgHud]); + } + + //Restore screen altering variables + { + quakeTimer = tempQuake; + roomDarkness = tempDark; + } +} + +void freeArrays() +{ + int i; + for (i = 0; i < MAX_EFFECTS; i++) { + effectDestroy(i); + } + + for (i = 0; i < MAX_OBJECTS; i++) { + objectDestroy(i); + } + + for (i = 0; i < MAX_ENEMIES; i++) { + enemyDestroy(i); + } + + for (i = 0; i < MAX_WEAPONS; i++) { + weaponDestroy(i); + } + + for (i = 0; i < MAX_PLATFORMS; i++) { + platformDestroy(i); + } +} + +void changeScreen(int dx, int dy) +{ + roomSecret = 0; + + freeArrays(); + + screenX += dx; + screenY += dy; + loadScreen(); + + writeSave(savename); +} + +int getTileType(int valx, int valy) { + int result = 0; + + if (valy == 11 && valx == 8) { + result = 3; //Ladder Top + }else + if (valy == 1 && valx == 1) { + result = 5; //Lava + }else + if (valy > 7) { + result = 1; //Solid + }else + //specifics + if (valy == 0 && (valx == 3 || valx == 5)) { + result = 2; //Ladders + }else + if (valy == 1 && valx == 5) { + result = 4; //Water + }else + if (valx == 0 && (valy == 1 || valy == 2)) { + result = 6; //Spikes + }else + if (valy == 11 && (valx == 0 || valx == 1 || valx == 2)) { + result = 1; //Breakable solid block + } + + if (level == 4 && valy == 3 && (valx == 0 || valx == 1 || valx == 2)) { + result = 6; //Spikes + } + + return result; +} + +//Save file load/save +int writeSave(char* fname) +{ + int result = 0; + //mkdir("data"); + FILE* f; + + char fullPath[128]; + strcpy(fullPath, ""); + #ifdef _3DS + strcat(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/"); + #endif + strcat(fullPath, fname); + + if ( (f = fopen(fullPath, "wb")) ) { + int size = 4548; + unsigned char* memblock = (unsigned char*)malloc(size); + memset(memblock, 0, size); + + memblock[0x0] = herohp; + memblock[0x4] = maxhp; + memblock[0x8] = heroAmmo; + memblock[0x0C] = maxAmmo; + + if (heroWeapon == -1) { + memblock[0x10] = 0; + }else{ + memblock[0x10] = heroWeapon; + } + memblock[0x14] = 1; //Unknown, but always resets to 1 + + int i; + for (i = 0; i < 60; i++) { + memblock[(0x3FC) + i] = flags[i]; + } + + for (i = 0; i < 5; i++) { + memblock[(0x7E4) + i] = hasWeapon[i]; + } + + int itemorder[28] = { 0x7F6, 0x7FA, 0x7F9, 0x7F8, 0x7F1, 0x7F3, 0x7F2, + 0x7FB, 0x7ED, 0x7EF, 0x7EE, 0x7F0, 0x7EC, 0x7F4, + 0x7F7, 0x7F5, 0x7EA, 0x7EB, 0x7FF, 0x803, 0x804, + 0x7FE, 0x802, 0x805, 0x800, 0x7FD, 0x7FC, 0x801 }; + + for (i = 0; i < 28; i++) { + memblock[itemorder[i]] = hasItem[i]; + } + + for (i = 0; i < 8; i++) { + memblock[(0x806) + i] = hasKey[i]; + } + + int writeHerox = herox; + int writeHeroy = heroy; + memcpy(&memblock[0x11B0], &writeHerox, 4); + memcpy(&memblock[0x11B4], &writeHeroy, 4); + + if (getHeroDirection() == 1) { + memblock[0x11C0] = 0; + }else{ + memblock[0x11C0] = 1; + } + + memblock[0x11B8] = level; + + //Screen + memblock[0x11BC] = (screenX) + (screenY * 12); + + //Time + memcpy(&memblock[0x11AC], &playTime, 4); + + fwrite(memblock, 1, size, f); + + free(memblock); + + result = 1; + fclose(f); + } + + + return result; +} + +void loadSave(char* fname) +{ + FILE* f; + + char fullPath[128]; + strcpy(fullPath, ""); + #ifdef _3DS + strcat(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/"); + #endif + strcat(fullPath, fname); + + if ((f = fopen(fullPath, "rb"))) { + //Reminder: read order matters + unsigned long loadTemp = 0; + //Hero HP + fread(&loadTemp, 4, 1, f); + herohp = loadTemp; + drawhp = herohp; + + //Max HP + fread(&loadTemp, 4, 1, f); + maxhp = loadTemp; + + //Ammo + fread(&loadTemp, 4, 1, f); + heroAmmo = loadTemp; + + //Max Ammo + fread(&loadTemp, 4, 1, f); + maxAmmo = loadTemp; + + int loadedWeapon = 0; + fread(&loadedWeapon, 1, 1, f); + + //Read Flags + fseek(f, 0x3FC, SEEK_SET); + int i; + for (i = 0; i < 60; i++) { + fread(&flags[i], 1, 1, f); + } + + //Read weapons + fseek(f, 0x7E4, SEEK_SET); + for (i = 0; i < 5; i++) { + fread(&hasWeapon[i], 1, 1, f); + } + + heroWeapon = -1; + if (hasWeapon[loadedWeapon] == 1) { + heroWeapon = loadedWeapon; + } + + //Read items + int itemorder[28] = { 16, 17, 12, 8, 10, 9, 11, + 4, 6, 5, 13, 15, 0, 14, + 3, 2, 1, 7, 26, 25, 21, + 18, 24, 27, 22, 19, 20, 23 }; + fseek(f, 0x7EA, SEEK_SET); + for (i = 0; i < 28; i++) { + fread(&hasItem[itemorder[i]], 1, 1, f); + } + + //Read keys + for (i = 0; i < 8; i++) { + fread(&hasKey[i], 1, 1, f); + } + + fseek(f, 0x11AC, SEEK_SET); + fread(&playTime, 4, 1, f); + + //fseek(f, 4540, SEEK_SET); + //Hero X and Y + fread(&loadTemp, 4, 1, f); + herox = loadTemp; + fread(&loadTemp, 4, 1, f); + heroy = loadTemp; + + //Level + fread(&loadTemp, 4, 1, f); + level = loadTemp; + + //Screen coords + fread(&loadTemp, 4, 1, f); + screenX = (loadTemp) % 12; + screenY = ((int)(loadTemp) / 12); + + //Direction + fread(&loadTemp, 4, 1, f); + if (loadTemp == 0) { + setHeroDirection(1); + }else{ + setHeroDirection(-1); + } + fclose(f); + } + +} + +int fileExists(char* fpath) +{ + int result = 0; + + char fullPath[128]; + strcpy(fullPath, ""); + #ifdef _3DS + strcat(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/"); + #endif + strcat(fullPath, fpath); + + FILE* f; + if ( (f = fopen(fullPath, "rb")) ) { + result = 1; + fclose(f); + } + + return result; +} + +void playSecret() +{ + PHL_StopMusic(); + secretTimer = 210; +} + +void secretCountdown() +{ + if (secretTimer > 0) { + secretTimer -= 1; + if (secretTimer <= 0) { + PHL_StopMusic(); + if (bossFlag == 0 && bossDefeatedFlag == 0) { + PHL_PlayMusic(bgmMusic); + } + }else if (secretTimer == 180) { + PHL_PlayMusic(bgmSecret); + } + } +} + +int getDrawHP() +{ + return drawhp; +} + +void setDrawHP(int val) +{ + drawhp = val; +} + +int getLevel() +{ + return level; +} + +void setBossRoom() +{ + bossFlag = 1; + PHL_StopMusic(); + secretTimer = 0; + + PHL_FreeMusic(bgmMusic); + if (level != 8) { + bgmMusic = PHL_LoadMusic("midi/boss", 1); + }else{ + bgmMusic = PHL_LoadMusic("midi/lastboss", 1); + } + PHL_PlayMusic(bgmMusic); +} + +void setAutoSave(char val) +{ + autoSave = val; +} + +char getAutoSave() +{ + return autoSave; +} + +void loadUncommonImages() +{ + //Seal Toungs + if (level == 4) { + images[imgMisc2040] = PHL_LoadQDA("chr20x40.BMP"); + } + //Darkness + if (level == 5) { + images[imgDark] = PHL_LoadQDA("dark.bmp"); + } + //Dragon Flame + if (level == 7 || level == 8) { + images[imgMisc6020] = PHL_LoadQDA("chr60x20.bmp"); + } +}
\ No newline at end of file |