From 215465df74a6065f4b0fdf199b8b04454520a398 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 2 Jun 2021 20:20:23 +0200 Subject: Update the renderer to support a text layer --- src/common.h | 667 ----------------------------------------------------------- 1 file changed, 667 deletions(-) delete mode 100644 src/common.h (limited to 'src/common.h') diff --git a/src/common.h b/src/common.h deleted file mode 100644 index fbe01a4..0000000 --- a/src/common.h +++ /dev/null @@ -1,667 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include "shorthand.h" - -#define CPU_FREQUENCY (2 << 23) - -// -// Memory sections. -// - -// Defines for the different memory sections in the GBA. -#define MEM_SROM 0x00000000 -#define MEM_EW 0x02000000 -#define MEM_IW 0x03000000 -#define MEM_IO 0x04000000 -#define MEM_PAL 0x05000000 -#define MEM_VRAM 0x06000000 -#define MEM_OAM 0x07000000 -#define MEM_PAK 0x08000000 -#define MEM_CART 0x0E000000 - -// -// Display modes. -// - -// Display registers. -#define DISP_CTRL *((vu32*)(MEM_IO + 0x0000)) -#define DISP_STATUS *((vu16*)(MEM_IO + 0x0004)) -#define DISP_VCOUNT *((vu16*)(MEM_IO + 0x0006)) - -// The first three bits in the DISP_CTRL are used to control the video mode. -#define DISP_MODE_0 0x0000 -#define DISP_MODE_1 0x0001 -#define DISP_MODE_2 0x0002 -#define DISP_MODE_3 0x0003 -#define DISP_MODE_4 0x0004 -#define DISP_MODE_5 0x0005 -#define DISP_GB (1 << 3) -#define DISP_PAGE (1 << 4) -#define DISP_OAM_HBLANK (1 << 5) -#define DISP_OBJ_1D (1 << 6) -#define DISP_BLANK (1 << 7) -#define DISP_BG_0 (1 << 8) -#define DISP_BG_1 (1 << 9) -#define DISP_BG_2 (1 << 10) -#define DISP_BG_3 (1 << 11) -#define DISP_OBJ (1 << 12) -#define DISP_ENABLE_SPRITES DISP_OBJ | DISP_OBJ_1D - -// These bits are used to control the DISP_STATUS register. -#define DISP_VBLANK_STATUS (1 << 0x0) -#define DISP_HBLANK_STATUS (1 << 0x1) -#define DISP_VCOUNT_STATUS (1 << 0x2) -#define DISP_VBLANK_IRQ (1 << 0x3) -#define DISP_HBLANK_IRQ (1 << 0x4) -#define DISP_VCOUNT_IRQ (1 << 0x5) -#define DISP_VCOUNT_TRIGGER(N) ((N) << 0x8) - -// Registers to control of BG layers. -#define BG_CTRL(N) *((vu16*)(0x04000008 + 0x0002 * (N))) - -// Bits to control the background. -#define BG_PRIORITY(N) ((N) & 0x3) -#define BG_CHARBLOCK(N) ((N) << 2) -#define BG_MOSAIC (1 << 6) -#define BG_HIGH_COLOR (1 << 7) -#define BG_SCREENBLOCK(N) ((N) << 8) -#define BG_AFFINE (1 << 0xD) -#define BG_SIZE(N) ((N) << 0xE) - -// BG registers for horizontal displacement. -#define BG_H_SCROLL_0 *((vu16*)(0x04000010 + 0x0004 * 0)) -#define BG_H_SCROLL_1 *((vu16*)(0x04000010 + 0x0004 * 1)) -#define BG_H_SCROLL_2 *((vu16*)(0x04000010 + 0x0004 * 2)) -#define BG_H_SCROLL_3 *((vu16*)(0x04000010 + 0x0004 * 3)) - -// BG registers for vertical displacement. -#define BG_V_SCROLL_0 *((vu16*)(0x04000012 + 0x0004 * 0)) -#define BG_V_SCROLL_1 *((vu16*)(0x04000012 + 0x0004 * 1)) -#define BG_V_SCROLL_2 *((vu16*)(0x04000012 + 0x0004 * 2)) -#define BG_V_SCROLL_3 *((vu16*)(0x04000012 + 0x0004 * 3)) - -// Screen settings. -#define SCREEN_WIDTH 240 -#define SCREEN_HEIGHT 160 - -// -// Colors. -// - -// The GBA in mode 3 expects rbg15 colors in the VRAM, where each component -// (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0). -typedef u16 Color; - -// A palette is composed of 16 colors, with color at index 0 being transparent -// for sprites. -typedef Color Palette[16]; - -// Inline function to calculate the 15 bit color value. -#define RGB15(R,G,B) (u16)(((B) << 10) | ((G) << 5) | (R)); - -// Some nice default colors. -#define COLOR_RED RGB15(31, 0,12) -#define COLOR_BLUE RGB15(2, 15,30) -#define COLOR_CYAN RGB15(0, 30,30) -#define COLOR_GREY RGB15(12,12,12) -#define COLOR_BLACK RGB15(0, 0, 0) -#define COLOR_WHITE RGB15(28,28,28) - -// -// Tile memory access. -// - -// NOTE: Only defining 4bpp tiles for now. -// TODO: typedef u32 Tile[8]; -typedef struct Tile { - u32 row[8]; -} Tile; - -// Screenblocks and charblocks (tile blocks). -typedef Tile TileBlock[512]; -#define TILE_MEM ((TileBlock*) MEM_VRAM) -typedef u16 ScreenBlock[1024]; -#define SCREENBLOCK_MEM ((ScreenBlock*)MEM_VRAM) - -// Screenblock entry bits. -#define SCREENBLOCK_ENTRY_H_FLIP (1 << 0xA) -#define SCREENBLOCK_ENTRY_V_FLIP (1 << 0xB) -#define SCREENBLOCK_ENTRY_PAL(N) ((N) << 0xC) - -inline size_t -se_index(size_t tile_x, size_t tile_y, size_t map_width) { - size_t sbb = ((tile_x >> 5) + (tile_y >> 5) * (map_width >> 5)); - return sbb * 1024 + ((tile_x & 31) + (tile_y & 31) * 32); -} - -// We can treat the screen as a HxW matrix. With the following macro we can -// write a pixel to the screen at the (x, y) position using: -// -// FRAMEBUFFER[y][x] = color; -// -typedef Color Scanline[SCREEN_WIDTH]; -#define FRAMEBUFFER ((Scanline*) MEM_VRAM) -#define SCREEN_BUFFER ((u16*) MEM_VRAM) -#define PAL_BUFFER_BG ((u16*) MEM_PAL) -#define PAL_BUFFER_SPRITES ((u16*)(MEM_PAL + 0x200)) -#define PAL_BANK_BG ((Palette*) MEM_PAL) -#define PAL_BANK_SPRITES ((Palette*)(MEM_PAL + 0x200)) - -// -// Sprites. -// - -// Using macros instead of aligned structs for setting up OBJ attributes and -// affine parameters. -// TODO: Benchmark if this would be slower or the same that TONC's -// implementation. -// TODO: Cleanup OBJ/OAM memory copying and access. -#define OBJ_ATTR_0(N) *((vu16*)(MEM_OAM + 0 + 8 * (N))) -#define OBJ_ATTR_1(N) *((vu16*)(MEM_OAM + 2 + 8 * (N))) -#define OBJ_ATTR_2(N) *((vu16*)(MEM_OAM + 4 + 8 * (N))) -#define OBJ_AFFINE_PA(N) *((vs16*)(MEM_OAM + 6 + 8 * 0 + 8 * 4 * (N))) -#define OBJ_AFFINE_PB(N) *((vs16*)(MEM_OAM + 6 + 8 * 1 + 8 * 4 * (N))) -#define OBJ_AFFINE_PC(N) *((vs16*)(MEM_OAM + 6 + 8 * 2 + 8 * 4 * (N))) -#define OBJ_AFFINE_PD(N) *((vs16*)(MEM_OAM + 6 + 8 * 3 + 8 * 4 * (N))) - -// OBJ_ATTR_0 parameters -#define OBJ_Y_COORD(N) ((N) & 0xFF) -#define OBJ_NORMAL (0x00 << 0x8) -#define OBJ_AFFINE (0x01 << 0x8) -#define OBJ_HIDDEN (0x02 << 0x8) -#define OBJ_AFFINE_2X (0x03 << 0x8) -#define OBJ_ALPHA_BLEND (0x01 << 0xA) -#define OBJ_WINDOW (0x02 << 0xA) -#define OBJ_SHAPE_SQUARE (0x00 << 0xE) -#define OBJ_SHAPE_WIDE (0x01 << 0xE) -#define OBJ_SHAPE_TALL (0x02 << 0xE) - -// OBJ_ATTR_1 parameters -#define OBJ_X_COORD(N) ((N) & 0x1FF) -#define OBJ_AFFINE_IDX(N) ((N) << 0x9) -#define OBJ_H_FLIP (0x01 << 0xC) -#define OBJ_V_FLIP (0x01 << 0xD) -#define OBJ_SIZE_SMALL (0x00 << 0xE) -#define OBJ_SIZE_MID (0x01 << 0xE) -#define OBJ_SIZE_BIG (0x02 << 0xE) -#define OBJ_SIZE_HUGE (0x03 << 0xE) - -// OBJ_ATTR_2 parameters -#define OBJ_TILE_INDEX(N) ((N) & 0x3FF) -#define OBJ_PRIORITY(N) ((N) << 0xA) -#define OBJ_PAL_BANK(N) ((N) << 0xC) - -// -// Mode 4 page flipping -// - -static inline -void -flip_page(vu16 *backbuffer) { - backbuffer = (u16*)((u32)backbuffer ^ 0x0A000); - DISP_CTRL ^= DISP_PAGE; -} - -#define SCREEN_PAGE_1 ((vu16*) MEM_VRAM) -#define SCREEN_PAGE_2 ((vu16*) (MEM_VRAM + 0xa000)) - -// -// Profiling. -// - -#define TIMER_DATA_0 *((vu16*) (0x04000100 + 0x04 * 0)) -#define TIMER_DATA_1 *((vu16*) (0x04000100 + 0x04 * 1)) -#define TIMER_DATA_2 *((vu16*) (0x04000100 + 0x04 * 2)) -#define TIMER_DATA_3 *((vu16*) (0x04000100 + 0x04 * 3)) -#define TIMER_CTRL_0 *((vu16*) (0x04000102 + 0x04 * 0)) -#define TIMER_CTRL_1 *((vu16*) (0x04000102 + 0x04 * 1)) -#define TIMER_CTRL_2 *((vu16*) (0x04000102 + 0x04 * 2)) -#define TIMER_CTRL_3 *((vu16*) (0x04000102 + 0x04 * 3)) - -// Timer control bits. -#define TIMER_CTRL_FREQ_0 0 -#define TIMER_CTRL_FREQ_1 1 -#define TIMER_CTRL_FREQ_2 2 -#define TIMER_CTRL_FREQ_3 3 -#define TIMER_CTRL_CASCADE (1 << 2) -#define TIMER_CTRL_IRQ (1 << 6) -#define TIMER_CTRL_ENABLE (1 << 7) -#define TIMER_CTRL_DISABLE (0 << 7) - -// We use timers 2 and 3 to count the number of cycles since the profile_start -// functions is called. Don't use if the code we are trying to profile make use -// of these timers. -static inline -void -profile_start(void) { - TIMER_DATA_2 = 0; - TIMER_DATA_3 = 0; - TIMER_CTRL_2 = 0; - TIMER_CTRL_3 = 0; - TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE; - TIMER_CTRL_2 = TIMER_CTRL_ENABLE; -} - -static inline -u32 -profile_stop(void) { - TIMER_CTRL_2 = 0; - return (TIMER_DATA_3 << 16) | TIMER_DATA_2; -} - -static inline -u32 -profile_measure(void) { - return (TIMER_DATA_3 << 16) | TIMER_DATA_2; -} - -// -// Input handling. -// - -// Memory address for key input and control register -#define KEY_INPUTS *((vu16*) 0x04000130) -#define KEY_CTRL *((vu16*) 0x04000132) - -// Key control register bits. -#define KEY_IRQ_KEY(N) (N) -#define KEY_IRQ (1 << 0xE) -#define KEY_IRQ_IF_SET (1 << 0xF) - -// Alias for key pressing bits. -#define KEY_A (1 << 0) -#define KEY_B (1 << 1) -#define KEY_SELECT (1 << 2) -#define KEY_START (1 << 3) -#define KEY_RIGHT (1 << 4) -#define KEY_LEFT (1 << 5) -#define KEY_UP (1 << 6) -#define KEY_DOWN (1 << 7) -#define KEY_R (1 << 8) -#define KEY_L (1 << 9) - -#define KEY_MASK 0x03FF - -// Saving the previous and current key states as globals for now. -static u16 key_curr = 0; -static u16 key_prev = 0; - -static inline -void -poll_keys(void) { - key_prev = key_curr; - key_curr = ~KEY_INPUTS & KEY_MASK; -} - -// Returns true if the given key has been pressed at time of calling and was not -// pressed since the previous call. For example, if a key is being held, this -// function will return `true` only on the frame where the key initially -// activated. -static inline -u32 -key_tap(u32 key) { - return (key_curr & key) & ~(key_prev & key); -} - -// Check if a given key is currently pressed. -static inline -u32 -key_pressed(u32 key) { - return (key_curr & key); -} - -// Check if a given key was just released. -static inline -u32 -key_released(u32 key) { - return ~(key_curr & key) & (key_prev & key); -} - -// Check if the given key is pressed and has been since at least one frame. -static inline -u32 -key_hold(u32 key) { - return key_curr & key_prev & key; -} - -// Check if the given key/button is currently pressed. -#define KEY_PRESSED(key) (~(KEY_INPUTS) & key) - -// Back/unpack bits. -static inline -u32 -unpack_1bb(u8 hex) { - const u32 conversion_u32[16] = { - 0x00000000, 0x00000001, 0x00000010, 0x00000011, - 0x00000100, 0x00000101, 0x00000110, 0x00000111, - 0x00001000, 0x00001001, 0x00001010, 0x00001011, - 0x00001100, 0x00001101, 0x00001110, 0x00001111, - }; - u8 low = hex & 0xF; - u8 high = (hex >> 4) & 0xF; - return (conversion_u32[high] << 16) | conversion_u32[low]; -} - -// Unpack N tiles packed at 1bpp. -static inline -void -unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { - u32 *target_src = src + n_tiles * 2; - while (src != target_src) { - *dst++ = unpack_1bb((*src >> 24) & 0xFF); - *dst++ = unpack_1bb((*src >> 16) & 0xFF); - *dst++ = unpack_1bb((*src >> 8) & 0xFF); - *dst++ = unpack_1bb(*src & 0xFF); - src++; - } -} - -// -// Direct Memory Access (DMA) -// - - -// Source, destination, and control registers. -#define DMA_SRC(N) *((vu32*) 0x040000B0 + (N) * 12) -#define DMA_DST(N) *((vu32*) 0x040000B4 + (N) * 12) -#define DMA_CTRL(N) *((vu32*) 0x040000B8 + (N) * 12) - -// DMA control bits. -#define DMA_DST_INC (0 << 0x15) -#define DMA_DST_DEC (1 << 0x15) -#define DMA_DST_FIXED (2 << 0x15) -#define DMA_DST_RELOAD (3 << 0x15) -#define DMA_SRC_INC (0 << 0x17) -#define DMA_SRC_DEC (1 << 0x17) -#define DMA_SRC_FIXED (2 << 0x17) -#define DMA_REPEAT (1 << 0x19) -#define DMA_CHUNK_16 (0 << 0x1A) -#define DMA_CHUNK_32 (1 << 0x1A) -#define DMA_NOW (0 << 0x1C) -#define DMA_VBLANK (1 << 0x1C) -#define DMA_HBLANK (2 << 0x1C) -#define DMA_REFRESH (3 << 0x1C) -#define DMA_IRQ (1 << 0x1E) -#define DMA_ENABLE (1 << 0x1F) - -// Custom struct for cleaner DMA transfer functions. -typedef struct DmaStr { - const void *src; - void *dst; - u32 ctrl; -} DmaStr; - -#define DMA_TRANSFER ((volatile DmaStr*) 0x040000B0) - -// Transfer `count` number of chunks from src to dst using a DMA channel. Note -// that chunks are not bytes, but instead configured based on bits set by -// DMA_CTRL. -inline -void -dma_transfer_copy(void *dst, const void *src, u32 count, int channel, u32 options) { - DMA_TRANSFER[channel].ctrl = 0; - DMA_TRANSFER[channel].src = src; - DMA_TRANSFER[channel].dst = dst; - DMA_TRANSFER[channel].ctrl = count | options; -} - -inline -void -dma_transfer_fill(void *dst, volatile u32 src, u32 count, int channel, u32 options) { - DMA_TRANSFER[channel].ctrl = 0; - DMA_TRANSFER[channel].src = (const void *)&src; - DMA_TRANSFER[channel].dst = dst; - DMA_TRANSFER[channel].ctrl = count | options | DMA_SRC_FIXED; -} - -// Copy N number of bytes using a DMA channel. -inline -void -dma_copy(void *dst, const void *src, u32 size, int channel) { - dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); -} - -// Fill the dst location with the word set at src. -inline -void -dma_fill(void *dst, vu32 src, u32 size, int channel) { - dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); -} - -// -// Interrupts. -// - -#define IRQ_ENABLE *((vu16*) 0x04000200) -#define IRQ_ACK *((vu16*) 0x04000202) -#define IRQ_CTRL *((vu16*) 0x04000208) -#define IRQ_ACK_BIOS *((vu16*) 0x03007FF8) - -typedef enum { - IRQ_VBLANK, - IRQ_HBLANK, - IRQ_VCOUNT, - IRQ_TIMER_0, - IRQ_TIMER_1, - IRQ_TIMER_2, - IRQ_TIMER_3, - IRQ_SERIAL, - IRQ_DMA_0, - IRQ_DMA_1, - IRQ_DMA_2, - IRQ_DMA_3, - IRQ_KEYPAD, - IRQ_GAMEPAK, -} IrqIndex; - -typedef void (*IrsFunc)(void); - -// Stub function pointer needed for when we want to enable interrupts that don't -// require a custom function, such as for the BIOS VSync. -void irs_stub(void); - -// Set and enable a given function in the interrupt table. If func is NULL, the -// interrupt will be disabled instead. -void irs_set(IrqIndex idx, IrsFunc func); - -// Initialize the function pointer for the main IRS routine written in ARM -// assembly and enable interrupts. -void irq_init(void); - -// -// BIOS function declarations. -// - -// These functions declarations can be used to call the BIOS functions from the -// asm code. -int bios_vblank_wait(); -int bios_div(int num, int denom); - -// -// Sound. -// - -// Sound registers. -#define SOUND_SQUARE1_SWEEP *((vu16*)(MEM_IO + 0x60)) -#define SOUND_SQUARE1_CTRL *((vu16*)(MEM_IO + 0x62)) -#define SOUND_SQUARE1_FREQ *((vu16*)(MEM_IO + 0x64)) -#define SOUND_SQUARE2_CTRL *((vu16*)(MEM_IO + 0x68)) -#define SOUND_SQUARE2_FREQ *((vu16*)(MEM_IO + 0x6C)) -#define SOUND_WAVE_MODE *((vu16*)(MEM_IO + 0x70)) -#define SOUND_WAVE_CTRL *((vu16*)(MEM_IO + 0x72)) -#define SOUND_WAVE_FREQ *((vu16*)(MEM_IO + 0x74)) -#define SOUND_NOISE_CTRL *((vu16*)(MEM_IO + 0x78)) -#define SOUND_NOISE_FREQ *((vu16*)(MEM_IO + 0x7C)) -#define SOUND_DMG_MASTER *((vu16*)(MEM_IO + 0x80)) -#define SOUND_DSOUND_MASTER *((vu16*)(MEM_IO + 0x82)) -#define SOUND_STATUS *((vu16*)(MEM_IO + 0x84)) -#define SOUND_BIAS *((vu16*)(MEM_IO + 0x88)) - -// Sound DMG master bits. -#define SOUND_VOLUME_LEFT(N) (N) -#define SOUND_VOLUME_RIGHT(N) ((N) << 4) -#define SOUND_ENABLE_SQUARE1_LEFT (1 << 0x8) -#define SOUND_ENABLE_SQUARE2_LEFT (1 << 0x9) -#define SOUND_ENABLE_WAVE_LEFT (1 << 0xA) -#define SOUND_ENABLE_NOISE_LEFT (1 << 0xB) -#define SOUND_ENABLE_SQUARE1_RIGHT (1 << 0xC) -#define SOUND_ENABLE_SQUARE2_RIGHT (1 << 0xD) -#define SOUND_ENABLE_WAVE_RIGHT (1 << 0xE) -#define SOUND_ENABLE_NOISE_RIGHT (1 << 0xF) - -typedef enum { - SOUND_DSOUND = (0x0 << 0), - SOUND_SQUARE1 = (0x1 << 0), - SOUND_SQUARE2 = (0x1 << 1), - SOUND_WAVE = (0x1 << 2), - SOUND_NOISE = (0x1 << 3), -} SoundChannel; - -inline u16 -sound_volume(SoundChannel channels, u8 volume) { - volume = volume & 0x7; - channels = channels & 0xF; - return volume | (volume << 0x4) | (channels << 0x8) | (channels << 0xC); -} - -// Sound Direct Sound master bits. -#define SOUND_DMG25 0x0 -#define SOUND_DMG50 0x1 -#define SOUND_DMG100 0x2 -#define SOUND_DSOUND_RATIO_A (1 << 0x2) -#define SOUND_DSOUND_RATIO_B (1 << 0x3) -#define SOUND_DSOUND_LEFT_A (1 << 0x8) -#define SOUND_DSOUND_RIGHT_A (1 << 0x9) -#define SOUND_DSOUND_TIMER_A (1 << 0xA) -#define SOUND_DSOUND_RESET_A (1 << 0xB) -#define SOUND_DSOUND_LEFT_B (1 << 0xC) -#define SOUND_DSOUND_RIGHT_B (1 << 0xD) -#define SOUND_DSOUND_TIMER_B (1 << 0xE) -#define SOUND_DSOUND_RESET_B (1 << 0xF) - -// Direct sound FIFO queues. -#define SOUND_FIFO_A ((u16*)(MEM_IO + 0xA0)) -#define SOUND_FIFO_B ((u16*)(MEM_IO + 0xA4)) - -// Sound status bits. -#define SOUND_ENABLE (1 << 0x7) - -// DMG square control bits. -#define SOUND_SQUARE_LEN(N) (N) -#define SOUND_SQUARE_DUTY(N) ((N) << 0x6) -#define SOUND_SQUARE_ENV_TIME(N) ((N) << 0x8) -#define SOUND_SQUARE_ENV_DIR(N) ((N) << 0xB) -#define SOUND_SQUARE_ENV_VOL(N) ((N) << 0xC) - -// DMG square 1 sweep control bits. -#define SOUND_SWEEP_NUMBER(N) (N) -#define SOUND_SWEEP_DIR(N) ((N) << 0x3) -#define SOUND_SWEEP_TIME(N) ((N) << 0x4) - -// DMG frequency bits (Square/Wave). -#define SOUND_FREQ_TIMED (1 << 0xE) -#define SOUND_FREQ_RESET (1 << 0xF) - -// DMG wave ram. -#define SOUND_WAVE_RAM_0 *((vu32*)(MEM_IO + 0x90)) -#define SOUND_WAVE_RAM_1 *((vu32*)(MEM_IO + 0x94)) -#define SOUND_WAVE_RAM_2 *((vu32*)(MEM_IO + 0x98)) -#define SOUND_WAVE_RAM_3 *((vu32*)(MEM_IO + 0x9C)) - -// DMG wave control bits. -#define SOUND_WAVE_LENGTH(N) (N) -#define SOUND_WAVE_MUTE 0x0 -#define SOUND_WAVE_VOL_100 (0x1 << 0xD) -#define SOUND_WAVE_VOL_75 (0x4 << 0xD) -#define SOUND_WAVE_VOL_50 (0x2 << 0xD) -#define SOUND_WAVE_VOL_25 (0x3 << 0xD) - -// DMG wave mode bits. -#define SOUND_WAVE_BANK_MODE(N) ((N) << 0x5) -#define SOUND_WAVE_BANK_SELECT(N) ((N) << 0x6) -#define SOUND_WAVE_ENABLE (1 << 0x7) - -typedef u8 WaveBank[32]; - -#define SOUND_WAVE_RAM ((WaveBank*)(MEM_IO + 0x90)) - -typedef enum { - NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 , - NOTE_E_2 , NOTE_F_2 , NOTE_F_SHARP_2 , NOTE_G_2 , - NOTE_G_SHARP_2 , NOTE_A_2 , NOTE_A_SHARP_2 , NOTE_B_2 , - NOTE_C_3 , NOTE_C_SHARP_3 , NOTE_D_3 , NOTE_D_SHARP_3 , - NOTE_E_3 , NOTE_F_3 , NOTE_F_SHARP_3 , NOTE_G_3 , - NOTE_G_SHARP_3 , NOTE_A_3 , NOTE_A_SHARP_3 , NOTE_B_3 , - NOTE_C_4 , NOTE_C_SHARP_4 , NOTE_D_4 , NOTE_D_SHARP_4 , - NOTE_E_4 , NOTE_F_4 , NOTE_F_SHARP_4 , NOTE_G_4 , - NOTE_G_SHARP_4 , NOTE_A_4 , NOTE_A_SHARP_4 , NOTE_B_4 , - NOTE_C_5 , NOTE_C_SHARP_5 , NOTE_D_5 , NOTE_D_SHARP_5 , - NOTE_E_5 , NOTE_F_5 , NOTE_F_SHARP_5 , NOTE_G_5 , - NOTE_G_SHARP_5 , NOTE_A_5 , NOTE_A_SHARP_5 , NOTE_B_5 , - NOTE_C_6 , NOTE_C_SHARP_6 , NOTE_D_6 , NOTE_D_SHARP_6 , - NOTE_E_6 , NOTE_F_6 , NOTE_F_SHARP_6 , NOTE_G_6 , - NOTE_G_SHARP_6 , NOTE_A_6 , NOTE_A_SHARP_6 , NOTE_B_6 , - NOTE_C_7 , NOTE_C_SHARP_7 , NOTE_D_7 , NOTE_D_SHARP_7 , - NOTE_E_7 , NOTE_F_7 , NOTE_F_SHARP_7 , NOTE_G_7 , - NOTE_G_SHARP_7 , NOTE_A_7 , NOTE_A_SHARP_7 , NOTE_B_7 , - NOTE_C_8 -} Note; - -static const u32 sound_rates[] = { - 44 , 156 , 262 , 363 , 457 , 547 , 631 , 710 , 785 , 856 , 923 , 986 , - 1046, 1102, 1155, 1205, 1252, 1297, 1339, 1379, 1416, 1452, 1485, 1517, - 1547, 1575, 1601, 1626, 1650, 1672, 1693, 1713, 1732, 1750, 1766, 1782, - 1797, 1811, 1824, 1837, 1849, 1860, 1870, 1880, 1890, 1899, 1907, 1915, - 1922, 1929, 1936, 1942, 1948, 1954, 1959, 1964, 1969, 1973, 1977, 1981, - 1985, 1988, 1992, 1995, 1998, 2001, 2003, 2006, 2008, 2010, 2012, 2014, - 2016, -}; - -// -// System control. -// - -// Used to configure gamepak access timings. -#define SYSTEM_WAIT *((vu16*)(MEM_IO + 0x0204)) - -// This register defaults to 0, but manufacture cartridges use the values -// provided below. -#define SYSTEM_WAIT_DEFAULT 0 -#define SYSTEM_WAIT_CARTRIDGE 0x4317 - -// -// Misc. -// - -// Custom VSync option. This will waste a lot of battery power, since the -// machine is not clocked down. Prefer using `bios_vblank_wait()` if interrupts -// are enabled. -static inline void -wait_vsync(void) { - while(DISP_VCOUNT >= 160); - while(DISP_VCOUNT < 160); -} - -// General utility macros. -#define MIN(A, B) ((A) <= (B) ? (A) : (B)) -#define MAX(A, B) ((A) >= (B) ? (A) : (B)) -#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) -#define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) - -// Fixed-point arithmetic for (i.P) numbers. -#define FP_MUL(A,B,P) (((A) * (B)) >> (P)) -#define FP_DIV(A,B,P) (((A) << (P)) / (B)) -#define FP_LERP(Y0,Y1,X,P) ((Y0) + FP_MUL((X), ((Y1) - (Y0)), P)) - -// -// Memory section macros for devkitARM. -// - -#define IWRAM_DATA __attribute__((section(".iwram"))) -#define IWRAM_CODE __attribute__((section(".iwram"), long_call, target("arm"))) -#define EWRAM_DATA __attribute__((section(".ewram"))) -#define EWRAM_CODE __attribute__((section(".ewram"), long_call)) -#define EWRAM_BSS __attribute__((section(".sbss"))) - -#endif // COMMON_H -- cgit v1.2.1