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
|
||||
*.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