Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ build
*.elf
*.map
*.bin
!code/bootstrap/icon.bin
code/bootstrap/nitrofiles
76 changes: 76 additions & 0 deletions code/bootstrap/AnimatedBannerPatch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# import os
from argparse import ArgumentParser
from struct import pack, unpack

# Thanks to "lifehackerhansol" and "RocketRobz" for the script
# https://github.com/DS-Homebrew/TWiLightMenu/blob/master/booter/animatedbannerpatch.py

# GBATEK swiCRC16 pseudocode
# https://problemkaputt.de/gbatek-bios-misc-functions.htm
def crc16(data):
crc = 0xFFFF
for byte in bytearray(data):
crc ^= byte
for i in range(8):
carry = (crc & 0x0001) > 0
crc = crc >> 1
if carry:
crc = crc ^ 0xA001
return pack("<H", crc)


def patch(path, banner):
with open(path, "rb+") as f:
# get total TWL ROM size
f.seek(0x210, 0)
romsize = unpack("<I", f.read(0x4))[0]

# we're going to make this look nice in a hex editor
while (romsize % 16 != 0):
romsize += 1

# new animated banner location
f.seek(0x68, 0)
f.write(pack("<I", romsize))

# total ROM size update, both DS and DSi header entry
# NTR ROM size is supposed to be NTR data only, meaning TWL ROM size is different.
# Ignore it, as new banner is added to EOF, so the whole thing has to be included anyway.
f.seek(0x80, 0)
f.write(pack("<I", romsize + 0x23c0))
f.seek(0x210, 0)
f.write(pack("<I", romsize + 0x23c0))

# total icon size update in TWL header
f.seek(0x208, 0)
f.write(pack("<I", 0x23c0))

# actually write the banner now
f.seek(romsize, 0)
infile = open(banner, "rb")
f.write(infile.read())
infile.close()

# update header CRC
f.seek(0, 0)
crc = crc16(f.read(0x15E))
f.seek(0x15E, 0)
f.write(crc)
f.close()
return 0


if __name__ == "__main__":
description = "Animated banner injector tool\n\
This must have a prepared animated banner binary!\n\
Only compatible with DSi-mode ROMs."
parser = ArgumentParser(description=description)
parser.add_argument("input", metavar="input.nds", type=str, nargs=1, help="DS ROM path")
parser.add_argument("banner", metavar="banner.bin", type=str, nargs=1, help="Animated banner path")
args = parser.parse_args()
print(description)
path = args.input[0]
banner = args.banner[0]

if (patch(path, banner)) == 0:
print("\nSuccess.")
24 changes: 22 additions & 2 deletions code/bootstrap/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif

ifneq (,$(shell command -v python3 2>/dev/null))
PYTHON := python3
else ifneq (,$(shell command -v python2 2>/dev/null))
PYTHON := python2
else ifneq (,$(shell command -v python 2>/dev/null))
PYTHON := python
else
$(error "Python not found in PATH, please install it.")
endif

export TARGET := GBARunner3
export TOPDIR := $(CURDIR)

Expand All @@ -16,10 +26,13 @@ else
NITRO_FILES :=
endif

# GAME_ICON is the image used to create the game icon, leave blank to use default rule
GAME_ICON := $(CURDIR)/icon.bmp

# These set the information text in the nds file
GAME_TITLE := GBARunner 3
GAME_TITLE := GBARunner3
GAME_SUBTITLE1 := By Gericom
GAME_SUBTITLE2 :=
GAME_SUBTITLE2 := ""

include $(DEVKITARM)/ds_rules

Expand All @@ -44,10 +57,17 @@ checkarm9:
$(MAKE) -C arm9

#---------------------------------------------------------------------------------
ANIMATED ?= ON

$(TARGET).nds : $(NITRO_FILES) ../core/arm7/$(TARGET).elf arm9/$(TARGET).elf
ndstool -c $(TARGET).nds -7 ../core/arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
-b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \
$(_ADDFILES)
ifeq ($(ANIMATED),ON)
$(PYTHON) AnimatedBannerPatch.py $@ icon.bin
else
@echo "Static Icon applied"
endif
ifdef GBAR3_ISNITRO
dlditool FatInNitroFS.dldi $(TARGET).nds
endif
Expand Down
Binary file added code/bootstrap/icon.bin
Binary file not shown.
Binary file added code/bootstrap/icon.bmp
Binary file not shown.