c-gba-example/source/main.c

141 lines
4.1 KiB
C

#include <stdlib.h>
#include <gba_console.h>
#include <gba_video.h>
#include <gba_interrupt.h>
#include <gba_systemcalls.h>
#include <gba_input.h>
#include <gba_base.h>
#include <gba_dma.h>
#include <maxmod.h>
#include <mm_types.h>
#include "together_8_img_bin.h"
#include "together_8_pal_bin.h"
// Define any soundbank includes here
#include "soundbank.h"
#include "soundbank_bin.h"
// Global mixing buffer for maxmod
u8 mixing_buffer[MM_MIXLEN_16KHZ] __attribute__((aligned(4)));
// Set the two variables below to start the palette fade
// The number of steps to fade the palette to black
const u8 palette_fade_steps = 12;
// The current step of the palette fade, set this to above to start the fade, the fade will decrement this value until it reaches 0
u8 palette_fade_step = 0;
const u8 fade_pause_frames = 120;
u8 fade_pause_frame_count = 0;
// Function Prototypes
void initializeSystem(void);
void loadIntroScreen(void);
void fadePaletteStep(void);
int main(void) {
// Initialize GBA system and maxmod
initializeSystem();
// Load intro screen
loadIntroScreen();
// Wait for VBlank before starting music
VBlankIntrWait();
mmStart(MOD_MOZARTSONATA, MM_PLAY_LOOP);
// Main game loop
while(1) {
VBlankIntrWait();
// Update sound system
mmFrame();
// Game logic goes here
scanKeys();
u16 keys = keysDown();
// Check for key presses
if (keys & KEY_A) {
mmEffect(SFX_WEAPON);
}
if ((keys & KEY_START) && palette_fade_step == 0) {
// Start the palette fade
palette_fade_step = palette_fade_steps;
}
else if (keys & KEY_SELECT) {
// Reset the palette to the original
DMA3COPY(together_8_pal_bin, BG_PALETTE, together_8_pal_bin_size >> 1);
}
fadePaletteStep();
}
return 0;
}
void initializeSystem(void) {
// Initialize GBA display and interrupt system
irqInit();
irqSet(IRQ_VBLANK, mmVBlank);
irqEnable(IRQ_VBLANK);
// Initialize display registers for Mode 4 (8-bit paletted bitmap)
SetMode(MODE_4 | BG2_ON); // Mode 4 + Enable BG2
mmInitDefault((mm_addr)soundbank_bin, 8);
}
void loadIntroScreen(void) {
// Wait for VBlank before copying
VBlankIntrWait();
// Load the palette
// Palette size needs to be in 16-bit units (divide by 2)
DMA3COPY(together_8_pal_bin, BG_PALETTE, together_8_pal_bin_size >> 1);
// Copy image data to first frame buffer
// Image size needs to be in 16-bit units (divide by 2)
DMA3COPY(together_8_img_bin, (void*)VRAM, together_8_img_bin_size >> 1);
}
// increment the palette fade step by 1
void fadePaletteStep(void) {
if (fade_pause_frame_count > fade_pause_frames) {
++fade_pause_frame_count;
return;
}
fade_pause_frame_count = 0;
if (palette_fade_steps && palette_fade_step) {
// Calculate how much to keep of each color component in this step
// As palette_fade_step goes from palette_fade_steps down to 1,
// this ratio goes from 1.0 down to nearly 0.0
// -1 is so the last step is fully black.
u16 keep_ratio = (((u16)palette_fade_step - 1) << 7) / (u16)palette_fade_steps;
// fade the palette to black, by iterating over the palette memory one position at a time
for (u16 i = 0; i < 256; ++i) {
u16 color = ((u16*)together_8_pal_bin)[i];
// Extract RGB components (GBA uses 5 bits per component)
u16 r = (color & 0x1F);
u16 g = (color >> 5) & 0x1F;
u16 b = (color >> 10) & 0x1F;
// Reduce each component based on current step
r = (r * keep_ratio) >> 7;
g = (g * keep_ratio) >> 7;
b = (b * keep_ratio) >> 7;
// Recombine the components
u16 new_color = (b << 10) | (g << 5) | r;
BG_PALETTE[i] = new_color;
}
--palette_fade_step;
}
}