mirror of
https://github.com/jonko0493/blocksdsl-min-repro.git
synced 2025-06-18 13:45:32 -04:00
Initial work
This commit is contained in:
parent
e9bef0c403
commit
593a4ba58c
38
.devcontainer/devcontainer.json
Normal file
38
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
|
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile
|
||||||
|
{
|
||||||
|
"name": "Existing Dockerfile",
|
||||||
|
"build": {
|
||||||
|
// Sets the run context to one level up instead of the .devcontainer folder.
|
||||||
|
"context": "..",
|
||||||
|
// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
|
||||||
|
"dockerfile": "../Dockerfile"
|
||||||
|
},
|
||||||
|
"runArgs": ["--privileged", "--add-host=host.docker.internal:host-gateway"],
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"ms-vscode.cpptools-extension-pack",
|
||||||
|
"ms-azuretools.vscode-docker",
|
||||||
|
"ms-python.python",
|
||||||
|
"ms-vscode.hexeditor"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||||
|
// "features": {},
|
||||||
|
|
||||||
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
|
// "forwardPorts": [3333],
|
||||||
|
|
||||||
|
// Uncomment the next line to run commands after the container is created.
|
||||||
|
"postCreateCommand": "python3 ./build.py -c -b"
|
||||||
|
|
||||||
|
// Configure tool-specific properties.
|
||||||
|
// "customizations": {},
|
||||||
|
|
||||||
|
// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
|
||||||
|
// "remoteUser": "devcontainer"
|
||||||
|
}
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,3 +1,10 @@
|
|||||||
|
*.nds
|
||||||
|
build/
|
||||||
|
*_readelf.txt
|
||||||
|
.ninja_deps
|
||||||
|
.ninja_log
|
||||||
|
build.ninja
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
|
|
||||||
|
36
.vscode/c_cpp_properties.json
vendored
Normal file
36
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "NDS (Linux)",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}",
|
||||||
|
"${workspaceFolder}/libs/**",
|
||||||
|
"/opt/wonderful/toolchain/gcc-arm-none-eabi/include/**",
|
||||||
|
"/opt/wonderful/thirdparty/blocksds/core/libs/dswifi/include/**",
|
||||||
|
"/opt/wonderful/thirdparty/blocksds/core/libs/libnds/include/**",
|
||||||
|
"/opt/wonderful/thirdparty/blocksds/core/libs/maxmod/include"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"_UNICODE",
|
||||||
|
"ARM7",
|
||||||
|
"ARM9"
|
||||||
|
],
|
||||||
|
"browse": {
|
||||||
|
"path": [
|
||||||
|
"${workspaceFolder}",
|
||||||
|
"${workspaceFolder}/libs/**",
|
||||||
|
"/opt/wonderful/toolchain/gcc-arm-none-eabi/include/**",
|
||||||
|
"/opt/wonderful/thirdparty/blocksds/core/libs/libnds/include/**"
|
||||||
|
],
|
||||||
|
"limitSymbolsToIncludedHeaders": true,
|
||||||
|
"databaseFilename": ""
|
||||||
|
},
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
"compilerPath": "/opt/wonderful/toolchain/gcc-arm-none-eabi/bin/arm-none-eabi-g++",
|
||||||
|
"intelliSenseMode": "gcc-arm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"memory": "cpp",
|
||||||
|
"unistd.h": "c"
|
||||||
|
}
|
||||||
|
}
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
FROM skylyrac/blocksds:slim-latest
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install python3-full python3-pip ninja-build wget libxxf86vm1 libxfixes3 libxi6 libxkbcommon-x11-0 libsm6 libgl1 libopengl-dev unzip -y
|
||||||
|
|
||||||
|
RUN git clone https://github.com/AntonioND/architectds.git && \
|
||||||
|
cd ./architectds && \
|
||||||
|
pip3 install wheel setuptools --break-system-packages && \
|
||||||
|
python3 setup.py bdist_wheel && \
|
||||||
|
pip3 install dist/architectds-*-py3-none-any.whl --break-system-packages && \
|
||||||
|
cd ../ && \
|
||||||
|
rm -rf architectds
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/bin/bash" ]
|
32
build.py
Normal file
32
build.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from architectds import *
|
||||||
|
|
||||||
|
arm9 = Arm9Binary(
|
||||||
|
sourcedirs=['src/arm9'],
|
||||||
|
libs=['nds9'],
|
||||||
|
cxxflags='-Werror -Wno-psabi -fpermissive -std=gnu++20',
|
||||||
|
libdirs=['${BLOCKSDS}/libs/libnds']
|
||||||
|
)
|
||||||
|
arm9.generate_elf()
|
||||||
|
|
||||||
|
example_lib = Arm9DynamicLibrary(
|
||||||
|
name='example',
|
||||||
|
main_binary=arm9,
|
||||||
|
sourcedirs=['src/lib_example'],
|
||||||
|
cxxflags='-Werror -Wno-psabi -fpermissive -std=gnu++20',
|
||||||
|
libdirs=['${BLOCKSDS}/libs/libnds']
|
||||||
|
)
|
||||||
|
example_lib.generate_dsl()
|
||||||
|
|
||||||
|
nitrofs = NitroFS()
|
||||||
|
nitrofs.add_arm9_dsl(example_lib)
|
||||||
|
nitrofs.generate_image()
|
||||||
|
|
||||||
|
nds = NdsRom(
|
||||||
|
binaries=[arm9, example_lib, nitrofs],
|
||||||
|
nds_path='dyn_lib_bug_min_repro.nds',
|
||||||
|
game_title='Dynamic Library',
|
||||||
|
game_subtitle='Bug Repro'
|
||||||
|
)
|
||||||
|
nds.generate_nds()
|
||||||
|
|
||||||
|
nds.run_command_line_arguments()
|
84
src/arm9/loader.cpp
Normal file
84
src/arm9/loader.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "loader.hpp"
|
||||||
|
|
||||||
|
typedef bool (fnIsFlagSet)(Save *, u16);
|
||||||
|
typedef void (fnSetFlag)(Save *, u16);
|
||||||
|
typedef void (fnClearFlag)(Save *, u16);
|
||||||
|
typedef u8 (fnGetGlobal)(Save *, u16);
|
||||||
|
typedef void (fnSetGlobal)(Save *, u16, u8);
|
||||||
|
|
||||||
|
typedef int (fnGetMemUsed)();
|
||||||
|
typedef int (fnGetMemFree)();
|
||||||
|
|
||||||
|
fnIsFlagSet *isFlagSetFn;
|
||||||
|
fnSetFlag *setFlagFn;
|
||||||
|
fnClearFlag *clearFlagFn;
|
||||||
|
fnGetGlobal *getGlobalFn;
|
||||||
|
fnSetGlobal *setGlobalFn;
|
||||||
|
|
||||||
|
fnGetMemUsed *getMemUsedFn;
|
||||||
|
fnGetMemFree *getMemFreeFn;
|
||||||
|
|
||||||
|
namespace Loader
|
||||||
|
{
|
||||||
|
void *exampleLib;
|
||||||
|
|
||||||
|
void loadExampleLib()
|
||||||
|
{
|
||||||
|
exampleLib = dlopen("nitro:/dsl/example.dsl", RTLD_NOW | RTLD_LOCAL);
|
||||||
|
|
||||||
|
isFlagSetFn = (fnIsFlagSet *)dlsym(exampleLib, "isFlagSet");
|
||||||
|
setFlagFn = (fnSetFlag *)dlsym(exampleLib, "setFlag");
|
||||||
|
clearFlagFn = (fnClearFlag *)dlsym(exampleLib, "clearFlag");
|
||||||
|
getGlobalFn = (fnGetGlobal *)dlsym(exampleLib, "getGlobal");
|
||||||
|
setGlobalFn = (fnSetGlobal *)dlsym(exampleLib, "setGlobal");
|
||||||
|
|
||||||
|
getMemUsedFn = (fnGetMemUsed *)dlsym(exampleLib, "getMemUsed");
|
||||||
|
getMemFreeFn = (fnGetMemFree *)dlsym(exampleLib, "getMemFree");
|
||||||
|
}
|
||||||
|
|
||||||
|
void unloadExmapleLib()
|
||||||
|
{
|
||||||
|
dlclose(exampleLib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SaveExtensions
|
||||||
|
{
|
||||||
|
bool isFlagSet(Save *save, u16 flag)
|
||||||
|
{
|
||||||
|
return isFlagSetFn(save, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFlag(Save *save, u16 flag)
|
||||||
|
{
|
||||||
|
setFlagFn(save, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearFlag(Save *save, u16 flag)
|
||||||
|
{
|
||||||
|
clearFlagFn(save, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 getGlobal(Save *save, u16 global)
|
||||||
|
{
|
||||||
|
return getGlobalFn(save, global);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGlobal(Save *save, u16 global, u8 value)
|
||||||
|
{
|
||||||
|
setGlobalFn(save, global, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Debug
|
||||||
|
{
|
||||||
|
int getMemUsed()
|
||||||
|
{
|
||||||
|
return getMemUsedFn();
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMemFree()
|
||||||
|
{
|
||||||
|
return getMemFreeFn();
|
||||||
|
}
|
||||||
|
}
|
26
src/arm9/loader.hpp
Normal file
26
src/arm9/loader.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include "save.hpp"
|
||||||
|
|
||||||
|
namespace Loader
|
||||||
|
{
|
||||||
|
void loadExampleLib();
|
||||||
|
void unloadExmapleLib();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SaveExtensions
|
||||||
|
{
|
||||||
|
bool isFlagSet(Save *save, u16 flag);
|
||||||
|
void setFlag(Save *save, u16 flag);
|
||||||
|
void clearFlag(Save *save, u16 flag);
|
||||||
|
u8 getGlobal(Save *save, u16 global);
|
||||||
|
void setGlobal(Save *save, u16 global, u8 value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Debug
|
||||||
|
{
|
||||||
|
int getMemUsed();
|
||||||
|
int getMemFree();
|
||||||
|
}
|
73
src/arm9/main.cpp
Normal file
73
src/arm9/main.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "main.hpp"
|
||||||
|
|
||||||
|
void wait_forever(void)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
swiWaitForVBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
defaultExceptionHandler();
|
||||||
|
|
||||||
|
PrintConsole topScreen;
|
||||||
|
PrintConsole bottomScreen;
|
||||||
|
|
||||||
|
videoSetMode(MODE_0_2D);
|
||||||
|
videoSetModeSub(MODE_0_2D);
|
||||||
|
|
||||||
|
vramSetBankA(VRAM_A_MAIN_BG);
|
||||||
|
vramSetBankC(VRAM_C_SUB_BG);
|
||||||
|
|
||||||
|
consoleInit(&topScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true);
|
||||||
|
consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
|
||||||
|
|
||||||
|
consoleSelect(&topScreen);
|
||||||
|
|
||||||
|
bool init_ok = nitroFSInit(NULL);
|
||||||
|
if (!init_ok)
|
||||||
|
{
|
||||||
|
perror("nitroFSInit()");
|
||||||
|
wait_forever();
|
||||||
|
}
|
||||||
|
// Initialize FAT for save files
|
||||||
|
if (!fatInitDefault())
|
||||||
|
{
|
||||||
|
perror("fatInitDefault()");
|
||||||
|
wait_forever();
|
||||||
|
}
|
||||||
|
swiWaitForVBlank();
|
||||||
|
|
||||||
|
printf("Creating save file...\n");
|
||||||
|
save = new Save();
|
||||||
|
|
||||||
|
printf("Loading example library...");
|
||||||
|
Loader::loadExampleLib();
|
||||||
|
|
||||||
|
SaveExtensions::setFlag(save, 5);
|
||||||
|
if (SaveExtensions::isFlagSet(save, 5))
|
||||||
|
{
|
||||||
|
printf("Flag 5 was set.");
|
||||||
|
}
|
||||||
|
SaveExtensions::setGlobal(save, 5, 20);
|
||||||
|
printf("Global 5 was set to %d", SaveExtensions::getGlobal(save, 5));
|
||||||
|
|
||||||
|
printf("Mem used: %d\nMem free: %d", Debug::getMemUsed(), Debug::getMemFree());
|
||||||
|
|
||||||
|
printf("Unloading example lib...");
|
||||||
|
Loader::unloadExmapleLib();
|
||||||
|
|
||||||
|
printf("Press START to exit to loader\n");
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
swiWaitForVBlank();
|
||||||
|
|
||||||
|
scanKeys();
|
||||||
|
|
||||||
|
if (keysHeld() & KEY_START)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
24
src/arm9/main.hpp
Normal file
24
src/arm9/main.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include <fat.h>
|
||||||
|
#include <filesystem.h>
|
||||||
|
#include <nds.h>
|
||||||
|
#include <nds/arm9/dldi.h>
|
||||||
|
|
||||||
|
#include "loader.hpp"
|
||||||
|
#include "save.hpp"
|
||||||
|
|
||||||
|
Save *save;
|
||||||
|
|
||||||
|
int main();
|
||||||
|
void update();
|
||||||
|
void render();
|
106
src/arm9/save.cpp
Normal file
106
src/arm9/save.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include "save.hpp"
|
||||||
|
|
||||||
|
// Make things unnecessarily complicated so we can use C++ stuff lol
|
||||||
|
void debugLog(string str)
|
||||||
|
{
|
||||||
|
printf(format("{}\n", str).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
string SaveManager::getSavePath()
|
||||||
|
{
|
||||||
|
string defaultDrive = string(fatGetDefaultDrive());
|
||||||
|
if (defaultDrive == "")
|
||||||
|
{
|
||||||
|
defaultDrive = "fat:/";
|
||||||
|
}
|
||||||
|
string path = format("{}into-the-dream-spring.sav", defaultDrive);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveManager::initializeSave(string path)
|
||||||
|
{
|
||||||
|
debugLog("Initializing save file...");
|
||||||
|
FILE *newSaveFile = fopen(path.c_str(), "wb");
|
||||||
|
u8 *cleanData = new u8[NUM_SAVE_SLOTS * SAVE_SLOT_SIZE];
|
||||||
|
fwrite(cleanData, sizeof(u8), NUM_SAVE_SLOTS * SAVE_SLOT_SIZE, newSaveFile);
|
||||||
|
fclose(newSaveFile);
|
||||||
|
delete cleanData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveManager::checkSave(string path)
|
||||||
|
{
|
||||||
|
if (access(path.c_str(), F_OK) != 0)
|
||||||
|
{
|
||||||
|
debugLog("Save file does not exist; initializing...");
|
||||||
|
initializeSave(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FILE *saveFile = fopen(path.c_str(), "rb");
|
||||||
|
fseek(saveFile, 0, SEEK_END);
|
||||||
|
long length = ftell(saveFile);
|
||||||
|
if (length != NUM_SAVE_SLOTS * SAVE_SLOT_SIZE)
|
||||||
|
{
|
||||||
|
debugLog(format("Save file was wrong size {:d} bytes; re-initializing...", length));
|
||||||
|
fclose(saveFile);
|
||||||
|
initializeSave(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveManager::save(int slot, Save *save)
|
||||||
|
{
|
||||||
|
string path = getSavePath();
|
||||||
|
debugLog(format("Attempting to save to {}...", path));
|
||||||
|
checkSave(path);
|
||||||
|
|
||||||
|
FILE *saveFile = fopen(path.c_str(), "rb+");
|
||||||
|
fseek(saveFile, slot * SAVE_SLOT_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
int flagWrite = fwrite(save->getSaveSlot()->flags, sizeof(u8), 512, saveFile);
|
||||||
|
debugLog(format("Wrote {:d} bytes of flags", flagWrite));
|
||||||
|
int globalWrite = fwrite(save->getSaveSlot()->globals, sizeof(u8), 512, saveFile);
|
||||||
|
debugLog(format("Wrote {:d} bytes of globals", globalWrite));
|
||||||
|
|
||||||
|
fclose(saveFile);
|
||||||
|
debugLog("Saved!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Save *SaveManager::load(int slot)
|
||||||
|
{
|
||||||
|
string path = getSavePath();
|
||||||
|
debugLog(format("Attempting to load from {}...", path));
|
||||||
|
checkSave(path);
|
||||||
|
|
||||||
|
FILE *saveFile = fopen(path.c_str(), "rb");
|
||||||
|
fseek(saveFile, slot * SAVE_SLOT_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
Save *save = new Save();
|
||||||
|
|
||||||
|
int flagRead = fread(save->getSaveSlot()->flags, sizeof(u8), 512, saveFile);
|
||||||
|
debugLog(format("Read {:d} bytes of flags", flagRead));
|
||||||
|
int globalRead = fwrite(save->getSaveSlot()->globals, sizeof(u8), 512, saveFile);
|
||||||
|
debugLog(format("Read {:d} bytes of globals", globalRead));
|
||||||
|
|
||||||
|
fclose(saveFile);
|
||||||
|
|
||||||
|
return save;
|
||||||
|
}
|
||||||
|
|
||||||
|
Save::Save()
|
||||||
|
{
|
||||||
|
this->saveSlot = new SaveSlot();
|
||||||
|
}
|
||||||
|
|
||||||
|
Save::Save(SaveSlot *save)
|
||||||
|
{
|
||||||
|
this->saveSlot = save;
|
||||||
|
}
|
||||||
|
|
||||||
|
Save::~Save()
|
||||||
|
{
|
||||||
|
delete saveSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveSlot *Save::getSaveSlot()
|
||||||
|
{
|
||||||
|
return this->saveSlot;
|
||||||
|
}
|
53
src/arm9/save.hpp
Normal file
53
src/arm9/save.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <nds.h>
|
||||||
|
#include <nds/arm9/dldi.h>
|
||||||
|
#include <fat.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define NUM_SAVE_SLOTS 30
|
||||||
|
#define SAVE_SLOT_SIZE 1024
|
||||||
|
|
||||||
|
struct SaveSlot
|
||||||
|
{
|
||||||
|
u8 *flags;
|
||||||
|
u8 *globals;
|
||||||
|
|
||||||
|
SaveSlot()
|
||||||
|
{
|
||||||
|
flags = new u8[512];
|
||||||
|
globals = new u8[512];
|
||||||
|
}
|
||||||
|
~SaveSlot()
|
||||||
|
{
|
||||||
|
delete flags;
|
||||||
|
delete globals;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Save
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SaveSlot *saveSlot;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Save();
|
||||||
|
Save(SaveSlot *save);
|
||||||
|
~Save();
|
||||||
|
SaveSlot *getSaveSlot();
|
||||||
|
};
|
||||||
|
|
||||||
|
class SaveManager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static string getSavePath();
|
||||||
|
static void initializeSave(string path);
|
||||||
|
static void checkSave(string path);
|
||||||
|
public:
|
||||||
|
static void save(int slot, Save *save);
|
||||||
|
static Save *load(int slot);
|
||||||
|
};
|
37
src/lib_example/debug.c
Normal file
37
src/lib_example/debug.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <nds.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define SYM_PUBLIC __attribute__((visibility ("default")))
|
||||||
|
|
||||||
|
extern u8 *fake_heap_end; // current heap start
|
||||||
|
extern u8 *fake_heap_start; // current heap end
|
||||||
|
|
||||||
|
u8* getHeapStart()
|
||||||
|
{
|
||||||
|
return fake_heap_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* getHeapEnd()
|
||||||
|
{
|
||||||
|
return (u8*)sbrk(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* getHeapLimit()
|
||||||
|
{
|
||||||
|
return fake_heap_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the amount of used memory in bytes
|
||||||
|
SYM_PUBLIC int getMemUsed()
|
||||||
|
{
|
||||||
|
struct mallinfo mi = mallinfo();
|
||||||
|
return mi.uordblks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the amount of free memory in bytes
|
||||||
|
SYM_PUBLIC int getMemFree()
|
||||||
|
{
|
||||||
|
struct mallinfo mi = mallinfo();
|
||||||
|
return mi.fordblks + (getHeapLimit() - getHeapEnd());
|
||||||
|
}
|
40
src/lib_example/save_extensions.cpp
Normal file
40
src/lib_example/save_extensions.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "../arm9/save.hpp"
|
||||||
|
|
||||||
|
#define SYM_PUBLIC __attribute__((visibility ("default")))
|
||||||
|
|
||||||
|
void setOrClearFlag(Save *save, u16 flag, bool set)
|
||||||
|
{
|
||||||
|
flag--;
|
||||||
|
int byte = flag >> 3;
|
||||||
|
int bit = flag & 7;
|
||||||
|
|
||||||
|
if (set)
|
||||||
|
{
|
||||||
|
save->getSaveSlot()->flags[byte] = save->getSaveSlot()->flags[byte] | (1 << bit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
save->getSaveSlot()->flags[byte] = save->getSaveSlot()->flags[byte] & ~(1 << bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SYM_PUBLIC bool isFlagSet(Save *save, u16 flag)
|
||||||
|
{
|
||||||
|
flag--;
|
||||||
|
return (save->getSaveSlot()->flags[flag >> 3] >> (flag & 7)) & 1;
|
||||||
|
}
|
||||||
|
SYM_PUBLIC void setFlag(Save *save, u16 flag)
|
||||||
|
{
|
||||||
|
setOrClearFlag(save, flag, true);
|
||||||
|
}
|
||||||
|
SYM_PUBLIC void clearFlag(Save *save, u16 flag)
|
||||||
|
{
|
||||||
|
setOrClearFlag(save, flag, false);
|
||||||
|
}
|
||||||
|
SYM_PUBLIC u8 getGlobal(Save *save, u16 global)
|
||||||
|
{
|
||||||
|
return save->getSaveSlot()->globals[--global];
|
||||||
|
}
|
||||||
|
SYM_PUBLIC void setGlobal(Save *save, u16 global, u8 value)
|
||||||
|
{
|
||||||
|
save->getSaveSlot()->globals[--global] = value;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user