Migrate old romloader code as an interface

This is loosely based on WAIO:
- Load akloader from a prebuilt akloader.nds. Must be extracted from a
  given kernel.
- Remaining code based on the R4 variant of romloader.cpp
- Add setting to alternate between nds-bootstrap and given kernel
This commit is contained in:
lifehackerhansol 2024-10-13 02:09:07 -07:00
parent 5c8bfca525
commit fc0e950f34
No known key found for this signature in database
GPG Key ID: 80FB184AFC0B3B0E
13 changed files with 274 additions and 60 deletions

View File

@ -22,12 +22,12 @@ GAME_SUBTITLE2 := www.acekard.com
include $(DEVKITARM)/ds_rules
.PHONY: checkarm7 checkarm9 checkarm9_dsi clean
.PHONY: checkarm7 checkarm9 checkarm9_ak2 checkarm9_dsi clean
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all: checkarm7 checkarm9 checkarm9_dsi $(TARGET).nds $(TARGET).dsi
all: checkarm7 checkarm9 checkarm9_ak2 checkarm9_dsi $(TARGET).nds $(TARGET)_ak2.nds $(TARGET).dsi
#---------------------------------------------------------------------------------
checkarm7:
@ -37,6 +37,10 @@ checkarm7:
checkarm9:
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
checkarm9_ak2:
$(MAKE) -C arm9_ak2
#---------------------------------------------------------------------------------
checkarm9_dsi:
$(MAKE) -C arm9_dsi
@ -47,6 +51,12 @@ $(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf
-b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \
$(_ADDFILES)
#---------------------------------------------------------------------------------
$(TARGET)_ak2.nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9_ak2/$(TARGET).elf
ndstool -c $@ -7 arm7/$(TARGET).elf -9 arm9_ak2/$(TARGET).elf \
-b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \
$(_ADDFILES)
#---------------------------------------------------------------------------------
$(TARGET).dsi : $(NITRO_FILES) arm7/$(TARGET).elf arm9_dsi/$(TARGET).elf
ndstool -c $@ -7 arm7/$(TARGET).elf -9 arm9_dsi/$(TARGET).elf \
@ -61,6 +71,10 @@ arm7/$(TARGET).elf:
arm9/$(TARGET).elf:
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
arm9_ak2/$(TARGET).elf:
$(MAKE) -C arm9_ak2
#---------------------------------------------------------------------------------
arm9_dsi/$(TARGET).elf:
$(MAKE) -C arm9_dsi
@ -68,6 +82,7 @@ arm9_dsi/$(TARGET).elf:
#---------------------------------------------------------------------------------
clean:
$(MAKE) -C arm9 clean
$(MAKE) -C arm9_ak2 clean
$(MAKE) -C arm9_dsi clean
$(MAKE) -C arm7 clean
rm -f *.nds *.dsi

View File

@ -42,6 +42,11 @@ cGlobalSettings::cGlobalSettings() {
show12hrClock = false;
autorunWithLastRom = false;
homebrewreset = false;
#ifndef __KERNEL_LAUNCHER_SUPPORT__
romLauncher = EKernelLauncher;
#else
romLauncher = ENdsBootstrapLauncher;
#endif
}
void cGlobalSettings::loadSettings() {
@ -81,6 +86,11 @@ void cGlobalSettings::loadSettings() {
temp = ini.GetString("system", "saveext", ".sav");
saveExt = (temp == ".sav");
#ifdef __KERNEL_LAUNCHER_SUPPORT__
temp = ini.GetString("system", "nds-bootstrap", "false");
romLauncher = (temp != "false") ? ENdsBootstrapLauncher : EKernelLauncher;
#endif
struct stat st;
if (0 == stat(SFN_CHEATS, &st)) cheatDB = true;

View File

@ -19,6 +19,7 @@ class cGlobalSettings {
enum TScrollSpeed { EScrollFast = 4, EScrollMedium = 10, EScrollSlow = 16 };
enum TViewMode { EViewList = 0, EViewIcon = 1, EViewInternal = 2 };
enum TSlot2Mode { ESlot2Ask = 0, ESlot2Gba = 1, ESlot2Nds = 2 };
enum TROMLauncher { EKernelLauncher = 0, ENdsBootstrapLauncher = 1 };
public:
cGlobalSettings();
@ -61,6 +62,7 @@ class cGlobalSettings {
bool show12hrClock;
bool autorunWithLastRom;
bool homebrewreset;
int romLauncher;
};
typedef t_singleton<cGlobalSettings> globalSettings_s;

View File

@ -1,24 +1,25 @@
/*
romloader.cpp
AcekardLauncher.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
Copyright (C) 2024 lifehackerhansol
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "romloader.h"
#include <fat.h>
#include <limits.h>
#include <climits>
#include <cstring>
#include <string>
#include <nds.h>
#include <string.h>
#include "../../../share/fifotool.h"
#include "AcekardLauncher.h"
#include "dbgtool.h"
//#include "akloader_arm7_bin.h"
//#include "akloader_arm9_bin.h"
#include "../../share/fifotool.h"
#include "globalsettings.h"
#include "savemngr.h"
#include "timetool.h"
// 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars
#define MAX_FILENAME_LENGTH 768
// FIFO_CHANNEL_BITS - number of bits used to specify the channel in a packet - default=4
#define FIFO_CHANNEL_BITS 4
@ -52,24 +53,39 @@ static void resetAndLoop() {
swiSoftReset();
}
bool loadRom(const std::string& filename, const std::string& savename, u32 flags, long cheatOffset,
size_t cheatSize) {
bool AcekardLauncher::launchRom(std::string romPath, std::string savePath, u32 flags,
u32 cheatOffset, u32 cheatSize) {
tNDSHeader header;
dbg_printf("load %s\n", romPath.c_str());
// akloaders are very old and expect the old-style libfat mount points
romPath.replace(0, 3, "fat0");
savePath.replace(0, 3, "fat0");
FILE* loader = fopen("fat:/__rpg/akloader.nds", "rb");
if (loader == NULL) return false;
fseek(loader, 0, SEEK_SET);
fread(&header, sizeof(header), 1, loader);
// copy loader's arm7 code
fseek(loader, header.arm7romOffset, SEEK_SET);
fread(header.arm7destination, 4, header.arm7binarySize >> 2, loader);
__NDSHeader->arm7executeAddress = header.arm7executeAddress;
// copy loader's arm9 code
fseek(loader, header.arm9romOffset, SEEK_SET);
fread(header.arm9destination, 4, header.arm9binarySize >> 2, loader);
__NDSHeader->arm9executeAddress = header.arm9executeAddress;
fclose(loader);
*(u32*)0x23fd900 = flags;
*(u32*)0x23fd904 = cheatOffset;
*(u32*)0x23fd908 = cheatSize;
memset((void*)0x23fda00, 0, PATH_MAX * 2);
strcpy((char*)0x23fda00, filename.c_str());
strcpy((char*)(0x23fda00 + PATH_MAX), savename.c_str());
dbg_printf("load %s\n", filename.c_str());
// copy loader's arm7 code
// memcpy( (void *)0x023FA000, akloader_arm7_bin, akloader_arm7_bin_size );
__NDSHeader->arm7executeAddress = (void*)0x023FA000;
// copy loader's arm9 code
// memcpy( (void *)0x023c0000, akloader_arm9_bin, akloader_arm9_bin_size );
__NDSHeader->arm9executeAddress = (void*)0x023c0000;
memset((void*)0x23fda00, 0, MAX_FILENAME_LENGTH * 2);
strcpy((char*)0x23fda00, romPath.c_str());
strcpy((char*)(0x23fda00 + MAX_FILENAME_LENGTH), savePath.c_str());
dbg_printf("load done\n");

View File

@ -0,0 +1,18 @@
/*
Copyright (C) 2024 lifehackerhansol
SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include <nds/ndstypes.h>
#include <string>
#include "ILauncher.h"
class AcekardLauncher : public ILauncher {
public:
bool launchRom(std::string romPath, std::string savePath, u32 flags, u32 cheatOffset,
u32 cheatSize) override;
};

View File

@ -22,7 +22,6 @@
#include "nand_banner_bin.h"
#include "nds_save_banner_bin.h"
#include "progresswnd.h"
#include "romloader.h"
#include "startmenu.h"
#include "systemfilenames.h"
#include "timetool.h"

View File

@ -27,7 +27,6 @@
#include "progresswnd.h"
#include "rominfownd.h"
#include "romlauncher.h"
#include "romloader.h"
#include <dirent.h>
#include <fat.h>
@ -670,7 +669,7 @@ void cMainWnd::onFolderChanged() {
}
}
if (mode == cGlobalSettings::ESlot2Nds) {
loadRom("slot2:/", "", 0, 0, 0);
// loadRom("slot2:/", "", 0, 0, 0);
} else {
CGbaLoader::StartGBA();
}

View File

@ -286,6 +286,7 @@ void cRomInfoWnd::onShow() {
#define ITEM_SAVETYPE 0, 0
#define ITEM_LINKAGE 0, 1
#define ITEM_RUMBLE 0, 2
#define ITEM_NDSBOOTSTRAP 0, 3
#define ITEM_CHEATS 1, 0
#define ITEM_SOFTRESET 1, 1
@ -328,6 +329,15 @@ void cRomInfoWnd::pressSaveType(void) {
settingWnd.addSettingItem(LANG("exp window", "strength"), _values,
_romInfo.saveInfo().getRumble());
#ifdef __KERNEL_LAUNCHER_SUPPORT__
_values.clear();
_values.push_back("nds-bootstrap");
_values.push_back("kernel");
_values.push_back(LANG("save type", "default"));
settingWnd.addSettingItem(LANG("loader", "text"), _values,
_romInfo.saveInfo().getNdsBootstrap());
#endif // __KERNEL_LAUNCHER_SUPPORT__
settingWnd.addSettingTab(LANG("save type", "tab2"));
_values.clear();
@ -399,7 +409,8 @@ void cRomInfoWnd::pressSaveType(void) {
settingWnd.getItemSelection(ITEM_SOFTRESET), settingWnd.getItemSelection(ITEM_CHEATS),
settingWnd.getItemSelection(ITEM_SAVESLOT), 2, 0,
settingWnd.getItemSelection(ITEM_LINKAGE), settingWnd.getItemSelection(ITEM_ICON), 2,
settingWnd.getItemSelection(ITEM_LANGUAGE));
settingWnd.getItemSelection(ITEM_LANGUAGE),
settingWnd.getItemSelection(ITEM_NDSBOOTSTRAP));
saveManager().updateCustomSaveList(_romInfo.saveInfo());
}

View File

@ -11,6 +11,7 @@
#include "flags.h"
#include "language.h"
#include "launcher/AcekardLauncher.h"
#include "launcher/HomebrewLauncher.h"
#include "launcher/ILauncher.h"
#include "launcher/NdsBootstrapLauncher.h"
@ -231,7 +232,14 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool
u8 language = aRomInfo.saveInfo().getLanguage();
if (language) flags |= (language << PATCH_LANGUAGE_SHIFT) & PATCH_LANGUAGE_MASK;
#ifndef __KERNEL_LAUNCHER_SUPPORT__
launcher = new NdsBootstrapLauncher();
#else // __KERNEL_LAUNCHER_SUPPORT__
if (aRomInfo.saveInfo().isNdsBootstrap())
launcher = new NdsBootstrapLauncher();
else
launcher = new AcekardLauncher();
#endif // __KERNEL_LAUNCHER_SUPPORT__
} else {
if (!aMenu) saveManager().saveLastInfo(aFullPath);
launcher = new HomebrewLauncher();

View File

@ -1,16 +0,0 @@
/*
romloader.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include <nds/ndstypes.h>
#include <string>
bool loadRom(const std::string& filename, const std::string& savename, u32 flags, long cheatOffset,
size_t cheatSize);

View File

@ -64,22 +64,24 @@ enum DISPLAY_SAVE_TYPE {
#define SAVE_INFO_EX_DMA 0x80
#define SAVE_INFO_EX_COMPARE_SIZE 18
// flags2
#define SAVE_INFO_EX_GLOBAL_DOWNLOAD_PLAY 0x00000001
#define SAVE_INFO_EX_GLOBAL_SOFT_RESET 0x00000002
#define SAVE_INFO_EX_GLOBAL_CHEAT 0x00000004
#define SAVE_INFO_EX_GLOBAL_DMA 0x00000008
#define SAVE_INFO_EX_GLOBAL_DOWNLOAD_PLAY (BIT(0))
#define SAVE_INFO_EX_GLOBAL_SOFT_RESET (BIT(1))
#define SAVE_INFO_EX_GLOBAL_CHEAT (BIT(2))
#define SAVE_INFO_EX_GLOBAL_DMA (BIT(3))
#define SAVE_INFO_EX_GLOBAL_MASK 0x0000000f
#define SAVE_INFO_EX_PROTECTION 0x00000010
#define SAVE_INFO_EX_LINKAGE 0x00000020
#define SAVE_INFO_EX_PROTECTION (BIT(4))
#define SAVE_INFO_EX_LINKAGE (BIT(5))
#define SAVE_INFO_EX_ICON_MASK 0x000000c0
#define SAVE_INFO_EX_ICON_SHIFT 6
#define SAVE_INFO_EX_ICON_TRANSPARENT 0
#define SAVE_INFO_EX_ICON_AS_IS 1
#define SAVE_INFO_EX_ICON_FIRMWARE 2
#define SAVE_INFO_EX_SD_SAVE 0x00000100
#define SAVE_INFO_EX_GLOBAL_SD_SAVE 0x00000200
#define SAVE_INFO_EX_SD_SAVE (BIT(8))
#define SAVE_INFO_EX_GLOBAL_SD_SAVE (BIT(9))
#define SAVE_INFO_EX_LANGUAGE_MASK 0x00001c00
#define SAVE_INFO_EX_LANGUAGE_SHIFT 10
#define SAVE_INFO_EX_NDSBOOTSTRAP (BIT(13))
#define SAVE_INFO_EX_GLOBAL_NDSBOOTSTRAP (BIT(14))
typedef struct SAVE_INFO_EX_T {
u8 gameTitle[12];
@ -106,6 +108,9 @@ typedef struct SAVE_INFO_EX_T {
u8 getLanguage(void) {
return (flags2 & SAVE_INFO_EX_LANGUAGE_MASK) >> SAVE_INFO_EX_LANGUAGE_SHIFT;
}
u8 getNdsBootstrap(void) {
return getFlag(SAVE_INFO_EX_NDSBOOTSTRAP, SAVE_INFO_EX_GLOBAL_NDSBOOTSTRAP, true);
};
bool isDownloadPlay(void) {
return getState(SAVE_INFO_EX_DOWNLOAD_PLAY, SAVE_INFO_EX_GLOBAL_DOWNLOAD_PLAY, false,
false);
@ -125,8 +130,12 @@ typedef struct SAVE_INFO_EX_T {
bool isSDSave(void) {
return getState(SAVE_INFO_EX_SD_SAVE, SAVE_INFO_EX_GLOBAL_SD_SAVE, gs().sdsave, true);
};
bool isNdsBootstrap(void) {
return getState(SAVE_INFO_EX_NDSBOOTSTRAP, SAVE_INFO_EX_GLOBAL_NDSBOOTSTRAP,
gs().romLauncher, true);
};
void setFlags(u8 rumble, u8 downloadplay, u8 reset, u8 cheat, u8 slot, u8 dma, u8 protection,
u8 linkage, u8 icon, u8 sdsave, u8 language) {
u8 linkage, u8 icon, u8 sdsave, u8 language, u8 ndsbootstrap) {
flags = rumble & SAVE_INFO_EX_RUMBLE;
flags2 = 0;
setFlag(SAVE_INFO_EX_DOWNLOAD_PLAY, SAVE_INFO_EX_GLOBAL_DOWNLOAD_PLAY, downloadplay, false);
@ -139,6 +148,7 @@ typedef struct SAVE_INFO_EX_T {
flags2 |= (icon << SAVE_INFO_EX_ICON_SHIFT) & SAVE_INFO_EX_ICON_MASK;
setFlag(SAVE_INFO_EX_SD_SAVE, SAVE_INFO_EX_GLOBAL_SD_SAVE, sdsave, true);
flags2 |= (language << SAVE_INFO_EX_LANGUAGE_SHIFT) & SAVE_INFO_EX_LANGUAGE_MASK;
setFlag(SAVE_INFO_EX_NDSBOOTSTRAP, SAVE_INFO_EX_GLOBAL_NDSBOOTSTRAP, ndsbootstrap, true);
};
u8 getFlag(u32 personal, u32 global, bool style) {
return (flags2 & global) ? 2 : ((style ? (flags2 & personal) : (flags & personal)) ? 1 : 0);
@ -173,7 +183,8 @@ typedef struct SAVE_INFO_EX_T {
saveType = ST_UNKNOWN;
flags = 0;
flags2 = SAVE_INFO_EX_GLOBAL_SOFT_RESET | SAVE_INFO_EX_GLOBAL_CHEAT |
SAVE_INFO_EX_GLOBAL_DMA | SAVE_INFO_EX_GLOBAL_SD_SAVE;
SAVE_INFO_EX_GLOBAL_DMA | SAVE_INFO_EX_GLOBAL_SD_SAVE |
SAVE_INFO_EX_GLOBAL_NDSBOOTSTRAP;
reserved[0] = reserved[1] = 0;
};
} SAVE_INFO_EX;

141
arm9_ak2/Makefile Normal file
View File

@ -0,0 +1,141 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/ds_rules
SOURCE_PATH := ../arm9
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
# DATA is a list of directories containing binary files embedded using bin2o
# GRAPHICS is a list of directories containing image files to be converted with grit
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD := build
SOURCES := $(SOURCE_PATH)/source $(SOURCE_PATH)/source/ui $(SOURCE_PATH)/source/font $(SOURCE_PATH)/source/launcher $(SOURCE_PATH)/source/saves
INCLUDES := $(SOURCE_PATH)/include ../share $(SOURCES)
DATA := $(SOURCE_PATH)/data ../data
GRAPHICS :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s
CFLAGS := -g -Wall -O3\
$(ARCH) $(INCLUDE) -DARM9
CFLAGS += -D_NO_BOOTSTUB_ -D__KERNEL_LAUNCHER_SUPPORT__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lfat -lnds9
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS) $(PORTLIBS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export ARM9ELF := $(CURDIR)/$(TARGET).elf
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))\
$(foreach dir,$(DATA),$(CURDIR)/$(dir))\
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(PNGFILES:.png=.o) $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(PNGFILES:.png=.h) $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir))\
$(foreach dir,$(LIBDIRS),-I$(dir)/include)\
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(ARM9ELF) : $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
# This rule creates assembly source files using grit
# grit takes an image file and a .grit describing how the file is to be processed
# add additional rules like this for each image extension
# you use in the graphics folders
#---------------------------------------------------------------------------------
%.s %.h: %.png %.grit
#---------------------------------------------------------------------------------
grit $< -fts -o$*
-include $(DEPSDIR)/*.d
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -275,7 +275,7 @@ microsd card = microSD Card
slot2 card = Slot2 Card
favorites = Favorites
[hbloader]
load failed = Failed to load homebrew app.
[loader]
text = Use ROM loader
[end]