Add TTMenu support

This needs TTMenu/YSMenu to already be installed, or at least
extinfo/infolib/ttpatch.
This commit is contained in:
lifehackerhansol 2024-10-31 21:00:14 -07:00
parent 8cada4d83d
commit 350dc13e90
No known key found for this signature in database
GPG Key ID: 80FB184AFC0B3B0E
7 changed files with 420 additions and 2 deletions

View File

@ -27,7 +27,7 @@ include $(DEVKITARM)/ds_rules
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all: checkarm7 checkarm9 checkarm9_ak2 checkarm9_dsi $(TARGET).nds $(TARGET)_ak2.nds $(TARGET).dsi
all: checkarm7 checkarm9 checkarm9_ak2 checkarm9_dsi checkarm9_tt $(TARGET).nds $(TARGET)_ak2.nds $(TARGET)_tt.nds $(TARGET).dsi
#---------------------------------------------------------------------------------
checkarm7:
@ -45,6 +45,10 @@ checkarm9_ak2:
checkarm9_dsi:
$(MAKE) -C arm9_dsi
#---------------------------------------------------------------------------------
checkarm9_tt:
$(MAKE) -C arm9_tt
#---------------------------------------------------------------------------------
$(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf
ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
@ -57,6 +61,12 @@ $(TARGET)_ak2.nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9_ak2/$(TARGET).elf
-b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \
$(_ADDFILES)
#---------------------------------------------------------------------------------
$(TARGET)_tt.nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9_tt/$(TARGET).elf
ndstool -c $@ -7 arm7/$(TARGET).elf -9 arm9_tt/$(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 \
@ -79,10 +89,15 @@ arm9_ak2/$(TARGET).elf:
arm9_dsi/$(TARGET).elf:
$(MAKE) -C arm9_dsi
#---------------------------------------------------------------------------------
arm9_tt/$(TARGET).elf:
$(MAKE) -C arm9_tt
#---------------------------------------------------------------------------------
clean:
$(MAKE) -C arm9 clean
$(MAKE) -C arm9_ak2 clean
$(MAKE) -C arm9_dsi clean
$(MAKE) -C arm9_tt clean
$(MAKE) -C arm7 clean
rm -f *.nds *.dsi

View File

@ -40,6 +40,10 @@ static u32 getSystem(void) {
return dsGen;
}
static void prepairResetTT() {
memcpy(__NDSHeader->arm7destination, *(void* volatile*)0x02FFFE00, __NDSHeader->arm7binarySize);
}
static void prepairReset() {
// enable sound
if (2 == getSystem())
@ -104,6 +108,8 @@ static void menuValue32Handler(u32 value, void* data) {
swiChangeSoundBias(0, 0x400);
swiSwitchToGBAMode();
} break;
case MENU_MSG_ARM7_REBOOT_TT:
prepairResetTT();
case MENU_MSG_ARM7_REBOOT:
prepairReset();
swiSoftReset();

View File

@ -0,0 +1,225 @@
/*
Copyright (C) 2024 lifehackerhansol
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <sys/stat.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <nds/ndstypes.h>
#include "../cheatwnd.h"
#include "../dsrom.h"
#include "../flags.h"
#include "../mainlist.h"
#include "../ui/progresswnd.h"
#include "ILauncher.h"
#include "TopToyLauncher.h"
static void resetAndLoop() {
DC_FlushAll();
DC_InvalidateAll();
fifoSendValue32(FIFO_USER_01, MENU_MSG_ARM7_REBOOT_TT);
*((vu32*)0x02FFFE04) = 0;
// Interrupt
REG_IME = 0;
REG_IE = 0;
REG_IF = ~0;
// wait for arm7
while (*((vu32*)0x02FFFE04) == 0)
;
swiSoftReset();
}
typedef struct {
char TTARMagic[4]; // usually "TTAR"
char gameCode[4]; // gameCode of title as seen in usrcheat.dat
u32 crc32; // crc32 of title header as seen in usrcheat.dat
u32 unk1; // TODO: what does this mean?
u32 cheatOffset; // relative from 0x1100 of file
u32 cheatSize; // size in bytes
u8 reserved[235];
} PACKED TTARHeader;
bool TopToyLauncher::prepareCheats() {
u32 gameCode, crc32;
if (cCheatWnd::romData(mRomPath, gameCode, crc32)) {
FILE* cheatDb = fopen("/__rpg/cheats/usrcheat.dat", "rb");
if (!cheatDb) goto cheat_failed;
long cheatOffset;
size_t cheatSize;
if (cCheatWnd::searchCheatData(cheatDb, gameCode, crc32, cheatOffset, cheatSize)) {
// Read cheat codes
cCheatWnd chtwnd((256) / 2, (192) / 2, 100, 100, NULL, mRomPath);
chtwnd.parse(mRomPath);
std::vector<u32> cheats(chtwnd.getCheats());
// YSMENU.ARP file creation
ALIGN(4) TTARHeader arHeader = {};
arHeader.TTARMagic[0] = 'T';
arHeader.TTARMagic[1] = 'T';
arHeader.TTARMagic[2] = 'A';
arHeader.TTARMagic[3] = 'R';
memcpy(&arHeader.gameCode, &gameCode, 4);
arHeader.crc32 = crc32;
// We will write the cheat codes directly to 0x1100.
arHeader.cheatOffset = 0;
arHeader.cheatSize = cheats.size() << 2;
FILE* cheatFile = fopen("/YSMENU.ARP", "wb");
fseek(cheatFile, 0, SEEK_SET);
// memdump. Actually just expanding the file seems to crash, but this works totally
// fine...
fwrite((void*)0x02400000, 4, 0x1100 >> 2, cheatFile);
fflush(cheatFile);
fseek(cheatFile, 0, SEEK_SET);
fwrite(&arHeader, 1, sizeof(TTARHeader), cheatFile);
fseek(cheatFile, 0x1100, SEEK_SET);
fwrite(cheats.data(), 4, cheats.size(), cheatFile);
fflush(cheatFile);
fclose(cheatFile);
} else {
fclose(cheatDb);
goto cheat_failed;
}
fclose(cheatDb);
}
return true;
cheat_failed:
// Remove cheat bin if exists
if (access("/YSMENU.ARP", F_OK) == 0) {
remove("/YSMENU.ARP");
}
return false;
}
// TODO: what are the unknowns?
typedef struct {
char TTSYSMagic[4];
u32 unk1;
u32 unk2; // always set to 1?
u32 softReset;
u32 useCheats;
u32 DMA;
u8 reserved[232];
} PACKED TTSYSHeader;
// TTMENU.SYS file creation. Sets up parameters for ttpatch.dat
bool TopToyLauncher::prepareTTSYS(void) {
TTSYSHeader* ttsys_header = (TTSYSHeader*)malloc(sizeof(TTSYSHeader));
ttsys_header->TTSYSMagic[0] = 't';
ttsys_header->TTSYSMagic[1] = 't';
ttsys_header->TTSYSMagic[2] = 'd';
ttsys_header->TTSYSMagic[3] = 's';
ttsys_header->unk1 = 0;
ttsys_header->unk2 = 1;
ttsys_header->softReset = mFlags & PATCH_SOFT_RESET ? 1 : 0;
ttsys_header->useCheats = mFlags & PATCH_CHEATS ? 1 : 0;
ttsys_header->DMA = mFlags & PATCH_DMA ? 1 : 0;
FILE* TTSYSFile = fopen("fat:/TTMENU.SYS", "rb+");
fseek(TTSYSFile, 0, SEEK_SET);
fwrite(ttsys_header, sizeof(TTSYSHeader), 1, TTSYSFile);
free(ttsys_header);
fseek(TTSYSFile, 0x100, SEEK_SET);
fwrite(mRomPath.c_str() + 4, 1, 0x1000, TTSYSFile);
fseek(TTSYSFile, 0x1100, SEEK_SET);
fwrite(mSavePath.c_str() + 4, 1, 0x1000, TTSYSFile);
if (mFlags & PATCH_CHEATS) {
fseek(TTSYSFile, 0x2100, SEEK_SET);
fwrite("/YSMENU.ARP", 1, 0x12, TTSYSFile);
}
fflush(TTSYSFile);
fclose(TTSYSFile);
return true;
}
bool TopToyLauncher::launchRom(std::string romPath, std::string savePath, u32 flags,
u32 cheatOffset, u32 cheatSize) {
#ifdef __TTLAUNCHER_M3__
if (access("fat:/TTMenu/m3patch.dat", F_OK) != 0)
#else
if (access("fat:/TTMenu/ttpatch.dat", F_OK) != 0)
#endif
return false;
mRomPath = romPath;
mSavePath = savePath;
mFlags = flags;
// Create TTMENU.SYS if it don't exist
if (access("fat:/TTMENU.SYS", F_OK) != 0) {
progressWnd().setTipText("Generating TTMENU.SYS...");
progressWnd().show();
progressWnd().setPercent(0);
FILE* TTSYSFile = fopen("fat:/TTMENU.SYS", "wb");
fseek(TTSYSFile, 0, SEEK_SET);
// memdump. Actually just expanding the file seems to crash, but this works totally fine...
fwrite((void*)0x02400000, 1, 0x400000, TTSYSFile);
fflush(TTSYSFile);
fclose(TTSYSFile);
progressWnd().setPercent(100);
progressWnd().hide();
}
// Prepare cheat codes if enabled
if (flags & PATCH_CHEATS) {
if (!prepareCheats()) return false;
}
// Setup TTMenu system parameters
if (!prepareTTSYS()) return false;
#ifdef __TTLAUNCHER_M3__
FILE* loader = fopen("fat:/TTMenu/m3patch.dat", "rb");
#else
FILE* loader = fopen("fat:/TTMenu/ttpatch.dat", "rb");
#endif
tNDSHeader* header = (tNDSHeader*)malloc(sizeof(tNDSHeader));
u8* loader_arm7 = NULL;
fseek(loader, 0, SEEK_SET);
fread(header, 1, sizeof(tNDSHeader), loader);
fseek(loader, header->arm9romOffset, SEEK_SET);
fread((void*)header->arm9destination, 1, header->arm9binarySize, loader);
fseek(loader, header->arm7romOffset, SEEK_SET);
loader_arm7 = (u8*)memalign(32, header->arm7binarySize);
fread(loader_arm7, 1, header->arm7binarySize, loader);
fclose(loader);
memcpy((void*)__NDSHeader, header, sizeof(tNDSHeader));
free(header);
*(u32*)0x02FFFE00 = (u32)loader_arm7;
// patch a loop in ARM9
// not sure why it's there. Some sort of obfuscation mechanism?
if (*((vu32*)0x023200EC) == 0xEAFFFFFE) // b #0; bad
*((vu32*)0x023200EC) = 0xE3A00000; // mov r0, #0
// ttpatch checks this for some reason
*((vu32*)0x02FFFC20) = 0x5555AAAA;
// set SD/SDHC flag to SDHC, right now our DLDI only does SDHC
*((vu32*)0x02FFFC24) = ~0;
// this int seems to be a flag to reinitialize the SD card in ttpatch
// if this is *not* -1, ttpatch sends an SDIO CMD12 (STOP_TRANSMISSION)
// other frontends set this to -1 by default, so let's do it too
*((vu32*)0x02FFFC28) = ~0;
resetAndLoop();
free(loader_arm7);
return false;
}

View File

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

View File

@ -15,6 +15,7 @@
#include "launcher/HomebrewLauncher.h"
#include "launcher/ILauncher.h"
#include "launcher/NdsBootstrapLauncher.h"
#include "launcher/TopToyLauncher.h"
static SAVE_TYPE PrefillGame(u32 aGameCode) {
if (0x45444759 == aGameCode) // YGDE: 2209 - Diary Girl (USA)
@ -238,7 +239,11 @@ TLaunchResult launchRom(const std::string& aFullPath, DSRomInfo& aRomInfo, bool
if (aRomInfo.saveInfo().isNdsBootstrap())
launcher = new NdsBootstrapLauncher();
else
#ifdef __TTLAUNCHER__
launcher = new TopToyLauncher();
#else // __TTLAUNCHER__
launcher = new AcekardLauncher();
#endif // __TTLAUNCHER__
#endif // __KERNEL_LAUNCHER_SUPPORT__
} else {
if (!aMenu) saveManager().saveLastInfo(aFullPath);

141
arm9_tt/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__ -D__TTLAUNCHER__
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

@ -18,3 +18,4 @@
#define MENU_MSG_BRIGHTNESS_SET2 10
#define MENU_MSG_BRIGHTNESS_SET3 11
#define MENU_MSG_SHUTDOWN 12
#define MENU_MSG_ARM7_REBOOT_TT 13