mirror of
https://github.com/SAT-R/sa2.git
synced 2026-10-28 09:43:38 +00:00
420 lines
13 KiB
C
420 lines
13 KiB
C
#ifndef GUARD_MAIN_H
|
|
#define GUARD_MAIN_H
|
|
|
|
#if !GEN_CTX
|
|
#include <string.h> // memcpy
|
|
#endif
|
|
|
|
#include "global.h"
|
|
#include "sprite.h"
|
|
#include "task.h"
|
|
#include "flags.h"
|
|
#include "tilemap.h"
|
|
#include "input_recorder.h"
|
|
#include "animation_commands.h"
|
|
|
|
struct MultiSioData_0_0 {
|
|
// id
|
|
u16 unk0;
|
|
// value
|
|
u8 unk2;
|
|
|
|
u8 unk3;
|
|
u32 unk4;
|
|
u16 unk8[3];
|
|
|
|
// TODO: all values from unkE onwards appear to be 'RoomEvent' types?
|
|
// This seems to apply to all 'MultiSioData_X_X' types?
|
|
u8 unkE;
|
|
u8 unkF;
|
|
u32 unk10;
|
|
};
|
|
|
|
struct MultiSioData_0_1 {
|
|
// id
|
|
u16 unk0;
|
|
// value
|
|
u8 unk2;
|
|
|
|
u8 unk3;
|
|
|
|
u16 unk4;
|
|
u16 unk6;
|
|
|
|
u16 unk8[3];
|
|
|
|
// TODO: all values from unkE onwards appear to be 'RoomEvent' types?
|
|
// This seems to apply to all 'MultiSioData_X_X' types?
|
|
u8 unkE;
|
|
u8 unkF;
|
|
u32 unk10;
|
|
};
|
|
struct MultiSioData_0_2 {
|
|
// id
|
|
u8 unk0;
|
|
u8 filler1;
|
|
// value
|
|
u8 unk2;
|
|
|
|
u8 unk3;
|
|
|
|
u16 unk4;
|
|
u16 unk6;
|
|
|
|
u16 unk8[3];
|
|
|
|
// TODO: all values from unkE onwards appear to be 'RoomEvent' types?
|
|
// This seems to apply to all 'MultiSioData_X_X' types?
|
|
u8 unkE;
|
|
u8 unkF;
|
|
u32 unk10;
|
|
};
|
|
|
|
struct MultiSioData_0_3 {
|
|
// id
|
|
u16 unk0;
|
|
// value
|
|
u8 unk2;
|
|
|
|
u8 unk3;
|
|
|
|
u16 unk4;
|
|
u16 unk6;
|
|
|
|
u32 unk8;
|
|
u16 unkC;
|
|
|
|
// TODO: all values from unkE onwards appear to be 'RoomEvent' types?
|
|
// This seems to apply to all 'MultiSioData_X_X' types?
|
|
u8 unkE;
|
|
u8 unkF;
|
|
u32 unk10;
|
|
};
|
|
|
|
struct MultiSioData_0_4 {
|
|
// id
|
|
u16 unk0;
|
|
// value
|
|
s16 x;
|
|
s16 y;
|
|
u16 unk6;
|
|
u16 unk8;
|
|
u8 unkA;
|
|
u8 unkB;
|
|
u8 unkC;
|
|
u8 unkD;
|
|
|
|
// TODO: all values from unkE onwards appear to be 'RoomEvent' types?
|
|
// This seems to apply to all 'MultiSioData_X_X' types?
|
|
u8 unkE;
|
|
u8 numRings;
|
|
u8 unk10;
|
|
u8 unk11;
|
|
u8 unk12;
|
|
u8 unk13;
|
|
};
|
|
|
|
struct MultiSioData_0_5 {
|
|
// id
|
|
u16 unk0;
|
|
// value
|
|
s16 x;
|
|
s16 y;
|
|
|
|
u8 filler3[0x9];
|
|
u8 sioId;
|
|
u8 unk10;
|
|
u8 unk11;
|
|
u8 unk12;
|
|
u8 unk13;
|
|
};
|
|
|
|
union MultiSioData {
|
|
struct MultiSioData_0_0 pat0;
|
|
struct MultiSioData_0_1 pat1;
|
|
struct MultiSioData_0_2 pat2;
|
|
struct MultiSioData_0_3 pat3;
|
|
struct MultiSioData_0_4 pat4;
|
|
struct MultiSioData_0_5 pat5;
|
|
}; /* size = MULTI_SIO_BLOCK_SIZE */
|
|
|
|
// TODO: Have we defined this somewhere else already?
|
|
#define MAP_LAYER_COUNT 2
|
|
|
|
#if (GAME == GAME_SA1)
|
|
typedef u16 collPxDim_t;
|
|
#else
|
|
typedef u32 collPxDim_t;
|
|
#endif
|
|
|
|
// Thanks @MainMemory_ for figuring out how collision is stored!
|
|
typedef struct {
|
|
/* 0x00 */ const s8 *height_map;
|
|
/* 0x04 */ const u8 *tile_rotation;
|
|
/* 0x08 */ const u16 *metatiles;
|
|
/* 0x0C */ const MetatileIndexType *map[MAP_LAYER_COUNT];
|
|
/* 0x14 */ const u16 *flags;
|
|
/* 0x18 */ u16 levelX, levelY;
|
|
/* 0x1C */ collPxDim_t pxWidth, pxHeight;
|
|
|
|
// unk20/unk22 are not in SA1
|
|
} Collision;
|
|
|
|
struct Unk_03003674_1_Sub {
|
|
u16 unk0, unk2, unk4, unk6;
|
|
s16 unk8, unkA;
|
|
}; /* size = 0xC */
|
|
|
|
struct Unk_03003674_1_Full {
|
|
struct Unk_03003674_1_Sub sub;
|
|
u32 unkC;
|
|
}; /* size = 0x10 */
|
|
|
|
union Unk_03003674_1 {
|
|
const struct Unk_03003674_1_Sub *sub;
|
|
const struct Unk_03003674_1_Full *full;
|
|
};
|
|
|
|
struct Unk_03003674 {
|
|
const union Unk_03003674_0 *const *unk0;
|
|
const union Unk_03003674_1 *unk4;
|
|
const u16 *const *unk8;
|
|
const void *unkC;
|
|
const void *unk10;
|
|
const void *unk14;
|
|
const s32 *unk18;
|
|
}; /* size = 0x1C */
|
|
|
|
struct SpriteTables {
|
|
/* 0x00 */ const ACmd **const *animations;
|
|
/* 0x04 */ const SpriteOffset *const *dimensions;
|
|
/* 0x08 */ const u16 **const oamData;
|
|
/* 0x0C */ const ColorRaw *const palettes;
|
|
/* 0x10 */ const u8 *const tiles_4bpp;
|
|
/* 0x14 */ const u8 *const tiles_8bpp;
|
|
};
|
|
|
|
// No idea why this exists when there is a
|
|
// better random number generator in the math
|
|
// module
|
|
#define PseudoRandom32() \
|
|
({ \
|
|
gPseudoRandom = (gPseudoRandom * 0x196225) + 0x3C6EF35F; \
|
|
gPseudoRandom; \
|
|
})
|
|
|
|
#define MultiplayerPseudoRandom32() \
|
|
({ \
|
|
gMultiplayerPseudoRandom = (gMultiplayerPseudoRandom * 0x196225) + 0x3C6EF35F; \
|
|
gMultiplayerPseudoRandom; \
|
|
})
|
|
|
|
// TODO: align the usage of this between both games
|
|
#if (GAME == GAME_SA1)
|
|
#define PseudoRandBetween(min, max) ((PseudoRandom32() & ((-min) + (max))) + (min))
|
|
#else
|
|
#define PseudoRandBetween(min, max) ((PseudoRandom32() & ((-min) + (max - 1))) + (min))
|
|
#endif
|
|
|
|
extern u32 gFlags;
|
|
extern u32 gFlagsPreVBlank;
|
|
|
|
extern u32 gFrameCount;
|
|
|
|
#define INTR_INDEX_SIO 0
|
|
#define INTR_INDEX_VBLANK 1
|
|
#define INTR_INDEX_HBLANK 2
|
|
#define INTR_INDEX_VCOUNT 3
|
|
#define INTR_INDEX_TIMER0 4
|
|
#define INTR_INDEX_TIMER1 5
|
|
#define INTR_INDEX_TIMER2 6
|
|
#define INTR_INDEX_DMA0 7
|
|
#define INTR_INDEX_DMA1 8
|
|
#define INTR_INDEX_DMA2 9
|
|
#define INTR_INDEX_DMA3 10
|
|
#define INTR_INDEX_KEYPAD 11
|
|
#define INTR_INDEX_GAMEPAK 12
|
|
extern IntrFunc gIntrTable[16];
|
|
extern IntrFunc const gIntrTableTemplate[14];
|
|
extern u32 gIntrMainBuf[0x80];
|
|
|
|
extern struct Task *gCurTask;
|
|
extern struct Task gTasks[MAX_TASK_NUM];
|
|
extern struct Task *gTaskPtrs[MAX_TASK_NUM];
|
|
extern struct Task *gNextTask;
|
|
extern struct Task gEmptyTask;
|
|
extern s32 gNumTasks;
|
|
|
|
extern u16 gInput;
|
|
extern u16 gPrevInput;
|
|
extern u16 gPhysicalInput;
|
|
extern u16 gReleasedKeys;
|
|
extern u16 gRepeatedKeys;
|
|
extern u16 gPressedKeys;
|
|
extern u8 gKeysFirstRepeatIntervals[10];
|
|
extern u8 gRepeatedKeysTestCounter[10];
|
|
extern u8 gKeysContinuedRepeatIntervals[10];
|
|
|
|
extern const u8 *gInputPlaybackData;
|
|
extern struct InputRecorder gInputRecorder;
|
|
extern u16 *gInputRecorderTapeBuffer;
|
|
|
|
extern union MultiSioData gMultiSioSend;
|
|
extern union MultiSioData gMultiSioRecv[4];
|
|
extern u32 gMultiSioStatusFlags;
|
|
extern bool8 gMultiSioEnabled;
|
|
|
|
extern HBlankIntrFunc gHBlankIntrs[4];
|
|
extern HBlankIntrFunc gHBlankCallbacks[4];
|
|
extern u8 gNumHBlankCallbacks;
|
|
extern u8 gNumHBlankIntrs;
|
|
|
|
extern u8 gIwramHeap[TASK_HEAP_SIZE];
|
|
|
|
extern void *gVramHeapStartAddr;
|
|
extern u16 gVramHeapMaxTileSlots;
|
|
extern u16 gVramHeapState[OBJ_VRAM_TOTAL_SIZE / VRAM_HEAP_SEGMENT_SIZE];
|
|
|
|
extern bool8 gExecSoundMain;
|
|
|
|
extern u16 gDispCnt;
|
|
|
|
#define WINREG_WIN0H 0
|
|
#define WINREG_WIN1H 1
|
|
#define WINREG_WIN0V 2
|
|
#define WINREG_WIN1V 3
|
|
#define WINREG_WININ 4
|
|
#define WINREG_WINOUT 5
|
|
|
|
// TODO: Use these everywhere in SA1!
|
|
#define PALETTE_LEN_4BPP 16u
|
|
#define GET_PALETTE_COLOR_OBJ(_paletteId, _colorId) gObjPalette[(_paletteId)*PALETTE_LEN_4BPP + (_colorId)]
|
|
#define GET_PALETTE_COLOR_BG(_paletteId, _colorId) gBgPalette[(_paletteId)*PALETTE_LEN_4BPP + (_colorId)]
|
|
#define SET_PALETTE_COLOR_OBJ(_paletteId, _colorId, _color) GET_PALETTE_COLOR_OBJ(_paletteId, _colorId) = (_color);
|
|
#define SET_PALETTE_COLOR_BG(_paletteId, _colorId, _color) GET_PALETTE_COLOR_BG(_paletteId, _colorId) = (_color);
|
|
|
|
extern winreg_t gWinRegs[6];
|
|
extern struct BlendRegs gBldRegs;
|
|
extern BgAffineReg gBgAffineRegs[NUM_AFFINE_BACKGROUNDS];
|
|
#if (GAME == GAME_SA1)
|
|
extern ColorRaw gObjPalette[OBJ_PLTT_SIZE / sizeof(u16)];
|
|
extern ColorRaw gBgPalette[BG_PLTT_SIZE / sizeof(u16)];
|
|
#else
|
|
extern ColorRaw gObjPalette[16 * PALETTE_LEN_4BPP];
|
|
extern ColorRaw gBgPalette[16 * PALETTE_LEN_4BPP];
|
|
#endif
|
|
extern u16 gBgCntRegs[4];
|
|
|
|
// TODO: Turn this into a struct-array?
|
|
// [4]{s16 x, s16 y}
|
|
extern s16 gBgScrollRegs[NUM_BACKGROUNDS][2];
|
|
|
|
extern OamData gOamMallocBuffer[OAM_ENTRY_COUNT];
|
|
extern OamData gOamBuffer[OAM_ENTRY_COUNT];
|
|
|
|
// NOTE(Jace): This could be u16[2][DISPLAY_HEIGHT][2] (or unsigned Vec2_16?)
|
|
extern int_vcount gBgOffsetsBuffer[2][DISPLAY_HEIGHT][4];
|
|
extern Background *gBackgroundsCopyQueue[16];
|
|
|
|
// This is used to buffer the xy-shift for each background scanline
|
|
extern void *gBgOffsetsHBlankPrimary;
|
|
|
|
extern u16 gSpriteTransformScaleX;
|
|
extern Vec2_16 gSpriteOffset;
|
|
extern u8 gOamMallocOrders_StartIndex[32];
|
|
extern IntrFunc gVBlankCallbacks[4];
|
|
|
|
extern u8 gOamFreeIndex;
|
|
extern u16 gSpriteTransformRotation;
|
|
extern u8 gNumVBlankIntrs;
|
|
extern s16 gSpriteTransformX;
|
|
|
|
extern Tilemap **gTilemapsRef;
|
|
extern u8 gBgSprites_Unknown2[4][4];
|
|
extern u8 gBgSprites_Unknown1[4];
|
|
|
|
#define LOG_GRAPHICS_QUEUE !TRUE
|
|
#if (!PLATFORM_GBA && LOG_GRAPHICS_QUEUE)
|
|
#define GFX_QUEUE_LOG_ADD(gfx) \
|
|
printf("GFX %d: src 0x%p, dst 0x%p, size 0x%04X\n", gVramGraphicsCopyQueueIndex, (gfx)->src, \
|
|
(void *)((intptr_t)(gfx)->dest - (intptr_t)VRAM), (gfx)->size);
|
|
#else
|
|
#define GFX_QUEUE_LOG_ADD(gfx)
|
|
#endif
|
|
extern struct GraphicsData *gVramGraphicsCopyQueue[32];
|
|
extern u8 gVramGraphicsCopyQueueIndex;
|
|
// Because the graphics in the queue only get copied if
|
|
// (gVramGraphicsCopyCursor != gVramGraphicsCopyQueueIndex),
|
|
// just making them equal will pause the queue.
|
|
#define PAUSE_GRAPHICS_QUEUE() gVramGraphicsCopyCursor = gVramGraphicsCopyQueueIndex;
|
|
|
|
#define INC_GRAPHICS_QUEUE_CURSOR(cursor) cursor = (cursor + 1) % ARRAY_COUNT(gVramGraphicsCopyQueue);
|
|
|
|
#if PORTABLE
|
|
// On the GBA we use a fixed heap to allocate memory
|
|
// but on other OS's we malloc and free memory which
|
|
// the graphics queue may be referring to. Instead we
|
|
// make a separate copy of the graphics queue with the
|
|
// pointers we need to copy so that a race condition
|
|
// happens where sprite has been freed but the copy
|
|
// has not happened we don't get invalid memory access
|
|
extern struct GraphicsData gVramGraphicsCopyQueueBuffer[32];
|
|
#define ADD_TO_GRAPHICS_QUEUE(gfx) \
|
|
memcpy(&gVramGraphicsCopyQueueBuffer[gVramGraphicsCopyQueueIndex], gfx, sizeof(struct GraphicsData)); \
|
|
gVramGraphicsCopyQueue[gVramGraphicsCopyQueueIndex] = &gVramGraphicsCopyQueueBuffer[gVramGraphicsCopyQueueIndex]; \
|
|
/* Log has to happen before gVramGraphicsCopyQueueIndex increment */ \
|
|
GFX_QUEUE_LOG_ADD(gfx) \
|
|
INC_GRAPHICS_QUEUE_CURSOR(gVramGraphicsCopyQueueIndex);
|
|
#else
|
|
#define ADD_TO_GRAPHICS_QUEUE(gfx) \
|
|
gVramGraphicsCopyQueue[gVramGraphicsCopyQueueIndex] = gfx; \
|
|
/* Log has to happen before gVramGraphicsCopyQueueIndex increment */ \
|
|
GFX_QUEUE_LOG_ADD(gfx) \
|
|
INC_GRAPHICS_QUEUE_CURSOR(gVramGraphicsCopyQueueIndex);
|
|
#endif
|
|
|
|
#define PAUSE_BACKGROUNDS_QUEUE() gBackgroundsCopyQueueCursor = gBackgroundsCopyQueueIndex;
|
|
|
|
#define INC_BACKGROUNDS_QUEUE_CURSOR(cursor) cursor = (cursor + 1) % ARRAY_COUNT(gBackgroundsCopyQueue);
|
|
|
|
#define ADD_TO_BACKGROUNDS_QUEUE(_bg) \
|
|
gBackgroundsCopyQueue[gBackgroundsCopyQueueIndex] = _bg; \
|
|
INC_BACKGROUNDS_QUEUE_CURSOR(gBackgroundsCopyQueueIndex);
|
|
|
|
extern void *gBgOffsetsHBlankSecondary;
|
|
extern void *gBgOffsetsSecondary;
|
|
#if (GAME == GAME_SA2)
|
|
extern s16 gMosaicReg;
|
|
extern u8 gUnknown_030026F4;
|
|
#endif
|
|
extern s16 gSpriteTransformY;
|
|
extern u8 gVCountSetting;
|
|
extern void *gHBlankCopyTarget;
|
|
extern u8 gBackgroundsCopyQueueIndex;
|
|
extern u8 gHBlankCopySize;
|
|
extern u16 SA2_LABEL(gUnknown_03002A8C);
|
|
//// When paused, the previously-active OAM elements get moved to the end
|
|
//// of the OAM. This is the index of the first currently-inactive element
|
|
extern u8 gOamFirstPausedIndex;
|
|
extern u8 gBackgroundsCopyQueueCursor;
|
|
extern Sprite *gBgSprites[16];
|
|
extern u8 gNumVBlankCallbacks;
|
|
extern void *gBgOffsetsPrimary;
|
|
extern u16 SA2_LABEL(gUnknown_03004D58);
|
|
extern u8 gVramGraphicsCopyCursor;
|
|
extern u8 gOamMallocOrders_EndIndex[0x20];
|
|
extern u8 gBgSpritesCount;
|
|
extern u16 gSpriteTransformScaleY;
|
|
extern u16 gSpriteTransformScaleUnknown;
|
|
extern IntrFunc gVBlankIntrs[4];
|
|
extern s32 gPseudoRandom;
|
|
extern u8 gOamMallocCopiedOrder[128];
|
|
extern struct MultiBootParam gMultiBootParam;
|
|
|
|
extern const struct SpriteTables *gRefSpriteTables;
|
|
|
|
void EngineInit(void);
|
|
void EngineMainLoop(void);
|
|
|
|
#endif
|