mirror of
https://github.com/SAT-R/sa2.git
synced 2026-10-28 09:43:38 +00:00
use libagbsyscall for all builds (#249)
This commit is contained in:
1 parent
9da592bb8e
commit
763812acc3
13 files changed
+383
-1454
No files matched your search
@@ -116,7 +116,7 @@ SDL_MINGW_LIB := $(SDL_MINGW_PKG)/lib
|
||||
SDL_MINGW_FLAGS := -I$(SDL_MINGW_INCLUDE) -D_THREAD_SAFE
|
||||
SDL_MINGW_LIBS := -L$(SDL_MINGW_LIB) -lSDL2main -lSDL2.dll
|
||||
|
||||
LIBABGSYSCALL_LIBS := -L$(ROOT_DIR)/libagbsyscall -lagbsyscall
|
||||
LIBABGSYSCALL_LIBS := -L$(ROOT_DIR)/libagbsyscall/build/$(PLATFORM) -lagbsyscall
|
||||
|
||||
### FILES ###
|
||||
|
||||
@@ -355,13 +355,13 @@ endif
|
||||
ifeq ($(PLATFORM),gba)
|
||||
LIBS := $(ROOT_DIR)/tools/agbcc/lib/libgcc.a $(ROOT_DIR)/tools/agbcc/lib/libc.a $(LIBABGSYSCALL_LIBS)
|
||||
else ifeq ($(PLATFORM),sdl)
|
||||
LIBS := $(shell sdl2-config --cflags --libs)
|
||||
LIBS := $(shell sdl2-config --cflags --libs) $(LIBABGSYSCALL_LIBS) -lm
|
||||
else ifeq ($(PLATFORM),sdl_psp)
|
||||
LIBS := -L$(PSPDEV)/psp/lib -L$(PSPSDK)/lib -lSDL2 -lm -lGL -lpspvram -lpspaudio -lpspvfpu -lpspdisplay -lpspgu -lpspge -lpsphprm -lpspctrl -lpsppower -lpspdebug -lpspnet -lpspnet_apctl -Wl,-zmax-page-size=128
|
||||
LIBS := -L$(PSPDEV)/psp/lib $(LIBABGSYSCALL_LIBS) -L$(PSPSDK)/lib -lSDL2 -lm -lGL -lpspvram -lpspaudio -lpspvfpu -lpspdisplay -lpspgu -lpspge -lpsphprm -lpspctrl -lpsppower -lpspdebug -lpspnet -lpspnet_apctl -Wl,-zmax-page-size=128
|
||||
else ifeq ($(PLATFORM),ps2)
|
||||
LIBS := -T$(PS2SDK)/ee/startup/linkfile -L$(PS2SDK)/common/lib -L$(PS2SDK)/ee/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -lgskit -ldmakit -lps2_drivers -lmc -lpatches -Wl,-zmax-page-size=128
|
||||
LIBS := -T$(PS2SDK)/ee/startup/linkfile $(LIBABGSYSCALL_LIBS) -L$(PS2SDK)/common/lib -L$(PS2SDK)/ee/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -lgskit -ldmakit -lps2_drivers -lmc -lpatches -Wl,-zmax-page-size=128
|
||||
else ifeq ($(PLATFORM),sdl_win32)
|
||||
LIBS := -mwin32 -lkernel32 -lwinmm -lmingw32 -lxinput $(SDL_MINGW_LIBS)
|
||||
LIBS := -mwin32 -lkernel32 -lwinmm -lmingw32 -lxinput $(LIBABGSYSCALL_LIBS) $(SDL_MINGW_LIBS)
|
||||
else ifeq ($(PLATFORM), win32)
|
||||
LIBS := -mwin32 -lkernel32 -lwinmm -lgdi32 -lxinput -lopengl32 $(LIBABGSYSCALL_LIBS)
|
||||
endif
|
||||
@@ -533,12 +533,11 @@ ifeq ($(PLATFORM),gba)
|
||||
$(ROM): $(ELF) libagbsyscall
|
||||
$(OBJCOPY) -O binary --pad-to 0x8400000 $< $@
|
||||
$(FIX) $@ -p -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(GAME_REVISION) --silent
|
||||
else ifeq ($(PLATFORM),win32)
|
||||
$(ROM): $(ELF) libagbsyscall
|
||||
$(OBJCOPY) -O pei-x86-64 $< $@
|
||||
else
|
||||
$(ROM): $(ELF)
|
||||
ifeq ($(PLATFORM),sdl)
|
||||
$(ROM): $(ELF) libagbsyscall
|
||||
ifeq ($(PLATFORM),win32)
|
||||
$(OBJCOPY) -O pei-x86-64 $< $@
|
||||
else ifeq ($(PLATFORM),sdl)
|
||||
cp $< $@
|
||||
else ifeq ($(PLATFORM),sdl_psp)
|
||||
@echo Creating $(ROM) from $(ELF)
|
||||
|
||||
@@ -3,24 +3,6 @@
|
||||
|
||||
#include "gba/types.h"
|
||||
|
||||
/* NOTE:
|
||||
* "Unsafe" versions included for compatibility.
|
||||
* This is just here so if someone accidentally calls
|
||||
* LZUnCompWram, LZUnCompVram, RLUnCompWram orRLUnCompVram, it doesn't fail.
|
||||
*
|
||||
* Please do NOT call them directly if you know the size of the compressed data!
|
||||
* Use Platform_LZDecompress and Platform_RLDecompress instead, and also
|
||||
* make sure to call Platform_LZFree, Platform_RLFree once the data is not needed
|
||||
* anymore.
|
||||
*/
|
||||
#define ENABLE_RL_LZ_LOGGING 1
|
||||
extern unsigned char *Platform_LZDecompress(unsigned char *src, int srcSize);
|
||||
extern unsigned char *Platform_RLDecompress(unsigned char *src, int srcSize);
|
||||
extern void Platform_LZFree(unsigned char *dest);
|
||||
extern void Platform_RLFree(unsigned char *dest);
|
||||
extern void Platform_LZDecompressUnsafe(unsigned char *src, unsigned char *dest);
|
||||
extern void Platform_RLDecompressUnsafe(unsigned char *src, unsigned char *dest);
|
||||
|
||||
extern void Platform_QueueAudio(const s16 *data, u32 numBytes);
|
||||
extern void Platform_ProcessBackgroundsCopyQueue(void);
|
||||
// TODO: Re-enable once #include-ing global.h/core.h/sprite.h does not result in compilation errors.
|
||||
|
||||
+19
-5
@@ -2,7 +2,13 @@
|
||||
PLATFORM ?= gba
|
||||
CPU_ARCH ?= arm
|
||||
|
||||
SHELL := /bin/bash -o pipefail
|
||||
SHELL := /bin/bash -o pipefail
|
||||
OBJ_DIR := build/$(PLATFORM)
|
||||
|
||||
# a special command which ensures that stdout and stderr
|
||||
# get printed instead of output into the makefile
|
||||
infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line))))
|
||||
$(call infoshell, mkdir -p $(OBJ_DIR))
|
||||
|
||||
ifeq ($(PLATFORM),gba)
|
||||
TOOLCHAIN := $(DEVKITARM)
|
||||
@@ -34,6 +40,13 @@ else ifeq ($(CPU_ARCH),i386)
|
||||
TOOLCHAIN := /usr/x86_64-w64-mingw32/
|
||||
PREFIX := x86_64-w64-mingw32-
|
||||
endif
|
||||
else ifeq ($(PLATFORM),sdl_psp)
|
||||
PSPDEV ?= $(HOME)/pspdev
|
||||
PSPSDK := $(PSPDEV)/psp/sdk
|
||||
export PATH := $(PSPDEV)/bin:$(PATH)
|
||||
PREFIX := psp-
|
||||
else ifeq ($(PLATFORM),ps2)
|
||||
PREFIX := mips64r5900el-ps2-elf-
|
||||
else ifneq ($(PLATFORM),sdl)
|
||||
$(error Unknown CPU architecture $(CPU_ARCH))
|
||||
endif # (PLATFORM == gba)
|
||||
@@ -83,10 +96,12 @@ ifneq ($(PLATFORM),gba)
|
||||
CPPFLAGS += -D CPU_ARCH_X86=0
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), sdl)
|
||||
ifeq ($(shell uname -s),Darwin)
|
||||
# -E: Pre-process only (needed for MacOS?)
|
||||
CPP := $(CC1) -E
|
||||
endif
|
||||
endif
|
||||
endif # PLATFORM != gba
|
||||
|
||||
|
||||
@@ -148,10 +163,9 @@ else
|
||||
SRCS := libagbsyscall.c
|
||||
endif
|
||||
|
||||
ASMS := $(foreach syscall, $(SYSCALLS), $(syscall).s) # $(syscall).s should only exist after compiling non-GBA
|
||||
OBJS := $(foreach syscall, $(SYSCALLS), $(syscall).o)
|
||||
OBJS := $(foreach syscall, $(SYSCALLS), $(OBJ_DIR)/$(syscall).o)
|
||||
|
||||
LIB := libagbsyscall.a
|
||||
LIB := $(OBJ_DIR)/libagbsyscall.a
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
@@ -159,7 +173,7 @@ all: $(LIB)
|
||||
@:
|
||||
|
||||
clean:
|
||||
rm -f $(LIB) $(OBJS) $(ASMS)
|
||||
rm -rf build
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
fprintf(stderr, format, __VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define UNUSED
|
||||
|
||||
#else
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
void LZDecompressUnsafe(unsigned char *src, unsigned char *dest, int *uncompressedSize)
|
||||
{
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned char flags = src[srcPos++];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags & 0x80) {
|
||||
int blockSize = (src[srcPos] >> 4) + 3;
|
||||
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
|
||||
|
||||
srcPos += 2;
|
||||
|
||||
int blockPos = destPos - blockDistance;
|
||||
|
||||
// Some Ruby/Sapphire tilesets overflow.
|
||||
if (destPos + blockSize > destSize) {
|
||||
blockSize = destSize - destPos;
|
||||
fprintf(stderr, "Destination buffer overflow.\n");
|
||||
}
|
||||
|
||||
if (blockPos < 0)
|
||||
goto fail;
|
||||
|
||||
for (int j = 0; j < blockSize; j++)
|
||||
dest[destPos++] = dest[blockPos + j];
|
||||
} else {
|
||||
if (destPos >= destSize)
|
||||
goto fail;
|
||||
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize) {
|
||||
*uncompressedSize = destSize;
|
||||
return;
|
||||
}
|
||||
|
||||
flags <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2016 YamaArashi
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
fprintf(stderr, format, __VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define UNUSED
|
||||
|
||||
#else
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
void RLDecompressUnsafe(unsigned char *src, unsigned char *dest, int *uncompressedSize)
|
||||
{
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned char flags = src[srcPos++];
|
||||
bool compressed = ((flags & 0x80) != 0);
|
||||
|
||||
if (compressed) {
|
||||
int length = (flags & 0x7F) + 3;
|
||||
unsigned char data = src[srcPos++];
|
||||
|
||||
if (destPos + length > destSize)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
dest[destPos++] = data;
|
||||
} else {
|
||||
int length = (flags & 0x7F) + 1;
|
||||
|
||||
if (destPos + length > destSize)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize) {
|
||||
*uncompressedSize = destSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while decompressing RL file.\n");
|
||||
}
|
||||
+204
-18
@@ -4,8 +4,7 @@
|
||||
#if CPU_ARCH_X86
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
#include "global.h"
|
||||
#include "gba/syscall.h"
|
||||
#include "gba/gba.h"
|
||||
|
||||
#if (!(defined PLATFORM_GBA) || (PLATFORM_GBA == 0))
|
||||
|
||||
@@ -52,8 +51,18 @@ void CpuSet(const void *inSrc, void *inDest, u32 control)
|
||||
#endif
|
||||
|
||||
#if L_CpuFastSet
|
||||
static uint32_t CPUReadMemory(const void *src)
|
||||
{
|
||||
uint32_t val;
|
||||
memcpy(&val, src, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void CPUWriteMemory(void *dest, uint32_t val) { memcpy(dest, &val, sizeof(val)); }
|
||||
|
||||
void CpuFastSet(const void *inSrc, void *inDest, u32 control)
|
||||
{
|
||||
#if CPU_ARCH_X86
|
||||
const u32 *src = inSrc;
|
||||
const u32 *dest = inDest;
|
||||
assert(((uintptr_t)src & 0x3) == 0); // should be aligned by 4
|
||||
@@ -63,8 +72,6 @@ void CpuFastSet(const void *inSrc, void *inDest, u32 control)
|
||||
word_count = ((word_count + 7) & ~0x7);
|
||||
|
||||
const u32 *target = &dest[word_count];
|
||||
|
||||
#if CPU_ARCH_X86
|
||||
if (control & CPU_FAST_SET_SRC_FIXED) {
|
||||
__m128i v = _mm_set_epi32(*src, *src, *src, *src);
|
||||
|
||||
@@ -86,7 +93,38 @@ void CpuFastSet(const void *inSrc, void *inDest, u32 control)
|
||||
src += 4;
|
||||
}
|
||||
#else
|
||||
assert(FALSE); // Arch not implemented
|
||||
int count = control & 0x1FFFFF;
|
||||
|
||||
const u8 *source = inSrc;
|
||||
u8 *dest = inDest;
|
||||
|
||||
// source = (u8 *)((uint32_t )source & ~3);
|
||||
// dest = (u8 *)((uint32_t )dest & ~3);
|
||||
|
||||
// fill?
|
||||
if ((control >> 24) & 1) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
while (count > 0) {
|
||||
// BIOS always transfers 32 bytes at a time
|
||||
for (int i = 0; i < 8; i++) {
|
||||
CPUWriteMemory(dest, value);
|
||||
dest += 4;
|
||||
}
|
||||
count -= 8;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count > 0) {
|
||||
// BIOS always transfers 32 bytes at a time
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
CPUWriteMemory(dest, value);
|
||||
source += 4;
|
||||
dest += 4;
|
||||
}
|
||||
count -= 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -205,12 +243,55 @@ void SoftResetExram(u32 resetFlags)
|
||||
u16 Sqrt(u32 num) { return (u16)sqrt((double)num); }
|
||||
#endif
|
||||
|
||||
#if L_ArcTan
|
||||
u16 ArcTan(s16 x) { return (u16)atanf((float)x); }
|
||||
#if L_ArcTan || L_ArcTan2
|
||||
// Source modified from mGBA
|
||||
// https://github.com/mgba-emu/mgba/blob/93fed7144836d20c9087ae88bc67dfdde834db9d/src/gba/bios.c#L291
|
||||
u16 ArcTan(s16 i)
|
||||
{
|
||||
s32 a = -((i * i) >> 14);
|
||||
s32 b = ((0xA9 * a) >> 14) + 0x390;
|
||||
b = ((b * a) >> 14) + 0x91C;
|
||||
b = ((b * a) >> 14) + 0xFB6;
|
||||
b = ((b * a) >> 14) + 0x16AA;
|
||||
b = ((b * a) >> 14) + 0x2081;
|
||||
b = ((b * a) >> 14) + 0x3651;
|
||||
b = ((b * a) >> 14) + 0xA2F9;
|
||||
|
||||
return (i * b) >> 16;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_ArcTan2
|
||||
u16 ArcTan2(s16 x, s16 y) { return (u16)atan2f((float)x, (float)y); }
|
||||
// Source modified from mGBA
|
||||
// https://github.com/mgba-emu/mgba/blob/93fed7144836d20c9087ae88bc67dfdde834db9d/src/gba/bios.c#L319
|
||||
u16 ArcTan2(s16 x, s16 y)
|
||||
{
|
||||
if (!y) {
|
||||
if (x >= 0)
|
||||
return 0;
|
||||
return 0x8000;
|
||||
}
|
||||
if (!x) {
|
||||
if (y >= 0)
|
||||
return 0x4000;
|
||||
return 0xC000;
|
||||
}
|
||||
if (y >= 0) {
|
||||
if (x >= 0) {
|
||||
if (x >= y)
|
||||
return ArcTan((y << 14) / x);
|
||||
} else if (-x >= y)
|
||||
return ArcTan((y << 14) / x) + 0x8000;
|
||||
return 0x4000 - ArcTan((x << 14) / y);
|
||||
} else {
|
||||
if (x <= 0) {
|
||||
if (-x > -y)
|
||||
return ArcTan((y << 14) / x) + 0x8000;
|
||||
} else if (x >= -y)
|
||||
return ArcTan((y << 14) / x) + 0x10000;
|
||||
return 0xC000 - ArcTan((x << 14) / y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_HuffUnComp
|
||||
@@ -218,35 +299,140 @@ void HuffUnComp(void) { }
|
||||
#endif
|
||||
|
||||
#if L_LZ77UnCompWram
|
||||
#include "platform/platform.h"
|
||||
#include "ext/gbagfx/lz.c"
|
||||
|
||||
void LZ77UnCompWram(const void *src, void *dest) { Platform_LZDecompressUnsafe(src, dest); }
|
||||
void LZ77UnCompWram(const void *src, void *dest)
|
||||
{
|
||||
int size = 0;
|
||||
LZDecompressUnsafe(src, dest, &size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_LZ77UnCompVram
|
||||
#include "platform/platform.h"
|
||||
#include "ext/gbagfx/lz.c"
|
||||
|
||||
void LZ77UnCompVram(const void *src, void *dest) { Platform_LZDecompressUnsafe(src, dest); }
|
||||
void LZ77UnCompVram(const void *src, void *dest)
|
||||
{
|
||||
int size = 0;
|
||||
LZDecompressUnsafe(src, dest, &size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_RLUnCompWram
|
||||
#include "platform/platform.h"
|
||||
#include "ext/gbagfx/rl.c"
|
||||
|
||||
void RLUnCompWram(const void *src, void *dest) { Platform_RLDecompressUnsafe(src, dest); }
|
||||
void RLUnCompWram(const void *src, void *dest)
|
||||
{
|
||||
int size = 0;
|
||||
RLDecompressUnsafe(src, dest, &size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_RLUnCompVram
|
||||
#include "platform/platform.h"
|
||||
#include "ext/gbagfx/rl.c"
|
||||
|
||||
void RLUnCompVram(const void *src, void *dest) { Platform_RLDecompressUnsafe(src, dest); }
|
||||
void RLUnCompVram(const void *src, void *dest)
|
||||
{
|
||||
int size = 0;
|
||||
RLDecompressUnsafe(src, dest, &size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_ObjAffineSet || L_BgAffineSet
|
||||
const s16 sineTable[256]
|
||||
= { (s16)0x0000, (s16)0x0192, (s16)0x0323, (s16)0x04B5, (s16)0x0645, (s16)0x07D5, (s16)0x0964, (s16)0x0AF1, (s16)0x0C7C, (s16)0x0E05,
|
||||
(s16)0x0F8C, (s16)0x1111, (s16)0x1294, (s16)0x1413, (s16)0x158F, (s16)0x1708, (s16)0x187D, (s16)0x19EF, (s16)0x1B5D, (s16)0x1CC6,
|
||||
(s16)0x1E2B, (s16)0x1F8B, (s16)0x20E7, (s16)0x223D, (s16)0x238E, (s16)0x24DA, (s16)0x261F, (s16)0x275F, (s16)0x2899, (s16)0x29CD,
|
||||
(s16)0x2AFA, (s16)0x2C21, (s16)0x2D41, (s16)0x2E5A, (s16)0x2F6B, (s16)0x3076, (s16)0x3179, (s16)0x3274, (s16)0x3367, (s16)0x3453,
|
||||
(s16)0x3536, (s16)0x3612, (s16)0x36E5, (s16)0x37AF, (s16)0x3871, (s16)0x392A, (s16)0x39DA, (s16)0x3A82, (s16)0x3B20, (s16)0x3BB6,
|
||||
(s16)0x3C42, (s16)0x3CC5, (s16)0x3D3E, (s16)0x3DAE, (s16)0x3E14, (s16)0x3E71, (s16)0x3EC5, (s16)0x3F0E, (s16)0x3F4E, (s16)0x3F84,
|
||||
(s16)0x3FB1, (s16)0x3FD3, (s16)0x3FEC, (s16)0x3FFB, (s16)0x4000, (s16)0x3FFB, (s16)0x3FEC, (s16)0x3FD3, (s16)0x3FB1, (s16)0x3F84,
|
||||
(s16)0x3F4E, (s16)0x3F0E, (s16)0x3EC5, (s16)0x3E71, (s16)0x3E14, (s16)0x3DAE, (s16)0x3D3E, (s16)0x3CC5, (s16)0x3C42, (s16)0x3BB6,
|
||||
(s16)0x3B20, (s16)0x3A82, (s16)0x39DA, (s16)0x392A, (s16)0x3871, (s16)0x37AF, (s16)0x36E5, (s16)0x3612, (s16)0x3536, (s16)0x3453,
|
||||
(s16)0x3367, (s16)0x3274, (s16)0x3179, (s16)0x3076, (s16)0x2F6B, (s16)0x2E5A, (s16)0x2D41, (s16)0x2C21, (s16)0x2AFA, (s16)0x29CD,
|
||||
(s16)0x2899, (s16)0x275F, (s16)0x261F, (s16)0x24DA, (s16)0x238E, (s16)0x223D, (s16)0x20E7, (s16)0x1F8B, (s16)0x1E2B, (s16)0x1CC6,
|
||||
(s16)0x1B5D, (s16)0x19EF, (s16)0x187D, (s16)0x1708, (s16)0x158F, (s16)0x1413, (s16)0x1294, (s16)0x1111, (s16)0x0F8C, (s16)0x0E05,
|
||||
(s16)0x0C7C, (s16)0x0AF1, (s16)0x0964, (s16)0x07D5, (s16)0x0645, (s16)0x04B5, (s16)0x0323, (s16)0x0192, (s16)0x0000, (s16)0xFE6E,
|
||||
(s16)0xFCDD, (s16)0xFB4B, (s16)0xF9BB, (s16)0xF82B, (s16)0xF69C, (s16)0xF50F, (s16)0xF384, (s16)0xF1FB, (s16)0xF074, (s16)0xEEEF,
|
||||
(s16)0xED6C, (s16)0xEBED, (s16)0xEA71, (s16)0xE8F8, (s16)0xE783, (s16)0xE611, (s16)0xE4A3, (s16)0xE33A, (s16)0xE1D5, (s16)0xE075,
|
||||
(s16)0xDF19, (s16)0xDDC3, (s16)0xDC72, (s16)0xDB26, (s16)0xD9E1, (s16)0xD8A1, (s16)0xD767, (s16)0xD633, (s16)0xD506, (s16)0xD3DF,
|
||||
(s16)0xD2BF, (s16)0xD1A6, (s16)0xD095, (s16)0xCF8A, (s16)0xCE87, (s16)0xCD8C, (s16)0xCC99, (s16)0xCBAD, (s16)0xCACA, (s16)0xC9EE,
|
||||
(s16)0xC91B, (s16)0xC851, (s16)0xC78F, (s16)0xC6D6, (s16)0xC626, (s16)0xC57E, (s16)0xC4E0, (s16)0xC44A, (s16)0xC3BE, (s16)0xC33B,
|
||||
(s16)0xC2C2, (s16)0xC252, (s16)0xC1EC, (s16)0xC18F, (s16)0xC13B, (s16)0xC0F2, (s16)0xC0B2, (s16)0xC07C, (s16)0xC04F, (s16)0xC02D,
|
||||
(s16)0xC014, (s16)0xC005, (s16)0xC000, (s16)0xC005, (s16)0xC014, (s16)0xC02D, (s16)0xC04F, (s16)0xC07C, (s16)0xC0B2, (s16)0xC0F2,
|
||||
(s16)0xC13B, (s16)0xC18F, (s16)0xC1EC, (s16)0xC252, (s16)0xC2C2, (s16)0xC33B, (s16)0xC3BE, (s16)0xC44A, (s16)0xC4E0, (s16)0xC57E,
|
||||
(s16)0xC626, (s16)0xC6D6, (s16)0xC78F, (s16)0xC851, (s16)0xC91B, (s16)0xC9EE, (s16)0xCACA, (s16)0xCBAD, (s16)0xCC99, (s16)0xCD8C,
|
||||
(s16)0xCE87, (s16)0xCF8A, (s16)0xD095, (s16)0xD1A6, (s16)0xD2BF, (s16)0xD3DF, (s16)0xD506, (s16)0xD633, (s16)0xD767, (s16)0xD8A1,
|
||||
(s16)0xD9E1, (s16)0xDB26, (s16)0xDC72, (s16)0xDDC3, (s16)0xDF19, (s16)0xE075, (s16)0xE1D5, (s16)0xE33A, (s16)0xE4A3, (s16)0xE611,
|
||||
(s16)0xE783, (s16)0xE8F8, (s16)0xEA71, (s16)0xEBED, (s16)0xED6C, (s16)0xEEEF, (s16)0xF074, (s16)0xF1FB, (s16)0xF384, (s16)0xF50F,
|
||||
(s16)0xF69C, (s16)0xF82B, (s16)0xF9BB, (s16)0xFB4B, (s16)0xFCDD, (s16)0xFE6E };
|
||||
#endif
|
||||
|
||||
#if L_BgAffineSet
|
||||
void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count) { }
|
||||
// Source modified from vba
|
||||
// https://github.com/visualboyadvance-m/visualboyadvance-m/blob/0ceab88df51ca8b0ceb3bd30d9c296553cfa583e/src/core/gba/internal/gbaBios.cpp#L196
|
||||
void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count)
|
||||
{
|
||||
for (s32 i = 0; i < count; i++) {
|
||||
s32 cx = src[i].texX;
|
||||
s32 cy = src[i].texY;
|
||||
s16 dispx = src[i].scrX;
|
||||
s16 dispy = src[i].scrY;
|
||||
s16 rx = src[i].sx;
|
||||
s16 ry = src[i].sy;
|
||||
u16 theta = src[i].alpha >> 8;
|
||||
s32 a = sineTable[(theta + 0x40) & 255];
|
||||
s32 b = sineTable[theta];
|
||||
|
||||
s16 dx = (rx * a) >> 14;
|
||||
s16 dmx = (rx * b) >> 14;
|
||||
s16 dy = (ry * b) >> 14;
|
||||
s16 dmy = (ry * a) >> 14;
|
||||
|
||||
dest[i].pa = dx;
|
||||
dest[i].pb = -dmx;
|
||||
dest[i].pc = dy;
|
||||
dest[i].pd = dmy;
|
||||
|
||||
s32 startx = cx - dx * dispx + dmx * dispy;
|
||||
s32 starty = cy - dy * dispx - dmy * dispy;
|
||||
|
||||
dest[i].dx = startx;
|
||||
dest[i].dy = starty;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if L_ObjAffineSet
|
||||
void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset) { }
|
||||
// Source modified from vba
|
||||
// https://github.com/visualboyadvance-m/visualboyadvance-m/blob/0ceab88df51ca8b0ceb3bd30d9c296553cfa583e/src/core/gba/internal/gbaBios.cpp#L796
|
||||
static void CPUWriteHalfWord(void *dest, uint16_t val) { memcpy(dest, &val, sizeof(val)); }
|
||||
|
||||
void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset)
|
||||
{
|
||||
for (s32 i = 0; i < count; i++) {
|
||||
s16 rx = src[i].xScale;
|
||||
s16 ry = src[i].yScale;
|
||||
u16 theta = src[i].rotation >> 8;
|
||||
|
||||
s32 a = (s32)sineTable[(theta + 64) & 255];
|
||||
s32 b = (s32)sineTable[theta];
|
||||
|
||||
s16 dx = ((s32)rx * a) >> 14;
|
||||
s16 dmx = ((s32)rx * b) >> 14;
|
||||
s16 dy = ((s32)ry * b) >> 14;
|
||||
s16 dmy = ((s32)ry * a) >> 14;
|
||||
|
||||
CPUWriteHalfWord(dest, dx);
|
||||
dest += offset;
|
||||
CPUWriteHalfWord(dest, -dmx);
|
||||
dest += offset;
|
||||
CPUWriteHalfWord(dest, dy);
|
||||
dest += offset;
|
||||
CPUWriteHalfWord(dest, dmy);
|
||||
dest += offset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Stubs */
|
||||
|
||||
@@ -280,7 +280,7 @@ include songs.mk
|
||||
|
||||
$(ELF): $(OBJS) $(LDSCRIPT) libagbsyscall
|
||||
@echo "$(LD) -T $(LD_SCRIPT) -Map $(MAP) <objects> <lib>"
|
||||
@$(LD) -T $(LDSCRIPT) -Map $(MAP) $(OBJS) ../../../tools/agbcc/lib/libgcc.a ../../../tools/agbcc/lib/libc.a -L../../../libagbsyscall -lagbsyscall -o $@
|
||||
@$(LD) -T $(LDSCRIPT) -Map $(MAP) $(OBJS) ../../../tools/agbcc/lib/libgcc.a ../../../tools/agbcc/lib/libc.a -L../../../libagbsyscall/build/gba -lagbsyscall -o $@
|
||||
|
||||
%.gba: %.elf
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "platform/ext/gbagfx/global.h"
|
||||
#include "platform/ext/gbagfx/lz.h"
|
||||
|
||||
unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize)
|
||||
{
|
||||
if (srcSize < 4)
|
||||
goto fail;
|
||||
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
|
||||
unsigned char *dest = malloc(destSize);
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;) {
|
||||
if (srcPos >= srcSize)
|
||||
goto fail;
|
||||
|
||||
unsigned char flags = src[srcPos++];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags & 0x80) {
|
||||
if (srcPos + 1 >= srcSize)
|
||||
goto fail;
|
||||
|
||||
int blockSize = (src[srcPos] >> 4) + 3;
|
||||
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
|
||||
|
||||
srcPos += 2;
|
||||
|
||||
int blockPos = destPos - blockDistance;
|
||||
|
||||
// Some Ruby/Sapphire tilesets overflow.
|
||||
if (destPos + blockSize > destSize) {
|
||||
blockSize = destSize - destPos;
|
||||
fprintf(stderr, "Destination buffer overflow.\n");
|
||||
}
|
||||
|
||||
if (blockPos < 0)
|
||||
goto fail;
|
||||
|
||||
for (int j = 0; j < blockSize; j++)
|
||||
dest[destPos++] = dest[blockPos + j];
|
||||
} else {
|
||||
if (srcPos >= srcSize || destPos >= destSize)
|
||||
goto fail;
|
||||
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize) {
|
||||
*uncompressedSize = destSize;
|
||||
return dest;
|
||||
}
|
||||
|
||||
flags <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
|
||||
}
|
||||
|
||||
void LZDecompressUnsafe(unsigned char *src, unsigned char *dest, int *uncompressedSize)
|
||||
{
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned char flags = src[srcPos++];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags & 0x80) {
|
||||
int blockSize = (src[srcPos] >> 4) + 3;
|
||||
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
|
||||
|
||||
srcPos += 2;
|
||||
|
||||
int blockPos = destPos - blockDistance;
|
||||
|
||||
// Some Ruby/Sapphire tilesets overflow.
|
||||
if (destPos + blockSize > destSize) {
|
||||
blockSize = destSize - destPos;
|
||||
fprintf(stderr, "Destination buffer overflow.\n");
|
||||
}
|
||||
|
||||
if (blockPos < 0)
|
||||
goto fail;
|
||||
|
||||
for (int j = 0; j < blockSize; j++)
|
||||
dest[destPos++] = dest[blockPos + j];
|
||||
} else {
|
||||
if (destPos >= destSize)
|
||||
goto fail;
|
||||
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize) {
|
||||
*uncompressedSize = destSize;
|
||||
return;
|
||||
}
|
||||
|
||||
flags <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
|
||||
}
|
||||
|
||||
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance)
|
||||
{
|
||||
if (srcSize <= 0)
|
||||
goto fail;
|
||||
|
||||
int worstCaseDestSize = 4 + srcSize + ((srcSize + 7) / 8);
|
||||
|
||||
// Round up to the next multiple of four.
|
||||
worstCaseDestSize = (worstCaseDestSize + 3) & ~3;
|
||||
|
||||
unsigned char *dest = malloc(worstCaseDestSize);
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
// header
|
||||
dest[0] = 0x10; // LZ compression type
|
||||
dest[1] = (unsigned char)srcSize;
|
||||
dest[2] = (unsigned char)(srcSize >> 8);
|
||||
dest[3] = (unsigned char)(srcSize >> 16);
|
||||
|
||||
int srcPos = 0;
|
||||
int destPos = 4;
|
||||
|
||||
for (;;) {
|
||||
unsigned char *flags = &dest[destPos++];
|
||||
*flags = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int bestBlockDistance = 0;
|
||||
int bestBlockSize = 0;
|
||||
int blockDistance = minDistance;
|
||||
|
||||
while (blockDistance <= srcPos && blockDistance <= 0x1000) {
|
||||
int blockStart = srcPos - blockDistance;
|
||||
int blockSize = 0;
|
||||
|
||||
while (blockSize < 18
|
||||
&& srcPos + blockSize < srcSize
|
||||
&& src[blockStart + blockSize] == src[srcPos + blockSize])
|
||||
blockSize++;
|
||||
|
||||
if (blockSize > bestBlockSize) {
|
||||
bestBlockDistance = blockDistance;
|
||||
bestBlockSize = blockSize;
|
||||
|
||||
if (blockSize == 18)
|
||||
break;
|
||||
}
|
||||
|
||||
blockDistance++;
|
||||
}
|
||||
|
||||
if (bestBlockSize >= 3) {
|
||||
*flags |= (0x80 >> i);
|
||||
srcPos += bestBlockSize;
|
||||
bestBlockSize -= 3;
|
||||
bestBlockDistance--;
|
||||
dest[destPos++] = (bestBlockSize << 4) | ((unsigned int)bestBlockDistance >> 8);
|
||||
dest[destPos++] = (unsigned char)bestBlockDistance;
|
||||
} else {
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (srcPos == srcSize) {
|
||||
// Pad to multiple of 4 bytes.
|
||||
int remainder = destPos % 4;
|
||||
|
||||
if (remainder != 0) {
|
||||
for (int i = 0; i < 4 - remainder; i++)
|
||||
dest[destPos++] = 0;
|
||||
}
|
||||
|
||||
*compressedSize = destPos;
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while compressing LZ file.\n");
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
// Copyright (c) 2016 YamaArashi
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "platform/ext/gbagfx/global.h"
|
||||
#include "platform/ext/gbagfx/rl.h"
|
||||
|
||||
unsigned char *RLDecompress(unsigned char *src, int srcSize, int *uncompressedSize)
|
||||
{
|
||||
if (srcSize < 4)
|
||||
goto fail;
|
||||
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
|
||||
unsigned char *dest = malloc(destSize);
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (srcPos >= srcSize)
|
||||
goto fail;
|
||||
|
||||
unsigned char flags = src[srcPos++];
|
||||
bool compressed = ((flags & 0x80) != 0);
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
int length = (flags & 0x7F) + 3;
|
||||
unsigned char data = src[srcPos++];
|
||||
|
||||
if (destPos + length > destSize)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
dest[destPos++] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = (flags & 0x7F) + 1;
|
||||
|
||||
if (destPos + length > destSize)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize)
|
||||
{
|
||||
*uncompressedSize = destSize;
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while decompressing RL file.\n");
|
||||
}
|
||||
|
||||
void RLDecompressUnsafe(unsigned char *src, unsigned char *dest, int *uncompressedSize)
|
||||
{
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned char flags = src[srcPos++];
|
||||
bool compressed = ((flags & 0x80) != 0);
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
int length = (flags & 0x7F) + 3;
|
||||
unsigned char data = src[srcPos++];
|
||||
|
||||
if (destPos + length > destSize)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
dest[destPos++] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = (flags & 0x7F) + 1;
|
||||
|
||||
if (destPos + length > destSize)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize)
|
||||
{
|
||||
*uncompressedSize = destSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while decompressing RL file.\n");
|
||||
}
|
||||
|
||||
unsigned char *RLCompress(unsigned char *src, int srcSize, int *compressedSize)
|
||||
{
|
||||
if (srcSize <= 0)
|
||||
goto fail;
|
||||
|
||||
int worstCaseDestSize = 4 + srcSize * 2;
|
||||
|
||||
// Round up to the next multiple of four.
|
||||
worstCaseDestSize = (worstCaseDestSize + 3) & ~3;
|
||||
|
||||
unsigned char *dest = malloc(worstCaseDestSize);
|
||||
|
||||
if (dest == NULL)
|
||||
goto fail;
|
||||
|
||||
// header
|
||||
dest[0] = 0x30; // RL compression type
|
||||
dest[1] = (unsigned char)srcSize;
|
||||
dest[2] = (unsigned char)(srcSize >> 8);
|
||||
dest[3] = (unsigned char)(srcSize >> 16);
|
||||
|
||||
int srcPos = 0;
|
||||
int destPos = 4;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bool compress = false;
|
||||
int uncompressedStart = srcPos;
|
||||
int uncompressedLength = 0;
|
||||
|
||||
while (srcPos < srcSize && uncompressedLength < (0x7F + 1))
|
||||
{
|
||||
compress = (srcPos + 2 < srcSize && src[srcPos] == src[srcPos + 1] && src[srcPos] == src[srcPos + 2]);
|
||||
|
||||
if (compress)
|
||||
break;
|
||||
|
||||
srcPos++;
|
||||
uncompressedLength++;
|
||||
}
|
||||
|
||||
if (uncompressedLength > 0)
|
||||
{
|
||||
dest[destPos++] = uncompressedLength - 1;
|
||||
|
||||
for (int i = 0; i < uncompressedLength; i++)
|
||||
dest[destPos++] = src[uncompressedStart + i];
|
||||
}
|
||||
|
||||
if (compress)
|
||||
{
|
||||
unsigned char data = src[srcPos];
|
||||
int compressedLength = 0;
|
||||
|
||||
while (compressedLength < (0x7F + 3)
|
||||
&& srcPos + compressedLength < srcSize
|
||||
&& src[srcPos + compressedLength] == data)
|
||||
{
|
||||
compressedLength++;
|
||||
}
|
||||
|
||||
dest[destPos++] = 0x80 | (compressedLength - 3);
|
||||
dest[destPos++] = data;
|
||||
|
||||
srcPos += compressedLength;
|
||||
}
|
||||
|
||||
if (srcPos == srcSize)
|
||||
{
|
||||
// Pad to multiple of 4 bytes.
|
||||
int remainder = destPos % 4;
|
||||
|
||||
if (remainder != 0)
|
||||
{
|
||||
for (int i = 0; i < 4 - remainder; i++)
|
||||
dest[destPos++] = 0;
|
||||
}
|
||||
|
||||
*compressedSize = destPos;
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
FATAL_ERROR("Fatal error while compressing RL file.\n");
|
||||
}
|
||||
@@ -20,10 +20,6 @@
|
||||
|
||||
#include "global.h"
|
||||
#include "core.h"
|
||||
#include "multi_sio.h"
|
||||
#include "gba/defines.h"
|
||||
#include "gba/io_reg.h"
|
||||
#include "gba/types.h"
|
||||
#include "lib/agb_flash/flash_internal.h"
|
||||
#include "platform/shared/dma.h"
|
||||
#include "platform/shared/input.h"
|
||||
@@ -665,405 +661,6 @@ u16 Platform_GetKeyInput(void)
|
||||
return keys;
|
||||
}
|
||||
|
||||
// BIOS function implementations are based on the VBA-M source code.
|
||||
|
||||
// safe unaligned access for MIPS
|
||||
static uint32_t CPUReadMemory(const void *src)
|
||||
{
|
||||
uint32_t val;
|
||||
memcpy(&val, src, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void CPUWriteMemory(void *dest, uint32_t val) { memcpy(dest, &val, sizeof(val)); }
|
||||
|
||||
static uint16_t CPUReadHalfWord(const void *src)
|
||||
{
|
||||
uint16_t val;
|
||||
memcpy(&val, src, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void CPUWriteHalfWord(void *dest, uint16_t val) { memcpy(dest, &val, sizeof(val)); }
|
||||
|
||||
static uint8_t CPUReadByte(const void *src) { return *(uint8_t *)src; }
|
||||
|
||||
static void CPUWriteByte(void *dest, uint8_t val) { *(uint8_t *)dest = val; }
|
||||
|
||||
void CpuSet(const void *src, void *dst, u32 cnt)
|
||||
{
|
||||
if (dst == NULL) {
|
||||
puts("Attempted to CpuSet to NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int count = cnt & 0x1FFFFF;
|
||||
|
||||
const u8 *source = src;
|
||||
u8 *dest = dst;
|
||||
|
||||
// 32-bit ?
|
||||
if ((cnt >> 26) & 1) {
|
||||
// assert(((uintptr_t)src & ~3) == (uintptr_t)src);
|
||||
// assert(((uintptr_t)dst & ~3) == (uintptr_t)dst);
|
||||
|
||||
// needed for 32-bit mode!
|
||||
// source = (u8 *)((uint32_t )source & ~3);
|
||||
// dest = (u8 *)((uint32_t )dest & ~3);
|
||||
|
||||
// fill ?
|
||||
if ((cnt >> 24) & 1) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
while (count) {
|
||||
CPUWriteMemory(dest, value);
|
||||
dest += 4;
|
||||
count--;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count) {
|
||||
CPUWriteMemory(dest, CPUReadMemory(source));
|
||||
source += 4;
|
||||
dest += 4;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No align on 16-bit fill?
|
||||
// assert(((uintptr_t)src & ~1) == (uintptr_t)src);
|
||||
// assert(((uintptr_t)dst & ~1) == (uintptr_t)dst);
|
||||
|
||||
// 16-bit fill?
|
||||
if ((cnt >> 24) & 1) {
|
||||
uint16_t value = CPUReadHalfWord(source);
|
||||
while (count) {
|
||||
CPUWriteHalfWord(dest, value);
|
||||
dest += 2;
|
||||
count--;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count) {
|
||||
CPUWriteHalfWord(dest, CPUReadHalfWord(source));
|
||||
source += 2;
|
||||
dest += 2;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CpuFastSet(const void *src, void *dst, u32 cnt)
|
||||
{
|
||||
if (dst == NULL) {
|
||||
puts("Attempted to CpuFastSet to NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int count = cnt & 0x1FFFFF;
|
||||
|
||||
const u8 *source = src;
|
||||
u8 *dest = dst;
|
||||
|
||||
// source = (u8 *)((uint32_t )source & ~3);
|
||||
// dest = (u8 *)((uint32_t )dest & ~3);
|
||||
|
||||
// fill?
|
||||
if ((cnt >> 24) & 1) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
while (count > 0) {
|
||||
// BIOS always transfers 32 bytes at a time
|
||||
for (int i = 0; i < 8; i++) {
|
||||
CPUWriteMemory(dest, value);
|
||||
dest += 4;
|
||||
}
|
||||
count -= 8;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count > 0) {
|
||||
// BIOS always transfers 32 bytes at a time
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
CPUWriteMemory(dest, value);
|
||||
source += 4;
|
||||
dest += 4;
|
||||
}
|
||||
count -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LZ77UnCompVram(const void *src_, void *dest_)
|
||||
{
|
||||
const u8 *src = (const u8 *)src_;
|
||||
u8 *dest = dest_;
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned char flags = src[srcPos++];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags & 0x80) {
|
||||
int blockSize = (src[srcPos] >> 4) + 3;
|
||||
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
|
||||
|
||||
srcPos += 2;
|
||||
|
||||
int blockPos = destPos - blockDistance;
|
||||
|
||||
// Some Ruby/Sapphire tilesets overflow.
|
||||
if (destPos + blockSize > destSize) {
|
||||
blockSize = destSize - destPos;
|
||||
// fprintf(stderr, "Destination buffer overflow.\n");
|
||||
puts("Destination buffer overflow.\n");
|
||||
}
|
||||
|
||||
if (blockPos < 0)
|
||||
goto fail;
|
||||
|
||||
for (int j = 0; j < blockSize; j++)
|
||||
dest[destPos++] = dest[blockPos + j];
|
||||
} else {
|
||||
if (destPos >= destSize)
|
||||
goto fail;
|
||||
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
flags <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
puts("Fatal error while decompressing LZ file.\n");
|
||||
}
|
||||
|
||||
void LZ77UnCompWram(const void *src, void *dst)
|
||||
{
|
||||
const uint8_t *source = src;
|
||||
uint8_t *dest = dst;
|
||||
|
||||
uint32_t header = CPUReadMemory(source);
|
||||
source += 4;
|
||||
|
||||
int len = header >> 8;
|
||||
|
||||
while (len > 0) {
|
||||
uint8_t d = CPUReadByte(source++);
|
||||
|
||||
if (d) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (d & 0x80) {
|
||||
uint16_t data = CPUReadByte(source++) << 8;
|
||||
data |= CPUReadByte(source++);
|
||||
int length = (data >> 12) + 3;
|
||||
int offset = (data & 0x0FFF);
|
||||
uint8_t *windowOffset = dest - offset - 1;
|
||||
for (int i2 = 0; i2 < length; i2++) {
|
||||
CPUWriteByte(dest++, CPUReadByte(windowOffset++));
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
CPUWriteByte(dest++, CPUReadByte(source++));
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
d <<= 1;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
CPUWriteByte(dest++, CPUReadByte(source++));
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RLUnCompWram(const void *src, void *dest)
|
||||
{
|
||||
int remaining = CPUReadMemory(src) >> 8;
|
||||
int blockHeader;
|
||||
int block;
|
||||
src += 4;
|
||||
while (remaining > 0) {
|
||||
blockHeader = CPUReadByte(src);
|
||||
src++;
|
||||
if (blockHeader & 0x80) // Compressed?
|
||||
{
|
||||
blockHeader &= 0x7F;
|
||||
blockHeader += 3;
|
||||
block = CPUReadByte(src);
|
||||
src++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
CPUWriteByte(dest, block);
|
||||
dest++;
|
||||
}
|
||||
} else // Uncompressed
|
||||
{
|
||||
blockHeader++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
u8 byte = CPUReadByte(src);
|
||||
src++;
|
||||
CPUWriteByte(dest, byte);
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RLUnCompVram(const void *src, void *dest)
|
||||
{
|
||||
int remaining = CPUReadMemory(src) >> 8;
|
||||
int padding = (4 - remaining) & 0x3;
|
||||
int blockHeader;
|
||||
int block;
|
||||
int halfWord = 0;
|
||||
src += 4;
|
||||
while (remaining > 0) {
|
||||
blockHeader = CPUReadByte(src);
|
||||
src++;
|
||||
if (blockHeader & 0x80) // Compressed?
|
||||
{
|
||||
blockHeader &= 0x7F;
|
||||
blockHeader += 3;
|
||||
block = CPUReadByte(src);
|
||||
src++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
if ((uintptr_t)dest & 1) {
|
||||
halfWord |= block << 8;
|
||||
CPUWriteHalfWord((void *)((uintptr_t)dest ^ 1), halfWord);
|
||||
} else
|
||||
halfWord = block;
|
||||
dest++;
|
||||
}
|
||||
} else // Uncompressed
|
||||
{
|
||||
blockHeader++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
u8 byte = CPUReadByte(src);
|
||||
src++;
|
||||
if ((uintptr_t)dest & 1) {
|
||||
halfWord |= byte << 8;
|
||||
CPUWriteHalfWord((void *)((uintptr_t)dest ^ 1), halfWord);
|
||||
} else
|
||||
halfWord = byte;
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uintptr_t)dest & 1) {
|
||||
padding--;
|
||||
dest++;
|
||||
}
|
||||
for (; padding > 0; padding -= 2, dest += 2)
|
||||
CPUWriteHalfWord(dest, 0);
|
||||
}
|
||||
|
||||
const s16 sineTable[256]
|
||||
= { (s16)0x0000, (s16)0x0192, (s16)0x0323, (s16)0x04B5, (s16)0x0645, (s16)0x07D5, (s16)0x0964, (s16)0x0AF1, (s16)0x0C7C, (s16)0x0E05,
|
||||
(s16)0x0F8C, (s16)0x1111, (s16)0x1294, (s16)0x1413, (s16)0x158F, (s16)0x1708, (s16)0x187D, (s16)0x19EF, (s16)0x1B5D, (s16)0x1CC6,
|
||||
(s16)0x1E2B, (s16)0x1F8B, (s16)0x20E7, (s16)0x223D, (s16)0x238E, (s16)0x24DA, (s16)0x261F, (s16)0x275F, (s16)0x2899, (s16)0x29CD,
|
||||
(s16)0x2AFA, (s16)0x2C21, (s16)0x2D41, (s16)0x2E5A, (s16)0x2F6B, (s16)0x3076, (s16)0x3179, (s16)0x3274, (s16)0x3367, (s16)0x3453,
|
||||
(s16)0x3536, (s16)0x3612, (s16)0x36E5, (s16)0x37AF, (s16)0x3871, (s16)0x392A, (s16)0x39DA, (s16)0x3A82, (s16)0x3B20, (s16)0x3BB6,
|
||||
(s16)0x3C42, (s16)0x3CC5, (s16)0x3D3E, (s16)0x3DAE, (s16)0x3E14, (s16)0x3E71, (s16)0x3EC5, (s16)0x3F0E, (s16)0x3F4E, (s16)0x3F84,
|
||||
(s16)0x3FB1, (s16)0x3FD3, (s16)0x3FEC, (s16)0x3FFB, (s16)0x4000, (s16)0x3FFB, (s16)0x3FEC, (s16)0x3FD3, (s16)0x3FB1, (s16)0x3F84,
|
||||
(s16)0x3F4E, (s16)0x3F0E, (s16)0x3EC5, (s16)0x3E71, (s16)0x3E14, (s16)0x3DAE, (s16)0x3D3E, (s16)0x3CC5, (s16)0x3C42, (s16)0x3BB6,
|
||||
(s16)0x3B20, (s16)0x3A82, (s16)0x39DA, (s16)0x392A, (s16)0x3871, (s16)0x37AF, (s16)0x36E5, (s16)0x3612, (s16)0x3536, (s16)0x3453,
|
||||
(s16)0x3367, (s16)0x3274, (s16)0x3179, (s16)0x3076, (s16)0x2F6B, (s16)0x2E5A, (s16)0x2D41, (s16)0x2C21, (s16)0x2AFA, (s16)0x29CD,
|
||||
(s16)0x2899, (s16)0x275F, (s16)0x261F, (s16)0x24DA, (s16)0x238E, (s16)0x223D, (s16)0x20E7, (s16)0x1F8B, (s16)0x1E2B, (s16)0x1CC6,
|
||||
(s16)0x1B5D, (s16)0x19EF, (s16)0x187D, (s16)0x1708, (s16)0x158F, (s16)0x1413, (s16)0x1294, (s16)0x1111, (s16)0x0F8C, (s16)0x0E05,
|
||||
(s16)0x0C7C, (s16)0x0AF1, (s16)0x0964, (s16)0x07D5, (s16)0x0645, (s16)0x04B5, (s16)0x0323, (s16)0x0192, (s16)0x0000, (s16)0xFE6E,
|
||||
(s16)0xFCDD, (s16)0xFB4B, (s16)0xF9BB, (s16)0xF82B, (s16)0xF69C, (s16)0xF50F, (s16)0xF384, (s16)0xF1FB, (s16)0xF074, (s16)0xEEEF,
|
||||
(s16)0xED6C, (s16)0xEBED, (s16)0xEA71, (s16)0xE8F8, (s16)0xE783, (s16)0xE611, (s16)0xE4A3, (s16)0xE33A, (s16)0xE1D5, (s16)0xE075,
|
||||
(s16)0xDF19, (s16)0xDDC3, (s16)0xDC72, (s16)0xDB26, (s16)0xD9E1, (s16)0xD8A1, (s16)0xD767, (s16)0xD633, (s16)0xD506, (s16)0xD3DF,
|
||||
(s16)0xD2BF, (s16)0xD1A6, (s16)0xD095, (s16)0xCF8A, (s16)0xCE87, (s16)0xCD8C, (s16)0xCC99, (s16)0xCBAD, (s16)0xCACA, (s16)0xC9EE,
|
||||
(s16)0xC91B, (s16)0xC851, (s16)0xC78F, (s16)0xC6D6, (s16)0xC626, (s16)0xC57E, (s16)0xC4E0, (s16)0xC44A, (s16)0xC3BE, (s16)0xC33B,
|
||||
(s16)0xC2C2, (s16)0xC252, (s16)0xC1EC, (s16)0xC18F, (s16)0xC13B, (s16)0xC0F2, (s16)0xC0B2, (s16)0xC07C, (s16)0xC04F, (s16)0xC02D,
|
||||
(s16)0xC014, (s16)0xC005, (s16)0xC000, (s16)0xC005, (s16)0xC014, (s16)0xC02D, (s16)0xC04F, (s16)0xC07C, (s16)0xC0B2, (s16)0xC0F2,
|
||||
(s16)0xC13B, (s16)0xC18F, (s16)0xC1EC, (s16)0xC252, (s16)0xC2C2, (s16)0xC33B, (s16)0xC3BE, (s16)0xC44A, (s16)0xC4E0, (s16)0xC57E,
|
||||
(s16)0xC626, (s16)0xC6D6, (s16)0xC78F, (s16)0xC851, (s16)0xC91B, (s16)0xC9EE, (s16)0xCACA, (s16)0xCBAD, (s16)0xCC99, (s16)0xCD8C,
|
||||
(s16)0xCE87, (s16)0xCF8A, (s16)0xD095, (s16)0xD1A6, (s16)0xD2BF, (s16)0xD3DF, (s16)0xD506, (s16)0xD633, (s16)0xD767, (s16)0xD8A1,
|
||||
(s16)0xD9E1, (s16)0xDB26, (s16)0xDC72, (s16)0xDDC3, (s16)0xDF19, (s16)0xE075, (s16)0xE1D5, (s16)0xE33A, (s16)0xE4A3, (s16)0xE611,
|
||||
(s16)0xE783, (s16)0xE8F8, (s16)0xEA71, (s16)0xEBED, (s16)0xED6C, (s16)0xEEEF, (s16)0xF074, (s16)0xF1FB, (s16)0xF384, (s16)0xF50F,
|
||||
(s16)0xF69C, (s16)0xF82B, (s16)0xF9BB, (s16)0xFB4B, (s16)0xFCDD, (s16)0xFE6E };
|
||||
|
||||
void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count)
|
||||
{
|
||||
for (s32 i = 0; i < count; i++) {
|
||||
s32 cx = src[i].texX;
|
||||
s32 cy = src[i].texY;
|
||||
s16 dispx = src[i].scrX;
|
||||
s16 dispy = src[i].scrY;
|
||||
s16 rx = src[i].sx;
|
||||
s16 ry = src[i].sy;
|
||||
u16 theta = src[i].alpha >> 8;
|
||||
s32 a = sineTable[(theta + 0x40) & 255];
|
||||
s32 b = sineTable[theta];
|
||||
|
||||
s16 dx = (rx * a) >> 14;
|
||||
s16 dmx = (rx * b) >> 14;
|
||||
s16 dy = (ry * b) >> 14;
|
||||
s16 dmy = (ry * a) >> 14;
|
||||
|
||||
dest[i].pa = dx;
|
||||
dest[i].pb = -dmx;
|
||||
dest[i].pc = dy;
|
||||
dest[i].pd = dmy;
|
||||
|
||||
s32 startx = cx - dx * dispx + dmx * dispy;
|
||||
s32 starty = cy - dy * dispx - dmy * dispy;
|
||||
|
||||
dest[i].dx = startx;
|
||||
dest[i].dy = starty;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset)
|
||||
{
|
||||
for (s32 i = 0; i < count; i++) {
|
||||
s16 rx = src[i].xScale;
|
||||
s16 ry = src[i].yScale;
|
||||
u16 theta = src[i].rotation >> 8;
|
||||
|
||||
s32 a = (s32)sineTable[(theta + 64) & 255];
|
||||
s32 b = (s32)sineTable[theta];
|
||||
|
||||
s16 dx = ((s32)rx * a) >> 14;
|
||||
s16 dmx = ((s32)rx * b) >> 14;
|
||||
s16 dy = ((s32)ry * b) >> 14;
|
||||
s16 dmy = ((s32)ry * a) >> 14;
|
||||
|
||||
CPUWriteHalfWord(dest, dx);
|
||||
dest += offset;
|
||||
CPUWriteHalfWord(dest, -dmx);
|
||||
dest += offset;
|
||||
CPUWriteHalfWord(dest, dy);
|
||||
dest += offset;
|
||||
CPUWriteHalfWord(dest, dmy);
|
||||
dest += offset;
|
||||
}
|
||||
}
|
||||
|
||||
void SoftReset(u32 resetFlags) { }
|
||||
|
||||
void SoftResetExram(u32 resetFlags) { }
|
||||
|
||||
#if ENABLE_VRAM_VIEW
|
||||
void VramDraw(SDL_Texture *texture)
|
||||
{
|
||||
@@ -1079,104 +676,3 @@ void VDraw(SDL_Texture *texture)
|
||||
SDL_UpdateTexture(texture, NULL, gameImage, DISPLAY_WIDTH * sizeof(Uint16));
|
||||
REG_VCOUNT = DISPLAY_HEIGHT + 1; // prep for being in VBlank period
|
||||
}
|
||||
|
||||
u8 BinToBcd(u8 bin)
|
||||
{
|
||||
int placeCounter = 1;
|
||||
u8 out = 0;
|
||||
do {
|
||||
out |= (bin % 10) * placeCounter;
|
||||
placeCounter *= 16;
|
||||
} while ((bin /= 10) > 0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Following functions taken from mGBA's source
|
||||
u16 ArcTan(s16 i)
|
||||
{
|
||||
s32 a = -((i * i) >> 14);
|
||||
s32 b = ((0xA9 * a) >> 14) + 0x390;
|
||||
b = ((b * a) >> 14) + 0x91C;
|
||||
b = ((b * a) >> 14) + 0xFB6;
|
||||
b = ((b * a) >> 14) + 0x16AA;
|
||||
b = ((b * a) >> 14) + 0x2081;
|
||||
b = ((b * a) >> 14) + 0x3651;
|
||||
b = ((b * a) >> 14) + 0xA2F9;
|
||||
|
||||
return (i * b) >> 16;
|
||||
}
|
||||
|
||||
u16 ArcTan2(s16 x, s16 y)
|
||||
{
|
||||
if (!y) {
|
||||
if (x >= 0)
|
||||
return 0;
|
||||
return 0x8000;
|
||||
}
|
||||
if (!x) {
|
||||
if (y >= 0)
|
||||
return 0x4000;
|
||||
return 0xC000;
|
||||
}
|
||||
if (y >= 0) {
|
||||
if (x >= 0) {
|
||||
if (x >= y)
|
||||
return ArcTan((y << 14) / x);
|
||||
} else if (-x >= y)
|
||||
return ArcTan((y << 14) / x) + 0x8000;
|
||||
return 0x4000 - ArcTan((x << 14) / y);
|
||||
} else {
|
||||
if (x <= 0) {
|
||||
if (-x > -y)
|
||||
return ArcTan((y << 14) / x) + 0x8000;
|
||||
} else if (x >= -y)
|
||||
return ArcTan((y << 14) / x) + 0x10000;
|
||||
return 0xC000 - ArcTan((x << 14) / y);
|
||||
}
|
||||
}
|
||||
|
||||
u16 Sqrt(u32 num)
|
||||
{
|
||||
if (!num)
|
||||
return 0;
|
||||
u32 lower;
|
||||
u32 upper = num;
|
||||
u32 bound = 1;
|
||||
while (bound < upper) {
|
||||
upper >>= 1;
|
||||
bound <<= 1;
|
||||
}
|
||||
while (1) {
|
||||
upper = num;
|
||||
u32 accum = 0;
|
||||
lower = bound;
|
||||
while (1) {
|
||||
u32 oldLower = lower;
|
||||
if (lower <= upper >> 1)
|
||||
lower <<= 1;
|
||||
if (oldLower >= upper >> 1)
|
||||
break;
|
||||
}
|
||||
while (1) {
|
||||
accum <<= 1;
|
||||
if (upper >= lower) {
|
||||
++accum;
|
||||
upper -= lower;
|
||||
}
|
||||
if (lower == bound)
|
||||
break;
|
||||
lower >>= 1;
|
||||
}
|
||||
u32 oldBound = bound;
|
||||
bound += accum;
|
||||
bound >>= 1;
|
||||
if (bound >= oldBound) {
|
||||
bound = oldBound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
int MultiBoot(struct MultiBootParam *mp) { return 0; }
|
||||
@@ -18,10 +18,6 @@
|
||||
// Game
|
||||
#include "global.h"
|
||||
#include "core.h"
|
||||
#include "multi_sio.h"
|
||||
#include "gba/defines.h"
|
||||
#include "gba/io_reg.h"
|
||||
#include "gba/types.h"
|
||||
#include "lib/agb_flash/flash_internal.h"
|
||||
|
||||
// Emulation
|
||||
@@ -476,435 +472,3 @@ static void CloseSaveFile()
|
||||
fclose(sSaveFile);
|
||||
}
|
||||
}
|
||||
|
||||
// BIOS function implementations are based on the VBA-M source code.
|
||||
// TODO: Link these functions from Libagbsyscall
|
||||
|
||||
// safe unaligned access for MIPS
|
||||
static uint32_t CPUReadMemory(const void *src)
|
||||
{
|
||||
uint32_t val;
|
||||
memcpy(&val, src, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void CPUWriteMemory(void *dest, uint32_t val) { memcpy(dest, &val, sizeof(val)); }
|
||||
|
||||
static uint16_t CPUReadHalfWord(const void *src)
|
||||
{
|
||||
uint16_t val;
|
||||
memcpy(&val, src, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void CPUWriteHalfWord(void *dest, uint16_t val) { memcpy(dest, &val, sizeof(val)); }
|
||||
|
||||
static uint8_t CPUReadByte(const void *src) { return *(uint8_t *)src; }
|
||||
|
||||
static void CPUWriteByte(void *dest, uint8_t val) { *(uint8_t *)dest = val; }
|
||||
|
||||
void CpuSet(const void *src, void *dst, u32 cnt)
|
||||
{
|
||||
if (dst == NULL) {
|
||||
puts("Attempted to CpuSet to NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int count = cnt & 0x1FFFFF;
|
||||
|
||||
const u8 *source = src;
|
||||
u8 *dest = dst;
|
||||
|
||||
// 32-bit ?
|
||||
if ((cnt >> 26) & 1) {
|
||||
// assert(((uintptr_t)src & ~3) == (uintptr_t)src);
|
||||
// assert(((uintptr_t)dst & ~3) == (uintptr_t)dst);
|
||||
|
||||
// needed for 32-bit mode!
|
||||
// source = (u8 *)((uint32_t )source & ~3);
|
||||
// dest = (u8 *)((uint32_t )dest & ~3);
|
||||
|
||||
// fill ?
|
||||
if ((cnt >> 24) & 1) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
while (count) {
|
||||
CPUWriteMemory(dest, value);
|
||||
dest += 4;
|
||||
count--;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count) {
|
||||
CPUWriteMemory(dest, CPUReadMemory(source));
|
||||
source += 4;
|
||||
dest += 4;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No align on 16-bit fill?
|
||||
// assert(((uintptr_t)src & ~1) == (uintptr_t)src);
|
||||
// assert(((uintptr_t)dst & ~1) == (uintptr_t)dst);
|
||||
|
||||
// 16-bit fill?
|
||||
if ((cnt >> 24) & 1) {
|
||||
uint16_t value = CPUReadHalfWord(source);
|
||||
while (count) {
|
||||
CPUWriteHalfWord(dest, value);
|
||||
dest += 2;
|
||||
count--;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count) {
|
||||
CPUWriteHalfWord(dest, CPUReadHalfWord(source));
|
||||
source += 2;
|
||||
dest += 2;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CpuFastSet(const void *src, void *dst, u32 cnt)
|
||||
{
|
||||
if (dst == NULL) {
|
||||
puts("Attempted to CpuFastSet to NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int count = cnt & 0x1FFFFF;
|
||||
|
||||
const u8 *source = src;
|
||||
u8 *dest = dst;
|
||||
|
||||
// source = (u8 *)((uint32_t )source & ~3);
|
||||
// dest = (u8 *)((uint32_t )dest & ~3);
|
||||
|
||||
// fill?
|
||||
if ((cnt >> 24) & 1) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
while (count > 0) {
|
||||
// BIOS always transfers 32 bytes at a time
|
||||
for (int i = 0; i < 8; i++) {
|
||||
CPUWriteMemory(dest, value);
|
||||
dest += 4;
|
||||
}
|
||||
count -= 8;
|
||||
}
|
||||
} else {
|
||||
// copy
|
||||
while (count > 0) {
|
||||
// BIOS always transfers 32 bytes at a time
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint32_t value = CPUReadMemory(source);
|
||||
CPUWriteMemory(dest, value);
|
||||
source += 4;
|
||||
dest += 4;
|
||||
}
|
||||
count -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LZ77UnCompVram(const void *src_, void *dest_)
|
||||
{
|
||||
const u8 *src = (const u8 *)src_;
|
||||
u8 *dest = dest_;
|
||||
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
|
||||
int srcPos = 4;
|
||||
int destPos = 0;
|
||||
|
||||
for (;;) {
|
||||
unsigned char flags = src[srcPos++];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (flags & 0x80) {
|
||||
int blockSize = (src[srcPos] >> 4) + 3;
|
||||
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
|
||||
|
||||
srcPos += 2;
|
||||
|
||||
int blockPos = destPos - blockDistance;
|
||||
|
||||
// Some Ruby/Sapphire tilesets overflow.
|
||||
if (destPos + blockSize > destSize) {
|
||||
blockSize = destSize - destPos;
|
||||
// fprintf(stderr, "Destination buffer overflow.\n");
|
||||
puts("Destination buffer overflow.\n");
|
||||
}
|
||||
|
||||
if (blockPos < 0)
|
||||
goto fail;
|
||||
|
||||
for (int j = 0; j < blockSize; j++)
|
||||
dest[destPos++] = dest[blockPos + j];
|
||||
} else {
|
||||
if (destPos >= destSize)
|
||||
goto fail;
|
||||
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
if (destPos == destSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
flags <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
puts("Fatal error while decompressing LZ file.\n");
|
||||
}
|
||||
|
||||
void LZ77UnCompWram(const void *src, void *dst)
|
||||
{
|
||||
const uint8_t *source = src;
|
||||
uint8_t *dest = dst;
|
||||
|
||||
uint32_t header = CPUReadMemory(source);
|
||||
source += 4;
|
||||
|
||||
int len = header >> 8;
|
||||
|
||||
while (len > 0) {
|
||||
uint8_t d = CPUReadByte(source++);
|
||||
|
||||
if (d) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (d & 0x80) {
|
||||
uint16_t data = CPUReadByte(source++) << 8;
|
||||
data |= CPUReadByte(source++);
|
||||
int length = (data >> 12) + 3;
|
||||
int offset = (data & 0x0FFF);
|
||||
uint8_t *windowOffset = dest - offset - 1;
|
||||
for (int i2 = 0; i2 < length; i2++) {
|
||||
CPUWriteByte(dest++, CPUReadByte(windowOffset++));
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
CPUWriteByte(dest++, CPUReadByte(source++));
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
d <<= 1;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
CPUWriteByte(dest++, CPUReadByte(source++));
|
||||
len--;
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RLUnCompWram(const void *src, void *dest)
|
||||
{
|
||||
int remaining = CPUReadMemory(src) >> 8;
|
||||
int blockHeader;
|
||||
int block;
|
||||
src += 4;
|
||||
while (remaining > 0) {
|
||||
blockHeader = CPUReadByte(src);
|
||||
src++;
|
||||
if (blockHeader & 0x80) // Compressed?
|
||||
{
|
||||
blockHeader &= 0x7F;
|
||||
blockHeader += 3;
|
||||
block = CPUReadByte(src);
|
||||
src++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
CPUWriteByte(dest, block);
|
||||
dest++;
|
||||
}
|
||||
} else // Uncompressed
|
||||
{
|
||||
blockHeader++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
u8 byte = CPUReadByte(src);
|
||||
src++;
|
||||
CPUWriteByte(dest, byte);
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RLUnCompVram(const void *src, void *dest)
|
||||
{
|
||||
int remaining = CPUReadMemory(src) >> 8;
|
||||
int padding = (4 - remaining) & 0x3;
|
||||
int blockHeader;
|
||||
int block;
|
||||
int halfWord = 0;
|
||||
src += 4;
|
||||
while (remaining > 0) {
|
||||
blockHeader = CPUReadByte(src);
|
||||
src++;
|
||||
if (blockHeader & 0x80) // Compressed?
|
||||
{
|
||||
blockHeader &= 0x7F;
|
||||
blockHeader += 3;
|
||||
block = CPUReadByte(src);
|
||||
src++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
if ((uintptr_t)dest & 1) {
|
||||
halfWord |= block << 8;
|
||||
CPUWriteHalfWord((void *)((uintptr_t)dest ^ 1), halfWord);
|
||||
} else
|
||||
halfWord = block;
|
||||
dest++;
|
||||
}
|
||||
} else // Uncompressed
|
||||
{
|
||||
blockHeader++;
|
||||
while (blockHeader-- && remaining) {
|
||||
remaining--;
|
||||
u8 byte = CPUReadByte(src);
|
||||
src++;
|
||||
if ((uintptr_t)dest & 1) {
|
||||
halfWord |= byte << 8;
|
||||
CPUWriteHalfWord((void *)((uintptr_t)dest ^ 1), halfWord);
|
||||
} else
|
||||
halfWord = byte;
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uintptr_t)dest & 1) {
|
||||
padding--;
|
||||
dest++;
|
||||
}
|
||||
for (; padding > 0; padding -= 2, dest += 2)
|
||||
CPUWriteHalfWord(dest, 0);
|
||||
}
|
||||
|
||||
const s16 sineTable[256]
|
||||
= { (s16)0x0000, (s16)0x0192, (s16)0x0323, (s16)0x04B5, (s16)0x0645, (s16)0x07D5, (s16)0x0964, (s16)0x0AF1, (s16)0x0C7C, (s16)0x0E05,
|
||||
(s16)0x0F8C, (s16)0x1111, (s16)0x1294, (s16)0x1413, (s16)0x158F, (s16)0x1708, (s16)0x187D, (s16)0x19EF, (s16)0x1B5D, (s16)0x1CC6,
|
||||
(s16)0x1E2B, (s16)0x1F8B, (s16)0x20E7, (s16)0x223D, (s16)0x238E, (s16)0x24DA, (s16)0x261F, (s16)0x275F, (s16)0x2899, (s16)0x29CD,
|
||||
(s16)0x2AFA, (s16)0x2C21, (s16)0x2D41, (s16)0x2E5A, (s16)0x2F6B, (s16)0x3076, (s16)0x3179, (s16)0x3274, (s16)0x3367, (s16)0x3453,
|
||||
(s16)0x3536, (s16)0x3612, (s16)0x36E5, (s16)0x37AF, (s16)0x3871, (s16)0x392A, (s16)0x39DA, (s16)0x3A82, (s16)0x3B20, (s16)0x3BB6,
|
||||
(s16)0x3C42, (s16)0x3CC5, (s16)0x3D3E, (s16)0x3DAE, (s16)0x3E14, (s16)0x3E71, (s16)0x3EC5, (s16)0x3F0E, (s16)0x3F4E, (s16)0x3F84,
|
||||
(s16)0x3FB1, (s16)0x3FD3, (s16)0x3FEC, (s16)0x3FFB, (s16)0x4000, (s16)0x3FFB, (s16)0x3FEC, (s16)0x3FD3, (s16)0x3FB1, (s16)0x3F84,
|
||||
(s16)0x3F4E, (s16)0x3F0E, (s16)0x3EC5, (s16)0x3E71, (s16)0x3E14, (s16)0x3DAE, (s16)0x3D3E, (s16)0x3CC5, (s16)0x3C42, (s16)0x3BB6,
|
||||
(s16)0x3B20, (s16)0x3A82, (s16)0x39DA, (s16)0x392A, (s16)0x3871, (s16)0x37AF, (s16)0x36E5, (s16)0x3612, (s16)0x3536, (s16)0x3453,
|
||||
(s16)0x3367, (s16)0x3274, (s16)0x3179, (s16)0x3076, (s16)0x2F6B, (s16)0x2E5A, (s16)0x2D41, (s16)0x2C21, (s16)0x2AFA, (s16)0x29CD,
|
||||
(s16)0x2899, (s16)0x275F, (s16)0x261F, (s16)0x24DA, (s16)0x238E, (s16)0x223D, (s16)0x20E7, (s16)0x1F8B, (s16)0x1E2B, (s16)0x1CC6,
|
||||
(s16)0x1B5D, (s16)0x19EF, (s16)0x187D, (s16)0x1708, (s16)0x158F, (s16)0x1413, (s16)0x1294, (s16)0x1111, (s16)0x0F8C, (s16)0x0E05,
|
||||
(s16)0x0C7C, (s16)0x0AF1, (s16)0x0964, (s16)0x07D5, (s16)0x0645, (s16)0x04B5, (s16)0x0323, (s16)0x0192, (s16)0x0000, (s16)0xFE6E,
|
||||
(s16)0xFCDD, (s16)0xFB4B, (s16)0xF9BB, (s16)0xF82B, (s16)0xF69C, (s16)0xF50F, (s16)0xF384, (s16)0xF1FB, (s16)0xF074, (s16)0xEEEF,
|
||||
(s16)0xED6C, (s16)0xEBED, (s16)0xEA71, (s16)0xE8F8, (s16)0xE783, (s16)0xE611, (s16)0xE4A3, (s16)0xE33A, (s16)0xE1D5, (s16)0xE075,
|
||||
(s16)0xDF19, (s16)0xDDC3, (s16)0xDC72, (s16)0xDB26, (s16)0xD9E1, (s16)0xD8A1, (s16)0xD767, (s16)0xD633, (s16)0xD506, (s16)0xD3DF,
|
||||
(s16)0xD2BF, (s16)0xD1A6, (s16)0xD095, (s16)0xCF8A, (s16)0xCE87, (s16)0xCD8C, (s16)0xCC99, (s16)0xCBAD, (s16)0xCACA, (s16)0xC9EE,
|
||||
(s16)0xC91B, (s16)0xC851, (s16)0xC78F, (s16)0xC6D6, (s16)0xC626, (s16)0xC57E, (s16)0xC4E0, (s16)0xC44A, (s16)0xC3BE, (s16)0xC33B,
|
||||
(s16)0xC2C2, (s16)0xC252, (s16)0xC1EC, (s16)0xC18F, (s16)0xC13B, (s16)0xC0F2, (s16)0xC0B2, (s16)0xC07C, (s16)0xC04F, (s16)0xC02D,
|
||||
(s16)0xC014, (s16)0xC005, (s16)0xC000, (s16)0xC005, (s16)0xC014, (s16)0xC02D, (s16)0xC04F, (s16)0xC07C, (s16)0xC0B2, (s16)0xC0F2,
|
||||
(s16)0xC13B, (s16)0xC18F, (s16)0xC1EC, (s16)0xC252, (s16)0xC2C2, (s16)0xC33B, (s16)0xC3BE, (s16)0xC44A, (s16)0xC4E0, (s16)0xC57E,
|
||||
(s16)0xC626, (s16)0xC6D6, (s16)0xC78F, (s16)0xC851, (s16)0xC91B, (s16)0xC9EE, (s16)0xCACA, (s16)0xCBAD, (s16)0xCC99, (s16)0xCD8C,
|
||||
(s16)0xCE87, (s16)0xCF8A, (s16)0xD095, (s16)0xD1A6, (s16)0xD2BF, (s16)0xD3DF, (s16)0xD506, (s16)0xD633, (s16)0xD767, (s16)0xD8A1,
|
||||
(s16)0xD9E1, (s16)0xDB26, (s16)0xDC72, (s16)0xDDC3, (s16)0xDF19, (s16)0xE075, (s16)0xE1D5, (s16)0xE33A, (s16)0xE4A3, (s16)0xE611,
|
||||
(s16)0xE783, (s16)0xE8F8, (s16)0xEA71, (s16)0xEBED, (s16)0xED6C, (s16)0xEEEF, (s16)0xF074, (s16)0xF1FB, (s16)0xF384, (s16)0xF50F,
|
||||
(s16)0xF69C, (s16)0xF82B, (s16)0xF9BB, (s16)0xFB4B, (s16)0xFCDD, (s16)0xFE6E };
|
||||
|
||||
void SoftReset(u32 resetFlags) { }
|
||||
|
||||
void SoftResetExram(u32 resetFlags) { }
|
||||
|
||||
// Following functions taken from mGBA's source
|
||||
u16 ArcTan(s16 i)
|
||||
{
|
||||
s32 a = -((i * i) >> 14);
|
||||
s32 b = ((0xA9 * a) >> 14) + 0x390;
|
||||
b = ((b * a) >> 14) + 0x91C;
|
||||
b = ((b * a) >> 14) + 0xFB6;
|
||||
b = ((b * a) >> 14) + 0x16AA;
|
||||
b = ((b * a) >> 14) + 0x2081;
|
||||
b = ((b * a) >> 14) + 0x3651;
|
||||
b = ((b * a) >> 14) + 0xA2F9;
|
||||
|
||||
return (i * b) >> 16;
|
||||
}
|
||||
|
||||
u16 ArcTan2(s16 x, s16 y)
|
||||
{
|
||||
if (!y) {
|
||||
if (x >= 0)
|
||||
return 0;
|
||||
return 0x8000;
|
||||
}
|
||||
if (!x) {
|
||||
if (y >= 0)
|
||||
return 0x4000;
|
||||
return 0xC000;
|
||||
}
|
||||
if (y >= 0) {
|
||||
if (x >= 0) {
|
||||
if (x >= y)
|
||||
return ArcTan((y << 14) / x);
|
||||
} else if (-x >= y)
|
||||
return ArcTan((y << 14) / x) + 0x8000;
|
||||
return 0x4000 - ArcTan((x << 14) / y);
|
||||
} else {
|
||||
if (x <= 0) {
|
||||
if (-x > -y)
|
||||
return ArcTan((y << 14) / x) + 0x8000;
|
||||
} else if (x >= -y)
|
||||
return ArcTan((y << 14) / x) + 0x10000;
|
||||
return 0xC000 - ArcTan((x << 14) / y);
|
||||
}
|
||||
}
|
||||
|
||||
u16 Sqrt(u32 num)
|
||||
{
|
||||
if (!num)
|
||||
return 0;
|
||||
u32 lower;
|
||||
u32 upper = num;
|
||||
u32 bound = 1;
|
||||
while (bound < upper) {
|
||||
upper >>= 1;
|
||||
bound <<= 1;
|
||||
}
|
||||
while (1) {
|
||||
upper = num;
|
||||
u32 accum = 0;
|
||||
lower = bound;
|
||||
while (1) {
|
||||
u32 oldLower = lower;
|
||||
if (lower <= upper >> 1)
|
||||
lower <<= 1;
|
||||
if (oldLower >= upper >> 1)
|
||||
break;
|
||||
}
|
||||
while (1) {
|
||||
accum <<= 1;
|
||||
if (upper >= lower) {
|
||||
++accum;
|
||||
upper -= lower;
|
||||
}
|
||||
if (lower == bound)
|
||||
break;
|
||||
lower >>= 1;
|
||||
}
|
||||
u32 oldBound = bound;
|
||||
bound += accum;
|
||||
bound >>= 1;
|
||||
if (bound >= oldBound) {
|
||||
bound = oldBound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bound;
|
||||
}
|
||||
|
||||
int MultiBoot(struct MultiBootParam *mp) { return 0; }
|
||||
@@ -1,59 +0,0 @@
|
||||
#if ENABLE_RL_LZ_LOGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "platform/platform.h"
|
||||
#include "platform/ext/gbagfx/global.h"
|
||||
#include "platform/ext/gbagfx/lz.h"
|
||||
#include "platform/ext/gbagfx/rl.h"
|
||||
|
||||
unsigned char *Platform_LZDecompress(unsigned char *src, int srcSize)
|
||||
{
|
||||
int uncompressedSize = 0;
|
||||
unsigned char *dest = LZDecompress(src, srcSize, &uncompressedSize);
|
||||
#if ENABLE_RL_LZ_LOGGING
|
||||
printf("LZDecompress(%p, %p) stored 0x%X bytes.\n", src, dest, uncompressedSize);
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
unsigned char *Platform_RLDecompress(unsigned char *src, int srcSize)
|
||||
{
|
||||
int uncompressedSize = 0;
|
||||
unsigned char *dest = RLDecompress(src, srcSize, &uncompressedSize);
|
||||
#if ENABLE_RL_LZ_LOGGING
|
||||
printf("RLDecompress(%p, %p) stored 0x%X bytes.\n", src, dest, uncompressedSize);
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void Platform_LZFree(unsigned char *dest) { free(dest); }
|
||||
|
||||
void Platform_RLFree(unsigned char *dest) { free(dest); }
|
||||
|
||||
/* NOTE:
|
||||
* "Unsafe" versions included for compatibility.
|
||||
* This is just here so it doesn't fail if someone accidentally calls
|
||||
* LZUnCompWram, LZUnCompVram, RLUnCompWram or RLUnCompVram.
|
||||
*
|
||||
* Please do NOT call them directly if you know the size of the compressed data!
|
||||
* (Use Platform_LZDecompress and Platform_RLDecompress instead!)
|
||||
*/
|
||||
void Platform_LZDecompressUnsafe(unsigned char *src, unsigned char *dest)
|
||||
{
|
||||
int uncompressedSize = 0;
|
||||
LZDecompressUnsafe(src, dest, &uncompressedSize);
|
||||
#if ENABLE_RL_LZ_LOGGING
|
||||
printf("LZDecompress(%p, %p) stored 0x%X bytes.\n", src, dest, uncompressedSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Platform_RLDecompressUnsafe(unsigned char *src, unsigned char *dest)
|
||||
{
|
||||
int uncompressedSize = 0;
|
||||
RLDecompressUnsafe(src, dest, &uncompressedSize);
|
||||
#if ENABLE_RL_LZ_LOGGING
|
||||
printf("RLDecompress(%p, %p) stored 0x%X bytes.\n", src, dest, uncompressedSize);
|
||||
#endif
|
||||
}
|
||||
Reference in new issue
Block a user