cenotaph/src/main.c
2026-03-18 13:23:51 -04:00

183 lines
No EOL
4.3 KiB
C

#include <genesis.h>
#include <resources.h>
#include "global.h"
#include "background.h"
#include "bullets.h"
#include "enemies.h"
#include "treasure.h"
#include "player.h"
#include "stage.h"
#include "chrome.h"
#include "start.h"
#include "starfield.h"
#include "sfx.h"
static void loadInternals(){
JOY_init();
JOY_setEventHandler(&updateControls);
VDP_setPlaneSize(128, 32, TRUE);
SPR_init();
VDP_loadFont(font.tileset, DMA);
PAL_setPalette(PAL0, font.palette->data, DMA);
PAL_setPalette(PAL1, shadow.palette->data, CPU);
PAL_setPalette(PAL2, shadow.palette->data, CPU);
VDP_setTextPriority(1);
}
static bool attractEnding;
static void startLevelFadeIn(){
u16 ft[48];
memcpy(ft, font.palette->data, 16 * sizeof(u16));
memcpy(ft + 16, shadow.palette->data, 16 * sizeof(u16));
memcpy(ft + 32, bgPal, 16 * sizeof(u16));
PAL_setColors(0, palette_black, 48, CPU);
PAL_fadeIn(0, 47, ft, 20, TRUE);
}
void clearLevel(){
for(s16 i = 0; i < BULLET_COUNT; i++)
if(bullets[i].active) killBullet(i, FALSE);
for(s16 i = 0; i < ENEMY_COUNT; i++)
if(enemies[i].active){ enemies[i].hp = 0; killEnemy(i); }
for(s16 i = 0; i < TREASURE_COUNT; i++)
if(treasures[i].active) killTreasure(i);
treasureBeingCarried = FALSE;
collectedCount = 0;
allTreasureCollected = FALSE;
treasureCollectedClock = 0;
levelEnemiesKilled = 0;
// black out everything
SPR_setVisibility(player.image, HIDDEN);
VDP_clearTileMapRect(BG_A, 0, 0, 128, 32);
VDP_clearTileMapRect(BG_B, 0, 0, 128, 32);
}
void loadGame(){
VDP_setVerticalScroll(BG_A, 0);
score = 0;
nextExtendScore = EXTEND_SCORE;
loadBackground();
loadPlayer();
loadChrome();
loadLevel(isAttract ? ATTRACT_LEVEL : START_LEVEL);
#if MUSIC_VOLUME > 0
if(!isAttract) XGM2_play(isBossLevel(level) ? bossMusic : stageMusic);
#endif
player.recoveringClock = 240;
player.recoverFlash = FALSE;
killBullets = TRUE;
attractEnding = FALSE;
started = TRUE;
startLevelFadeIn();
}
static void updateGame(){
if(isAttract){
if(!attractEnding){
if(ctrlHW.start || ctrlHW.a || ctrlHW.b || ctrlHW.c){
attractEnding = TRUE;
PAL_fadeOut(0, 47, 20, TRUE);
}
if(attractClock > 0){
attractClock--;
if(attractClock == 20)
PAL_fadeOut(0, 47, 20, TRUE);
} else {
SYS_hardReset();
}
} else if(!PAL_isDoingFade()){
SYS_hardReset();
}
}
updateChrome();
if(levelClearing){
levelClearClock++;
if(levelClearClock == 73)
XGM2_stop();
if(levelClearClock == 1){
clearLevel();
loadStarfield(level % 3);
u16 transPal[32];
memcpy(transPal, font.palette->data, 16 * sizeof(u16));
memcpy(transPal + 16, shadow.palette->data, 16 * sizeof(u16));
PAL_fadeIn(0, 31, transPal, 20, TRUE);
}
if(levelClearClock == 220)
PAL_fadeOut(0, 31, 20, TRUE);
if(levelClearClock >= 240){
levelClearing = FALSE;
player.pos.y = FIX32(112);
player.camera = player.pos.x - FIX32(160);
playerVelX = 0;
clearStarfield();
loadBackground();
loadChrome();
loadLevel(level + 1);
startLevelFadeIn();
player.pendingShow = TRUE;
player.recoveringClock = 240;
player.recoverFlash = FALSE;
killBullets = TRUE;
XGM2_stop();
#if MUSIC_VOLUME > 0
if(!isAttract) XGM2_play(isBossLevel(level) ? bossMusic : stageMusic);
#endif
}
if(levelClearing) updateStarfield();
return;
}
if(levelWaitClock > 0){
levelWaitClock--;
#if MUSIC_VOLUME > 0
if(levelWaitClock == 209 && !isAttract)
XGM2_play(treasureMusic);
#endif
if(levelWaitClock == 20)
PAL_fadeOut(0, 47, 20, TRUE);
if(levelWaitClock == 0){
statEnemiesKilled = levelEnemiesKilled;
statTreasures = collectedCount;
levelClearing = TRUE;
levelClearClock = 0;
return;
}
}
if(!paused){
updatePlayer();
updateBackground();
if(clock % 2 == 0){
updateEnemies();
if(!gameOver && enemyCount == 0 && levelWaitClock == 0){
if(level >= LEVEL_COUNT - 1){
gameOver = TRUE;
XGM2_stop();
} else {
levelWaitClock = 210;
killBullets = TRUE;
if(paused){ paused = FALSE; clearPause(); }
XGM2_stop();
}
}
updateTreasures();
} else {
updateBullets();
}
}
}
int main(bool hardReset){
loadInternals();
if(SKIP_START) loadGame();
else loadStart();
while(1){
if(started) updateGame();
else updateStart();
clock++;
if(clock >= CLOCK_LIMIT) clock = 600;
SPR_update();
SYS_doVBlankProcess();
}
return(0);
}