diff --git a/Makefile b/Makefile index f15de24..1540438 100644 --- a/Makefile +++ b/Makefile @@ -1,166 +1,7 @@ -# SPDX-License-Identifier: CC0-1.0 -# -# SPDX-FileContributor: Antonio Niño Díaz, 2022 +CFLAGS = -lm -# User config -# =========== +build: + cc ./main.c $(CFLAGS) -DVBUF -o ./cube -# ROM config -# ---------- - -NAME := vi -GAME_TITLE := "VIOLET'S CV" -GAME_CODE := "00" - -# Defines passed to all files -# --------------------------- - -DEFINES := - -# Libraries -# --------- - -LIBS := -lc -LIBDIRS := # A list of paths - -# Include paths -# ------------- - -INCLUDES := # A list of paths - -# Tools -# ----- - -PREFIX := arm-none-eabi- -CC := $(PREFIX)gcc -CXX := $(PREFIX)g++ -OBJDUMP := $(PREFIX)objdump -OBJCOPY := $(PREFIX)objcopy -MKDIR := mkdir -RM := rm -rf - -# Verbose flag -# ------------ - -# `make V=` builds the binary in verbose build mode -V := @ - -# Directories -# ----------- - -SOURCEDIR := source -BUILDDIR := build - -# Build artfacts -# -------------- - -ELF := $(NAME).elf -DUMP := $(NAME).dump -ROM := $(NAME).gba -MAP := $(NAME).map - -GBAFIX := gbafix/gbafix - -# Source files -# ------------ - -SOURCES_S := $(wildcard $(SOURCEDIR)/*.s $(SOURCEDIR)/**/*.s) -SOURCES_C := $(wildcard $(SOURCEDIR)/*.c $(SOURCEDIR)/**/*.c) -SOURCES_CPP := $(wildcard $(SOURCEDIR)/*.cpp $(SOURCEDIR)/**/*.cpp) - -# Compiler and linker flags -# ------------------------- - -DEFINES += -D__GBA__ - -ARCH := -mcpu=arm7tdmi -mtune=arm7tdmi - -WARNFLAGS := -Wall - -INCLUDEFLAGS := $(foreach path,$(INCLUDES),-I$(path)) \ - $(foreach path,$(LIBDIRS),-I$(path)/include) - -LIBDIRSFLAGS := $(foreach path,$(LIBDIRS),-L$(path)/lib) - -ASFLAGS += -x assembler-with-cpp $(DEFINES) $(ARCH) \ - -mthumb -mthumb-interwork $(INCLUDEFLAGS) \ - -ffunction-sections -fdata-sections -lm - -CFLAGS += -std=gnu11 $(WARNFLAGS) $(DEFINES) $(ARCH) \ - -mthumb -mthumb-interwork $(INCLUDEFLAGS) -O2 \ - -ffunction-sections -fdata-sections -lm -g - -CXXFLAGS += -std=gnu++14 $(WARNFLAGS) $(DEFINES) $(ARCH) \ - -mthumb -mthumb-interwork $(INCLUDEFLAGS) -O2 \ - -ffunction-sections -fdata-sections \ - -fno-exceptions -fno-rtti - -LDFLAGS := -mthumb -mthumb-interwork $(LIBDIRSFLAGS) \ - -Wl,-Map,$(MAP) -Wl,--gc-sections \ - -specs=nano.specs -T source/sys/gba_cart.ld \ - -Wl,--start-group $(LIBS) -Wl,--end-group -lm - -# Intermediate build files -# ------------------------ - -OBJS := \ - $(patsubst $(SOURCEDIR)/%.s,$(BUILDDIR)/%.s.o,$(SOURCES_S)) \ - $(patsubst $(SOURCEDIR)/%.c,$(BUILDDIR)/%.c.o,$(SOURCES_C)) \ - $(patsubst $(SOURCEDIR)/%.cpp,$(BUILDDIR)/%.cpp.o,$(SOURCES_CPP)) - -DEPS := $(OBJS:.o=.d) - -# Rules -# ----- - -$(BUILDDIR)/%.s.o : $(SOURCEDIR)/%.s - @echo " AS $<" - @$(MKDIR) -p $(@D) # Build target's directory if it doesn't exist - $(V)$(CC) $(ASFLAGS) -MMD -MP -c -o $@ $< - -$(BUILDDIR)/%.c.o : $(SOURCEDIR)/%.c - @echo " CC $<" - @$(MKDIR) -p $(@D) # Build target's directory if it doesn't exist - $(V)$(CC) $(CFLAGS) -MMD -MP -c -o $@ $< - -$(BUILDDIR)/%.cpp.o : $(SOURCEDIR)/%.cpp - @echo " CXX $<" - @$(MKDIR) -p $(@D) # Build target's directory if it doesn't exist - $(V)$(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $< - - -# Targets -# ------- - -.PHONY: all clean dump - -all: $(ROM) - -$(GBAFIX): - $(V)cd gbafix && make - -$(ELF): $(OBJS) - @echo " LD $@" - $(V)$(CC) -o $@ $(OBJS) $(LDFLAGS) - -$(ROM): $(ELF) $(GBAFIX) - @echo " OBJCOPY $<" - $(V)$(OBJCOPY) -O binary $< $@ - @echo " GBAFIX $@" - $(V)$(GBAFIX) $@ -t$(GAME_TITLE) -c$(GAME_CODE) - -$(DUMP): $(ELF) - @echo " OBJDUMP $@" - $(V)$(OBJDUMP) -h -C -S $< > $@ - -dump: $(DUMP) - -clean: - @echo " CLEAN" - $(V)$(RM) $(ROM) $(ELF) $(DUMP) $(MAP) $(BUILDDIR) - $(V)cd gbafix && make clean - -# Include dependency files if they exist -# -------------------------------------- - --include $(DEPS) +run: build + ./cube diff --git a/gbafix/.gitignore b/gbafix/.gitignore deleted file mode 100644 index 23abdd2..0000000 --- a/gbafix/.gitignore +++ /dev/null @@ -1 +0,0 @@ -gbafix diff --git a/gbafix/Makefile b/gbafix/Makefile deleted file mode 100644 index c6bbdf8..0000000 --- a/gbafix/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: CC0-1.0 -# -# SPDX-FileContributor: Antonio Niño Díaz, 2022 - -NAME := gbafix - -CC := gcc -RM := rm -rf - -# `make V=` builds the binary in verbose build mode -V := @ - -CFLAGS := -Wall -O3 - -.PHONY: all clean - -all: $(NAME) - -$(NAME): gbafix.c - @echo " HOSTCC $<" - $(V)$(CC) $(CFLAGS) -o $@ $< - -clean: - @echo " CLEAN" - $(V)$(RM) $(NAME) diff --git a/gbafix/gbafix.c b/gbafix/gbafix.c deleted file mode 100644 index 7f8ef7f..0000000 --- a/gbafix/gbafix.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - "$Id: gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $" - - DevkitPro GBA ROM fix utility - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. - - Please report all bugs and problems through the bug tracker at - "http://sourceforge.net/tracker/?group_id=114505&atid=668551". - - "$Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/tools/gba/gbatools/gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $" - -*/ -//--------------------------------------------------------------------------------- -// gbafix.c -//--------------------------------------------------------------------------------- -/* - Gameboy Advance ROM fixer (by Dark Fader / BlackThunder / WinterMute / Diegoisawesome) - Validates header of GBA roms. - - History - ------- - v1.05 - added debug offset argument, (Diegoisawesome) - v1.04 - converted to plain C, (WinterMute) - v1.03 - header.fixed, header.device_type - v1.02 - redefined the options (rgbfix style), checksum=0 - v1.01 - fix in parameters - v1.00 - logo, complement -*/ - -#pragma pack(1) - -#include -#include -#include -#include - -#define VER "1.05" -#define ARGV argv[arg] -#define VALUE (ARGV+2) -#define NUMBER strtoul(VALUE, NULL, 0) - -typedef struct -{ - uint32_t start_code; // B instruction - uint8_t logo[0xA0-0x04]; // logo data - uint8_t title[0xC]; // game title name - uint32_t game_code; // - uint16_t maker_code; // - uint8_t fixed; // 0x96 - uint8_t unit_code; // 0x00 - uint8_t device_type; // 0x00 - uint8_t unused[7]; // - uint8_t game_version; // 0x00 - uint8_t complement; // 800000A0..800000BC - uint16_t checksum; // 0x0000 -} Header; - - -Header header; - -unsigned short checksum_without_header = 0; - -const Header good_header = -{ - // start_code - 0xEA00002E, - // logo - { 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD, - 0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20, - 0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF, - 0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC, - 0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76, - 0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD, - 0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25, - 0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44, - 0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF, - 0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07 } , - // title - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - // game code - 0x00000000, - // maker code - 0x3130, - // fixed - 0x96, - // unit_code - 0x00, - // device type - 0x00, - // unused - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - // game version - 0x00, - // complement - 0x00, - // checksum - 0x0000 -}; - -//--------------------------------------------------------------------------------- -char HeaderComplement(void) -/*--------------------------------------------------------------------------------- - Calculate Header complement check ----------------------------------------------------------------------------------*/ -{ - int n; - char c = 0; - char *p = (char *)&header + 0xA0; - for (n=0; n<0xBD-0xA0; n++) - { - c += *p++; - } - return -(0x19+c); -} - - -//--------------------------------------------------------------------------------- -int main(int argc, char *argv[]) -//--------------------------------------------------------------------------------- -{ - int arg; - char *argfile = 0; - FILE *infile; - - int size,bit; - - // show syntax - if (argc <= 1) - { - printf("GBA ROM fixer v"VER" by Dark Fader / BlackThunder / WinterMute / Diegoisawesome \n"); - printf("Syntax: gbafix [-p] [-t[title]] [-c] [-m] [-r] [-d]\n"); - printf("\n"); - printf("parameters:\n"); - printf(" -p Pad to next exact power of 2. No minimum size!\n"); - printf(" -t[] Patch title. Stripped filename if none given.\n"); - printf(" -c<game_code> Patch game code (four characters)\n"); - printf(" -m<maker_code> Patch maker code (two characters)\n"); - printf(" -r<version> Patch game version (number)\n"); - printf(" -d<debug> Enable debugging handler and set debug entry point (0 or 1)\n"); - return -1; - } - - // get filename - for (arg=1; arg<argc; arg++) - { - if ((ARGV[0] != '-')) { argfile=ARGV; break; } - } - - // check filename - if (!argfile) - { - printf("Filename needed!\n"); - return -1; - } - - // read file - infile = fopen(argfile, "r+b"); - if (!infile) { printf("Error opening input file!\n"); return -1; } - fseek(infile, 0, SEEK_SET); - if (fread(&header, sizeof(header), 1, infile) != 1) - { - printf("Error reading header of input file!\n"); - return -1; - } - - // fix some data - memcpy(header.logo, good_header.logo, sizeof(header.logo)); - memcpy(&header.fixed, &good_header.fixed, sizeof(header.fixed)); - memcpy(&header.device_type, &good_header.device_type, sizeof(header.device_type)); - - // parse command line - for (arg=1; arg<argc; arg++) - { - if ((ARGV[0] == '-')) - { - switch (ARGV[1]) - { - case 'p': // pad - { - fseek(infile, 0, SEEK_END); - size = ftell(infile); - for (bit=31; bit>=0; bit--) if (size & (1<<bit)) break; - if (size != (1<<bit)) - { - int todo = (1<<(bit+1)) - size; - while (todo--) fputc(0xFF, infile); - } - fseek(infile, 0, SEEK_SET); - break; - } - - case 't': // title - { - char title[256]; - memset(title, 0, sizeof(title)); - if (VALUE[0]) - { - strncpy(title, VALUE, sizeof(header.title)); - } - else - { - // use filename - char s[256], *begin=s, *t; strcpy(s, argfile); - t = strrchr(s, '\\'); if (t) begin = t+1; - t = strrchr(s, '/'); if (t) begin = t+1; - t = strrchr(s, '.'); if (t) *t = 0; - snprintf(title, sizeof(header.title), "%s", begin); - printf("%s\n",begin); - } - memcpy(header.title, title, sizeof(header.title)); // copy - break; - } - - case 'c': // game code - { - //if (!VALUE[0]) { printf("Need value for %s\n", ARGV); break; } - //header.game_code = NUMBER; - header.game_code = VALUE[0] | VALUE[1]<<8 | VALUE[2]<<16 | VALUE[3]<<24; - break; - } - - case 'm': // maker code - { - //if (!VALUE[0]) { printf("Need value for %s\n", ARGV); break; } - //header.maker_code = (unsigned short)NUMBER; - header.maker_code = VALUE[0] | VALUE[1]<<8; - break; - } - - case 'v': // ignored, compatability with other gbafix - { - break; - } - - case 'r': // version - { - if (!VALUE[0]) { printf("Need value for %s\n", ARGV); break; } - header.game_version = (unsigned char)NUMBER; - break; - } - - case 'd': // debug - { - if (!VALUE[0]) { printf("Need value for %s\n", ARGV); break; } - header.logo[0x9C-0x04] = 0xA5; // debug enable - header.device_type = (unsigned char)((NUMBER & 1) << 7); // debug handler entry point - break; - } - - default: - { - printf("Invalid option: %s\n", ARGV); - } - } - } - } - - // update complement check & total checksum - header.complement = 0; - header.checksum = 0; // must be 0 - header.complement = HeaderComplement(); - //header.checksum = checksum_without_header + HeaderChecksum(); - - fseek(infile, 0, SEEK_SET); - fwrite(&header, sizeof(header), 1, infile); - fclose(infile); - - printf("ROM fixed!\n"); - - return 0; -} diff --git a/source/main.c b/source/main.c deleted file mode 100644 index 5d58d7a..0000000 --- a/source/main.c +++ /dev/null @@ -1,543 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 -// -// SPDX-FileContributor: Antonio Niño Díaz, 2022 - -#include <stdint.h> - -#define GBA_SCREEN_W 240 -#define GBA_SCREEN_H 160 - -#define REG_DISPCNT *((volatile uint16_t *)0x04000000) - -#define REG_KEYINPUT *((volatile uint16_t *)0x04000130) -#define DEFAULT_REG_KEYINPUT *((volatile uint16_t *)0x04000130) -#define KEY_DOWN_NOW(key) (~(REG_KEYINPUT) & key) - -#define KEY_A 1 -#define KEY_B 2 -#define KEY_SELECT 3 -#define KEY_START 4 -#define KEY_DPAD_RIGHT 5 -#define KEY_DPAD_LEFT 6 -#define KEY_DPAD_UP 7 -#define KEY_DPAD_DOWN 8 -#define KEY_TRIGGER_LEFT 9 -#define KEY_TRIGGER_RIGHT 10 - -#define DISPCNT_BG_MODE_MASK (0x7) -#define DISPCNT_BG_MODE(n) ((n) & DISPCNT_BG_MODE_MASK) // 0 to 5 - -#define DISPCNT_BG2_ENABLE (1 << 10) - -#define MEM_VRAM_MODE3_FB ((uint16_t *)0x06000000) - -#define FIXED_POINT int32_t -#define fp 12 -#define SHIFT_THRESHOLD 0.05 -#define SHIFT_THRESHOLD_FP ((1 << fp) * SHIFT_THRESHOLD) - -#define FLOAT2FIXED(value) (int)((value) * (1 << fp)) -#define FIXED2FLOAT(value) ((value) / (float)(1 << fp)) - -static inline uint16_t -RGB15(uint16_t r, uint16_t g, uint16_t b) -{ - return (r & 0x1F) | ((g & 0x1F) << 5) | ((b & 0x1F) << 10); -} - -/////////////////////////////////////////////////////////// - -#include <stdio.h> -#include <math.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <float.h> - -#define VWIDTH 50 -#define VHEIGHT 50 -#define CUBE_WIDTH 10 -#define CUBE_WIDTH_FP ((1 << fp) * CUBE_WIDTH) - -enum faces { - FACE_FRONT = 0, - FACE_LEFT, - FACE_RIGHT, - FACE_BOTTOM, - FACE_TOP, - FACE_BACK, - NUM_FACES, -}; - -#define STEP 5 -#define STEP_FP ((1 << fp) * STEP) - -#define ACTION_STEP 0.1 -#define ACTION_STEP_FP ((1 << fp) * ACTION_STEP) - -#define PITCH_STEP 0.05 -#define ROLL_STEP 0.05 -#define YAW_STEP 0.05 - -volatile FIXED_POINT K1 = 60; -volatile FIXED_POINT K2 = (2 * CUBE_WIDTH) + 20; - - -#define MULT_FP(a,b) ((a * b) >> fp) - -#define SQ(n) (n * n) -#define SQ_FP(n) (MULT_FP(n, n)) - -#define COORD2INDEX(x, y) (y * VWIDTH + x) -#define COUPLE2INDEX(x) (COORD2INDEX(x[0], x[1])) - -#define GET_ROTATE_X_Q(a) ({ float _a = (FIXED2FLOAT(a)) ; \ - struct Quaternions q = {}; q.w = FLOAT2FIXED(cos(_a * .5)); \ - q.x = FLOAT2FIXED(sin(_a * .5)); q; }) -#define GET_ROTATE_Y_Q(a) ({ float _a = (FIXED2FLOAT(a)) ; \ - struct Quaternions q = {}; q.w = FLOAT2FIXED(cos(_a * .5)); \ - q.y = FLOAT2FIXED(sin(_a * .5)); q; }) -#define GET_ROTATE_Z_Q(a) ({ float _a = (FIXED2FLOAT(a)) ; \ - struct Quaternions q = {}; q.w = FLOAT2FIXED(cos(_a * .5)); \ - q.z = FLOAT2FIXED(sin(_a * .5)); q; }) - -//TODO Idle animations -#define IS_IDLE (Idle.x || Idle.y || Idle.z) -#define RESET_IDLE {Idle.x = 0; Idle.y = 0; Idle.z = 0;} - -struct { - char x; - char y; - char z; -} Idle; - - -struct Quaternions { - FIXED_POINT w; - FIXED_POINT x; - FIXED_POINT y; - FIXED_POINT z; -} Target, Current; - -FIXED_POINT interpolationStep = 0; -FIXED_POINT zBuffer[VHEIGHT * VWIDTH]; -char output[VHEIGHT * VWIDTH]; - -static volatile char shouldBreak = 1; -static volatile char currentlyMoving = 0; -static volatile char currentCountR = 0; -static volatile char frontFacingFace = FACE_FRONT; - -void -normalize(struct Quaternions *q) -{ - float n = sqrt(FIXED2FLOAT(SQ_FP(q->w) + SQ_FP(q->x) + - SQ_FP(q->y) + SQ_FP(q->z))); - if (n == 0) - return; - q->w = FLOAT2FIXED(FIXED2FLOAT(q->w) / n); - q->x = FLOAT2FIXED(FIXED2FLOAT(q->x) / n); - q->y = FLOAT2FIXED(FIXED2FLOAT(q->y) / n); - q->z = FLOAT2FIXED(FIXED2FLOAT(q->z) / n); -} - -struct Quaternions -mult(struct Quaternions q, FIXED_POINT x, FIXED_POINT y, FIXED_POINT z) -{ - //p = q * p * qbar - struct Quaternions res; - - res.w = 0; - res.x = MULT_FP(x, (SQ_FP(q.w) + SQ_FP(q.x) - SQ_FP(q.y) - SQ_FP(q.z))) - + (MULT_FP(y, (MULT_FP(q.x, q.y) - MULT_FP(q.w, q.z))) * 2) - + (MULT_FP(z, (MULT_FP(q.x, q.z) + MULT_FP(q.w, q.y))) * 2); - - res.y = (MULT_FP(x, (MULT_FP(q.x, q.y) + MULT_FP(q.w,q.z))) * 2) - + (MULT_FP(y, (SQ_FP(q.w) - SQ_FP(q.x) + SQ_FP(q.y) - SQ_FP(q.z)))) - + (MULT_FP(z, (MULT_FP(q.y, q.z) - MULT_FP(q.w, q.x))) << 2); - - res.z = (MULT_FP(x, (MULT_FP(q.x, q.z) - MULT_FP(q.w, q.y)))* 2) - + (MULT_FP(y, (MULT_FP(q.y, q.z) + MULT_FP(q.w, q.x))) * 2) - + MULT_FP(z, (SQ_FP(q.w) - SQ_FP(q.x) - SQ_FP(q.y) + SQ_FP(q.z))); - - return res; -} - -struct Quaternions -multQ(struct Quaternions p, struct Quaternions q) -{ - if (p.x <= SHIFT_THRESHOLD_FP && p.x >= -SHIFT_THRESHOLD_FP - && p.y <= SHIFT_THRESHOLD_FP && p.y >= -SHIFT_THRESHOLD_FP - && p.z <= SHIFT_THRESHOLD_FP && p.z >= -SHIFT_THRESHOLD_FP) - return q; - - if (q.x <= SHIFT_THRESHOLD_FP && q.x >= -SHIFT_THRESHOLD_FP - && q.y <= SHIFT_THRESHOLD_FP && q.y >= -SHIFT_THRESHOLD_FP - && q.z <= SHIFT_THRESHOLD_FP && q.z >= -SHIFT_THRESHOLD_FP) - return p; - - struct Quaternions res = { - .w = MULT_FP(p.w, q.w) - MULT_FP(p.x, q.x) - - MULT_FP(p.y, q.y) - MULT_FP(p.z, q.z), - .x = MULT_FP(p.w, q.x) + MULT_FP(p.x, q.w) + - MULT_FP(p.y, q.z) - MULT_FP(p.z, q.y), - .y = MULT_FP(p.w, q.y) - MULT_FP(p.x, q.z) + - MULT_FP(p.y, q.w) + MULT_FP(p.z, q.x), - .z = MULT_FP(p.w, q.z) + MULT_FP(p.x, q.y) - - MULT_FP(p.y, q.x) + MULT_FP(p.z, q.w), - }; - - return res; -} - -uint16_t -chooseColor(char c) -{ - switch (c) { - case FACE_FRONT: - return RGB15(31, 0, 0); - case FACE_BACK: - return RGB15(31, 15, 31); - case FACE_BOTTOM: - return RGB15(31, 0, 31); - case FACE_LEFT: - return RGB15(0, 0, 31); - case FACE_RIGHT: - return RGB15(0, 31, 31); - case FACE_TOP: - return RGB15(0, 31, 0); - default: - // BG - return RGB15(31, 31, 31); - } -} - -char -chooseMainFace() -{ - int total = 0; - int faces[NUM_FACES] = {0}; - - for (int k = 0; k < VWIDTH * VHEIGHT; ++k) - if (output[k] >= 0 && output[k] < NUM_FACES) { - faces[output[k]]++; - ++total; - } - - int max = 0, idx = 0; - for (int k = 0; k < NUM_FACES; ++k) - if (faces[k] > max) { - max = faces[k]; - idx = k; - } - - frontFacingFace = max > total * 0.9 ? idx : -1; - return frontFacingFace; -} - -char -isInQuad(char curr[2], char top[2], char left[2], - char right[2], char bot[2]) -{ - char *points[4] = {top, left, bot, right}; - - char pos = 0, neg = 0; - char x = curr[0]; - char y = curr[1];; - int d; - - for (char i = 0; i < 4; ++i) { - if (points[i][0] == curr[0] && points[i][1] == curr[1]) - return 1; - - //Form a segment between the i'th point - char x1 = points[i][0]; - char y1 = points[i][1]; - - //And the i+1'th, or if i is the last, with the first point - char i2 = (i + 1) % 4; - - char x2 = points[i2][0]; - char y2 = points[i2][1]; - - - //Compute the cross product - d = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1); - - if (d > 0) ++pos; - if (d < 0) ++neg; - - //If the sign changes, then point is outside - if (pos > 0 && neg > 0) - return 0; - } - - return 1; -} - -void -fill_quads(char current_face, char top[2], char left[2], - char right[2], char bot[2]) -{ - if (current_face != 0) return; - output[COUPLE2INDEX(top)] = RGB15(0, 0, 15); - output[COUPLE2INDEX(left)] = RGB15(0, 0, 15); - output[COUPLE2INDEX(right)] = RGB15(0, 0, 15); - - for (int y = top[1] ; y < bot[1] ; ++y) { - for (int x = left[0] ; x < right[0] ; ++x) { - char curr[2] = {x, y}; - if (isInQuad(curr, top, left, right, bot)) - //zbuffer issue - {} - //output[COORD2INDEX(x, y)] = current_face; - } - } -} - -void -detect_and_fill_quads() -{ - for (int current_face = 0 ; current_face < NUM_FACES ; ++current_face) { - char last_top [2] = {VWIDTH, VHEIGHT}; - char last_left[2] = {VWIDTH, 0}; - char last_right [2] = {0, 0}; - char last_bot[2] = {0, 0}; - char top [2] = {VWIDTH, VHEIGHT}; - char left[2] = {VWIDTH, 0}; - char right [2] = {0, 0}; - char bot[2] = {0, 0}; - for (char y = 0; y < VHEIGHT; ++y) { - for (char x = 0; x < VWIDTH; ++x) { - if (output[COORD2INDEX(x, y)] != current_face) - continue; - if (x <= left[0]) { - left[0] = x; - left[1] = y; - } - if (y <= top[1]) { - top[0] = x; - top[1] = y; - } - if (x >= right[0]) { - right[0] = x; - right[1] = y; - } - if (y >= bot[1]) { - bot[0] = x; - bot[1] = y; - } - } - } - fill_quads(current_face, top, left, right, bot); - } - -} - -void -printAscii() -{ - // TODO scale up - MEM_VRAM_MODE3_FB[120 + 80 * GBA_SCREEN_W] = RGB15(currentCountR, 31 - currentCountR, 0); - MEM_VRAM_MODE3_FB[136 + 80 * GBA_SCREEN_W] = RGB15(currentCountR, 31 - currentCountR, 0); - MEM_VRAM_MODE3_FB[120 + 96 * GBA_SCREEN_W] = RGB15(currentCountR, 31 - currentCountR, 0); - currentCountR = currentCountR == 31 ? 0 : 31; - - detect_and_fill_quads(); - - for (int i = 0; i < VHEIGHT; ++i) { - for (int j = 0; j < VWIDTH; ++j) { - char prevc = 0; - char *c = output + (i * VWIDTH + j); - MEM_VRAM_MODE3_FB[(i + 50) * GBA_SCREEN_W + j + 50] = chooseColor(*c); - } - } -} - -void -rotateCube(FIXED_POINT cubeX, FIXED_POINT cubeY, FIXED_POINT cubeZ, char ch) -{ - struct Quaternions q = mult(Current, cubeX, cubeY, cubeZ); - - int x = q.x >> fp; - int y = q.y >> fp; - - // not fixed point yet!! - float invZ = (1 << fp) / (float)(q.z + K2 * (1 << fp)); - - int screenX = (int)(VWIDTH * 0.5) + (int)((x) * K1) * invZ; - int screenY = (int)(VHEIGHT * 0.5) + (int)((y) * K1) * invZ; - //TODO luminescence - - if (screenX > VWIDTH || screenX < 0) return; - - int idx = screenY * VWIDTH + screenX; - if (idx >= 0 && idx < VWIDTH * VHEIGHT) { - invZ = FLOAT2FIXED(invZ); - if (zBuffer[idx] < invZ) { - zBuffer[idx] = invZ; - output[idx] = ch; - } - } -} - -struct Quaternions -interpolate(struct Quaternions qa, struct Quaternions qb) -{ - frontFacingFace = -1; - struct Quaternions res; - float cosHalfTheta = - FIXED2FLOAT(MULT_FP(qa.w, qb.w) + - MULT_FP(qa.x, qb.x) + - MULT_FP(qa.y, qb.y) + - MULT_FP(qa.z, qb.z)); - //if qa = qb or qa = -qb then theta = 0 and we can return qa - if (cosHalfTheta >= 1.0 || cosHalfTheta <= -1.0) { - res.w = qa.w; - res.x = qa.x; - res.y = qa.y; - res.z = qa.z; - goto exit; - } - if (cosHalfTheta < 0) { - qb.w = -qb.w; - qb.x = -qb.x; - qb.y = -qb.y; - qb.z = qb.z; - cosHalfTheta = -cosHalfTheta; - } - - float halfTheta = acos(cosHalfTheta); - float sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta); - //if theta = 180 degrees then result is not fully defined - // we could rotate around any axis normal to qa or qb - if (sinHalfTheta < 0.001 && sinHalfTheta > -0.001) { - res.w = ((qa.w >> 1) + (qb.w >> 1)); - res.x = ((qa.x >> 1) + (qb.x >> 1)); - res.y = ((qa.y >> 1) + (qb.y >> 1)); - res.z = ((qa.z >> 1) + (qb.z >> 1)); - goto exit; - } - - - FIXED_POINT ratioA = FLOAT2FIXED(sin((1 - FIXED2FLOAT(interpolationStep)) * halfTheta) / sinHalfTheta); - FIXED_POINT ratioB = FLOAT2FIXED(sin(FIXED2FLOAT(interpolationStep) * halfTheta) / sinHalfTheta); - - res.w = (MULT_FP(qa.w, ratioA) + MULT_FP(qb.w, ratioB)); - res.x = (MULT_FP(qa.x, ratioA) + MULT_FP(qb.x, ratioB)); - res.y = (MULT_FP(qa.y, ratioA) + MULT_FP(qb.y, ratioB)); - res.z = (MULT_FP(qa.z, ratioA) + MULT_FP(qb.z, ratioB)); - -exit: - interpolationStep += ACTION_STEP_FP; - return res; -} - -void -handleAngle(char input) -{ - // TODO - if (currentlyMoving == 0) { - currentlyMoving = input; - switch (input) { - case 'w': - case 'W': - Target = multQ(GET_ROTATE_X_Q(FLOAT2FIXED(M_PI_2)), Current); - break; - case 'a': - case 'A': - Target = multQ(GET_ROTATE_Y_Q(-FLOAT2FIXED(M_PI_2)), Current); - break; - case 's': - case 'S': - Target = multQ(GET_ROTATE_X_Q(-FLOAT2FIXED(M_PI_2)), Current); - break; - case 'd': - case 'D': - Target = multQ(GET_ROTATE_Y_Q(FLOAT2FIXED(M_PI_2)), Current); - break; - case 'q': - case 'Q': - Target = multQ(GET_ROTATE_Z_Q(-FLOAT2FIXED(M_PI_2)), Current); - break; - case 'e': - case 'E': - Target = multQ(GET_ROTATE_Z_Q(FLOAT2FIXED(M_PI_2)), Current); - break; - default: - currentlyMoving = 0; - //TODO idle movement - } - normalize(&Target); - } else { - if (interpolationStep < (1 << fp) - ACTION_STEP_FP * 2) { - Current = interpolate(Current, Target); - normalize(&Current); - } - else { - Current = Target; - interpolationStep = 0; - currentlyMoving = 0; - } - } -} - -char -getInput() -{ - // TODO - char c = 'd'; - handleAngle(c); - return c; -} - - -int -main() -{ - REG_DISPCNT = DISPCNT_BG_MODE(3) | DISPCNT_BG2_ENABLE; - - Current = GET_ROTATE_Z_Q(0); - - while (1) { - memset(output, NUM_FACES, VWIDTH * VHEIGHT); - memset(zBuffer, 0xffffffff, VWIDTH * VHEIGHT * sizeof(FIXED_POINT)); - - for (FIXED_POINT cubeX = -CUBE_WIDTH_FP + STEP_FP ; - cubeX <= CUBE_WIDTH_FP - STEP_FP; cubeX += STEP_FP) { - for (FIXED_POINT cubeY = -CUBE_WIDTH_FP + STEP_FP; - cubeY <= CUBE_WIDTH_FP - STEP_FP; cubeY += STEP_FP) { - switch (FACE_FRONT) { - case FACE_FRONT: - rotateCube(cubeX, cubeY, -CUBE_WIDTH_FP, FACE_FRONT); - break; - case FACE_LEFT: - rotateCube(-CUBE_WIDTH_FP, cubeX, cubeY, FACE_LEFT); - break; - case FACE_RIGHT: - rotateCube(CUBE_WIDTH_FP, cubeX, cubeY, FACE_RIGHT); - break; - case FACE_BOTTOM: - rotateCube(cubeX, -CUBE_WIDTH_FP, cubeY, FACE_BOTTOM); - break; - case FACE_TOP: - rotateCube(cubeX, CUBE_WIDTH_FP, cubeY, FACE_TOP); - break; - case FACE_BACK: - rotateCube(cubeX, cubeY, CUBE_WIDTH_FP, FACE_BACK); - break; - default: // idk render all - rotateCube(cubeX, cubeY, -CUBE_WIDTH_FP, FACE_FRONT); - rotateCube(-CUBE_WIDTH_FP, cubeX, cubeY, FACE_LEFT); - rotateCube(CUBE_WIDTH_FP, cubeX, cubeY, FACE_RIGHT); - rotateCube(cubeX, -CUBE_WIDTH_FP, cubeY, FACE_TOP); - rotateCube(cubeX, CUBE_WIDTH_FP, cubeY, FACE_BOTTOM); - rotateCube(cubeX, cubeY, CUBE_WIDTH_FP, FACE_BACK); - } - } - } - - printAscii(); - getInput(); - } -} diff --git a/source/sys/gba_cart.ld b/source/sys/gba_cart.ld deleted file mode 100644 index d190710..0000000 --- a/source/sys/gba_cart.ld +++ /dev/null @@ -1,233 +0,0 @@ -/* - * SPDX-License-Identifier: CC0-1.0 - * - * SPDX-FileContributor: Antonio Niño Díaz, 2022 - */ - -/* - * Some links with information about linker scripts: - * - * - https://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/specialsections.html - * - * - https://blog.thea.codes/the-most-thoroughly-commented-linker-script/ - * - * - http://beefchunk.com/documentation/sys-programming/binary_formats/elf/elf_from_the_programmers_perspective/node4.html - */ - -OUTPUT_FORMAT("elf32-littlearm") -OUTPUT_ARCH(arm) -ENTRY(entrypoint) - -MEMORY { - ROM : ORIGIN = 0x08000000, LENGTH = 32M - IWRAM : ORIGIN = 0x03000000, LENGTH = 32K - EWRAM : ORIGIN = 0x02000000, LENGTH = 256K -} - -/* Set stack pointers the same way as the BIOS */ - -__STACK_SVC_SIZE__ = 0x40; -__STACK_IRQ_SIZE__ = 0xA0; -__STACK_USR_SIZE_MIN__ = 0x200; /* Minimum size, the real size may be bigger */ - -__STACK_END__ = ORIGIN(IWRAM) + LENGTH(IWRAM) - 0x20; /* Used by BIOS */ -__STACK_SVC_END__ = __STACK_END__; -__STACK_SVC_START__ = __STACK_SVC_END__ - __STACK_SVC_SIZE__; -__STACK_IRQ_END__ = __STACK_SVC_START__; -__STACK_IRQ_START__ = __STACK_IRQ_END__ - __STACK_IRQ_SIZE__; -__STACK_USR_END__ = __STACK_IRQ_START__; -__STACK_USR_START__ = __STACK_USR_END__ - __STACK_USR_SIZE_MIN__; -__STACK_START__ = __STACK_USR_START__; - -SECTIONS -{ - /* - * ROM sections - * ============ - */ - - /* Header and crt0 */ - - .gba_crt0 : ALIGN(4) - { - KEEP (*(.gba_crt0)) - } > ROM - - /* Code */ - - .text : ALIGN(4) - { - *(.text) - *(.text*) - *(.gnu.linkonce.t.*) /* Used for vague linking */ - - /* ARM/Thumb interworking code */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - - /* Array of functions to be called at the start of the program */ - KEEP(*(.init)) - /* Array of functions to be called at the end of the program */ - KEEP(*(.fini)) - } > ROM - - /* Read-only data */ - - .rodata : ALIGN(4) - { - *(.rodata) - *(.rodata*) - *(.gnu.linkonce.r.*) /* Used for vague linking */ - } > ROM - - /* - * Required for C++ and for C programs that try to examine backtraces. Each - * function that can throw exceptions has entries in exidx and extab. - * - * - exidx is used to contain index entries for stack unwinding. - * - extab names sections containing exception unwinding information. - */ - - .ARM.extab : ALIGN(4) - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > ROM - - .ARM.exidx : ALIGN(4) - { - PROVIDE_HIDDEN(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE_HIDDEN(__exidx_end = .); - } > ROM - - /* Array of functions to be called during initialization of the program */ - - .preinit_array : ALIGN(4) - { - __preinit_array_start = .; - KEEP(*(.preinit_array*)) - __preinit_array_end = .; - } > ROM - - /* - * Array of functions to be called during initialization of the program. - * They are called after calling everything in .preinit_array - */ - - .init_array : ALIGN(4) - { - __init_array_start = .; - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array*)) - __init_array_end = .; - } > ROM - - /* Array of functions called when the program ends. */ - - .fini_array : ALIGN(4) - { - __fini_array_start = .; - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array*)) - __fini_array_end = .; - } > ROM - - /* - * IWRAM sections - * ============== - */ - - /* Uninitialized variables */ - - .bss (NOLOAD) : ALIGN(4) - { - *(.bss) - *(.bss*) - *(.gnu.linkonce.b.*) /* Used for vague linking */ - *(COMMON) /* In case -fcommon is used in gcc (not used by default) */ - . = ALIGN(4); - } > IWRAM - - __IWRAM_BSS_START__ = ADDR(.bss); - __IWRAM_BSS_SIZE__ = SIZEOF(.bss); - __IWRAM_BSS_END__ = __IWRAM_BSS_START__ + __IWRAM_BSS_SIZE__; - - /* Read-write data goes into IWRAM */ - - .data : ALIGN(4) - { - __DATA_START__ = .; - *(.data) - *(.data*) - *(.gnu.linkonce.d.*) /* Used for vague linking */ - . = ALIGN(4); - __DATA_END__ = .; - } > IWRAM AT> ROM - - __DATA_SIZE__ = __DATA_END__ - __DATA_START__; - __DATA_LMA__ = LOADADDR(.data); - - /* Sections that the user requests to add to IWRAM */ - - .iwram : ALIGN(4) - { - __IWRAM_START__ = .; - *(.iwram) - *(.iwram*) - *iwram.*(.text*) - *iwram.*(.data*) - . = ALIGN(4); - __IWRAM_END__ = .; - } > IWRAM AT> ROM - - __IWRAM_SIZE__ = __IWRAM_END__ - __IWRAM_START__; - __IWRAM_LMA__ = LOADADDR(.iwram); - - /* The stack goes afterwards, check that there aren't overflows */ - - ASSERT(__IWRAM_END__ <= __STACK_START__, - "Not enough free IWRAM for stack") - - /* Calculate real size of the user stack */ - - __STACK_USR_SIZE__ = __STACK_USR_END__ - __IWRAM_END__; - - /* - * EWRAM sections - * ============== - */ - - /* - * Uninitialized data explicitly placed in EWRAM. This section must be - * called ".sbss" for compatibility with devkitARM. - */ - - .sbss (NOLOAD) : ALIGN(4) - { - *(.sbss) - *(.sbss*) - . = ALIGN(4); - } > EWRAM - - /* Initialized data explicitly placed in EWRAM */ - - .ewram : ALIGN(4) - { - __EWRAM_START__ = .; - *(.ewram) - *(.ewram*) - *ewram.*(.text*) - *ewram.*(.data*) - . = ALIGN(4); - __EWRAM_END__ = .; - } > EWRAM AT > ROM - - __EWRAM_SIZE__ = __EWRAM_END__ - __EWRAM_START__; - __EWRAM_LMA__ = LOADADDR(.ewram); - - /* The heap information should be after the last EWRAM section */ - - __HEAP_START__ = __EWRAM_END__; - __HEAP_END__ = ORIGIN(EWRAM) + LENGTH(EWRAM); - __HEAP_SIZE__ = __HEAP_END__ - __HEAP_START__; -} diff --git a/source/sys/gba_crt0.s b/source/sys/gba_crt0.s deleted file mode 100644 index a731f1d..0000000 --- a/source/sys/gba_crt0.s +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 -// -// SPDX-FileContributor: Antonio Niño Díaz, 2022 - - .section .gba_crt0, "ax" - .global entrypoint - .cpu arm7tdmi - - .arm - -entrypoint: - b header_end - - .fill 156, 1, 0 // Nintendo Logo - .fill 12, 1, 0 // Game Title - .fill 4, 1, 0 // Game Code - .byte 0x30, 0x30 // Maker Code ("00") - .byte 0x96 // Fixed Value (must be 0x96) - .byte 0x00 // Main unit code - .byte 0x00 // Device Type - .fill 7, 1, 0 // Reserved Area - .byte 0x00 // Software version - .byte 0x00 // Complement check (header checksum) - .byte 0x00, 0x00 // Reserved Area - -header_end: - b start_vector - - // Multiboot Header Entries - .byte 0 // Boot mode - .byte 0 // Slave ID Number - .fill 26, 1, 0 // Not used - .word 0 // JOYBUS entrypoint - - .align - -start_vector: - - // Disable interrupts - mov r0, #0x4000000 - mov r1, #0 - str r1, [r0, #0x208] // IME - - // Setup IRQ mode stack - mov r0, #0x12 - msr cpsr, r0 - ldr sp, =__STACK_IRQ_END__ - - // Setup system mode stack - mov r0, #0x1F - msr cpsr, r0 - ldr sp, =__STACK_USR_END__ - - // Switch to Thumb mode - add r0, pc, #1 - bx r0 - - .thumb - - // Clear IWRAM - ldr r0, =#0x3000000 - ldr r1, =#(32 * 1024) - bl mem_zero - - // Copy data section from ROM to RAM - ldr r0, =__DATA_LMA__ - ldr r1, =__DATA_START__ - ldr r2, =__DATA_SIZE__ - bl mem_copy - - // Copy IWRAM data from ROM to RAM - ldr r0, =__IWRAM_LMA__ - ldr r1, =__IWRAM_START__ - ldr r2, =__IWRAM_SIZE__ - bl mem_copy - - // Clear EWRAM - ldr r0, =#0x2000000 - ldr r1, =#(256 * 1024) - bl mem_zero - - // Copy EWRAM data from ROM to RAM - ldr r0, =__EWRAM_LMA__ - ldr r1, =__EWRAM_START__ - ldr r2, =__EWRAM_SIZE__ - bl mem_copy - - // Global constructors - ldr r2, =__libc_init_array - bl blx_r2_trampoline - - // Call main() - mov r0, #0 // int argc - mov r1, #0 // char *argv[] - ldr r2, =main - bl blx_r2_trampoline - - // Global destructors - ldr r2, =__libc_fini_array - bl blx_r2_trampoline - - // If main() returns, reboot the GBA using SoftReset - swi #0x00 - -// r0 = Base address -// r1 = Size -mem_zero: - and r1, r1 - beq 2f // Return if size is 0 - - mov r2, #0 -1: - stmia r0!, {r2} - sub r1, #4 - bne 1b - -2: - bx lr - -// r0 = Source address -// r1 = Destination address -// r2 = Size -mem_copy: - and r2, r2 - beq 2f // Return if size is 0 - -1: - ldmia r0!, {r3} - stmia r1!, {r3} - sub r2, #4 - bne 1b - -2: - bx lr - -// r2 = Address to jump to -blx_r2_trampoline: - bx r2 - - .align - .pool - .end diff --git a/source/sys/syscalls.c b/source/sys/syscalls.c deleted file mode 100644 index f10a3ae..0000000 --- a/source/sys/syscalls.c +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 -// -// SPDX-FileContributor: Antonio Niño Díaz, 2022 - -#include <errno.h> -#include <sys/stat.h> -#include <sys/times.h> -#include <time.h> - -// This file implements stubs for system calls. For more information about it, -// check the documentation of newlib: -// -// https://sourceware.org/newlib/libc.html#Syscalls - -#undef errno -extern int errno; - -char *__env[1] = { 0 }; -char **environ = __env; - -int _getpid(void) -{ - return 1; -} - -int _kill(int pid, int sig) -{ - (void)pid; - (void)sig; - - errno = EINVAL; - return -1; -} - -void _exit(int status) -{ - _kill(status, -1); - - // Hang, there is nowhere to go - while (1); -} - -__attribute__((weak)) int _read(int file, char *ptr, int len) -{ - (void)file; - (void)ptr; - - return len; -} - -__attribute__((weak)) int _write(int file, char *ptr, int len) -{ - (void)file; - (void)ptr; - - return len; -} - -int _close(int file) -{ - (void)file; - - return -1; -} - - -int _fstat(int file, struct stat *st) -{ - (void)file; - - st->st_mode = S_IFCHR; - return 0; -} - -int _isatty(int file) -{ - (void)file; - - return 1; -} - -int _lseek(int file, int ptr, int dir) -{ - (void)file; - (void)ptr; - (void)dir; - - return 0; -} - -int _open(char *path, int flags, ...) -{ - (void)path; - (void)flags; - - return -1; -} - -int _wait(int *status) -{ - (void)status; - - errno = ECHILD; - return -1; -} - -int _unlink(char *name) -{ - (void)name; - - errno = ENOENT; - return -1; -} - -int _times(struct tms *buf) -{ - (void)buf; - - return -1; -} - -int _stat(char *file, struct stat *st) -{ - (void)file; - - st->st_mode = S_IFCHR; - return 0; -} - -int _link(char *old, char *new) -{ - (void)old; - (void)new; - - errno = EMLINK; - return -1; -} - -int _fork(void) -{ - errno = EAGAIN; - return -1; -} - -int _execve(char *name, char **argv, char **env) -{ - (void)name; - (void)argv; - (void)env; - - errno = ENOMEM; - return -1; -} - -void *_sbrk(int incr) -{ - // Symbols defined by the linker - extern char __HEAP_START__[]; - extern char __HEAP_END__[]; - const uintptr_t HEAP_START = (uintptr_t) __HEAP_START__; - const uintptr_t HEAP_END = (uintptr_t) __HEAP_END__; - - // Pointer to the current end of the heap - static uintptr_t heap_end = HEAP_START; - - if (heap_end + incr > HEAP_END) - { - errno = ENOMEM; - return (void *)-1; - } - - uintptr_t prev_heap_end = heap_end; - - heap_end += incr; - - return (void *)prev_heap_end; -}