mirror of
https://github.com/Lorenzooone/Pokemon-Gen3-to-Gen-X.git
synced 2026-03-21 17:24:39 -05:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11bf35dfce | ||
|
|
652e30f888 | ||
|
|
4aca1adaef | ||
|
|
cff5d3a96c | ||
|
|
37bf016e8e | ||
|
|
10cdba19fe | ||
|
|
4b96c30fee | ||
|
|
133f5a37ff | ||
|
|
75fb2859c1 | ||
|
|
401767e16a | ||
|
|
b7c3bb550f | ||
|
|
6730a50457 | ||
|
|
23510710dd | ||
|
|
2a5efee9ec | ||
|
|
1970dad8a8 | ||
|
|
53cb31d84a | ||
|
|
b5ae450131 | ||
|
|
c97e951ac2 | ||
|
|
9e8887ca72 | ||
|
|
c3ee0e7ed9 | ||
|
|
2a3bd9b97f | ||
|
|
571490d1aa | ||
|
|
a43cb36f69 | ||
|
|
597a4da1f8 | ||
|
|
7b4d8ee2a3 | ||
|
|
746378de6b | ||
|
|
6b0752bf9d | ||
|
|
e314b40efa | ||
|
|
012b6e89c6 | ||
|
|
97bb4f0d26 | ||
|
|
f3499c1803 | ||
|
|
40fe49bf82 | ||
|
|
b24341a877 | ||
|
|
e9a15640db | ||
|
|
892d586af0 | ||
|
|
1fdee3d5cd | ||
|
|
d230e487c1 | ||
|
|
5f6927b0ad | ||
|
|
cd982c0fa7 |
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
|||
build/
|
||||
out/
|
||||
*.elf
|
||||
*.nds
|
||||
*.NDS
|
||||
|
|
|
|||
8
Makefile
8
Makefile
|
|
@ -31,11 +31,11 @@ ARCH := -mthumb -mthumb-interwork
|
|||
|
||||
CFLAGS := -g -Wall -Wstrict-overflow=5 -Wextra\
|
||||
-Wpointer-arith -Wpedantic -Wcast-qual -Wswitch-default\
|
||||
-Wstrict-prototypes -Wmissing-prototypes\
|
||||
-Wmissing-prototypes\
|
||||
-Wshadow -Wwrite-strings -save-temps -Os -s\
|
||||
-mcpu=arm7tdmi -mtune=arm7tdmi\
|
||||
-fomit-frame-pointer\
|
||||
-ffast-math \
|
||||
-mcpu=arm7tdmi -mtune=arm7tdmi -masm-syntax-unified\
|
||||
-fomit-frame-pointer -flto=auto \
|
||||
-ffast-math -D__GBA__\
|
||||
-fno-tree-loop-distribute-patterns \
|
||||
$(ARCH)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ SDIMAGE := image.bin
|
|||
|
||||
SOURCEDIRS := source
|
||||
INCLUDEDIRS := include
|
||||
GFXDIRS := graphics
|
||||
GFXDIRS :=
|
||||
BINDIRS := data
|
||||
AUDIODIRS := audio
|
||||
AUDIODIRS :=
|
||||
NITROFATDIR :=
|
||||
|
||||
# Defines passed to all files
|
||||
|
|
@ -101,7 +101,7 @@ SOURCES_CPP := $(shell find -L $(SOURCEDIRS) -name "*.cpp")
|
|||
# Compiler and linker flags
|
||||
# -------------------------
|
||||
|
||||
DEFINES += -D__NDS__ -DARM9
|
||||
DEFINES += -D__NDS__ -DARM9 -D__BLOCKSDS__
|
||||
|
||||
ARCH := -march=armv5te -mtune=arm946e-s
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ CFLAGS += -std=gnu11 $(WARNFLAGS) $(DEFINES) $(ARCH) \
|
|||
-Wall -Wstrict-overflow=5 -Wextra\
|
||||
-Wpointer-arith -Wpedantic -Wcast-qual -Wswitch-default\
|
||||
-Wstrict-prototypes -Wmissing-prototypes\
|
||||
-Wshadow -Wwrite-strings \
|
||||
-Wshadow -Wwrite-strings -masm-syntax-unified\
|
||||
-ffunction-sections -fdata-sections \
|
||||
-fomit-frame-pointer
|
||||
|
||||
|
|
|
|||
132
Makefile.arm9libnds2
Normal file
132
Makefile.arm9libnds2
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# 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
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(shell basename $(CURDIR))
|
||||
BUILD := build_ds
|
||||
SOURCES := gfx source data
|
||||
INCLUDES := include $(BUILD)
|
||||
NAME_MAKEFILE := Makefile.arm9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv5te -mtune=arm946e-s -mthumb
|
||||
|
||||
CFLAGS := -g -Wall\
|
||||
-Wstrict-overflow=5 -Wextra\
|
||||
-Wpointer-arith -Wpedantic -Wcast-qual -Wswitch-default\
|
||||
-Wmissing-prototypes\
|
||||
-Wshadow -Wwrite-strings -save-temps -Os -s\
|
||||
-masm-syntax-unified\
|
||||
-fomit-frame-pointer -flto=auto \
|
||||
-ffast-math \
|
||||
-fno-tree-loop-distribute-patterns \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM9
|
||||
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 := -lnds9 -lagbabi
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(LIBNDS) $(LIBAGBABI)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(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)))
|
||||
BINFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(BINFILES:.bin=.bin.o) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(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)/$(NAME_MAKEFILE)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).ds.gba
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).nds : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
|
@ -34,6 +34,7 @@ The "Act as" option allows one to choose whether the console will act as the mai
|
|||
- Trading across Generations is a lossy operation. As such, some information (like ribbons) will be lost!!!
|
||||
- You will not be able to trade Pokémon which did not exist in the target games.
|
||||
- These include: Unown ? and !, all Shiny Unown but I and V, certain Female Shiny Pokémon, Pokémon holding Mail.
|
||||
- When trading, markings may be applied to Pokémon from Gen 1 or Gen 2 games to preserve some data regarding the OT. Editing the markings may cause data loss.
|
||||
|
||||
### Clock Settings
|
||||
In the Settings inside of the Main Menu, the Clock Settings will be available if you're playing Pokémon Ruby/Sapphire/Emerald.
|
||||
|
|
@ -66,6 +67,7 @@ Inside the Cheats menu, you will find Special options which can be useful for va
|
|||
- "Cross-Gen Evo." can be used to allow evolution of Pokémon which would not evolve in the target generation (A Scyther holding Metal Coat from Gen 1 will evolve with this option enabled).
|
||||
- "Tradeless Evo." can be used to execute trade evolutions without a link cable.
|
||||
- "Undistr. Events" can be used to make it so Celebi and Mew from Gen 1 and Gen 2 games will not be Japanese (but they will be illegal).
|
||||
- "Event Pokémon" can be used to make it so Celebi and Mew from Gen 1 and Gen 2 games will not replace OT data (but they will be illegal).
|
||||
- "Fast Hatch Eggs" when enabled reduces the steps incoming eggs will need in order to hatch.
|
||||
- "Give Pokérus to Party", can be used to fix the fact that it's impossible to get Pokérus in Pokémon Fire Red/Leaf Green.
|
||||
|
||||
|
|
@ -83,3 +85,8 @@ Everything else, and the programming code, is governed by the MIT license.
|
|||
|
||||
## Example
|
||||
[This is a Video showing how to use the homebrew](https://youtu.be/3-EKe_lQREY).
|
||||
|
||||
## Building
|
||||
Docker allows easily building without having to install the dependencies.
|
||||
- To build for the GBA, while in the root of the project, run: `docker run --rm -it -v ${PWD}:/home/builder/pokemon_gen3_to_genx lorenzooone/pokemon_gen3_to_genx:gba_builder`
|
||||
- To build for the NDS, while in the root of the project, run: `docker run --rm -it -v ${PWD}:/home/builder/pokemon_gen3_to_genx lorenzooone/pokemon_gen3_to_genx:nds_builder`
|
||||
|
|
|
|||
Binary file not shown.
2
data/default_names_int_gen_i_ii.bin
Executable file
2
data/default_names_int_gen_i_ii.bin
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
.aEP&
|
||||
£P@göP»NP@€‘†„<E280A0>“ŽP‹”‚€’‡P†ˆ†ˆP<CB86>”€’‡P‰€‚ŠP<C5A0>€ €’‡P‰€‚ŠP<C5A0>„€’‡P‰€ˆŒ„P<E2809E>€€™”‹P†€‘˜P‰€<E280B0>‹€”P†€‘˜P‰ <20>‹”P†€‘˜P<CB9C>ˆ<10>‹”„P†€‘˜P‰<04>‹”„P‘„†ˆ’P†€‘˜P‰Ž‡<C5BD>P<EFBFBD>$†€‘˜P‰”€<E2809D>P<EFBFBD>€†€‘˜P<CB9C>ˆ<EFBFBD><CB86>ŽP†„‹<E2809E>P€’‡P‰€ †ˆ€‹‹ŽP€’‡P†ˆ†ˆP<CB86>”Ž•ŽP†Ž‹ƒP‡ˆ‘ŽP“†Ž‹ƒP‰”‹ˆ„<CB86>†”€‹ƒŽP€’‡P€†®«£Pƒ€<C692>ˆ„‹ ‰€‚ŠP<C5A0>€Œ„P<E2809E> ‰€‚ŠP<C5A0>„–<E28093>€‰€ˆŒ„P<E2809E>”„•Ž€‰„€<E2809E>P<EFBFBD>ŽŒœP‘‰Ž‡<C5BD>P<EFBFBD>€Œ„P‘ ‰Ž‡<C5BD>P<EFBFBD>„–<E28093>€‰”€<E2809D>P<EFBFBD>”„•ހޑŽP‡ˆ‘ŽP“ހޑŽP<C5BD>€Ž‹ŽPƒ<10>€”‹P<E280B9>ŽŒœP<C593><08>ˆ<EFBFBD><CB86>ŽP<C5BD>”Ž•Ž<10>‹€“€PŠ€ŒŽ<C592>€‘„ƒP€’‡P‰€‚‘„ƒP’€‚‡€P<E282AC>‘„†ˆ’P‰„€<E2809E>P‘މŽP€’‡P‰€€‘Ž’’ŽP€’‡P†‘Ž“P€’‡P‰€‚ ’€‚‡€P<E282AC>€”‹P’ˆ‹•„‘Pƒ€<C692>ˆ’ˆ‹•„‘PŠ€ŒŽ’¨«¡¤±P“‡ŽŒ ˜„‹‹Ž–P€’‡P˜„‹‹Ž–P’€‚‡
|
||||
1
data/default_names_jpn_gen_i_ii.bin
Executable file
1
data/default_names_jpn_gen_i_ii.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<07><><EFBFBD>P<EFBFBD> <09><>P<><0B><>P,<<0B><><EFBFBD>P,<0B><>P,<<1B><>P<EFBFBD><50><02><><EFBFBD><EFBFBD>P<EFBFBD><02><><EFBFBD>P<0B><02><08>P<0B><02><><19>P<EFBFBD><02><><EFBFBD>P<02><>P<><50>
|
||||
Binary file not shown.
51
data_raw/pokemon_names_kr_gen2.bin
Normal file
51
data_raw/pokemon_names_kr_gen2.bin
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
gPPPPPPPPœÃ
|
||||
x¾PPœÃ
|
||||
x
|
||||
>PPœÃ
|
||||
xùPP ôœ>PPPP>ªEPPPP>ª™PPPPï.²PPPPîÏ.²PP%/5PPPP <09>
|
||||
gPPPPܲPPPPö <09>
|
||||
cPPPP¤æœPPPPlæœPPPP 8PPPPˆˆPPPPPP
|
||||
gPPPPPP
|
||||
g ÅPPPPïïPPPPPPé ÞÃPPPPÊaœPPPPÊaEAæÆPPPPPPÆ yPPPP
|
||||
g òPPPPÜòPPPP<04>Ñ.&PPM&PPPPPPÏEáõPPPÏE>:PPÏE mPPPPÏEáïPPPÏE>‹PPÏE ‡PPPP¯¯PPPPPP
|
||||
hcPPPPPPdJ §ŸPP:ž §ŸPP
|
||||
:@PPPPPP
|
||||
: y@PPPPîPPPPPPaîPPPPPP¡÷ÝPPPPOÅïPPPPÃ
|
||||
cécÆ ôÃJPPPP ôÃí ÞPP < þPPPPPP:>PPPP`§ÙPPPPÚ Þ> PP:+PPPPPP
|
||||
3c"PPMà ôöPPaöPPPPPPa €PPPPPPêh.PPPP`PPPPPPy`PPPPPP߬œPPPP&*¬œPP
¬œPPPP œcPPPP<07>6ÃPPPP
|
||||
ÄbPPPPPPË »“PPPP©€“PPPP{ò“PPPP<04>Ù
|
||||
gPPPPL÷PPPPL÷ ÞPP5«
|
||||
xPPPP ô>PPPPïFPPPPˆ>PPPPlˆ>PPPP
|
||||
'Ï ˆPPPP?FPPPPßPPPPPPßÅPPPP :ŸPPPPPPéî :ŸPP ô >PPPP..PPPPPP. Þ> PPPPPPPPéOPPPP*
|
||||
œPPPP*…²PPPPïßPPPPPP ô3ïPPPPM JPPPPMLJ ÞPP
|
||||
¢PPPPPPJ ¶PPPPM>
|
||||
aPPPPM>
|
||||
PPPP yÖPPPPPP ‡ yÖPPPPŽ>>hPP5PPPPPPÆÃ>PPPP:cPPPPPP ‘ˆ>PPPP ¦ˆ>PPPPcÓPP
|
||||
«&“PPPPKÌPPPP—JPPPP—JPP¤ ‹PPPP :¡>PPPPà €PPPPPPˆ>PPPP PPPPPPŽEÃPPPPcEÃPPPP < PPPPPP5 < PPPP·>PPÆ MJ ˆPPF£gPPPPJà yPPPPÃPPPPéJPPPPF§FPPPPª·œÊPP + ˆþJPP§î ‡PPPPÃJPPÃ
|
||||
aÃJPP~ ˆ™PPPPœJœPPPPÎÌEPPPP
|
||||
gƒõPP.J <09>PPPP
|
||||
*>OPPPPÏ:œ ÞPPÏJ ˆPPPP ňPPPPPP ň
|
||||
:JPP
|
||||
a §ÃPPPP±HPPPP
|
||||
a>ÞPPPPƒõPPPPPP ôœîPPPP̨PPPPPPe¨PPPPPPa:¨PPPPÂ÷PPPPPPÂPPPPPPPP :> ˆPPœ>
|
||||
aPP~ÏbPPJ )žPPPPF§ )žPPMéœüPP>Æ :PPPP>4œPPµ yþÙŸï>áPPPPÙï>PPPP.L.PPPPß.ûPPPPé`ÙPPPPé`ÈPPPP
|
||||
œ+PPPPÆ>ÆJ yþîPPPPÊòPPPPÓ ŸPPPPPP
|
||||
gòPPPPPP¯PPPPPPPP
|
||||
:
|
||||
:@PPPP ´4
|
||||
gPPPP ´4 íPPPPwœ ìPPPPwœ ì PP~>
|
||||
aPPPPPPPPÌPPPPPPÆ3 :PPPPFAPPPPPPFA>PPPPï&<04>PPPP5ˆ>PPPP » » :PPPP. :PPPPPP :PPPPœ úPPPP
|
||||
xj÷PPPP
|
||||
xÌPPPP5ª>PPPPL ôPPPPPP© PPPPPPJœPPPPMÑ €PPPPÏþLPPPPß ‡PPPP«LFPPPPÈ“PPPPPPFªKPPPP €E €PPPP
|
||||
g <PPPPPPŽ <PPPPPP‹M PPPP«Ãœ%PP
¶ ¶PPPPMPPPPPP§ËMPP ÙPPPP
|
||||
v¿PPPPPPÜÜ&PPPP
|
||||
ŒÃ yþJ
|
||||
'
|
||||
:ÏPPPPÄ&ePPPPEePPPPPPF§F§PPF§ 3M >PPPP~ >PPPP :º
|
||||
£PPPPÑîPPPPPPë
|
||||
'«‹PPd>öEPPH ˆžPPPP«µæPPPPdPPPPPP
|
||||
<EFBFBD>PPPPPP ‡EÃPPPP : :>PPPP :> PPPP
|
||||
*>OøPPP‹Ã €PPPPJPPPPè €PPPP
|
||||
'ÃPP——ÃPPPPé €EPPF§aPPPPÐ š yPPPP
|
||||
x
|
||||
gjJPPÜ :PPPPØ §œPPPPJœ OPPPPÖöÃJPP²ÃJPPF²ÃJPP²ÆPPPP ÆæPPPPìéaPPPPgPPPPPPPPËPPPPPPPPgPPPPPPPPgPPPPPPPP
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ENG/blue_eng_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ENG/blue_eng_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
°売P<EFBFBD>遭P猿㍾P剛<EFBFBD>項
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ENG/gold_eng_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ENG/gold_eng_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ENG/red_eng_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ENG/red_eng_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
槍ケ仲P園jP剛<EFBFBD>項
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ENG/silver_eng_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ENG/silver_eng_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
宙虚яP橿月
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ENG/yellow_eng_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ENG/yellow_eng_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>給事P仲P園jP剛<EFBFBD>項
|
||||
1
data_raw/trailing_default_names_gen_i_ii/FRA/blue_fra_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/FRA/blue_fra_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/FRA/gold_fra_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/FRA/gold_fra_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>泣P鉛笈ы
|
||||
1
data_raw/trailing_default_names_gen_i_ii/FRA/red_fra_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/FRA/red_fra_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/FRA/silver_fra_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/FRA/silver_fra_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
宙虚яPム壕
|
||||
1
data_raw/trailing_default_names_gen_i_ii/FRA/yellow_fra_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/FRA/yellow_fra_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/GER/blue_ger_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/GER/blue_ger_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/GER/gold_ger_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/GER/gold_ger_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>ォ」Pム壕щ
|
||||
1
data_raw/trailing_default_names_gen_i_ii/GER/red_ger_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/GER/red_ger_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/GER/silver_ger_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/GER/silver_ger_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
暢ォ。、アP島詞
|
||||
1
data_raw/trailing_default_names_gen_i_ii/GER/yellow_ger_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/GER/yellow_ger_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ITA/blue_ita_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ITA/blue_ita_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ITA/gold_ita_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ITA/gold_ita_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ITA/red_ita_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ITA/red_ita_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
綜鋳傘仲P<EFBFBD><EFBFBD>P鵠歯傘
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ITA/silver_ita_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ITA/silver_ita_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/ITA/yellow_ita_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/ITA/yellow_ita_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>給傘仲P<EFBFBD><EFBFBD>P鵠歯傘
|
||||
1
data_raw/trailing_default_names_gen_i_ii/JPN/blue_jpn_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/JPN/blue_jpn_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<1B>P<EFBFBD><50><EFBFBD>P⑪P,<
|
||||
1
data_raw/trailing_default_names_gen_i_ii/JPN/gold_jpn_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/JPN/gold_jpn_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
礒P<>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/JPN/green_jpn_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/JPN/green_jpn_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<07><><EFBFBD>P<EFBFBD><08>P<0B><>P,<
|
||||
1
data_raw/trailing_default_names_gen_i_ii/JPN/red_jpn_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/JPN/red_jpn_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
ァャP鞄輝ュャ⑰,
|
||||
1
data_raw/trailing_default_names_gen_i_ii/JPN/silver_jpn_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/JPN/silver_jpn_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><19>P<EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/JPN/yellow_jpn_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/JPN/yellow_jpn_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<ィ絮鞄輝ュャ⑰,
|
||||
2
data_raw/trailing_default_names_gen_i_ii/KOR/gold_kor_names.bin
Executable file
2
data_raw/trailing_default_names_gen_i_ii/KOR/gold_kor_names.bin
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
aEP&
|
||||
£P
|
||||
1
data_raw/trailing_default_names_gen_i_ii/KOR/silver_kor_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/KOR/silver_kor_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
g<04>サNP
|
||||
1
data_raw/trailing_default_names_gen_i_ii/SPA/blue_spa_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/SPA/blue_spa_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
剩輝<EFBFBD>遭P鉛恒鵠<EFBFBD><EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/SPA/gold_spa_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/SPA/gold_spa_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
資傘㊧綜P梼
|
||||
1
data_raw/trailing_default_names_gen_i_ii/SPA/red_spa_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/SPA/red_spa_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/SPA/silver_spa_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/SPA/silver_spa_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1
data_raw/trailing_default_names_gen_i_ii/SPA/yellow_spa_names.bin
Executable file
1
data_raw/trailing_default_names_gen_i_ii/SPA/yellow_spa_names.bin
Executable file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
38
docker-scripts/build-dockers/Dockerfile
Normal file
38
docker-scripts/build-dockers/Dockerfile
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
################################################################################
|
||||
### Build agbabi ###
|
||||
################################################################################
|
||||
FROM debian:stable-slim as agbabi
|
||||
RUN apt-get update && apt-get install -y build-essential cmake gcc-arm-none-eabi git
|
||||
RUN git clone https://github.com/felixjones/agbabi && \
|
||||
cd agbabi && \
|
||||
git checkout 2adf1e6c01f9d4acd6f8e728892c5e18aae5332e && \
|
||||
cmake -S . -DCMAKE_TOOLCHAIN_FILE=cross/agb.cmake -DCMAKE_BUILD_TYPE=MinSizeRel -B build && \
|
||||
cmake --build build && \
|
||||
cmake --install build
|
||||
|
||||
###############################################################################
|
||||
### NDS Builder ###
|
||||
###############################################################################
|
||||
FROM skylyrac/blocksds:slim-latest as ds-build
|
||||
RUN mkdir -p /home/builder/pokemon_gen3_to_genx
|
||||
RUN mkdir -p /home/builder/building
|
||||
RUN chown -R ubuntu:ubuntu /home/builder
|
||||
COPY --from=agbabi /usr/local/ /opt/agbabi/
|
||||
ENV LIBAGBABI=/opt/agbabi
|
||||
WORKDIR /home/builder/building
|
||||
USER ubuntu
|
||||
CMD /home/builder/pokemon_gen3_to_genx/docker-scripts/docker_build_nds
|
||||
|
||||
###############################################################################
|
||||
### GBA Builder ###
|
||||
###############################################################################
|
||||
FROM devkitpro/devkitarm as gba-build
|
||||
RUN useradd builder -m
|
||||
RUN mkdir -p /home/builder/pokemon_gen3_to_genx
|
||||
RUN mkdir -p /home/builder/building
|
||||
RUN chown -R builder:builder /home/builder
|
||||
COPY --from=agbabi /usr/local/ /opt/agbabi/
|
||||
ENV LIBAGBABI=/opt/agbabi
|
||||
WORKDIR /home/builder/building
|
||||
USER builder
|
||||
CMD /home/builder/pokemon_gen3_to_genx/docker-scripts/docker_build_gba
|
||||
3
docker-scripts/build-dockers/build-gba-builder.sh
Executable file
3
docker-scripts/build-dockers/build-gba-builder.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
docker image rm lorenzooone/pokemon_gen3_to_genx:gba_builder
|
||||
docker build --target gba-build . -t lorenzooone/pokemon_gen3_to_genx:gba_builder
|
||||
3
docker-scripts/build-dockers/build-nds-builder.sh
Executable file
3
docker-scripts/build-dockers/build-nds-builder.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
docker image rm lorenzooone/pokemon_gen3_to_genx:nds_builder
|
||||
docker build --target ds-build . -t lorenzooone/pokemon_gen3_to_genx:nds_builder
|
||||
11
docker-scripts/docker_build_gba
Executable file
11
docker-scripts/docker_build_gba
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
cp -R /home/builder/pokemon_gen3_to_genx/. .
|
||||
|
||||
make clean
|
||||
make 2>&1 >/dev/null | grep ^$(pwd);
|
||||
|
||||
mkdir -p /home/builder/pokemon_gen3_to_genx/out
|
||||
cp building_mb.gba /home/builder/pokemon_gen3_to_genx/out/pokemon_gen3_to_genx_mb.gba
|
||||
|
||||
|
||||
11
docker-scripts/docker_build_nds
Executable file
11
docker-scripts/docker_build_nds
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
cp -R /home/builder/pokemon_gen3_to_genx/. .
|
||||
|
||||
make -f Makefile.arm9 clean
|
||||
make -f Makefile.arm9 2>&1 >/dev/null | grep ^$(pwd);
|
||||
|
||||
mkdir -p /home/builder/pokemon_gen3_to_genx/out
|
||||
cp Pokemon_Gen3_to_GenX.nds /home/builder/pokemon_gen3_to_genx/out/pokemon_gen3_to_genx.nds
|
||||
|
||||
|
||||
|
|
@ -1,25 +1,27 @@
|
|||
#ifndef BASE_INCLUDE__
|
||||
#define BASE_INCLUDE__
|
||||
|
||||
#ifndef __NDS__
|
||||
#ifdef __GBA__
|
||||
|
||||
// GBA defines and all
|
||||
#include <gba.h>
|
||||
#include "useful_qualifiers.h"
|
||||
#define SCANLINES 0xE4
|
||||
#define ROM 0x8000000
|
||||
ALWAYS_INLINE MAX_OPTIMIZE void __set_next_vcount_interrupt_gba(int scanline) {
|
||||
REG_DISPSTAT = (REG_DISPSTAT &0xFF) | (scanline<<8);
|
||||
REG_DISPSTAT = (REG_DISPSTAT & 0xFF) | (scanline<<8);
|
||||
}
|
||||
ALWAYS_INLINE MAX_OPTIMIZE int __get_next_vcount_interrupt(void) {
|
||||
return REG_DISPSTAT >> 8;
|
||||
u16 reg_val = REG_DISPSTAT;
|
||||
return reg_val >> 8;
|
||||
}
|
||||
#define __set_next_vcount_interrupt(x) __set_next_vcount_interrupt_gba(x)
|
||||
#define SCANLINE_IRQ_BIT LCDC_VCNT
|
||||
#define REG_WAITCNT *(vu16*)(REG_BASE + 0x204) // Wait state Control
|
||||
#define SRAM_READING_VALID_WAITCYCLES 3
|
||||
#define SRAM_ACCESS_CYCLES 9
|
||||
#define NON_SRAM_MASK 0xFFFC
|
||||
#define BASE_WAITCNT_VAL 0x4314
|
||||
#define TIMEOUT_INCREASE 0
|
||||
#define OVRAM_START ((uintptr_t)OBJ_BASE_ADR)
|
||||
#define TILE_1D_MAP 0
|
||||
#define ACTIVATE_SCREEN_HW 0
|
||||
|
|
@ -28,31 +30,33 @@ ALWAYS_INLINE MAX_OPTIMIZE int __get_next_vcount_interrupt(void) {
|
|||
#define VRAM_0 VRAM
|
||||
#define HAS_SIO
|
||||
#define CLOCK_SPEED 16777216
|
||||
#define SCANLINES 0xE4
|
||||
#define SAME_ON_BOTH_SCREENS 0
|
||||
#ifndef __GBA__
|
||||
#define __GBA__
|
||||
#endif
|
||||
#define CONSOLE_LETTER 'G'
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef __NDS__
|
||||
|
||||
// NDS defines and all
|
||||
#include <nds.h>
|
||||
#include "useful_qualifiers.h"
|
||||
#include "decompress.h"
|
||||
#define SCANLINES 0x107
|
||||
#define ROM GBAROM
|
||||
ALWAYS_INLINE MAX_OPTIMIZE int __get_next_vcount_interrupt(void) {
|
||||
return (REG_DISPSTAT >> 8) | ((REG_DISPSTAT & 0x80) << 1);
|
||||
u16 reg_val = REG_DISPSTAT;
|
||||
return (reg_val >> 8) | ((reg_val & 0x80) << 1);
|
||||
}
|
||||
ALWAYS_INLINE MAX_OPTIMIZE void __reset_vcount(void) {
|
||||
REG_VCOUNT = (REG_VCOUNT & 0xFE00) | (SCANLINES - 2);
|
||||
}
|
||||
#define __set_next_vcount_interrupt(x) SetYtrigger(x)
|
||||
#define SCANLINE_IRQ_BIT DISP_YTRIGGER_IRQ
|
||||
#define REG_WAITCNT REG_EXMEMCNT // Wait state Control
|
||||
#define SRAM_READING_VALID_WAITCYCLES 3
|
||||
#define SRAM_ACCESS_CYCLES (2 * 18)
|
||||
#define NON_SRAM_MASK 0xFFFC
|
||||
#define EXMEMCNT_MASK_SLOT2_CLOCKRATE (3<<5)
|
||||
#define EXMEMCNT_SLOT2_CLOCKRATE_1 (1<<5)
|
||||
#define BASE_WAITCNT_VAL EXMEMCNT_SLOT2_CLOCKRATE_1
|
||||
#define TIMEOUT_INCREASE 2
|
||||
#define BASE_WAITCNT_VAL 0x0014
|
||||
#define OVRAM_START ((uintptr_t)SPRITE_GFX)
|
||||
#define OVRAM_START_SUB ((uintptr_t)SPRITE_GFX_SUB)
|
||||
#define OBJ_ON DISPLAY_SPR_ACTIVE
|
||||
|
|
@ -66,7 +70,6 @@ ALWAYS_INLINE MAX_OPTIMIZE int __get_next_vcount_interrupt(void) {
|
|||
#define ARM7_CLOCK_SPEED 33554432
|
||||
#define ARM7_GBA_CLOCK_SPEED 16777216
|
||||
#define CLOCK_SPEED ARM9_CLOCK_SPEED
|
||||
#define SCANLINES 0x107
|
||||
#define SAME_ON_BOTH_SCREENS 1
|
||||
#define CONSOLE_LETTER 'D'
|
||||
|
||||
|
|
@ -82,10 +85,29 @@ typedef struct {
|
|||
#define Div(x, y) swiDivide(x, y)
|
||||
#define DivMod(x, y) swiRemainder(x, y)
|
||||
#define Sqrt(x) swiSqrt(x)
|
||||
#define LZ77UnCompWram(x, y) swiDecompressLZSSWram(x, y)
|
||||
#define LZ77UnCompWram(x, y) swi_LZ77UnCompWrite8bit(x, y)
|
||||
#ifdef __BLOCKSDS__
|
||||
#define CpuFastSet(x, y, z) swiFastCopy(x, y, z)
|
||||
#define VBlankIntrWait() swiWaitForVBlank()
|
||||
#define Halt() CP15_WaitForInterrupt()
|
||||
#else
|
||||
static void CpuFastSet(volatile const void*, volatile void*, volatile int);
|
||||
static void Halt(void);
|
||||
|
||||
ALWAYS_INLINE MAX_OPTIMIZE void CpuFastSet(volatile const void* source, volatile void* dest, volatile int flags)
|
||||
{
|
||||
register uint32_t src asm("r0") = (uint32_t)source;
|
||||
register uint32_t dst asm("r1") = (uint32_t)dest;
|
||||
register uint32_t flg asm("r2") = (uint32_t)flags;
|
||||
register uint32_t after_destroyed asm("r3");
|
||||
|
||||
asm volatile(
|
||||
"swi 0xC;" : "=r"(src), "=r"(dst), "=r"(flg) :
|
||||
"r"(src), "r"(dst), "r"(flg), "r"(after_destroyed) :
|
||||
);
|
||||
}
|
||||
ALWAYS_INLINE void Halt() {__asm__("swi 0x6");}
|
||||
#endif
|
||||
#define VBlankIntrWait() swiWaitForVBlank()
|
||||
#define DIV_SWI_VAL "0x09"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ void set_default_settings(void);
|
|||
void set_sys_language(u8);
|
||||
void set_target_int_language(u8);
|
||||
void set_conversion_colo_xd(u8);
|
||||
void set_prioritize_ot_gender(u8);
|
||||
void set_default_conversion_game(u8);
|
||||
void set_gen1_everstone(u8);
|
||||
void set_allow_cross_gen_evos(u8);
|
||||
|
|
@ -39,6 +40,7 @@ void set_single_colour(u8, u8, u8);
|
|||
void set_evolve_without_trade(u8);
|
||||
void set_allow_undistributed_events(u8);
|
||||
void set_fast_hatch_eggs(u8);
|
||||
void set_event_info_replacement(u8);
|
||||
void increase_egg_met_location(void);
|
||||
void decrease_egg_met_location(void);
|
||||
u8 set_applied_ball(u16);
|
||||
|
|
@ -46,6 +48,7 @@ u8 get_sys_language(void);
|
|||
u8 get_target_int_language(void);
|
||||
u8 get_filtered_target_int_language(void);
|
||||
u8 get_conversion_colo_xd(void);
|
||||
u8 get_prioritize_ot_gender(void);
|
||||
u8 get_default_conversion_game(void);
|
||||
u16 get_full_colour(u8);
|
||||
u8 get_single_colour(u8, u8);
|
||||
|
|
@ -56,6 +59,7 @@ u8 get_allow_undistributed_events(void);
|
|||
u8 get_fast_hatch_eggs(void);
|
||||
u8 get_egg_met_location(void);
|
||||
u16 get_applied_ball(void);
|
||||
u8 get_event_info_replacement(void);
|
||||
const struct version_t* get_version(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
1
include/decompress.h
Normal file
1
include/decompress.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#ifndef _DCMPRSS_HEADER_
#define _DCMPRSS_HEADER_
extern int swi_LZ77UnCompWrite16bit(const void *source, void *destination);
extern int swi_LZ77UnCompWrite8bit(const void *source, void *destination);
#endif
|
||||
10
include/delays.h
Normal file
10
include/delays.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef DELAYS__
|
||||
#define DELAYS__
|
||||
|
||||
#define CLOCK_CYCLES_PER_MS(x) ((((x) * ((uint64_t)CLOCK_SPEED)) + 999) / 1000)
|
||||
#define CLOCK_CYCLES_PER_MUS(x) ((((x) * ((uint64_t)CLOCK_SPEED)) + 999999) / 1000000)
|
||||
|
||||
void delay_cycles(u32);
|
||||
void delay_cycles_until(u32, vu8*, u8, u8);
|
||||
|
||||
#endif
|
||||
|
|
@ -24,5 +24,6 @@ u8 get_pokemon_gender_kind_gen2(u8, u8, u8);
|
|||
const u8* get_pokemon_name_gen2_gen3_enc(int, u8, u8);
|
||||
const u8* get_pokemon_name_gen2(int, u8, u8, u8*);
|
||||
const u8* get_default_trainer_name_gen2(u8, u8*);
|
||||
const u8* get_actual_ot_name(const u8*, u8, u8, u8);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ void enable_rtc_reset(struct clock_events_t*);
|
|||
void disable_rtc_reset(struct clock_events_t*);
|
||||
u8 is_rtc_reset_enabled(struct clock_events_t*);
|
||||
u8 is_daily_update_safe(struct game_data_t*, struct clock_events_t*, struct saved_time_t*);
|
||||
u8 has_init_succeded(void);
|
||||
u8 update_base_time(void);
|
||||
void init_rtc_time(void);
|
||||
void run_daily_update(struct game_data_t*, struct clock_events_t*, struct saved_time_t*, u8);
|
||||
u8 is_daytime(struct clock_events_t*, struct saved_time_t*);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ void alter_nature(struct gen3_mon_data_unenc*, u8);
|
|||
void set_alter_data(struct gen3_mon_data_unenc*, struct alternative_data_gen3*);
|
||||
void preload_if_fixable(struct gen3_mon_data_unenc*);
|
||||
|
||||
void convert_trainer_name_gen3_to_gen12(u8*, u8*, u8, u8);
|
||||
void convert_trainer_name_gen3_to_gen12(u8*, u8*, u8, u8, u8);
|
||||
void convert_trainer_name_gen12_to_gen3(u8*, u8*, u8, u8, u8);
|
||||
|
||||
u8 gen3_to_gen2(struct gen2_mon*, struct gen3_mon_data_unenc*, u32);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define CANCEL_INFO 0xFF
|
||||
#define CANCEL_TRADING 0xFF
|
||||
#define CANCEL_IV_FIX 0xFF
|
||||
#define CANCEL_MULTIBOOT 0xFF
|
||||
#define EXIT_EVOLUTION 0xFF
|
||||
#define DENIED_LEARNING 0xFF
|
||||
#define EXIT_BASE_SETTINGS 0xFF
|
||||
|
|
@ -16,18 +17,19 @@
|
|||
#define EXIT_CLOCK_WARNING_SETTINGS 0xFF
|
||||
#define EXIT_COLOURS_SETTINGS 0xFF
|
||||
#define DO_NOT_FORGET_MOVE 0xFF
|
||||
#define CANCEL_TRADE_START 0xFF
|
||||
#define CANCEL_TRADE_OPTIONS 0xFF
|
||||
#define CANCEL_NATURE 0xFF
|
||||
#define ENTER_COLOUR_MENU 1
|
||||
#define ENTER_CLOCK_MENU 2
|
||||
#define ENTER_CHEATS_MENU 3
|
||||
#define ENTER_GEN12_MENU 4
|
||||
#define ENTER_LEARN_MENU 1
|
||||
#define CONFIRM_IV_FIX 1
|
||||
#define CANCEL_NATURE 0xFF
|
||||
#define CONFIRM_MULTIBOOT 0x35
|
||||
#define CONFIRM_NATURE 3
|
||||
#define INC_NATURE 1
|
||||
#define DEC_NATURE 2
|
||||
#define CANCEL_TRADE_START 0xFF
|
||||
#define CANCEL_TRADE_OPTIONS 0xFF
|
||||
#define OFFER_INFO_DISPLAY 0x12
|
||||
#define START_MULTIBOOT 0x49
|
||||
#define START_PRINT_READ_INFO 0x57
|
||||
|
|
@ -38,6 +40,7 @@
|
|||
#define PAGES_TOTAL 5
|
||||
#define FIRST_PAGE 1
|
||||
|
||||
u8 handle_input_multiboot_settings(u16, u8*, u8*);
|
||||
u8 handle_input_multiboot_menu(u16);
|
||||
u8 handle_input_learnable_message_moves_menu(u16, u8*);
|
||||
u8 handle_input_learnable_moves_menu(u16, u8*);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ void print_set_nature(u8, struct gen3_mon_data_unenc*);
|
|||
void print_iv_fix(struct gen3_mon_data_unenc*);
|
||||
void print_pokemon_pages(u8, u8, struct gen3_mon_data_unenc*, u8);
|
||||
void print_main_menu(u8, u8, u8, u8, struct game_data_t*, struct game_data_priv_t*);
|
||||
void print_multiboot_settings(u8, u8);
|
||||
void print_multiboot_mid_process(u8);
|
||||
void print_multiboot(enum MULTIBOOT_RESULTS);
|
||||
void print_start_trade(void);
|
||||
|
|
@ -40,6 +41,7 @@ void print_colour_settings_menu(u8);
|
|||
void print_evolution_menu(struct gen3_mon_data_unenc*, u16, u8, u8);
|
||||
void print_evolution_window(struct gen3_mon_data_unenc*);
|
||||
void print_cheats_menu(u8);
|
||||
void print_clock_variable_menu(struct clock_events_t*, struct saved_time_t*, u8);
|
||||
void print_clock_menu(struct clock_events_t*, struct saved_time_t*, u8);
|
||||
void print_warning_when_clock_changed(void);
|
||||
void print_load_warnings(struct game_data_t*, struct game_data_priv_t*);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#define MULTIBOOT_MAX_SIZE 0x3FF40
|
||||
|
||||
enum MULTIBOOT_RESULTS {MB_SUCCESS, MB_NO_INIT_SYNC, MB_WRONG_ANSWER, MB_HEADER_ISSUE, MB_SWI_FAILURE};
|
||||
enum MULTIBOOT_RESULTS {MB_SUCCESS, MB_NO_INIT_SYNC, MB_WRONG_ANSWER, MB_HEADER_ISSUE, MB_PALETTE_FAILURE, MB_SWI_FAILURE};
|
||||
|
||||
enum MULTIBOOT_RESULTS multiboot_normal(u16*, u16*);
|
||||
enum MULTIBOOT_RESULTS multiboot_normal(u16*, u16*, int);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@
|
|||
|
||||
#define GEN2_EGG 253
|
||||
#define GEN2_NO_MON 255
|
||||
#define GEN12_MAX_MOVE_PP 40
|
||||
|
||||
#define CELEBI_AGATE_OT_ID 31121
|
||||
|
||||
|
|
@ -173,6 +174,10 @@
|
|||
#define ROAMER_ENCOUNTER 2
|
||||
#define UNOWN_ENCOUNTER 3
|
||||
|
||||
#define SPECIAL_NAME_MARKS_VALUE 0xF
|
||||
|
||||
//#define ALLOW_KOREAN
|
||||
|
||||
#define NUM_LANGUAGES 8
|
||||
#define NUM_POKEMON_NAME_LANGUAGES 4
|
||||
#define FIRST_VALID_LANGUAGE 1
|
||||
|
|
@ -185,6 +190,11 @@
|
|||
#define GERMAN_LANGUAGE 5
|
||||
#define KOREAN_LANGUAGE 6
|
||||
#define SPANISH_LANGUAGE 7
|
||||
#ifdef ALLOW_KOREAN
|
||||
#define ALL_LANGUAGES ((1 << JAPANESE_LANGUAGE) | (1 << ENGLISH_LANGUAGE) | (1 << FRENCH_LANGUAGE) | (1 << ITALIAN_LANGUAGE) | (1 << GERMAN_LANGUAGE) | (1 << KOREAN_LANGUAGE) | (1 << SPANISH_LANGUAGE))
|
||||
#else
|
||||
#define ALL_LANGUAGES ((1 << JAPANESE_LANGUAGE) | (1 << ENGLISH_LANGUAGE) | (1 << FRENCH_LANGUAGE) | (1 << ITALIAN_LANGUAGE) | (1 << GERMAN_LANGUAGE) | (1 << SPANISH_LANGUAGE))
|
||||
#endif
|
||||
|
||||
#define GET_LANGUAGE_IS_JAPANESE(x) ((x) == JAPANESE_LANGUAGE)
|
||||
#define GET_LANGUAGE_NICKNAME_LIMIT(x) (GET_LANGUAGE_IS_JAPANESE(x) ? NICKNAME_JP_GEN3_SIZE : NICKNAME_GEN3_SIZE)
|
||||
|
|
@ -321,11 +331,13 @@ struct gen3_mon {
|
|||
u8 is_bad_egg : 1;
|
||||
u8 has_species : 1;
|
||||
u8 use_egg_name : 1;
|
||||
u8 unused : 5;
|
||||
u8 block_box_rs : 1;
|
||||
u8 unused : 4;
|
||||
u8 ot_name[OT_NAME_GEN3_MAX_SIZE];
|
||||
u8 marks;
|
||||
u8 marks : 4;
|
||||
u8 unused2 : 4;
|
||||
u16 checksum;
|
||||
u16 unk;
|
||||
u16 unused3;
|
||||
u32 enc_data[ENC_DATA_SIZE>>2];
|
||||
u32 status;
|
||||
u8 level;
|
||||
|
|
|
|||
|
|
@ -10,15 +10,19 @@ void generate_unown_shiny_info_letter_preloaded(u8, u8, u16, u32*, u32*);
|
|||
void generate_unown_info(u8, u16, u16, u32*, u32*);
|
||||
void generate_unown_info_letter_preloaded(u8, u16, u8, u16, u32*, u32*);
|
||||
void generate_static_shiny_info(u8, u16, u32*, u32*);
|
||||
void generate_generic_genderless_shadow_shiny_info_colo(u8, u16, u32*, u32*, u8*);
|
||||
void generate_static_info(u8, u16, u16, u32*, u32*);
|
||||
void generate_generic_genderless_shadow_shiny_info_colo(u8, u16, u32*, u32*, u8*);
|
||||
void generate_generic_genderless_shadow_info_colo(u8, u16, u16, u32*, u32*, u8*);
|
||||
void generate_generic_genderless_shadow_info_xd(u8, u8, u16, u16, u32*, u32*, u8*);
|
||||
void generate_egg_shiny_info(u8, u8, u16, u16, u8, u32*, u32*);
|
||||
void generate_egg_info(u8, u8, u16, u16, u8, u32*, u32*);
|
||||
void generate_channel_shiny_info(u8, u32*, u32*, u16*, u8*, u8*);
|
||||
void generate_channel_info(u8, u16, u32*, u32*, u16*, u8*, u8*);
|
||||
u32 generate_ot(u16, u8*);
|
||||
u8 are_colo_valid_tid_sid(u16, u16);
|
||||
u8 are_rs_valid_tid_sid(u16, u16);
|
||||
void convert_roamer_to_colo_info(u8, u16, u8, u8, u16, u32*, u32*, u8*);
|
||||
void convert_shiny_roamer_to_colo_info(u8, u8, u8, u16, u32*, u32*, u8*);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,12 +7,16 @@
|
|||
#define SIO_MASTER 1
|
||||
#define SIO_SLAVE 0
|
||||
|
||||
#define MAX_NUM_SLAVES 3
|
||||
|
||||
#define SIO_DEFAULT_VALUE 0xFE
|
||||
|
||||
void init_sio_normal(int, int);
|
||||
void init_sio_multi(int);
|
||||
int sio_normal(int, int, int, u8*);
|
||||
void sio_normal_prepare_irq_slave(int);
|
||||
int timed_sio_normal_master(int, int, int);
|
||||
void timed_sio_multi_master(int, int, u16*);
|
||||
void sio_handle_irq_slave(int);
|
||||
void sio_stop_irq_slave(void);
|
||||
int sio_read(u8);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#define DEFAULT_FILLER 0
|
||||
|
||||
#define USELESS_SYNC_BYTES 6
|
||||
#define USELESS_SYNC_BYTES 5
|
||||
#define USELESS_SYNC_VALUE 0x20
|
||||
|
||||
#define NUM_SIZES 4
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
|
||||
#define NO_INLINE __attribute__((noinline))
|
||||
#define MAX_OPTIMIZE __attribute__((optimize(3)))
|
||||
#ifndef PACKED
|
||||
#define PACKED __attribute__((packed))
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#define DEFAULT_SYS_LANGUAGE ENGLISH_LANGUAGE
|
||||
#define DEFAULT_TARGET_INT_LANGUAGE UNKNOWN_LANGUAGE
|
||||
#define DEFAULT_CONVERSION_COLO_XD 1
|
||||
#define DEFAULT_PRIORITIZE_OT_GENDER 1
|
||||
#define DEFAULT_DEFAULT_CONVERSION_GAME FR_VERSION_ID
|
||||
#define DEFAULT_GEN1_EVERSTONE 0
|
||||
#define DEFAULT_ALLOW_CROSS_GEN_EVOS 0
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
#define DEFAULT_ALLOW_UNDISTRIBUTED_EVENTS 0
|
||||
#define DEFAULT_FAST_HATCH_EGGS 0
|
||||
#define DEFAULT_BALL POKEBALL_ID
|
||||
#define DEFAULT_EVENT_INFO_REPLACEMENT 1
|
||||
|
||||
void sanitize_egg_met_location(void);
|
||||
const u8* get_valid_egg_met_locs(void);
|
||||
|
|
@ -28,6 +30,7 @@ const u8* get_valid_egg_met_locs(void);
|
|||
static u8 sys_language;
|
||||
static u8 target_int_language;
|
||||
static u8 conversion_colo_xd;
|
||||
static u8 prioritize_ot_gender;
|
||||
static u8 default_conversion_game;
|
||||
static u8 default_colours[NUM_COLOURS][NUM_SUB_COLOURS];
|
||||
static u8 gen1_everstone;
|
||||
|
|
@ -38,14 +41,16 @@ static u8 fast_hatch_eggs;
|
|||
static u16 applied_ball;
|
||||
static u8 egg_met_location;
|
||||
static u8 first_set_egg_met_location;
|
||||
static u8 event_info_replacement;
|
||||
|
||||
const struct version_t version = { .main_version = 1, .sub_version = 1, .revision_version = 8, .revision_letter = CONSOLE_LETTER};
|
||||
const struct version_t version = { .main_version = 1, .sub_version = 1, .revision_version = 14, .revision_letter = CONSOLE_LETTER};
|
||||
const u8* egg_valid_met_locations[NUMBER_OF_GAMES+FIRST_VERSION_ID] = {valid_egg_locations_rs_bin, valid_egg_locations_rs_bin, valid_egg_locations_rs_bin, valid_egg_locations_e_bin, valid_egg_locations_frlg_bin, valid_egg_locations_frlg_bin};
|
||||
|
||||
void set_default_settings() {
|
||||
set_sys_language(DEFAULT_SYS_LANGUAGE);
|
||||
set_target_int_language(DEFAULT_TARGET_INT_LANGUAGE);
|
||||
set_conversion_colo_xd(DEFAULT_CONVERSION_COLO_XD);
|
||||
set_prioritize_ot_gender(DEFAULT_PRIORITIZE_OT_GENDER);
|
||||
first_set_egg_met_location = 1;
|
||||
set_default_conversion_game(DEFAULT_DEFAULT_CONVERSION_GAME);
|
||||
for(size_t i = 0; i < NUM_COLOURS; i++)
|
||||
|
|
@ -57,6 +62,7 @@ void set_default_settings() {
|
|||
set_allow_undistributed_events(DEFAULT_ALLOW_UNDISTRIBUTED_EVENTS);
|
||||
set_fast_hatch_eggs(DEFAULT_FAST_HATCH_EGGS);
|
||||
set_applied_ball(DEFAULT_BALL);
|
||||
set_event_info_replacement(DEFAULT_EVENT_INFO_REPLACEMENT);
|
||||
}
|
||||
|
||||
const u8* get_valid_egg_met_locs() {
|
||||
|
|
@ -103,6 +109,10 @@ void set_conversion_colo_xd(u8 new_val) {
|
|||
conversion_colo_xd = new_val;
|
||||
}
|
||||
|
||||
void set_prioritize_ot_gender(u8 new_val) {
|
||||
prioritize_ot_gender = new_val;
|
||||
}
|
||||
|
||||
void set_default_conversion_game(u8 new_val) {
|
||||
if((new_val < FIRST_VERSION_ID) || (new_val == ((u8)(FIRST_VERSION_ID-1))))
|
||||
new_val = NUMBER_OF_GAMES-1+FIRST_VERSION_ID;
|
||||
|
|
@ -132,6 +142,10 @@ void set_fast_hatch_eggs(u8 new_val) {
|
|||
fast_hatch_eggs = new_val;
|
||||
}
|
||||
|
||||
void set_event_info_replacement(u8 new_val) {
|
||||
event_info_replacement = new_val;
|
||||
}
|
||||
|
||||
void increase_egg_met_location() {
|
||||
const u8* valid_met_locs = get_valid_egg_met_locs();
|
||||
u8 base_val = egg_met_location;
|
||||
|
|
@ -202,6 +216,10 @@ u8 get_conversion_colo_xd() {
|
|||
return conversion_colo_xd;
|
||||
}
|
||||
|
||||
u8 get_prioritize_ot_gender() {
|
||||
return prioritize_ot_gender;
|
||||
}
|
||||
|
||||
u8 get_default_conversion_game() {
|
||||
return default_conversion_game;
|
||||
}
|
||||
|
|
@ -248,6 +266,10 @@ u16 get_applied_ball() {
|
|||
return applied_ball;
|
||||
}
|
||||
|
||||
u8 get_event_info_replacement() {
|
||||
return event_info_replacement;
|
||||
}
|
||||
|
||||
const struct version_t* get_version() {
|
||||
return &version;
|
||||
}
|
||||
|
|
|
|||
253
source/decompress.s
Normal file
253
source/decompress.s
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
@-------------------------------------------------------------
|
||||
@ Original code by fleroviux, distributed under the MIT License:
|
||||
@ Link: https://github.com/Cult-of-GBA/BIOS
|
||||
@ Copyright 2020 - 2021 DenSinH fleroviux
|
||||
@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@-------------------------------------------------------------
|
||||
@ Speed optimizations by Lorenzooone - 2024
|
||||
@ 8bit version not included because the optimized 16bit version is faster.
|
||||
@ Works fine even with 1 as the window offset (fixes LZ77 VRAM bug).
|
||||
@-------------------------------------------------------------
|
||||
|
||||
.arm
|
||||
.align
|
||||
.global swi_LZ77UnCompWrite16bit
|
||||
.global swi_LZ77UnCompWrite8bit
|
||||
.type swi_LZ77UnCompWrite16bit,function
|
||||
.type swi_LZ77UnCompWrite8bit,function
|
||||
#ifdef __NDS__
|
||||
.section .itcm, "ax", %progbits
|
||||
#else
|
||||
.section .iwram, "ax", %progbits
|
||||
#endif
|
||||
|
||||
@ALIGNMENT_FIX has an impact of around 0.25% on performance, but it prevents
|
||||
@alignment warnings (which wouldn't affect real hardware).
|
||||
#define ALIGNMENT_FIX
|
||||
|
||||
@OVERRUN_PROTECTION has an impact of around 0.9% on performance, but it
|
||||
@prevents overrunning the buffer by up to 2 extra bytes if the compressed data
|
||||
@has issues. Apparently, the regular BIOS functions lack any kind of overrun
|
||||
@protection. So instead of potentially writing 2 extra bytes, they could
|
||||
@write way more...
|
||||
#define OVERRUN_PROTECTION
|
||||
|
||||
@PREVENT_OOB_READS has an impact of around 2% on performance. It prevents
|
||||
@the LZ77 window from going to an address before the initial destination one.
|
||||
@Such LZ77 data is badly formed, and this shouldn't be enabled at all
|
||||
@unless you don't trust the data coming in...
|
||||
@#define PREVENT_OOB_READS
|
||||
|
||||
swi_LZ77UnCompWrite16bit:
|
||||
swi_LZ77UnCompWrite8bit:
|
||||
stmfd sp!, {r3 - r8}
|
||||
|
||||
@ Read header word:
|
||||
@ bit0-3: reserved
|
||||
@ bit4-7: compressed type (1 for LZ77)
|
||||
@ bit8-31: size of compressed data
|
||||
ldrb r2, [r0, #0]
|
||||
lsr r2, r2, #4
|
||||
@ Stop if this isn't LZ77
|
||||
cmp r2, #1
|
||||
bne .lz77_16bit_end
|
||||
|
||||
@ Don't make any assumption about initial alignment to
|
||||
@ read the size of the data
|
||||
ldrb r2, [r0, #1]
|
||||
ldrb r3, [r0, #2]
|
||||
lsl r3, r3, #8
|
||||
orr r2, r2, r3
|
||||
ldrb r3, [r0, #3]
|
||||
add r0, r0, #4
|
||||
lsl r3, r3, #16
|
||||
orrs r2, r2, r3
|
||||
@ ignore zero-length decompression requests
|
||||
beq .lz77_16bit_end
|
||||
|
||||
@ Cover un-aligned destination
|
||||
tst r1, #1
|
||||
ldrneb r7, [r1, #-1]
|
||||
|
||||
#ifdef PREVENT_OOB_READS
|
||||
@ Store the initial address in r8
|
||||
movs r8, r1
|
||||
#endif
|
||||
|
||||
.lz77_16bit_loop:
|
||||
@ read encoder byte, shift to MSB for easier access.
|
||||
ldrb r3, [r0], #1
|
||||
orr r3, #0x01000000
|
||||
.lz77_16bit_encoder_loop:
|
||||
tst r3, #0x80
|
||||
bne .lz77_16bit_copy_window
|
||||
.lz77_16bit_copy_byte:
|
||||
@ copy byte from current source to current destination
|
||||
ldrb r4, [r0], #1
|
||||
tst r1, #1
|
||||
moveq r7, r4
|
||||
orrne r7, r4, lsl #8
|
||||
strneh r7, [r1, #-1]
|
||||
add r1, #1
|
||||
|
||||
@ check if decompressed length has been reached.
|
||||
subs r2, #1
|
||||
beq .lz77_16bit_done
|
||||
|
||||
@ read next encoder or process next block
|
||||
lsls r3, #1
|
||||
bcc .lz77_16bit_encoder_loop
|
||||
|
||||
@ read encoder byte, shift to MSB for easier access.
|
||||
ldrb r3, [r0], #1
|
||||
orr r3, #0x01000000
|
||||
tst r3, #0x80
|
||||
beq .lz77_16bit_copy_byte
|
||||
|
||||
.lz77_16bit_copy_window:
|
||||
@ read window tuple {displacement, size}
|
||||
ldrb r4, [r0], #1
|
||||
ldrb r5, [r0], #1
|
||||
|
||||
@ r5 = window displacement
|
||||
orr r5, r5, r4, lsl #8
|
||||
bic r5, #0xF000
|
||||
add r5, #1
|
||||
|
||||
@ r4 = window size
|
||||
lsr r4, #4
|
||||
add r4, #3
|
||||
cmp r4, r2
|
||||
movgt r4, r2
|
||||
subs r2, r4
|
||||
subs r5, r1, r5
|
||||
#ifdef PREVENT_OOB_READS
|
||||
subs r6, r5, r8
|
||||
cmp r6, #0
|
||||
blt .lz77_16bit_done
|
||||
#endif
|
||||
@ About 50% of the time, the two addresses will be aligned. Abuse this...
|
||||
eor r6, r1, r5
|
||||
tst r6, #1
|
||||
bne .lz77_16bit_copy_window_not_aligned_check
|
||||
tst r1, #1
|
||||
beq .lz77_optimized_16bit_copy_window_pre_loop
|
||||
ldrb r6, [r5], #1
|
||||
orr r7, r6, lsl #8
|
||||
#ifdef ALIGNMENT_FIX
|
||||
subs r1, #1
|
||||
strh r7, [r1], #2
|
||||
#else
|
||||
strh r7, [r1], #1
|
||||
#endif
|
||||
subs r4, #1
|
||||
.lz77_optimized_16bit_copy_window_pre_loop:
|
||||
#ifdef OVERRUN_PROTECTION
|
||||
cmp r4, #1
|
||||
ble .lz77_optimized_16bit_copy_window_after_loop
|
||||
#endif
|
||||
.lz77_optimized_16bit_copy_window_loop:
|
||||
ldrh r6, [r5], #2
|
||||
strh r6, [r1], #2
|
||||
subs r4, #2
|
||||
cmp r4, #1
|
||||
bgt .lz77_optimized_16bit_copy_window_loop
|
||||
.lz77_optimized_16bit_copy_window_after_loop:
|
||||
@ copy byte from window to current destination
|
||||
ldreqb r7, [r5]
|
||||
addeq r1, #1
|
||||
|
||||
@ check if decompressed length has been reached
|
||||
cmp r2, #0
|
||||
beq .lz77_16bit_done
|
||||
|
||||
@ read next encoder or process next block
|
||||
lsls r3, #1
|
||||
bcc .lz77_16bit_encoder_loop
|
||||
b .lz77_16bit_loop
|
||||
|
||||
.lz77_16bit_copy_window_not_aligned_check:
|
||||
subs r1, #1
|
||||
cmp r1, r5
|
||||
beq .set_previous_byte
|
||||
tst r5, #1
|
||||
ldrneb r7, [r5], #1
|
||||
addne r1, #1
|
||||
subne r4, #1
|
||||
|
||||
#ifdef OVERRUN_PROTECTION
|
||||
cmp r4, #1
|
||||
ble .lz77_16bit_copy_window_not_aligned_after_loop
|
||||
#endif
|
||||
.lz77_16bit_copy_window_not_aligned_loop:
|
||||
ldrh r6, [r5], #2
|
||||
orr r7, r6, lsl #8
|
||||
strh r7, [r1], #2
|
||||
lsr r7, #16
|
||||
subs r4, #2
|
||||
cmp r4, #1
|
||||
bgt .lz77_16bit_copy_window_not_aligned_loop
|
||||
.lz77_16bit_copy_window_not_aligned_after_loop:
|
||||
@ copy byte from window to current destination
|
||||
ldreqb r6, [r5]
|
||||
orreq r7, r6, lsl #8
|
||||
streqh r7, [r1], #1
|
||||
|
||||
add r1, #1
|
||||
@ check if decompressed length has been reached
|
||||
cmp r2, #0
|
||||
beq .lz77_16bit_done
|
||||
|
||||
@ read next encoder or process next block
|
||||
lsls r3, #1
|
||||
bcc .lz77_16bit_encoder_loop
|
||||
b .lz77_16bit_loop
|
||||
|
||||
.set_previous_byte:
|
||||
tst r1, #1
|
||||
beq .got_byte_in_r7
|
||||
ldrb r7, [r1], #1
|
||||
movs r6, r7
|
||||
orr r7, r6, lsl #8
|
||||
b .pre_set_loop
|
||||
.got_byte_in_r7:
|
||||
movs r6, r7
|
||||
orr r7, r6, lsl #8
|
||||
strh r7, [r1], #2
|
||||
subs r4, #1
|
||||
.pre_set_loop:
|
||||
#ifdef OVERRUN_PROTECTION
|
||||
cmp r4, #1
|
||||
ble .set_after_loop
|
||||
#endif
|
||||
.set_loop:
|
||||
strh r7, [r1], #2
|
||||
subs r4, #2
|
||||
cmp r4, #1
|
||||
bgt .set_loop
|
||||
.set_after_loop:
|
||||
@ copy byte from window to current destination
|
||||
lsreq r7, #8
|
||||
addeq r1, #1
|
||||
|
||||
@ check if decompressed length has been reached
|
||||
cmp r2, #0
|
||||
beq .lz77_16bit_done
|
||||
|
||||
@ read next encoder or process next block
|
||||
lsls r3, #1
|
||||
bcc .lz77_16bit_encoder_loop
|
||||
b .lz77_16bit_loop
|
||||
|
||||
.lz77_16bit_done:
|
||||
@ Cover un-aligned end
|
||||
tst r1, #1
|
||||
ldrneb r6, [r1]
|
||||
orrne r7, r6, lsl #8
|
||||
strneh r7, [r1, #-1]
|
||||
|
||||
.lz77_16bit_end:
|
||||
ldmfd sp!, {r3 - r8}
|
||||
bx lr
|
||||
35
source/delays.c
Normal file
35
source/delays.c
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include "base_include.h"
|
||||
#include <stddef.h>
|
||||
#include "useful_qualifiers.h"
|
||||
#include "timing_basic.h"
|
||||
#include "delays.h"
|
||||
|
||||
#ifdef __GBA__
|
||||
#define NUM_CYCLES_PER_ITER 4
|
||||
#define NUM_CYCLES_PER_ITER_CHECK 8
|
||||
#else
|
||||
#define NUM_CYCLES_PER_ITER 4
|
||||
#define NUM_CYCLES_PER_ITER_CHECK 14
|
||||
#endif
|
||||
|
||||
NO_INLINE IWRAM_CODE void delay_cycles(u32 num_cycles) {
|
||||
num_cycles = (num_cycles + NUM_CYCLES_PER_ITER - 1 + (NUM_CYCLES_PER_ITER / 2)) / NUM_CYCLES_PER_ITER;
|
||||
__asm__ volatile (
|
||||
"L1%=: subs %[wait], #1;"
|
||||
"bne L1%=;"
|
||||
: [wait] "+l" (num_cycles)
|
||||
);
|
||||
}
|
||||
|
||||
NO_INLINE IWRAM_CODE void delay_cycles_until(u32 num_cycles, vu8* data, u8 wanted, u8 cycles_per_load) {
|
||||
num_cycles = (num_cycles + (NUM_CYCLES_PER_ITER_CHECK + cycles_per_load) - 1 + ((NUM_CYCLES_PER_ITER_CHECK + cycles_per_load) / 2)) / (NUM_CYCLES_PER_ITER_CHECK + cycles_per_load);
|
||||
__asm__ volatile (
|
||||
"L1%=: ldrb r3, [%[data], #0];"
|
||||
"cmp r3, %[wanted];"
|
||||
"beq L2%=;"
|
||||
"subs %[wait], #1;"
|
||||
"bne L1%=;"
|
||||
"L2%=:;"
|
||||
: [wait] "+l" (num_cycles) : [data]"l"(data), [wanted]"l"(wanted) : "r3"
|
||||
);
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@
|
|||
#include "pokemon_gender_bin.h"
|
||||
#include "pokemon_stats_gen1_bin.h"
|
||||
#include "pokemon_stats_bin.h"
|
||||
#include "default_names_int_gen_i_ii_bin.h"
|
||||
#include "default_names_jpn_gen_i_ii_bin.h"
|
||||
|
||||
const u8* set_buffer_with_gen2(const u8*, u8, u8*);
|
||||
u16 get_stat_exp_contribution(u16);
|
||||
|
|
@ -153,9 +155,7 @@ u8 is_pokerus_strain_valid_gen2(u8 pokerus_byte) {
|
|||
u8 get_pokerus_strain_max_days_gen2(u8 pokerus_byte) {
|
||||
if(!is_pokerus_strain_valid_gen2(pokerus_byte))
|
||||
return 0;
|
||||
if(!(pokerus_byte >> 4))
|
||||
return 1;
|
||||
return (((pokerus_byte >> 4) - 1) & 3) + 1;
|
||||
return ((pokerus_byte >> 4) & 3) + 1;
|
||||
}
|
||||
|
||||
u8 are_pokerus_days_valid_gen2(u8 pokerus_byte) {
|
||||
|
|
@ -230,6 +230,43 @@ const u8* get_default_trainer_name_gen2(u8 language, u8* buffer) {
|
|||
return set_buffer_with_gen2(get_default_trainer_name(language), language, buffer);
|
||||
}
|
||||
|
||||
const u8* get_actual_ot_name(const u8* gen2_ot_name, u8 is_jp, u8 terminator_stop, u8 language_target) {
|
||||
const u8* names_list = default_names_int_gen_i_ii_bin;
|
||||
if(is_jp)
|
||||
names_list = default_names_jpn_gen_i_ii_bin;
|
||||
|
||||
u8 names_size = names_list[0] - 1;
|
||||
u8 num_entries = names_list[1];
|
||||
|
||||
u16 curr_pos = 2;
|
||||
u8 found = 0;
|
||||
for(int i = 0; i < num_entries; i++) {
|
||||
int diff = 0;
|
||||
for(int j = 0; j < names_size; j++) {
|
||||
diff = gen2_ot_name[j] - names_list[curr_pos + j];
|
||||
if(diff != 0)
|
||||
break;
|
||||
if(terminator_stop && (gen2_ot_name[j] == GEN2_EOL))
|
||||
break;
|
||||
}
|
||||
if(diff == 0) {
|
||||
if((language_target == 0) || (names_list[curr_pos + names_size] & (1 << language_target))) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Use the fact that the list is sorted
|
||||
if(diff < 0)
|
||||
break;
|
||||
curr_pos += names_size + 1;
|
||||
}
|
||||
|
||||
if(!found)
|
||||
return NULL;
|
||||
|
||||
return &names_list[curr_pos];
|
||||
}
|
||||
|
||||
u8 get_pokemon_gender_gen2(u8 index, u8 atk_ivs, u8 is_egg, u8 curr_gen) {
|
||||
u8 gender_kind = get_pokemon_gender_kind_gen2(index, is_egg, curr_gen);
|
||||
switch(gender_kind){
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ const u16 berry_trees_pos[NUM_MAIN_GAME_ID] = {0x688, 0, 0x71C};
|
|||
const u16 daily_show_thresholds[TOTAL_DAILY_SHOW_VARS] = {100, 50, 100, 20, 20, 20, 30};
|
||||
static u32 time_events_rng_seed;
|
||||
#endif
|
||||
static u8 init_successful;
|
||||
|
||||
u8 has_rtc_events(struct game_identity* game_id) {
|
||||
if(game_id->game_main_version == RS_MAIN_GAME_CODE)
|
||||
|
|
@ -196,51 +197,76 @@ void change_tide(struct clock_events_t* clock_events, struct saved_time_t* extra
|
|||
increase_clock(extra_time, 0xFFFF, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
u8 has_init_succeded() {
|
||||
return init_successful;
|
||||
}
|
||||
|
||||
u8 update_base_time() {
|
||||
#if ACTIVE_RTC_FUNCTIONS
|
||||
__agbabi_datetime_t datetime = __agbabi_rtc_datetime();
|
||||
u16 year = bcd_decode(datetime[0], 1);
|
||||
u8 month = bcd_decode(datetime[0] >> 8, 1);
|
||||
u8 day = bcd_decode(datetime[0] >> 16, 1);
|
||||
u8 hour = bcd_decode(datetime[1], 1);
|
||||
u8 minute = bcd_decode(datetime[1] >> 8, 1);
|
||||
u8 second = bcd_decode(datetime[1] >> 16, 1);
|
||||
u8 error_out = 0;
|
||||
if(year == ((u16)ERROR_OUT_BCD))
|
||||
error_out = 1;
|
||||
if((month == ((u8)ERROR_OUT_BCD)) || (month == 0) || (month > NUM_MONTHS))
|
||||
error_out = 1;
|
||||
// There is no checking for overflows here, normally... :/
|
||||
u8 checking_month = 0;
|
||||
if((month > 0) && (month <= NUM_MONTHS))
|
||||
checking_month = month - 1;
|
||||
u8 max_day = num_days_per_month[checking_month];
|
||||
if((month == LEAP_YEAR_EXTRA_DAY_MONTH) && is_leap_year(year))
|
||||
max_day++;
|
||||
// What if the day is 0? And if it's the max_day?! :/
|
||||
if((day == ((u8)ERROR_OUT_BCD)) || (day > max_day))
|
||||
error_out = 1;
|
||||
// What if the hour is 0? And if it's MAX_HOURS?! :/
|
||||
if((hour == ((u8)ERROR_OUT_BCD)) || (hour > MAX_HOURS))
|
||||
error_out = 1;
|
||||
// What if the minute is 0? And if it's MAX_MINUTES?! :/
|
||||
if((minute == ((u8)ERROR_OUT_BCD)) || (minute > MAX_MINUTES))
|
||||
error_out = 1;
|
||||
// What if the second is 0? And if it's MAX_SECONDS?! :/
|
||||
if((second == ((u8)ERROR_OUT_BCD)) || (second > MAX_SECONDS))
|
||||
error_out = 1;
|
||||
if(!error_out) {
|
||||
u16 final_days = get_num_days(year, month, day);
|
||||
u8 final_hours = hour;
|
||||
u8 final_minutes = minute;
|
||||
u8 final_seconds = second;
|
||||
u8 updated = 0;
|
||||
if(base_rtc_time.d != final_days)
|
||||
updated = 1;
|
||||
if(base_rtc_time.h != final_hours)
|
||||
updated = 1;
|
||||
if(base_rtc_time.m != final_minutes)
|
||||
updated = 1;
|
||||
if(base_rtc_time.s != final_seconds)
|
||||
updated = 1;
|
||||
base_rtc_time.d = final_days;
|
||||
base_rtc_time.h = final_hours;
|
||||
base_rtc_time.m = final_minutes;
|
||||
base_rtc_time.s = final_seconds;
|
||||
return 1 + updated;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_rtc_time() {
|
||||
base_rtc_time.d = 1;
|
||||
base_rtc_time.h = 0;
|
||||
base_rtc_time.m = 0;
|
||||
base_rtc_time.s = 0;
|
||||
init_successful = 0;
|
||||
#if ACTIVE_RTC_FUNCTIONS
|
||||
if(!__agbabi_rtc_init()) {
|
||||
__agbabi_datetime_t datetime = __agbabi_rtc_datetime();
|
||||
u16 year = bcd_decode(datetime[0], 1);
|
||||
u8 month = bcd_decode(datetime[0] >> 8, 1);
|
||||
u8 day = bcd_decode(datetime[0] >> 16, 1);
|
||||
u8 hour = bcd_decode(datetime[1], 1);
|
||||
u8 minute = bcd_decode(datetime[1] >> 8, 1);
|
||||
u8 second = bcd_decode(datetime[1] >> 16, 1);
|
||||
u8 error_out = 0;
|
||||
if(year == ((u16)ERROR_OUT_BCD))
|
||||
error_out = 1;
|
||||
if((month == ((u8)ERROR_OUT_BCD)) || (month == 0) || (month > NUM_MONTHS))
|
||||
error_out = 1;
|
||||
// There is no checking for overflows here, normally... :/
|
||||
u8 checking_month = 0;
|
||||
if((month > 0) && (month <= NUM_MONTHS))
|
||||
checking_month = month - 1;
|
||||
u8 max_day = num_days_per_month[checking_month];
|
||||
if((month == LEAP_YEAR_EXTRA_DAY_MONTH) && is_leap_year(year))
|
||||
max_day++;
|
||||
// What if the day is 0? And if it's the max_day?! :/
|
||||
if((day == ((u8)ERROR_OUT_BCD)) || (day > max_day))
|
||||
error_out = 1;
|
||||
// What if the hour is 0? And if it's MAX_HOURS?! :/
|
||||
if((hour == ((u8)ERROR_OUT_BCD)) || (hour > MAX_HOURS))
|
||||
error_out = 1;
|
||||
// What if the minute is 0? And if it's MAX_MINUTES?! :/
|
||||
if((minute == ((u8)ERROR_OUT_BCD)) || (minute > MAX_MINUTES))
|
||||
error_out = 1;
|
||||
// What if the second is 0? And if it's MAX_SECONDS?! :/
|
||||
if((second == ((u8)ERROR_OUT_BCD)) || (second > MAX_SECONDS))
|
||||
error_out = 1;
|
||||
if(!error_out) {
|
||||
base_rtc_time.d = get_num_days(year, month, day);
|
||||
base_rtc_time.h = hour;
|
||||
base_rtc_time.m = minute;
|
||||
base_rtc_time.s = second;
|
||||
}
|
||||
}
|
||||
if((!__agbabi_rtc_init()) && update_base_time())
|
||||
init_successful = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -426,8 +452,8 @@ void run_daily_update(struct game_data_t* game_data, struct clock_events_t* cloc
|
|||
#else
|
||||
void run_daily_update(struct game_data_t* game_data, struct clock_events_t* clock_events, struct saved_time_t* extra_time, u8 UNUSED(is_game_cleared)) {
|
||||
#endif
|
||||
if(has_rtc_events(&game_data->game_identifier))
|
||||
init_rtc_time();
|
||||
if(has_rtc_events(&game_data->game_identifier) && has_init_succeded())
|
||||
update_base_time();
|
||||
swap_time(&clock_events->saved_time);
|
||||
u16 d = clock_events->saved_time.d;
|
||||
add_time(&clock_events->saved_time, extra_time, &clock_events->saved_time);
|
||||
|
|
@ -488,8 +514,8 @@ void wipe_clock(struct clock_events_t* clock_events) {
|
|||
}
|
||||
|
||||
u8 is_daily_update_safe(struct game_data_t* game_data, struct clock_events_t* clock_events, struct saved_time_t* extra_time) {
|
||||
if(has_rtc_events(&game_data->game_identifier))
|
||||
init_rtc_time();
|
||||
if(has_rtc_events(&game_data->game_identifier) && has_init_succeded())
|
||||
update_base_time();
|
||||
swap_time(&clock_events->saved_time);
|
||||
struct saved_time_t tmp;
|
||||
u16 days_increase = clock_events->saved_time.d;
|
||||
|
|
|
|||
|
|
@ -527,8 +527,10 @@ void read_party(int slot, struct game_data_t* game_data, struct game_data_priv_t
|
|||
game_data_priv->game_is_suspended = 0;
|
||||
}
|
||||
|
||||
if(section_id == SECTION_LOCATION_ID)
|
||||
if(section_id == SECTION_LOCATION_ID) {
|
||||
game_data_priv->curr_map = read_short_save((slot * SAVE_SLOT_SIZE) + (i * SECTION_SIZE) + LOCATION_POS);
|
||||
game_data_priv->curr_map = ((game_data_priv->curr_map & 0xFF) << 8) | ((game_data_priv->curr_map & 0xFF00) >> 8);
|
||||
}
|
||||
|
||||
if(section_id == SECTION_BASE_DEX_ID) {
|
||||
game_data_priv->nat_dex_magic = read_byte_save((slot * SAVE_SLOT_SIZE) + (i * SECTION_SIZE) + nat_dex_magic_pos[game_id]);
|
||||
|
|
@ -823,14 +825,18 @@ IWRAM_CODE u8 has_cartridge_been_removed(){
|
|||
|
||||
ALWAYS_INLINE void start_gen3_save_data_transfer() {
|
||||
#ifdef __NDS__
|
||||
#ifdef __BLOCKSDS__
|
||||
disableSleep();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void end_gen3_save_data_transfer() {
|
||||
#ifdef __NDS__
|
||||
#ifdef __BLOCKSDS__
|
||||
enableSleep();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
u8 read_gen_3_data(struct game_data_t* game_data, struct game_data_priv_t* game_data_priv){
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include "rng.h"
|
||||
#include "pid_iv_tid.h"
|
||||
#include "fast_pokemon_methods.h"
|
||||
#include "optimized_swi.h"
|
||||
#include "useful_qualifiers.h"
|
||||
#include <stddef.h>
|
||||
|
||||
|
|
@ -75,7 +74,7 @@ void convert_strings_of_gen3_generic(struct gen3_mon*, u16, u8*, u8*, u8, u8, u8
|
|||
void convert_strings_of_gen12(struct gen3_mon*, u8, u8*, u8*, u8, u8);
|
||||
void special_convert_strings_distribution(struct gen3_mon*, u16);
|
||||
u8 text_handling_gen12_to_gen3(struct gen3_mon*, u16, u16, u8, u8*, u8*, u8, u8);
|
||||
void set_language_gen12_to_gen3(struct gen3_mon*, u16, u8, u8*, u8);
|
||||
void set_language_gen12_to_gen3(struct gen3_mon*, u16, u8, const u8*, const u8*, u8);
|
||||
void sanitize_ot_name_gen3_to_gen12(u8*, u8*, u8, u8);
|
||||
void sanitize_ot_name_gen12_to_gen3(u8*, u8*, u8);
|
||||
void clean_name_gen12(u8*, u8);
|
||||
|
|
@ -205,9 +204,10 @@ u8 convert_moves_of_gen3(struct gen3_mon_attacks* attacks, u8 pp_bonuses, u8* mo
|
|||
if(!found) {
|
||||
u8 bonus_pp = (pp_bonuses>>(2*i))&3;
|
||||
u8 base_pp = get_pp_of_move(move, bonus_pp, last_valid_move);
|
||||
// Limit the PP to its maximum of 61
|
||||
if(base_pp > 61)
|
||||
base_pp = 61;
|
||||
// Limit the PP to the real maximum
|
||||
u8 max_gen12_move_pps = GEN12_MAX_MOVE_PP + (((GEN12_MAX_MOVE_PP / 5) - 1) * bonus_pp);
|
||||
if(base_pp >= max_gen12_move_pps)
|
||||
base_pp = max_gen12_move_pps;
|
||||
base_pp |= (bonus_pp << 6);
|
||||
pps[used_slots] = base_pp;
|
||||
moves[used_slots++] = move;
|
||||
|
|
@ -287,7 +287,7 @@ void convert_exp_nature_of_gen3(struct gen3_mon* src, struct gen3_mon_growth* gr
|
|||
u8 nature = get_nature(src->pid);
|
||||
|
||||
// Nature handling
|
||||
u8 exp_nature = DivMod(exp, NUM_NATURES);
|
||||
u8 exp_nature = get_nature(exp);
|
||||
if(exp_nature > nature)
|
||||
nature += NUM_NATURES;
|
||||
exp += nature - exp_nature;
|
||||
|
|
@ -337,7 +337,7 @@ u8 get_exp_nature(struct gen3_mon* dst, struct gen3_mon_growth* growth, u8 level
|
|||
s32 exp = get_proper_exp_from_gen12(mon_index, level, is_egg, given_exp);
|
||||
|
||||
// Save nature in experience, like the Gen I-VII conversion
|
||||
u8 nature = SWI_DivMod(exp, NUM_NATURES);
|
||||
u8 nature = get_nature(exp);
|
||||
|
||||
// Store exp and level
|
||||
dst->level = level;
|
||||
|
|
@ -551,6 +551,10 @@ void preload_if_fixable(struct gen3_mon_data_unenc* data_src) {
|
|||
data_src->fixed_ivs.ot_id = generate_ot(data_src->src->ot_id & 0xFFFF, data_src->src->ot_name);
|
||||
data_src->fix_has_altered_ot = 1;
|
||||
}
|
||||
if(data_src->misc.origins_info >> 15) {
|
||||
data_src->fixed_ivs.origins_info &= ~(1 << 15);
|
||||
data_src->fix_has_altered_ot = 1;
|
||||
}
|
||||
u8 wanted_nature = get_nature(data_src->src->pid);
|
||||
u32 ot_id = data_src->fixed_ivs.ot_id;
|
||||
u8 is_shiny = is_shiny_gen3_raw(data_src, ot_id);
|
||||
|
|
@ -603,7 +607,7 @@ void alter_nature(struct gen3_mon_data_unenc* data_src, u8 wanted_nature) {
|
|||
return;
|
||||
|
||||
// Normalize nature
|
||||
SWI_DivMod(wanted_nature, NUM_NATURES);
|
||||
wanted_nature = get_nature(wanted_nature);
|
||||
|
||||
if(wanted_nature == get_nature(data_src->src->pid))
|
||||
return;
|
||||
|
|
@ -635,7 +639,7 @@ void alter_nature(struct gen3_mon_data_unenc* data_src, u8 wanted_nature) {
|
|||
switch(encounter_type) {
|
||||
case STATIC_ENCOUNTER:
|
||||
case ROAMER_ENCOUNTER:
|
||||
if(species == CELEBI_SPECIES) {
|
||||
if(get_event_info_replacement() && (species == CELEBI_SPECIES)) {
|
||||
generate_generic_genderless_shadow_info_xd(wanted_nature, 0, wanted_ivs, tsv, pid_ptr, ivs_ptr, ability_ptr);
|
||||
is_ability_set = 1;
|
||||
}
|
||||
|
|
@ -693,6 +697,9 @@ void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_data_unenc* data_ds
|
|||
u8 trainer_game_version = id_to_version(&trainer_data->game_identifier);
|
||||
u8 trainer_gender = trainer_data->trainer_gender;
|
||||
|
||||
// Normalize nature
|
||||
wanted_nature = get_nature(wanted_nature);
|
||||
|
||||
// Handle eggs separately
|
||||
u32 ot_id = dst->ot_id;
|
||||
if(is_egg)
|
||||
|
|
@ -722,7 +729,7 @@ void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_data_unenc* data_ds
|
|||
switch(encounter_type) {
|
||||
case STATIC_ENCOUNTER:
|
||||
valid_balls = VALID_POKEBALL_NO_EGG;
|
||||
if(species == CELEBI_SPECIES) {
|
||||
if(get_event_info_replacement() && (species == CELEBI_SPECIES)) {
|
||||
valid_balls = VALID_POKEBALL_CELEBI;
|
||||
chosen_version = R_VERSION_ID;
|
||||
generate_generic_genderless_shadow_info_xd(wanted_nature, 0, wanted_ivs, tsv, &dst->pid, &ivs, &ability);
|
||||
|
|
@ -731,11 +738,12 @@ void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_data_unenc* data_ds
|
|||
}
|
||||
else if(!is_shiny) {
|
||||
// Prefer Colosseum/XD encounter, if possible
|
||||
if(get_conversion_colo_xd() && is_static_in_xd(species) && are_colo_valid_tid_sid(ot_id & 0xFFFF, ot_id >> 0x10)) {
|
||||
if(get_conversion_colo_xd() && is_static_in_xd(species) && are_colo_valid_tid_sid(ot_id & 0xFFFF, ot_id >> 0x10) && ((ot_gender == 0) || (!get_prioritize_ot_gender()))) {
|
||||
chosen_version = COLOSSEUM_CODE;
|
||||
generate_generic_genderless_shadow_info_xd(wanted_nature, has_prev_check_tsv_in_xd(species), wanted_ivs, tsv, &dst->pid, &ivs, &ability);
|
||||
misc->ribbons |= COLO_RIBBON_VALUE;
|
||||
is_ability_set = 1;
|
||||
ot_gender = 0;
|
||||
data_dst->learnable_moves = (const struct learnset_data_mon_moves*)get_learnset_for_species((const u16*)learnset_static_xd_bin, species);
|
||||
}
|
||||
else
|
||||
|
|
@ -749,7 +757,7 @@ void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_data_unenc* data_ds
|
|||
case ROAMER_ENCOUNTER:
|
||||
valid_balls = VALID_POKEBALL_NO_EGG;
|
||||
// Prefer Colosseum/XD encounter, if possible
|
||||
if(get_conversion_colo_xd() && are_colo_valid_tid_sid(ot_id & 0xFFFF, ot_id >> 0x10)) {
|
||||
if(get_conversion_colo_xd() && are_colo_valid_tid_sid(ot_id & 0xFFFF, ot_id >> 0x10) && ((ot_gender == 0) || (!get_prioritize_ot_gender()))) {
|
||||
chosen_version = COLOSSEUM_CODE;
|
||||
if(!is_shiny)
|
||||
generate_generic_genderless_shadow_info_colo(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs, &ability);
|
||||
|
|
@ -757,6 +765,7 @@ void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_data_unenc* data_ds
|
|||
generate_generic_genderless_shadow_shiny_info_colo(wanted_nature, tsv, &dst->pid, &ivs, &ability);
|
||||
misc->ribbons |= COLO_RIBBON_VALUE;
|
||||
is_ability_set = 1;
|
||||
ot_gender = 0;
|
||||
}
|
||||
else {
|
||||
if(!is_shiny)
|
||||
|
|
@ -902,7 +911,7 @@ void sanitize_ot_name_gen12_to_gen3(u8* src, u8* dst, u8 language) {
|
|||
sanitize_name_gen12_to_gen3(src, dst, get_default_trainer_name(language), gen2_name_cap, gen3_ot_name_cap);
|
||||
}
|
||||
|
||||
void convert_trainer_name_gen3_to_gen12(u8* src, u8* dst, u8 src_language, u8 dst_language) {
|
||||
void convert_trainer_name_gen3_to_gen12(u8* src, u8* dst, u8 src_language, u8 dst_language, u8 marks) {
|
||||
u8 is_jp_gen3 = GET_LANGUAGE_IS_JAPANESE(src_language);
|
||||
u8 is_jp_target = GET_LANGUAGE_IS_JAPANESE(dst_language);
|
||||
|
||||
|
|
@ -924,6 +933,26 @@ void convert_trainer_name_gen3_to_gen12(u8* src, u8* dst, u8 src_language, u8 ds
|
|||
|
||||
// Do some sanitization
|
||||
sanitize_ot_name_gen3_to_gen12(src, dst, src_language, dst_language);
|
||||
|
||||
// Apply special OT Name handling with special markings value
|
||||
if(marks == SPECIAL_NAME_MARKS_VALUE) {
|
||||
const u8* special_name = get_actual_ot_name(dst, is_jp_target, 1, src_language);
|
||||
if(special_name) {
|
||||
for(size_t i = 0; i < gen12_ot_name_size; i++)
|
||||
dst[i] = special_name[i];
|
||||
return;
|
||||
}
|
||||
marks = 0;
|
||||
}
|
||||
|
||||
// Apply special OT Name handling and 0 out certain parts of the name
|
||||
if(marks > gen12_ot_name_size)
|
||||
marks = 0;
|
||||
size_t pos_zeros = text_gen2_size(dst, gen12_ot_name_cap) + 1;
|
||||
if(marks > pos_zeros)
|
||||
pos_zeros = marks;
|
||||
for(; pos_zeros < gen12_ot_name_size; pos_zeros++)
|
||||
dst[pos_zeros] = 0;
|
||||
}
|
||||
|
||||
void convert_trainer_name_gen12_to_gen3(u8* src, u8* dst, u8 src_is_jp, u8 dst_language, u8 max_size) {
|
||||
|
|
@ -987,7 +1016,7 @@ void convert_strings_of_gen3_generic(struct gen3_mon* src, u16 species, u8* ot_n
|
|||
text_gen2_replace(nickname, gen12_nickname_cap, GEN2_DOT, GEN1_DOT);
|
||||
*/
|
||||
|
||||
convert_trainer_name_gen3_to_gen12(src->ot_name, ot_name, src->language, target_language);
|
||||
convert_trainer_name_gen3_to_gen12(src->ot_name, ot_name, src->language, target_language, src->marks);
|
||||
}
|
||||
|
||||
void convert_strings_of_gen3(struct gen3_mon* src, u16 species, u8* ot_name, u8* ot_name_jp, u8* nickname, u8* nickname_jp, u8 is_egg, u8 is_gen2) {
|
||||
|
|
@ -1264,21 +1293,54 @@ void clean_name_gen12(u8* name, u8 is_jp) {
|
|||
text_gen2_replace(name, gen2_name_cap, GEN1_DOT, GEN2_DOT);
|
||||
}
|
||||
|
||||
void set_language_gen12_to_gen3(struct gen3_mon* dst, u16 species, u8 is_egg, u8* nickname, u8 is_jp) {
|
||||
void set_language_gen12_to_gen3(struct gen3_mon* dst, u16 species, u8 is_egg, const u8* ot_name, const u8* nickname, u8 is_jp) {
|
||||
u8 gen2_buffer[STRING_GEN2_MAX_SIZE];
|
||||
u8 int_language = get_filtered_target_int_language();
|
||||
u32 possible_languages = ALL_LANGUAGES & (~(1 << JAPANESE_LANGUAGE));
|
||||
u8 gen12_ot_name_size = STRING_GEN2_INT_SIZE;
|
||||
if(is_jp) {
|
||||
possible_languages = (1 << JAPANESE_LANGUAGE);
|
||||
gen12_ot_name_size = STRING_GEN2_JP_SIZE;
|
||||
}
|
||||
|
||||
const u8* special_name = get_actual_ot_name(ot_name, is_jp, 0, 0);
|
||||
|
||||
// Abuse markings to store info about the Gen 1/2 OT Name's trailing bytes
|
||||
if(special_name != NULL) {
|
||||
possible_languages &= special_name[gen12_ot_name_size];
|
||||
dst->marks = SPECIAL_NAME_MARKS_VALUE;
|
||||
}
|
||||
else {
|
||||
size_t end_eol = gen12_ot_name_size;
|
||||
for(; end_eol > 0; end_eol--) {
|
||||
if(ot_name[end_eol - 1] == GEN2_EOL)
|
||||
break;
|
||||
}
|
||||
dst->marks = end_eol;
|
||||
}
|
||||
|
||||
// Fix possible bad language filtering (Korean)
|
||||
if(!possible_languages) {
|
||||
possible_languages = ALL_LANGUAGES & (~(1 << JAPANESE_LANGUAGE));
|
||||
dst->marks = 0;
|
||||
}
|
||||
|
||||
if((!is_jp) && (get_target_int_language() == UNKNOWN_LANGUAGE)) {
|
||||
u32 found_languages = 0;
|
||||
for(size_t i = FIRST_INTERNATIONAL_VALID_LANGUAGE; i < NUM_LANGUAGES; i++)
|
||||
if(text_gen2_is_same(nickname, get_pokemon_name_gen2(species, is_egg, i, gen2_buffer), STRING_GEN2_INT_CAP, STRING_GEN2_INT_CAP))
|
||||
found_languages |= 1<<i;
|
||||
if(found_languages && (!(found_languages & (1<<int_language))))
|
||||
for(size_t i = FIRST_INTERNATIONAL_VALID_LANGUAGE; i < NUM_LANGUAGES; i++)
|
||||
if(found_languages & (1<<i)) {
|
||||
int_language = i;
|
||||
break;
|
||||
}
|
||||
found_languages |= 1 << i;
|
||||
// OT Name has priority
|
||||
if(possible_languages & found_languages)
|
||||
possible_languages &= found_languages;
|
||||
}
|
||||
|
||||
if((!is_jp) && (!(possible_languages & (1 << int_language)))) {
|
||||
for(size_t i = FIRST_INTERNATIONAL_VALID_LANGUAGE; i < NUM_LANGUAGES; i++)
|
||||
if(possible_languages & (1 << i)) {
|
||||
int_language = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_jp)
|
||||
|
|
@ -1286,7 +1348,7 @@ void set_language_gen12_to_gen3(struct gen3_mon* dst, u16 species, u8 is_egg, u8
|
|||
else
|
||||
dst->language = int_language;
|
||||
|
||||
if((species == MEW_SPECIES) || (species == CELEBI_SPECIES)) {
|
||||
if(get_event_info_replacement() && ((species == MEW_SPECIES) || (species == CELEBI_SPECIES))) {
|
||||
if((!get_allow_undistributed_events()) || is_jp)
|
||||
dst->language = JAPANESE_LANGUAGE;
|
||||
else
|
||||
|
|
@ -1302,10 +1364,10 @@ u8 text_handling_gen12_to_gen3(struct gen3_mon* dst, u16 species, u16 swapped_ot
|
|||
clean_name_gen12(nickname, is_jp);
|
||||
|
||||
// Handle language
|
||||
set_language_gen12_to_gen3(dst, species, is_egg, nickname, is_jp);
|
||||
set_language_gen12_to_gen3(dst, species, is_egg, ot_name, nickname, is_jp);
|
||||
|
||||
// Specially handle Celebi's event
|
||||
if((species == CELEBI_SPECIES) && (!is_egg)) {
|
||||
if(get_event_info_replacement() && (species == CELEBI_SPECIES) && (!is_egg)) {
|
||||
dst->ot_id = CELEBI_AGATE_OT_ID;
|
||||
special_convert_strings_distribution(dst, species);
|
||||
return no_restrictions;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ void convert_3bpp_forward_even(const u8*, u32*, size_t);
|
|||
|
||||
MAX_OPTIMIZE void load_pokemon_sprite_gfx(const u32* src, u32* dst, u8 is_3bpp, u8 zero_fill, u8 index, u8* colors){
|
||||
|
||||
u32 zero = 0;
|
||||
u32 buffer[BUFFER_SIZE];
|
||||
CpuFastSet(&zero, buffer, BUFFER_SIZE|CPUFASTSET_FILL);
|
||||
LZ77UnCompWram(src, buffer);
|
||||
size_t processed_size = TOTAL_POKEMON_SPRITE_SIZE;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,24 @@
|
|||
#include "useful_qualifiers.h"
|
||||
#include "config_settings.h"
|
||||
|
||||
u8 handle_input_multiboot_settings(u16 keys, u8* is_normal, u8* update) {
|
||||
if(keys & KEY_A)
|
||||
return CONFIRM_MULTIBOOT;
|
||||
if(keys & KEY_B)
|
||||
return CANCEL_MULTIBOOT;
|
||||
|
||||
if(*is_normal && (keys & KEY_RIGHT)) {
|
||||
*is_normal = 0;
|
||||
*update = 1;
|
||||
}
|
||||
else if((!(*is_normal)) && (keys & KEY_LEFT)) {
|
||||
*is_normal = 1;
|
||||
*update = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 handle_input_multiboot_menu(u16 keys) {
|
||||
if(keys & KEY_A)
|
||||
return 1;
|
||||
|
|
@ -489,7 +507,7 @@ u8 handle_input_gen12_settings_menu(u16 keys, u8* cursor_y_pos, u8* update) {
|
|||
switch(*cursor_y_pos) {
|
||||
case 0:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos = 6;
|
||||
*cursor_y_pos = 7;
|
||||
else if(keys & KEY_DOWN)
|
||||
*cursor_y_pos += 1;
|
||||
else if((keys & KEY_RIGHT) || (keys & KEY_A)) {
|
||||
|
|
@ -531,11 +549,21 @@ u8 handle_input_gen12_settings_menu(u16 keys, u8* cursor_y_pos, u8* update) {
|
|||
else if(keys & KEY_DOWN)
|
||||
*cursor_y_pos += 1;
|
||||
else if((keys & KEY_RIGHT) || (keys & KEY_A) || (keys & KEY_LEFT)) {
|
||||
set_gen1_everstone(!get_gen1_everstone());
|
||||
set_prioritize_ot_gender(!get_prioritize_ot_gender());
|
||||
*update = 1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos -= 1;
|
||||
else if(keys & KEY_DOWN)
|
||||
*cursor_y_pos += 1;
|
||||
else if((keys & KEY_RIGHT) || (keys & KEY_A) || (keys & KEY_LEFT)) {
|
||||
set_gen1_everstone(!get_gen1_everstone());
|
||||
*update = 1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos -= 1;
|
||||
else if(keys & KEY_DOWN)
|
||||
|
|
@ -553,7 +581,7 @@ u8 handle_input_gen12_settings_menu(u16 keys, u8* cursor_y_pos, u8* update) {
|
|||
*update = 1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos -= 1;
|
||||
else if(keys & KEY_DOWN)
|
||||
|
|
@ -567,7 +595,7 @@ u8 handle_input_gen12_settings_menu(u16 keys, u8* cursor_y_pos, u8* update) {
|
|||
*update = 1;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos -= 1;
|
||||
else if(keys & KEY_DOWN)
|
||||
|
|
@ -687,7 +715,7 @@ u8 handle_input_cheats_menu(u16 keys, u8* cursor_y_pos, u8* update) {
|
|||
switch(*cursor_y_pos) {
|
||||
case 0:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos = 4;
|
||||
*cursor_y_pos = 5;
|
||||
else if(keys & KEY_DOWN)
|
||||
*cursor_y_pos += 1;
|
||||
else if((keys & KEY_RIGHT) || (keys & KEY_A) || (keys & KEY_LEFT)) {
|
||||
|
|
@ -721,11 +749,21 @@ u8 handle_input_cheats_menu(u16 keys, u8* cursor_y_pos, u8* update) {
|
|||
else if(keys & KEY_DOWN)
|
||||
*cursor_y_pos += 1;
|
||||
else if((keys & KEY_RIGHT) || (keys & KEY_A) || (keys & KEY_LEFT)) {
|
||||
set_fast_hatch_eggs(!get_fast_hatch_eggs());
|
||||
set_event_info_replacement(!get_event_info_replacement());
|
||||
*update = 1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(keys & KEY_UP)
|
||||
*cursor_y_pos -= 1;
|
||||
else if(keys & KEY_DOWN)
|
||||
*cursor_y_pos += 1;
|
||||
else if((keys & KEY_RIGHT) || (keys & KEY_A) || (keys & KEY_LEFT)) {
|
||||
set_fast_hatch_eggs(!get_fast_hatch_eggs());
|
||||
*update = 1;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if(keys & KEY_A)
|
||||
return 1;
|
||||
else if(keys & KEY_UP)
|
||||
|
|
@ -854,8 +892,11 @@ u8 handle_input_clock_menu(u16 keys, struct clock_events_t* clock_events, struct
|
|||
}
|
||||
break;
|
||||
case BOTTOM_Y_CURSOR_CLOCK_SETTINGS_MENU_VALUE:
|
||||
if(keys & KEY_A)
|
||||
return 1;
|
||||
if(keys & KEY_A) {
|
||||
if((time_change->d != 0) || (time_change->h != 0) || (time_change->m != 0) || (time_change->s != 0))
|
||||
return 1;
|
||||
return EXIT_CLOCK_SETTINGS;
|
||||
}
|
||||
else if(keys & KEY_UP)
|
||||
*cursor_y_pos = 9;
|
||||
else if(keys & KEY_DOWN)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ void complete_save_menu(struct game_data_t*, struct game_data_priv_t*, u8, u8);
|
|||
void complete_cartridge_loading(struct game_data_t*, struct game_data_priv_t*, u8, u8, u8, u8*);
|
||||
int main(void);
|
||||
|
||||
enum STATE {MAIN_MENU, MULTIBOOT, TRADING_MENU, INFO_MENU, START_TRADE, WAITING_DATA, TRADE_OPTIONS, NATURE_SETTING, OFFER_MENU, TRADING_ANIMATION, OFFER_INFO_MENU, IV_FIX_MENU, LEARNABLE_MOVES_MESSAGE, LEARNABLE_MOVES_MESSAGE_MENU, LEARNABLE_MOVES_MENU, SWAP_CARTRIDGE_MENU, BASE_SETTINGS_MENU, COLOURS_SETTINGS_MENU, CLOCK_SETTINGS_MENU, CHEATS_MENU, EVOLUTION_MENU, WARNINGS_WHEN_LOADING, WARNING_WHEN_ADVANCING_CLOCK, PRINT_READ_INFO, GEN12_SETTINGS_MENU};
|
||||
enum STATE {MAIN_MENU, MULTIBOOT, TRADING_MENU, INFO_MENU, START_TRADE, WAITING_DATA, TRADE_OPTIONS, NATURE_SETTING, OFFER_MENU, TRADING_ANIMATION, OFFER_INFO_MENU, IV_FIX_MENU, LEARNABLE_MOVES_MESSAGE, LEARNABLE_MOVES_MESSAGE_MENU, LEARNABLE_MOVES_MENU, SWAP_CARTRIDGE_MENU, BASE_SETTINGS_MENU, COLOURS_SETTINGS_MENU, CLOCK_SETTINGS_MENU, CHEATS_MENU, EVOLUTION_MENU, WARNINGS_WHEN_LOADING, WARNING_WHEN_ADVANCING_CLOCK, PRINT_READ_INFO, GEN12_SETTINGS_MENU, MULTIBOOT_SETTINGS_MENU};
|
||||
enum STATE curr_state;
|
||||
u32 counter = 0;
|
||||
u32 input_counter = 0;
|
||||
|
|
@ -129,6 +129,10 @@ IWRAM_CODE void vblank_update_function() {
|
|||
// Handle trading animation
|
||||
if(curr_state == TRADING_ANIMATION)
|
||||
advance_trade_animation();
|
||||
#ifdef __NDS__
|
||||
// Increase FPS on NDS
|
||||
//__reset_vcount();
|
||||
#endif
|
||||
#ifdef HAS_SIO
|
||||
// Handle slave communications
|
||||
if((REG_SIOCNT & SIO_IRQ) && (!(REG_SIOCNT & SIO_START)))
|
||||
|
|
@ -642,10 +646,13 @@ void clock_settings_menu_init(struct game_data_priv_t* game_data_priv, struct sa
|
|||
set_screen(BASE_SCREEN);
|
||||
disable_all_screens_but_current();
|
||||
disable_all_cursors();
|
||||
if(reset_time)
|
||||
if(reset_time) {
|
||||
wipe_time(time_change);
|
||||
init_rtc_time();
|
||||
}
|
||||
print_clock_menu(&game_data_priv->clock_events, time_change, 1);
|
||||
enable_screen(BASE_SCREEN);
|
||||
enable_screen(BASE_SCREEN + 1);
|
||||
*cursor_y_pos = 0;
|
||||
update_cursor_base_x(BASE_X_CURSOR_CLOCK_SETTINGS_MENU);
|
||||
cursor_update_clock_settings_menu(*cursor_y_pos);
|
||||
|
|
@ -707,6 +714,9 @@ void prepare_crash_screen(enum CRASH_REASONS reason) {
|
|||
print_crash(reason);
|
||||
enable_screen(CRASH_WINDOW_SCREEN);
|
||||
prepare_flush();
|
||||
#if defined(__NDS__) && (!defined(__BLOCKSDS__))
|
||||
pmMainLoop();
|
||||
#endif
|
||||
}
|
||||
|
||||
void crash_on_cartridge_removed() {
|
||||
|
|
@ -752,8 +762,15 @@ void complete_save_menu(struct game_data_t* game_data, struct game_data_priv_t*
|
|||
|
||||
void complete_cartridge_loading(struct game_data_t* game_data, struct game_data_priv_t* game_data_priv, u8 target, u8 region, u8 master, u8* cursor_y_pos) {
|
||||
init_game_data(game_data);
|
||||
get_game_id(&game_data->game_identifier);
|
||||
read_gen_3_data(game_data, game_data_priv);
|
||||
u8 can_check_cart = 1;
|
||||
#ifdef __NDS__
|
||||
if(isDSiMode())
|
||||
can_check_cart = 0;
|
||||
#endif
|
||||
if(can_check_cart) {
|
||||
get_game_id(&game_data->game_identifier);
|
||||
read_gen_3_data(game_data, game_data_priv);
|
||||
}
|
||||
prepare_main_options(game_data, game_data_priv);
|
||||
if((!get_valid_options_main()) || (!loaded_data_has_warnings(game_data, game_data_priv)))
|
||||
main_menu_init(game_data, game_data_priv, target, region, master, cursor_y_pos);
|
||||
|
|
@ -766,6 +783,10 @@ int main(void)
|
|||
#ifdef __GBA__
|
||||
RegisterRamReset(RESET_SIO|RESET_SOUND|RESET_OTHER);
|
||||
disable_all_irqs();
|
||||
#else
|
||||
#ifndef __BLOCKSDS__
|
||||
gbacartOpen();
|
||||
#endif
|
||||
#endif
|
||||
curr_state = MAIN_MENU;
|
||||
counter = 0;
|
||||
|
|
@ -806,6 +827,7 @@ int main(void)
|
|||
u8 returned_val;
|
||||
u8 move_go_on = 0;
|
||||
u8 update = 0;
|
||||
u8 is_normal = 1;
|
||||
u8 target = 1;
|
||||
u8 region = 0;
|
||||
u8 master = 0;
|
||||
|
|
@ -832,10 +854,13 @@ int main(void)
|
|||
//PRINT_FUNCTION("\n\n0x\x0D: 0x\x0D\n", REG_MEMORY_CONTROLLER_ADDR, 8, REG_MEMORY_CONTROLLER, 8);
|
||||
scanKeys();
|
||||
keys = keysDown();
|
||||
|
||||
|
||||
while(1) {
|
||||
|
||||
do {
|
||||
#if defined(__NDS__) && (!defined(__BLOCKSDS__))
|
||||
pmMainLoop();
|
||||
#endif
|
||||
prepare_flush();
|
||||
VBlankIntrWait();
|
||||
scanKeys();
|
||||
|
|
@ -987,6 +1012,9 @@ int main(void)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case CLOCK_SETTINGS_MENU:
|
||||
print_clock_variable_menu(&game_data_priv.clock_events, &time_change, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -999,14 +1027,10 @@ int main(void)
|
|||
print_main_menu(update, target, region, master, &game_data[0], &game_data_priv);
|
||||
cursor_update_main_menu(cursor_y_pos);
|
||||
if(returned_val == START_MULTIBOOT) {
|
||||
curr_state = MULTIBOOT;
|
||||
#ifdef HAS_SIO
|
||||
sio_stop_irq_slave();
|
||||
irqDisable(IRQ_SERIAL);
|
||||
#endif
|
||||
curr_state = MULTIBOOT_SETTINGS_MENU;
|
||||
is_normal = 1;
|
||||
disable_cursor();
|
||||
init_save_data();
|
||||
print_multiboot(multiboot_normal((u16*)EWRAM, (u16*)(EWRAM + MULTIBOOT_MAX_SIZE)));
|
||||
print_multiboot_settings(is_normal, 1);
|
||||
}
|
||||
if(returned_val == START_PRINT_READ_INFO) {
|
||||
curr_state = PRINT_READ_INFO;
|
||||
|
|
@ -1077,6 +1101,22 @@ int main(void)
|
|||
else
|
||||
print_pokemon_pages(returned_val, submenu_cursor_y_pos != prev_val, &game_data[submenu_cursor_y_pos].party_3_undec[*party_selected_mons[submenu_cursor_y_pos]], curr_page);
|
||||
break;
|
||||
case MULTIBOOT_SETTINGS_MENU:
|
||||
returned_val = handle_input_multiboot_settings(keys, &is_normal, &update);
|
||||
if(returned_val == CONFIRM_MULTIBOOT) {
|
||||
curr_state = MULTIBOOT;
|
||||
#ifdef HAS_SIO
|
||||
sio_stop_irq_slave();
|
||||
irqDisable(IRQ_SERIAL);
|
||||
#endif
|
||||
init_save_data();
|
||||
print_multiboot(multiboot_normal((u16*)EWRAM, (u16*)(EWRAM + MULTIBOOT_MAX_SIZE), is_normal));
|
||||
}
|
||||
else if(returned_val == CANCEL_MULTIBOOT)
|
||||
main_menu_init(&game_data[0], &game_data_priv, target, region, master, &cursor_y_pos);
|
||||
else
|
||||
print_multiboot_settings(is_normal, update);
|
||||
break;
|
||||
case MULTIBOOT:
|
||||
if(handle_input_multiboot_menu(keys)) {
|
||||
loading_print_screen();
|
||||
|
|
|
|||
|
|
@ -450,18 +450,28 @@ void print_gen12_settings_menu(u8 update) {
|
|||
default_reset_screen();
|
||||
PRINT_FUNCTION("\n Target Language: <\x01>\n\n", get_language_string(get_target_int_language()));
|
||||
PRINT_FUNCTION(" Convert to: <\x01>\n\n", game_strings[get_default_conversion_game()]);
|
||||
PRINT_FUNCTION(" Prioritize Colo/XD:");
|
||||
if(get_conversion_colo_xd())
|
||||
PRINT_FUNCTION(" Prioritize Colo/XD: <True>\n\n");
|
||||
PRINT_FUNCTION(" <True>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" Prioritize Colo/XD: <False>\n\n");
|
||||
PRINT_FUNCTION(" <False>\n\n");
|
||||
PRINT_FUNCTION(" Preserve OT Gender:");
|
||||
if(get_prioritize_ot_gender())
|
||||
PRINT_FUNCTION(" <True>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" <False>\n\n");
|
||||
PRINT_FUNCTION(" Gen 1 Everstone: ");
|
||||
if(get_gen1_everstone())
|
||||
PRINT_FUNCTION(" Gen 1 Everstone: <Enabled>\n\n");
|
||||
PRINT_FUNCTION("<Enabled>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" Gen 1 Everstone: <Disabled>\n\n");
|
||||
PRINT_FUNCTION("<Disabled>\n\n");
|
||||
PRINT_FUNCTION(" Caught in: <\x01 Ball>\n\n", get_pokeball_base_name_gen3_pure(get_applied_ball()));
|
||||
PRINT_FUNCTION(" Hatched at: <\x0B> +/- 1\n\n", get_egg_met_location(), 3);
|
||||
PRINT_FUNCTION(" Hatched at: <\x0B> +/- 10\n\n\n", get_egg_met_location(), 3);
|
||||
PRINT_FUNCTION("Hatched at: \x01\n\n", get_met_location_name_gen3_pure(get_egg_met_location(), get_default_conversion_game()));
|
||||
PRINT_FUNCTION(" Hatched at: ");
|
||||
PRINT_FUNCTION("<\x0B> +/- 1\n\n", get_egg_met_location(), 3);
|
||||
PRINT_FUNCTION(" Hatched at: ");
|
||||
PRINT_FUNCTION("<\x0B> +/- 10\n\n", get_egg_met_location(), 3);
|
||||
PRINT_FUNCTION("Hatched at: ");
|
||||
PRINT_FUNCTION("\x01", get_met_location_name_gen3_pure(get_egg_met_location(), get_default_conversion_game()));
|
||||
|
||||
print_bottom_info();
|
||||
}
|
||||
|
|
@ -507,32 +517,58 @@ void print_base_settings_menu(struct game_identity* game_identifier, u8 is_loade
|
|||
PRINT_FUNCTION("V.\x03.\x03.\x03\x02", version->main_version, version->sub_version, version->revision_version, version->revision_letter);
|
||||
}
|
||||
|
||||
void print_clock_menu(struct clock_events_t* clock_events, struct saved_time_t* time_change, u8 update) {
|
||||
if(!update)
|
||||
void print_clock_variable_menu(struct clock_events_t* clock_events, struct saved_time_t* time_change, u8 force_print) {
|
||||
u8 update_value = 0;
|
||||
if(has_init_succeded())
|
||||
update_value = update_base_time();
|
||||
|
||||
if((update_value != 2) && (!force_print))
|
||||
return;
|
||||
|
||||
init_rtc_time();
|
||||
struct saved_time_t base_time;
|
||||
struct saved_time_t new_time;
|
||||
|
||||
get_clean_time(&clock_events->saved_time, &base_time);
|
||||
get_increased_time(&clock_events->saved_time, time_change, &new_time);
|
||||
|
||||
default_reset_screen();
|
||||
u8 old_screen = get_screen_num();
|
||||
set_screen(old_screen + 1);
|
||||
reset_screen(BLANK_FILL);
|
||||
|
||||
set_text_y(1);
|
||||
set_text_x(8);
|
||||
|
||||
if(is_daytime(clock_events, time_change))
|
||||
PRINT_FUNCTION("\n Time: <Day>\n\n");
|
||||
PRINT_FUNCTION("<Day>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION("\n Time: <Night>\n\n");
|
||||
PRINT_FUNCTION("<Night>\n\n");
|
||||
set_text_x(19);
|
||||
if(is_high_tide(clock_events, time_change))
|
||||
PRINT_FUNCTION(" Shoal Cave Tide: <High>\n\n");
|
||||
PRINT_FUNCTION("<High>");
|
||||
else
|
||||
PRINT_FUNCTION(" Shoal Cave Tide: <Low>\n\n");
|
||||
PRINT_FUNCTION("<Low>");
|
||||
set_text_y(Y_LIMIT-6);
|
||||
set_text_x(11);
|
||||
PRINT_FUNCTION("\x0B-\x0B:\x0B:\x0B\n", base_time.d, 5, base_time.h, 2, base_time.m, 2, base_time.s, 2);
|
||||
set_text_x(11);
|
||||
PRINT_FUNCTION("\x0B-\x0B:\x0B:\x0B\n", new_time.d, 5, new_time.h, 2, new_time.m, 2, new_time.s, 2);
|
||||
set_screen(old_screen);
|
||||
}
|
||||
|
||||
void print_clock_menu(struct clock_events_t* clock_events, struct saved_time_t* time_change, u8 update) {
|
||||
if(!update)
|
||||
return;
|
||||
|
||||
default_reset_screen();
|
||||
|
||||
PRINT_FUNCTION("\n Time: \n\n");
|
||||
PRINT_FUNCTION(" Shoal Cave Tide: \n\n");
|
||||
u8 curr_y = get_text_y();
|
||||
PRINT_FUNCTION(" Clock Reset Menu: ");
|
||||
if(is_rtc_reset_enabled(clock_events))
|
||||
PRINT_FUNCTION(" Clock Reset Menu: <Enabled>");
|
||||
PRINT_FUNCTION("<Enabled>");
|
||||
else
|
||||
PRINT_FUNCTION(" Clock Reset Menu: <Disabled>");
|
||||
PRINT_FUNCTION("<Disabled>");
|
||||
set_text_y(curr_y+2);
|
||||
|
||||
PRINT_FUNCTION(" Days Increase: <\x0B>\n", time_change->d, 5);
|
||||
|
|
@ -542,14 +578,15 @@ void print_clock_menu(struct clock_events_t* clock_events, struct saved_time_t*
|
|||
|
||||
set_text_y(Y_LIMIT-8);
|
||||
PRINT_FUNCTION(" Save and Exit\n\n");
|
||||
PRINT_FUNCTION("Base Time: \x0B-\x0B:\x0B:\x0B\n", base_time.d, 5, base_time.h, 2, base_time.m, 2, base_time.s, 2);
|
||||
PRINT_FUNCTION("New Time: \x0B-\x0B:\x0B:\x0B\n", new_time.d, 5, new_time.h, 2, new_time.m, 2, new_time.s, 2);
|
||||
set_text_y(Y_LIMIT-4);
|
||||
PRINT_FUNCTION("Base Time:\n");
|
||||
PRINT_FUNCTION("New Time:\n");
|
||||
PRINT_FUNCTION("Issues may arise when changing");
|
||||
set_text_y(Y_LIMIT-3);
|
||||
PRINT_FUNCTION("the time of a Working Battery.");
|
||||
set_text_y(Y_LIMIT-1);
|
||||
PRINT_FUNCTION("B: Exit Without Saving");
|
||||
|
||||
print_clock_variable_menu(clock_events, time_change, 1);
|
||||
}
|
||||
|
||||
void print_cheats_menu(u8 update) {
|
||||
|
|
@ -557,22 +594,31 @@ void print_cheats_menu(u8 update) {
|
|||
return;
|
||||
|
||||
default_reset_screen();
|
||||
PRINT_FUNCTION("\n Cross-Gen Evo.:");
|
||||
if(get_allow_cross_gen_evos())
|
||||
PRINT_FUNCTION("\n Cross-Gen Evo.: <Enabled>\n\n");
|
||||
PRINT_FUNCTION(" <Enabled>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION("\n Cross-Gen Evo.: <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" Tradeless Evo.:");
|
||||
if(get_evolve_without_trade())
|
||||
PRINT_FUNCTION(" Tradeless Evo.: <Enabled>\n\n");
|
||||
PRINT_FUNCTION(" <Enabled>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" Tradeless Evo.: <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" Undistr. Events:");
|
||||
if(get_allow_undistributed_events())
|
||||
PRINT_FUNCTION(" Undistr. Events: <Enabled>\n\n");
|
||||
PRINT_FUNCTION(" <Enabled>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" Undistr. Events: <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" Event Pok\xE9mon:");
|
||||
if(get_event_info_replacement())
|
||||
PRINT_FUNCTION(" <Legit Data>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" <Keep Data>\n\n");
|
||||
PRINT_FUNCTION(" Fast Hatch Eggs:");
|
||||
if(get_fast_hatch_eggs())
|
||||
PRINT_FUNCTION(" Fast Hatch Eggs: <Enabled>\n\n");
|
||||
PRINT_FUNCTION(" <Enabled>\n\n");
|
||||
else
|
||||
PRINT_FUNCTION(" Fast Hatch Eggs: <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" <Disabled>\n\n");
|
||||
PRINT_FUNCTION(" Give Pok\xE9rus to Party\n\n");
|
||||
|
||||
print_bottom_info();
|
||||
|
|
@ -768,8 +814,10 @@ void print_basic_alter_conf_data(struct gen3_mon_data_unenc* mon, struct alterna
|
|||
PRINT_FUNCTION(" \x09\x02", calc_stats_gen3_raw_alternative(mon, altered, i), 4, get_nature_symbol(altered->pid, i));
|
||||
PRINT_FUNCTION(" \x09 \x09", get_ivs_gen3(&mon->misc, i), 3, get_ivs_gen3_pure(altered->ivs, i), 3);
|
||||
}
|
||||
PRINT_FUNCTION("\n\nOld Hidden Power: \x01 \x03", get_hidden_power_type_name_gen3(&mon->misc), get_hidden_power_power_gen3(&mon->misc));
|
||||
PRINT_FUNCTION("\nNew Hidden Power: \x01 \x03", get_hidden_power_type_name_gen3_pure(altered->ivs), get_hidden_power_power_gen3_pure(altered->ivs));
|
||||
PRINT_FUNCTION("\n\nOld ");
|
||||
PRINT_FUNCTION("Hidden Power: \x01 \x03", get_hidden_power_type_name_gen3(&mon->misc), get_hidden_power_power_gen3(&mon->misc));
|
||||
PRINT_FUNCTION("\nNew ");
|
||||
PRINT_FUNCTION("Hidden Power: \x01 \x03", get_hidden_power_type_name_gen3_pure(altered->ivs), get_hidden_power_power_gen3_pure(altered->ivs));
|
||||
}
|
||||
|
||||
void print_set_nature(u8 load_sprites, struct gen3_mon_data_unenc* mon) {
|
||||
|
|
@ -1211,28 +1259,31 @@ void print_main_menu(u8 update, u8 curr_gen, u8 is_jp, u8 is_master, struct game
|
|||
set_text_y(1);
|
||||
set_text_x(MAIN_MENU_DISTANCE_FROM_BORDER);
|
||||
curr_gen = options[curr_gen];
|
||||
PRINT_FUNCTION("Target: ");
|
||||
if(get_number_of_higher_ordered_options(options, curr_gen, TOTAL_GENS) > 0 && get_number_of_lower_ordered_options(options, curr_gen, TOTAL_GENS) > 0)
|
||||
PRINT_FUNCTION("Target: <\x01>", target_strings[curr_gen-1]);
|
||||
PRINT_FUNCTION("<\x01>", target_strings[curr_gen-1]);
|
||||
else if(get_number_of_higher_ordered_options(options, curr_gen, TOTAL_GENS) > 0)
|
||||
PRINT_FUNCTION("Target: \x01>", target_strings[curr_gen-1]);
|
||||
PRINT_FUNCTION(" \x01>", target_strings[curr_gen-1]);
|
||||
else if(get_number_of_lower_ordered_options(options, curr_gen, TOTAL_GENS) > 0)
|
||||
PRINT_FUNCTION("Target: <\x01", target_strings[curr_gen-1]);
|
||||
PRINT_FUNCTION("<\x01", target_strings[curr_gen-1]);
|
||||
else
|
||||
PRINT_FUNCTION("Target: \x01", target_strings[curr_gen-1]);
|
||||
PRINT_FUNCTION(" \x01", target_strings[curr_gen-1]);
|
||||
set_text_y(3);
|
||||
set_text_x(MAIN_MENU_DISTANCE_FROM_BORDER);
|
||||
if(curr_gen < 3) {
|
||||
PRINT_FUNCTION("Target Region: ");
|
||||
if(!is_jp)
|
||||
PRINT_FUNCTION("Target Region: \x01>", region_strings[0]);
|
||||
PRINT_FUNCTION(" \x01>", region_strings[0]);
|
||||
else
|
||||
PRINT_FUNCTION("Target Region: <\x01", region_strings[1]);
|
||||
PRINT_FUNCTION("<\x01", region_strings[1]);
|
||||
}
|
||||
set_text_y(5);
|
||||
set_text_x(MAIN_MENU_DISTANCE_FROM_BORDER);
|
||||
PRINT_FUNCTION("Act as: ");
|
||||
if(!is_master)
|
||||
PRINT_FUNCTION("Act as: \x01>", actor_strings[1]);
|
||||
PRINT_FUNCTION(" \x01>", actor_strings[1]);
|
||||
else
|
||||
PRINT_FUNCTION("Act as: <\x01", actor_strings[0]);
|
||||
PRINT_FUNCTION("<\x01", actor_strings[0]);
|
||||
set_text_y(7);
|
||||
set_text_x(MAIN_MENU_DISTANCE_FROM_BORDER);
|
||||
PRINT_FUNCTION("Start Trade");
|
||||
|
|
@ -1256,6 +1307,20 @@ void print_main_menu(u8 update, u8 curr_gen, u8 is_jp, u8 is_master, struct game
|
|||
}
|
||||
}
|
||||
|
||||
void print_multiboot_settings(u8 is_normal, u8 update) {
|
||||
if(!update)
|
||||
return;
|
||||
|
||||
default_reset_screen();
|
||||
PRINT_FUNCTION("\nCable type: ");
|
||||
if(is_normal)
|
||||
PRINT_FUNCTION(" GBC> (Fast)");
|
||||
else
|
||||
PRINT_FUNCTION("<GBA (Slow)");
|
||||
set_text_y(Y_LIMIT-1);
|
||||
PRINT_FUNCTION("A: Start - B: Go Back");
|
||||
}
|
||||
|
||||
void print_multiboot_mid_process(u8 initial_handshake) {
|
||||
default_reset_screen();
|
||||
PRINT_FUNCTION("\nInitiating handshake!\n");
|
||||
|
|
|
|||
|
|
@ -6,45 +6,62 @@
|
|||
#include "timing_basic.h"
|
||||
#include "useful_qualifiers.h"
|
||||
|
||||
#define MAX_PALETTE_ATTEMPTS 128
|
||||
#define MULTIBOOT_WAIT_TIME_NS 36000
|
||||
#define MULTIBOOT_VCOUNTWAIT (((MULTIBOOT_WAIT_TIME_NS/NS_PER_SCANLINE) + ((MULTIBOOT_WAIT_TIME_NS%NS_PER_SCANLINE) == 0 ? 0 : 1))+1)
|
||||
|
||||
int multiboot_normal_send(int);
|
||||
void multiboot_send(int, int, u16*);
|
||||
|
||||
int multiboot_normal_send(int data) {
|
||||
#ifndef HAS_SIO
|
||||
void multiboot_send(int UNUSED(data), int UNUSED(is_normal), u16* UNUSED(out_buffer)) {
|
||||
#else
|
||||
void multiboot_send(int data, int is_normal, u16* out_buffer) {
|
||||
// Only this part of REG_SIODATA32 is used during setup.
|
||||
// The rest is handled by SWI $25
|
||||
return timed_sio_normal_master(data, SIO_32, MULTIBOOT_VCOUNTWAIT) >> 0x10;
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
||||
out_buffer[i] = 0;
|
||||
if(is_normal)
|
||||
out_buffer[0] = timed_sio_normal_master(data, SIO_32, MULTIBOOT_VCOUNTWAIT) >> 0x10;
|
||||
else
|
||||
timed_sio_multi_master(data, MULTIBOOT_VCOUNTWAIT, out_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_SIO
|
||||
enum MULTIBOOT_RESULTS multiboot_normal (u16* data, u16* end) {
|
||||
#ifndef HAS_SIO
|
||||
enum MULTIBOOT_RESULTS multiboot_normal (u16* UNUSED(data), u16* UNUSED(end), int UNUSED(is_normal)) {
|
||||
#else
|
||||
enum MULTIBOOT_RESULTS multiboot_normal (u16* UNUSED(data), u16* UNUSED(end)) {
|
||||
#endif
|
||||
#ifdef HAS_SIO
|
||||
int response;
|
||||
enum MULTIBOOT_RESULTS multiboot_normal (u16* data, u16* end, int is_normal) {
|
||||
u16 response[MAX_NUM_SLAVES];
|
||||
u8 clientMask = 0;
|
||||
u8 client_bit;
|
||||
int attempts, sends, halves;
|
||||
u8 answer, handshake;
|
||||
u8 answers[MAX_NUM_SLAVES] = {0xFF, 0xFF, 0xFF};
|
||||
u8 handshake;
|
||||
u8 sendMask;
|
||||
u8 attempt_counter;
|
||||
const u8 palette = 0x81;
|
||||
const int paletteCmd = 0x6300 | palette;
|
||||
enum MULTIBOOT_MODES mb_mode = MODE32_NORMAL;
|
||||
MultiBootParam mp;
|
||||
|
||||
if(!is_normal)
|
||||
mb_mode = MODE16_MULTI;
|
||||
|
||||
init_sio_normal(SIO_MASTER, SIO_32);
|
||||
if(is_normal)
|
||||
init_sio_normal(SIO_MASTER, SIO_32);
|
||||
else
|
||||
init_sio_multi(SIO_MASTER);
|
||||
|
||||
print_multiboot_mid_process(0);
|
||||
prepare_flush();
|
||||
|
||||
for(attempts = 0; attempts < 128; attempts++) {
|
||||
for(sends = 0; sends < 16; sends++) {
|
||||
response = multiboot_normal_send(0x6200);
|
||||
multiboot_send(0x6200, is_normal, response);
|
||||
|
||||
if((response & 0xfff0) == 0x7200) {
|
||||
clientMask = (response & 0xf);
|
||||
if(clientMask)
|
||||
break;
|
||||
}
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
||||
if((response[i] & 0xFFF0) == 0x7200) {
|
||||
clientMask |= response[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(clientMask)
|
||||
|
|
@ -58,46 +75,85 @@ enum MULTIBOOT_RESULTS multiboot_normal (u16* UNUSED(data), u16* UNUSED(end)) {
|
|||
}
|
||||
|
||||
clientMask &= 0xF;
|
||||
response = multiboot_normal_send(0x6100 | clientMask);
|
||||
if(response != (0x7200 | clientMask))
|
||||
return MB_WRONG_ANSWER;
|
||||
multiboot_send(0x6100 | clientMask, is_normal, response);
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
||||
client_bit = 1 << (i + 1);
|
||||
|
||||
for(halves = 0; halves < 0x60; ++halves)
|
||||
if(multiboot_normal_send(*data++) != ((0x60 - halves) << 8 | clientMask))
|
||||
return MB_HEADER_ISSUE;
|
||||
if ((clientMask & client_bit) && (response[i] != (0x7200 | client_bit)))
|
||||
return MB_WRONG_ANSWER;
|
||||
}
|
||||
|
||||
response = multiboot_normal_send(0x6200);
|
||||
if(response != (clientMask))
|
||||
return MB_WRONG_ANSWER;
|
||||
for(halves = 0; halves < 0x60; ++halves) {
|
||||
multiboot_send(*data++, is_normal, response);
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
||||
client_bit = 1 << (i + 1);
|
||||
|
||||
response = multiboot_normal_send(0x6200 | clientMask);
|
||||
if(response != (0x7200 | clientMask))
|
||||
return MB_WRONG_ANSWER;
|
||||
if ((clientMask & client_bit) && (response[i] != (((0x60 - halves) << 8) | client_bit)))
|
||||
return MB_HEADER_ISSUE;
|
||||
}
|
||||
}
|
||||
|
||||
while((response & 0xFF00) != 0x7300)
|
||||
response = multiboot_normal_send(paletteCmd);
|
||||
multiboot_send(0x6200, is_normal, response);
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
||||
client_bit = 1 << (i + 1);
|
||||
|
||||
answer = response&0xFF;
|
||||
handshake = 0x11 + 0xFF + 0xFF + answer;
|
||||
if ((clientMask & client_bit) && (response[i] != client_bit))
|
||||
return MB_WRONG_ANSWER;
|
||||
}
|
||||
|
||||
response = multiboot_normal_send(0x6400 | handshake);
|
||||
if((response & 0xFF00) != 0x7300)
|
||||
return MB_WRONG_ANSWER;
|
||||
multiboot_send(0x6200 | clientMask, is_normal, response);
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
||||
client_bit = 1 << (i + 1);
|
||||
|
||||
if ((clientMask & client_bit) && (response[i] != (0x7200 | client_bit)))
|
||||
return MB_WRONG_ANSWER;
|
||||
}
|
||||
|
||||
sendMask = clientMask;
|
||||
attempt_counter = 0;
|
||||
|
||||
while(sendMask) {
|
||||
multiboot_send(0x6300 | palette, is_normal, response);
|
||||
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
||||
client_bit = 1 << (i + 1);
|
||||
|
||||
if ((clientMask & client_bit) && ((response[i] & 0xFF00) == 0x7300)) {
|
||||
answers[i] = response[i] & 0xFF;
|
||||
sendMask &= ~client_bit;
|
||||
}
|
||||
}
|
||||
attempt_counter++;
|
||||
|
||||
if((attempt_counter == MAX_PALETTE_ATTEMPTS) && sendMask)
|
||||
return MB_PALETTE_FAILURE;
|
||||
}
|
||||
|
||||
handshake = 0x11;
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
||||
handshake += answers[i];
|
||||
|
||||
multiboot_send(0x6400 | handshake, is_normal, response);
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
||||
client_bit = 1 << (i + 1);
|
||||
|
||||
if ((clientMask & client_bit) && ((response[i] & 0xFF00) != 0x7300))
|
||||
return MB_WRONG_ANSWER;
|
||||
}
|
||||
|
||||
print_multiboot_mid_process(1);
|
||||
prepare_flush();
|
||||
VBlankIntrWait();
|
||||
|
||||
mp.handshake_data = handshake;
|
||||
mp.client_data[0] = answer;
|
||||
mp.client_data[1] = 0xFF;
|
||||
mp.client_data[2] = 0xFF;
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
||||
mp.client_data[i] = answers[i];
|
||||
mp.palette_data = palette;
|
||||
mp.client_bit = clientMask;
|
||||
mp.boot_srcp = (u8*)data;
|
||||
mp.boot_endp = (u8*)end;
|
||||
|
||||
if(MultiBoot(&mp, MODE32_NORMAL))
|
||||
if(MultiBoot(&mp, mb_mode))
|
||||
return MB_SWI_FAILURE;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -926,13 +926,14 @@ void recalc_stats_gen3(struct gen3_mon_data_unenc* data_dst, struct gen3_mon* ds
|
|||
u8 is_pokerus_strain_valid_gen3(u8 pokerus_byte) {
|
||||
if(!pokerus_byte)
|
||||
return 1;
|
||||
if(!((pokerus_byte >> 4) & 7))
|
||||
return 0;
|
||||
// Ruby and Sapphire can have Pokerus strains 0 and 8
|
||||
//if(!((pokerus_byte >> 4) & 7))
|
||||
// return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
u8 get_pokerus_strain_max_days_gen3(u8 pokerus_byte) {
|
||||
if(!((pokerus_byte >> 4) & 7))
|
||||
if(!is_pokerus_strain_valid_gen3(pokerus_byte))
|
||||
return 0;
|
||||
return ((pokerus_byte >> 4) & 3) + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@
|
|||
#define COLO_MOD_PART 0x12D96
|
||||
#define COLO_DIV_PART 0x2732
|
||||
|
||||
#define CHANNEL_SEED_SPACE_SIZE (1 << (32 - 4))
|
||||
#define CHANNEL_SEED_MASK (CHANNEL_SEED_SPACE_SIZE - 1)
|
||||
|
||||
#define STATIC_IV_MASK (((0xF<<10) | (0xF<<5))<<(16+1))
|
||||
|
||||
#define NUM_SEEDS 0x10000
|
||||
|
|
@ -70,6 +73,11 @@ void _generate_egg_info(u8, u16, u16, u8, u8, u32*, u32*, u32);
|
|||
void _generate_egg_shiny_info(u8, u16, u8, u8, u32*, u32*, u32);
|
||||
void _convert_roamer_to_colo_info(u8, u16, u8, u8, u16, u32*, u32*, u8*, u32);
|
||||
void _generate_generic_genderless_info(u8, u16, u16, u32*, u32*, u8*, u32, genderless_generator_functions_t);
|
||||
static u8 validate_channel_pattern_seed(u32);
|
||||
static u8 validate_channel_seed(u32);
|
||||
void _generate_channel_info(u8, u16, u32*, u32*, u32, u16*, u8*, u8*);
|
||||
static u8 is_shiny_channel_valid_seed(u32, u16, u16, u8, u32*, u32*, u16*, u8*, u8*);
|
||||
void _generate_channel_shiny_info(u8, u32*, u32*, u32, u16*, u8*, u8*);
|
||||
u8 _generator_static_info(u16, u16, u8, u16, u32*, u32*, u8*);
|
||||
u8 _generator_generic_shadow_info_colo(u16, u16, u8, u16, u32*, u32*, u8*);
|
||||
u8 _generator_generic_shadow_info_xd(u16, u16, u8, u16, u32*, u32*, u8*);
|
||||
|
|
@ -299,6 +307,11 @@ u8 are_colo_valid_tid_sid(u16 tid, u16 sid) {
|
|||
return (get_seed_colo(possible_seeds, tid, sid) > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
u8 are_rs_valid_tid_sid(u16 tid, u16 sid) {
|
||||
u32 possible_seeds[3];
|
||||
return (get_seed_gba3(possible_seeds, sid, tid) > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
u32 generate_ot(u16 tid, u8* name) {
|
||||
// Worst case: ANY
|
||||
// This should NOT be random...
|
||||
|
|
@ -321,7 +334,7 @@ u32 generate_ot(u16 tid, u8* name) {
|
|||
seed = get_next_seed(seed);
|
||||
sid = seed >> 0x10;
|
||||
}
|
||||
while(is_bad_tsv(sid^tid) && (!are_colo_valid_tid_sid(tid, sid)));
|
||||
while(is_bad_tsv(sid^tid) && (!are_colo_valid_tid_sid(tid, sid)) && (!are_rs_valid_tid_sid(tid, sid)));
|
||||
|
||||
return (sid << 0x10) | tid;
|
||||
}
|
||||
|
|
@ -609,6 +622,213 @@ void _generate_generic_genderless_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv
|
|||
*dst_ivs = 0;
|
||||
}
|
||||
|
||||
// Adapted from: https://github.com/Admiral-Fish/PokeFinder/blob/master/Source/Core/Gen3/Searchers/GameCubeSearcher.cpp
|
||||
ALWAYS_INLINE u8 validate_channel_pattern_seed(u32 base_pattern_seed) {
|
||||
u8 target = base_pattern_seed >> 30;
|
||||
|
||||
if(target == 0)
|
||||
return 0;
|
||||
|
||||
u8 mask = 1 << target;
|
||||
while ((mask & 14) != 14) {
|
||||
base_pattern_seed = get_prev_seed_colo(base_pattern_seed);
|
||||
u8 num = base_pattern_seed >> 30;
|
||||
if (num == target)
|
||||
return 0;
|
||||
|
||||
mask |= 1 << num;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Adapted from: https://github.com/Admiral-Fish/PokeFinder/blob/master/Source/Core/Gen3/Searchers/GameCubeSearcher.cpp
|
||||
ALWAYS_INLINE u8 validate_channel_seed(u32 origin_seed) {
|
||||
u32 first_seed = get_prev_seed_colo(origin_seed);
|
||||
u32 second_seed = get_prev_seed_colo(first_seed);
|
||||
u32 third_seed = get_prev_seed_colo(second_seed);
|
||||
u16 num1 = first_seed >> 16;
|
||||
u16 num2 = second_seed >> 16;
|
||||
u16 num3 = third_seed >> 16;
|
||||
u32 six_seed = get_prev_seed_colo(get_prev_seed_colo(get_prev_seed_colo(third_seed)));
|
||||
u32 seven_seed = get_prev_seed_colo(six_seed);
|
||||
|
||||
// 8 advances
|
||||
if((num3 > 0x4000) && (num2 > 0x547a) && validate_channel_pattern_seed(get_prev_seed_colo(seven_seed)))
|
||||
return 1;
|
||||
|
||||
// 7 advances
|
||||
if((num2 > 0x4000) && (num1 <= 0x547a) && validate_channel_pattern_seed(seven_seed))
|
||||
return 1;
|
||||
|
||||
// 6 advances
|
||||
if((num1 <= 0x4000) && validate_channel_pattern_seed(six_seed))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWRAM_CODE MAX_OPTIMIZE void _generate_channel_info(u8 wanted_nature, u16 wanted_ivs, u32* dst_pid, u32* dst_ivs, u32 start_seed, u16* dst_sid, u8* dst_gender, u8* dst_game) {
|
||||
// Very slow code to convert to a Channel mon (not actually used)
|
||||
u8 base_atk_ivs = ((wanted_ivs>>4) & 0xF)<<1;
|
||||
u8 base_def_ivs = ((wanted_ivs) & 0xF)<<1;
|
||||
u8 base_spe_ivs = ((wanted_ivs>>12) & 0xF)<<1;
|
||||
u8 base_spa_ivs = ((wanted_ivs>>8) & 0xF)<<1;
|
||||
|
||||
u32 rng_base_seed = start_seed & CHANNEL_SEED_MASK;
|
||||
int increase = 1;
|
||||
if(start_seed & CHANNEL_SEED_SPACE_SIZE)
|
||||
increase = -1;
|
||||
|
||||
// Iter the free bits for attack
|
||||
for(size_t i = 0; i < CHANNEL_SEED_SPACE_SIZE; i++) {
|
||||
u32 atk_seed = (base_atk_ivs << 28) | rng_base_seed;
|
||||
rng_base_seed = (rng_base_seed + increase) & CHANNEL_SEED_MASK;
|
||||
u8 atk_iv = atk_seed >> 27;
|
||||
u32 curr_seed = get_next_seed_colo(atk_seed);
|
||||
u8 def_iv = curr_seed >> 27;
|
||||
if((def_iv & (0xF << 1)) != base_def_ivs)
|
||||
continue;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 spe_iv = curr_seed >> 27;
|
||||
if((spe_iv & (0xF << 1)) != base_spe_ivs)
|
||||
continue;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 spa_iv = curr_seed >> 27;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 spd_iv = curr_seed >> 27;
|
||||
if((((spa_iv + spd_iv) >> 1) & (0xF << 1)) != base_spa_ivs)
|
||||
continue;
|
||||
curr_seed = get_prev_seed_colo(atk_seed);
|
||||
u8 hp_iv = curr_seed >> 27;
|
||||
curr_seed = get_prev_seed_colo(curr_seed);
|
||||
u8 gender = curr_seed >> 31;
|
||||
curr_seed = get_prev_seed_colo(curr_seed);
|
||||
u8 game = curr_seed >> 31;
|
||||
curr_seed = get_prev_seed_colo(curr_seed);
|
||||
//u8 berry = curr_seed >> 31;
|
||||
curr_seed = get_prev_seed_colo(curr_seed);
|
||||
u16 low = curr_seed >> 16;
|
||||
curr_seed = get_prev_seed_colo(curr_seed);
|
||||
u16 high = curr_seed >> 16;
|
||||
curr_seed = get_prev_seed_colo(curr_seed);
|
||||
u16 sid = curr_seed >> 16;
|
||||
const u16 tid = 40122;
|
||||
if(tid ^ sid ^ high ^ (low < 8))
|
||||
high ^= 0x8000;
|
||||
u32 pid = (high << 16) | low;
|
||||
if((tid ^ sid ^ high ^ low) < 8)
|
||||
continue;
|
||||
u8 nature = get_nature_fast(pid);
|
||||
if(nature != wanted_nature)
|
||||
continue;
|
||||
if(validate_channel_seed(get_prev_seed_colo(curr_seed))) {
|
||||
*dst_pid = pid;
|
||||
*dst_sid = sid;
|
||||
*dst_gender = gender;
|
||||
*dst_game = game;
|
||||
*dst_ivs = (hp_iv << 0) | (atk_iv << 5) | (def_iv << 10) | (spe_iv << 15) | (spa_iv << 20) | (spd_iv << 25);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*dst_pid = 0;
|
||||
*dst_sid = 0;
|
||||
*dst_gender = 0;
|
||||
*dst_game = 0;
|
||||
*dst_ivs = 0;
|
||||
}
|
||||
|
||||
void generate_channel_info(u8 wanted_nature, u16 wanted_ivs, u32* dst_pid, u32* dst_ivs, u16* dst_sid, u8* dst_gender, u8* dst_game) {
|
||||
_generate_channel_info(wanted_nature, wanted_ivs, dst_pid, dst_ivs, get_rng(), dst_sid, dst_gender, dst_game);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u8 is_shiny_channel_valid_seed(u32 sid_seed, u16 high, u16 low, u8 is_forward, u32* dst_pid, u32* dst_ivs, u16* dst_sid, u8* dst_gender, u8* dst_game) {
|
||||
const u16 tid = 40122;
|
||||
u16 sid = sid_seed >> 16;
|
||||
u32 pid = (high << 16) | low;
|
||||
if(is_forward && (tid ^ sid ^ high ^ (low < 8)))
|
||||
return 0;
|
||||
if((!is_forward) && (!(tid ^ sid ^ (high ^ 0x8000) ^ (low < 8))))
|
||||
return 0;
|
||||
if((tid ^ sid ^ high ^ low) >= 8)
|
||||
return 0;
|
||||
if(validate_channel_seed(get_prev_seed_colo(sid_seed))) {
|
||||
*dst_pid = pid;
|
||||
*dst_sid = sid;
|
||||
u32 curr_seed = get_next_seed_colo(get_next_seed_colo(get_next_seed_colo(sid_seed)));
|
||||
//u8 berry = curr_seed >> 31;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 game = curr_seed >> 31;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 gender = curr_seed >> 31;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 hp_iv = curr_seed >> 27;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 atk_iv = curr_seed >> 27;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 def_iv = curr_seed >> 27;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 spe_iv = curr_seed >> 27;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 spa_iv = curr_seed >> 27;
|
||||
curr_seed = get_next_seed_colo(curr_seed);
|
||||
u8 spd_iv = curr_seed >> 27;
|
||||
*dst_gender = gender;
|
||||
*dst_game = game;
|
||||
*dst_ivs = (hp_iv << 0) | (atk_iv << 5) | (def_iv << 10) | (spe_iv << 15) | (spa_iv << 20) | (spd_iv << 25);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWRAM_CODE MAX_OPTIMIZE void _generate_channel_shiny_info(u8 wanted_nature, u32* dst_pid, u32* dst_ivs, u32 start_seed, u16* dst_sid, u8* dst_gender, u8* dst_game) {
|
||||
// Code to convert to a shiny Channel mon (not actually used)
|
||||
u32 pid = start_seed;
|
||||
u8 nature = get_nature_fast(pid);
|
||||
u8 nature_diff = wanted_nature - nature;
|
||||
if(nature > wanted_nature)
|
||||
nature_diff = wanted_nature - nature + NUM_NATURES;
|
||||
pid += nature_diff;
|
||||
if(pid < NUM_NATURES)
|
||||
pid = wanted_nature;
|
||||
u32 start_pid = pid;
|
||||
|
||||
do {
|
||||
u16 high = pid >> 16;
|
||||
u16 low = pid & 0xFFFF;
|
||||
u32 possible_seeds[4];
|
||||
u8 num_found = 0;
|
||||
|
||||
num_found = get_seed_colo(possible_seeds, high, low);
|
||||
|
||||
for(size_t i = 0; i < num_found; i++)
|
||||
if(is_shiny_channel_valid_seed(possible_seeds[i], high, low, 1, dst_pid, dst_ivs, dst_sid, dst_gender, dst_game))
|
||||
return;
|
||||
|
||||
num_found = get_seed_colo(possible_seeds, high ^ 0x8000, low);
|
||||
|
||||
for(size_t i = 0; i < num_found; i++)
|
||||
if(is_shiny_channel_valid_seed(possible_seeds[i], high, low, 0, dst_pid, dst_ivs, dst_sid, dst_gender, dst_game))
|
||||
return;
|
||||
|
||||
pid += NUM_NATURES;
|
||||
if(pid < NUM_NATURES)
|
||||
pid = wanted_nature;
|
||||
} while(pid != start_pid);
|
||||
|
||||
*dst_pid = 0;
|
||||
*dst_sid = 0;
|
||||
*dst_gender = 0;
|
||||
*dst_game = 0;
|
||||
*dst_ivs = 0;
|
||||
}
|
||||
|
||||
void generate_channel_shiny_info(u8 wanted_nature, u32* dst_pid, u32* dst_ivs, u16* dst_sid, u8* dst_gender, u8* dst_game) {
|
||||
_generate_channel_shiny_info(wanted_nature, dst_pid, dst_ivs, get_rng(), dst_sid, dst_gender, dst_game);
|
||||
}
|
||||
|
||||
u8 _generator_static_info(u16 first, u16 second, u8 wanted_nature, u16 tsv, u32* dst_pid, u32* dst_ivs, u8* UNUSED(dst_ability)) {
|
||||
u32 possible_seeds[3*2*2];
|
||||
u8 num_found = get_reverse_masked_ivs_gba3(possible_seeds, second, first);
|
||||
|
|
@ -1112,7 +1332,8 @@ void worst_case_conversion_tester(vu32* counter) {
|
|||
u32 curr_counter = *counter;
|
||||
u32 max_counter = 0;
|
||||
u32 pid, ivs;
|
||||
u8 ability;
|
||||
u16 sid;
|
||||
u8 ability, game, gender;
|
||||
|
||||
VBlankIntrWait();
|
||||
curr_counter = *counter;
|
||||
|
|
@ -1204,5 +1425,23 @@ void worst_case_conversion_tester(vu32* counter) {
|
|||
max_counter = ((*counter)-curr_counter);
|
||||
|
||||
PRINT_FUNCTION("Max time conv s: 0x\x04\n", max_counter);
|
||||
|
||||
VBlankIntrWait();
|
||||
curr_counter = *counter;
|
||||
|
||||
_generate_channel_info(4, 0xFFFF, &pid, &ivs, 0, &sid, &gender, &game);
|
||||
|
||||
max_counter = ((*counter)-curr_counter);
|
||||
|
||||
PRINT_FUNCTION("Random time c p: 0x\x04\n", max_counter);
|
||||
|
||||
VBlankIntrWait();
|
||||
curr_counter = *counter;
|
||||
|
||||
_generate_channel_shiny_info(4, &pid, &ivs, 0, &sid, &gender, &game);
|
||||
|
||||
max_counter = ((*counter)-curr_counter);
|
||||
|
||||
PRINT_FUNCTION("Random time c s: 0x\x04\n", max_counter);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,13 @@ void init_text_system() {
|
|||
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
|
||||
REG_DISPCNT_SUB = 0 | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
|
||||
#endif
|
||||
|
||||
#ifdef __NDS__
|
||||
vramSetBankA(VRAM_A_MAIN_BG);
|
||||
vramSetBankB(VRAM_B_MAIN_SPRITE);
|
||||
vramSetBankC(VRAM_C_SUB_BG);
|
||||
vramSetBankD(VRAM_D_SUB_SPRITE);
|
||||
#endif
|
||||
screens_flush = 0;
|
||||
for(int i = 0; i < TOTAL_BG; i++) {
|
||||
enabled_screen[i] = 0;
|
||||
|
|
|
|||
174
source/save.c
174
source/save.c
|
|
@ -3,6 +3,7 @@
|
|||
#include <stddef.h>
|
||||
#include "useful_qualifiers.h"
|
||||
#include "timing_basic.h"
|
||||
#include "delays.h"
|
||||
|
||||
#define IS_FLASH 1
|
||||
#define SAVE_POS SRAM
|
||||
|
|
@ -14,8 +15,9 @@
|
|||
#define FLASH_TERM_CMD *((vu8*)(SAVE_POS+0x5555)) = 0xF0;
|
||||
#define FLASH_ENTER_MAN_CMD BASE_FLASH_CMD *((vu8*)(SAVE_POS+0x5555)) = 0x90;
|
||||
#define FLASH_EXIT_MAN_CMD BASE_FLASH_CMD FLASH_TERM_CMD FLASH_TERM_CMD
|
||||
#define TIMEOUT (50000*(((CLOCK_SPEED + GBA_CLOCK_SPEED - 1)/GBA_CLOCK_SPEED) + TIMEOUT_INCREASE))
|
||||
#define ERASE_TIMEOUT (TIMEOUT)
|
||||
#define ID_TIMEOUT_CYCLES CLOCK_CYCLES_PER_MS(28)
|
||||
#define TIMEOUT_CYCLES CLOCK_CYCLES_PER_MS(10)
|
||||
#define ERASE_TIMEOUT_CYCLES CLOCK_CYCLES_PER_MS(2000)
|
||||
#define ERASED_BYTE 0xFF
|
||||
#define BANK_SIZE 0x10000
|
||||
#define NUM_BANKS 2
|
||||
|
|
@ -31,30 +33,31 @@
|
|||
#define BANK_LIMIT (NUM_BANKS * BANK_SIZE)
|
||||
#endif
|
||||
|
||||
uintptr_t bank_check(uintptr_t);
|
||||
static uintptr_t bank_check(uintptr_t);
|
||||
static size_t sanitize_save_size(uintptr_t, size_t);
|
||||
static u8 read_direct_single_byte_save(uintptr_t);
|
||||
static void write_direct_single_byte_save(uintptr_t, u8);
|
||||
|
||||
u8 current_bank;
|
||||
u8 is_macronix;
|
||||
|
||||
IWRAM_CODE void init_bank(){
|
||||
IWRAM_CODE void init_bank() {
|
||||
REG_WAITCNT &= NON_SRAM_MASK;
|
||||
REG_WAITCNT |= SRAM_READING_VALID_WAITCYCLES;
|
||||
current_bank = NUM_BANKS;
|
||||
is_macronix = 0;
|
||||
#if IS_FLASH
|
||||
FLASH_ENTER_MAN_CMD
|
||||
for(vu32 j = 0; j < TIMEOUT; j++);
|
||||
delay_cycles(ID_TIMEOUT_CYCLES);
|
||||
u8 man_id = *((vu8*)SAVE_POS);
|
||||
if((man_id == MACRONIX_MAN_ID) || (man_id == SANYO_MAN_ID) || (man_id == DEFAULT_MAN_ID))
|
||||
is_macronix = 1;
|
||||
FLASH_EXIT_MAN_CMD
|
||||
for(vu32 j = 0; j < TIMEOUT; j++);
|
||||
delay_cycles(ID_TIMEOUT_CYCLES);
|
||||
#endif
|
||||
}
|
||||
|
||||
IWRAM_CODE uintptr_t bank_check(uintptr_t address){
|
||||
IWRAM_CODE uintptr_t bank_check(uintptr_t address) {
|
||||
address %= (NUM_BANKS * BANK_SIZE);
|
||||
#if IS_FLASH
|
||||
u8 bank = address / BANK_SIZE;
|
||||
|
|
@ -84,7 +87,7 @@ IWRAM_CODE void erase_sector(uintptr_t address) {
|
|||
save_data[address+(SECTOR_SIZE-1)-j] = ERASED_BYTE;
|
||||
#endif
|
||||
|
||||
for(vu32 j = 0; j < ERASE_TIMEOUT; j++);
|
||||
delay_cycles_until(ERASE_TIMEOUT_CYCLES, &save_data[address], 0xFF, SRAM_ACCESS_CYCLES);
|
||||
|
||||
failed = 0;
|
||||
for(size_t j = 0; j < SECTOR_SIZE; j++)
|
||||
|
|
@ -108,109 +111,116 @@ IWRAM_CODE void write_direct_single_byte_save(uintptr_t address, u8 data) {
|
|||
FLASH_WRITE_CMD
|
||||
#endif
|
||||
save_data[address] = data;
|
||||
for(vu32 j = 0; (j < TIMEOUT) && (save_data[address] != data); j++);
|
||||
delay_cycles_until(TIMEOUT_CYCLES, &save_data[address], data, SRAM_ACCESS_CYCLES);
|
||||
if(is_macronix && (save_data[address] != data))
|
||||
FLASH_TERM_CMD
|
||||
}
|
||||
}
|
||||
|
||||
IWRAM_CODE u8 read_byte_save(uintptr_t address){
|
||||
IWRAM_CODE u8 read_byte_save(uintptr_t address) {
|
||||
address = bank_check(address);
|
||||
return read_direct_single_byte_save(address);
|
||||
}
|
||||
|
||||
IWRAM_CODE void write_byte_save(uintptr_t address, u8 data){
|
||||
IWRAM_CODE u16 read_short_save(uintptr_t address) {
|
||||
u16 data_out = 0;
|
||||
copy_save_to_ram(address, (u8*)&data_out, sizeof(u16));
|
||||
return data_out;
|
||||
}
|
||||
|
||||
IWRAM_CODE u32 read_int_save(uintptr_t address) {
|
||||
u32 data_out = 0;
|
||||
copy_save_to_ram(address, (u8*)&data_out, sizeof(u32));
|
||||
return data_out;
|
||||
}
|
||||
|
||||
IWRAM_CODE void write_byte_save(uintptr_t address, u8 data) {
|
||||
address = bank_check(address);
|
||||
write_direct_single_byte_save(address, data);
|
||||
}
|
||||
|
||||
IWRAM_CODE u32 read_int_save(uintptr_t address){
|
||||
IWRAM_CODE void write_short_save(uintptr_t address, u16 data) {
|
||||
u16 data_in = data;
|
||||
copy_ram_to_save((u8*)&data_in, address, sizeof(u16));
|
||||
}
|
||||
|
||||
IWRAM_CODE void write_int_save(uintptr_t address, u32 data) {
|
||||
u32 data_in = data;
|
||||
copy_ram_to_save((u8*)&data_in, address, sizeof(u32));
|
||||
}
|
||||
|
||||
IWRAM_CODE size_t sanitize_save_size(uintptr_t address, size_t size) {
|
||||
address %= NUM_BANKS * BANK_SIZE;
|
||||
if((address + size) > (NUM_BANKS * BANK_SIZE))
|
||||
size = (NUM_BANKS * BANK_SIZE) - address;
|
||||
return size;
|
||||
}
|
||||
|
||||
IWRAM_CODE void copy_save_to_ram(uintptr_t address, u8* destination, size_t size) {
|
||||
// Sanitize size
|
||||
size = sanitize_save_size(address, size);
|
||||
|
||||
address = bank_check(address);
|
||||
u32 data_out = 0;
|
||||
if((address + sizeof(u32)) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < sizeof(u32); i++)
|
||||
data_out += read_byte_save(address + i) << (i*8);
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < sizeof(u32); i++)
|
||||
data_out += read_direct_single_byte_save(address + i) << (i*8);
|
||||
}
|
||||
return data_out;
|
||||
}
|
||||
size_t num_banks = (address + size + BANK_SIZE - 1) / BANK_SIZE;
|
||||
for(size_t n = 0; n < num_banks; n++) {
|
||||
size_t inner_size = size;
|
||||
if(n != (num_banks - 1))
|
||||
inner_size = BANK_SIZE - address;
|
||||
|
||||
IWRAM_CODE u16 read_short_save(uintptr_t address){
|
||||
address = bank_check(address);
|
||||
u16 data_out = 0;
|
||||
if((address + sizeof(u16)) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < sizeof(u16); i++)
|
||||
data_out += read_byte_save(address + i) << (i*8);
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < sizeof(u16); i++)
|
||||
data_out += read_direct_single_byte_save(address + i) << (i*8);
|
||||
}
|
||||
return data_out;
|
||||
}
|
||||
for(size_t i = 0; i < inner_size; i++)
|
||||
destination[i] = read_direct_single_byte_save(address + i);
|
||||
|
||||
IWRAM_CODE void write_int_save(uintptr_t address, u32 data){
|
||||
address = bank_check(address);
|
||||
if((address + sizeof(u32)) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < sizeof(u32); i++)
|
||||
write_byte_save(address + i, (data >> (i*8)) & 0xFF);
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < sizeof(u32); i++)
|
||||
write_direct_single_byte_save(address + i, (data >> (i*8)) & 0xFF);
|
||||
if(n != (num_banks - 1)) {
|
||||
address = bank_check(address + inner_size);
|
||||
destination += inner_size;
|
||||
size -= inner_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IWRAM_CODE void write_short_save(uintptr_t address, u16 data){
|
||||
address = bank_check(address);
|
||||
if((address + sizeof(u16)) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < sizeof(u16); i++)
|
||||
write_byte_save(address + i, (data >> (i*8)) & 0xFF);
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < sizeof(u16); i++)
|
||||
write_direct_single_byte_save(address + i, (data >> (i*8)) & 0xFF);
|
||||
}
|
||||
}
|
||||
IWRAM_CODE void copy_ram_to_save(u8* base_address, uintptr_t save_address, size_t size) {
|
||||
// Sanitize size
|
||||
size = sanitize_save_size(save_address, size);
|
||||
|
||||
IWRAM_CODE void copy_save_to_ram(uintptr_t base_address, u8* new_address, size_t size){
|
||||
base_address = bank_check(base_address);
|
||||
if((base_address + size) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < size; i++)
|
||||
new_address[i] = read_byte_save(base_address + i);
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < size; i++)
|
||||
new_address[i] = read_direct_single_byte_save(base_address + i);
|
||||
}
|
||||
}
|
||||
|
||||
IWRAM_CODE void copy_ram_to_save(u8* base_address, uintptr_t save_address, size_t size){
|
||||
save_address = bank_check(save_address);
|
||||
if((save_address + size) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < size; i++)
|
||||
write_byte_save(save_address + i, base_address[i]);
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < size; i++)
|
||||
size_t num_banks = (save_address + size + BANK_SIZE - 1) / BANK_SIZE;
|
||||
for(size_t n = 0; n < num_banks; n++) {
|
||||
size_t inner_size = size;
|
||||
if(n != (num_banks - 1))
|
||||
inner_size = BANK_SIZE - save_address;
|
||||
|
||||
for(size_t i = 0; i < inner_size; i++)
|
||||
write_direct_single_byte_save(save_address + i, base_address[i]);
|
||||
|
||||
if(n != (num_banks - 1)) {
|
||||
save_address = bank_check(save_address + inner_size);
|
||||
base_address += inner_size;
|
||||
size -= inner_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IWRAM_CODE u8 is_save_correct(u8* base_address, uintptr_t save_address, size_t size) {
|
||||
// Sanitize size
|
||||
size = sanitize_save_size(save_address, size);
|
||||
|
||||
save_address = bank_check(save_address);
|
||||
if((save_address + size) > BANK_LIMIT) {
|
||||
for(size_t i = 0; i < size; i++)
|
||||
if(read_byte_save(save_address + i) != base_address[i])
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
for(size_t i = 0; i < size; i++)
|
||||
size_t num_banks = (save_address + size + BANK_SIZE - 1) / BANK_SIZE;
|
||||
for(size_t n = 0; n < num_banks; n++) {
|
||||
size_t inner_size = size;
|
||||
if(n != (num_banks - 1))
|
||||
inner_size = BANK_SIZE - save_address;
|
||||
|
||||
for(size_t i = 0; i < inner_size; i++)
|
||||
if(read_direct_single_byte_save(save_address + i) != base_address[i])
|
||||
return 0;
|
||||
|
||||
if(n != (num_banks - 1)) {
|
||||
save_address = bank_check(save_address + inner_size);
|
||||
base_address += inner_size;
|
||||
size -= inner_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
91
source/sio.c
91
source/sio.c
|
|
@ -6,33 +6,46 @@
|
|||
|
||||
void sio_normal_inner_slave(void);
|
||||
u8 sio_normal_inner_master(void);
|
||||
void sio_write(u32);
|
||||
void timed_wait_master(int);
|
||||
|
||||
#ifdef HAS_SIO
|
||||
IWRAM_CODE int timed_sio_normal_master(int data, int is_32, int vCountWait) {
|
||||
IWRAM_CODE void timed_wait_master(int vCountWait) {
|
||||
u8 curr_vcount, target_vcount;
|
||||
|
||||
if(is_32)
|
||||
REG_SIODATA32 = data;
|
||||
else
|
||||
REG_SIODATA8 = (data & 0xFF);
|
||||
|
||||
|
||||
// - Wait at least 36 us between sends (this is a bit more, but it works)
|
||||
curr_vcount = REG_VCOUNT;
|
||||
target_vcount = curr_vcount + vCountWait;
|
||||
if(target_vcount >= SCANLINES)
|
||||
target_vcount -= SCANLINES;
|
||||
while (target_vcount != REG_VCOUNT);
|
||||
|
||||
|
||||
// - Set Start flag.
|
||||
REG_SIOCNT |= SIO_START;
|
||||
// - Wait for IRQ (or for Start bit to become zero).
|
||||
while (REG_SIOCNT & SIO_START);
|
||||
}
|
||||
|
||||
IWRAM_CODE int timed_sio_normal_master(int data, int is_32, int vCountWait) {
|
||||
sio_write(data);
|
||||
|
||||
timed_wait_master(vCountWait);
|
||||
|
||||
// - Process received data.
|
||||
if(is_32)
|
||||
return REG_SIODATA32;
|
||||
else
|
||||
return (REG_SIODATA8 & 0xFF);
|
||||
return sio_read(is_32);
|
||||
}
|
||||
|
||||
IWRAM_CODE void timed_sio_multi_master(int data, int vCountWait, u16* out_buff) {
|
||||
if(REG_SIOCNT & SIO_RDY)
|
||||
return;
|
||||
|
||||
REG_SIOMLT_SEND = (data & 0xFFFF);
|
||||
|
||||
timed_wait_master(vCountWait);
|
||||
|
||||
// - Process received data.
|
||||
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
||||
out_buff[i] = *((®_SIOMULTI1) + i);
|
||||
}
|
||||
|
||||
IWRAM_CODE void sio_normal_inner_slave() {
|
||||
|
|
@ -54,8 +67,7 @@ IWRAM_CODE void sio_normal_inner_slave() {
|
|||
IWRAM_CODE MAX_OPTIMIZE void sio_handle_irq_slave(int next_data) {
|
||||
REG_SIOCNT |= SIO_SO_HIGH;
|
||||
|
||||
REG_SIODATA32 = next_data;
|
||||
REG_SIODATA8 = next_data;
|
||||
sio_write(next_data);
|
||||
|
||||
REG_SIOCNT &= ~(SIO_START | SIO_SO_HIGH);
|
||||
// - Set Start=1 and SO=1 (SO=HIGH indicates not ready, applied after transfer).
|
||||
|
|
@ -67,12 +79,17 @@ IWRAM_CODE MAX_OPTIMIZE void sio_handle_irq_slave(int next_data) {
|
|||
}
|
||||
|
||||
IWRAM_CODE MAX_OPTIMIZE int sio_read(u8 is_32) {
|
||||
u32 data = REG_SIODATA8;
|
||||
u32 data = (REG_SIODATA8 & 0xFF);
|
||||
if(is_32)
|
||||
data = REG_SIODATA32;
|
||||
return data;
|
||||
}
|
||||
|
||||
IWRAM_CODE MAX_OPTIMIZE void sio_write(u32 data) {
|
||||
REG_SIODATA32 = data;
|
||||
REG_SIODATA8 = (data & 0xFF);
|
||||
}
|
||||
|
||||
IWRAM_CODE void sio_stop_irq_slave() {
|
||||
REG_SIOCNT &= ~SIO_SO_HIGH;
|
||||
REG_SIOCNT &= ~SIO_IRQ;
|
||||
|
|
@ -80,9 +97,8 @@ IWRAM_CODE void sio_stop_irq_slave() {
|
|||
|
||||
IWRAM_CODE void sio_normal_prepare_irq_slave(int data) {
|
||||
// - Initialize data which is to be sent to master.
|
||||
REG_SIODATA32 = data;
|
||||
REG_SIODATA8 = (data & 0xFF);
|
||||
|
||||
sio_write(data);
|
||||
|
||||
REG_SIOCNT |= SIO_IRQ;
|
||||
|
||||
// - Set Start=0 and SO=0 (SO=LOW indicates that slave is (almost) ready).
|
||||
|
|
@ -97,8 +113,8 @@ IWRAM_CODE void sio_normal_prepare_irq_slave(int data) {
|
|||
|
||||
IWRAM_CODE MAX_OPTIMIZE u32 sio_send_if_ready_master(u32 data, u8 is_32, u8* success) {
|
||||
// - Wait for SI to become LOW (slave ready). (Check timeout here!)
|
||||
REG_SIODATA32 = data;
|
||||
REG_SIODATA8 = (data & 0xFF);
|
||||
sio_write(data);
|
||||
|
||||
if (!(REG_SIOCNT & SIO_RDY)) {
|
||||
// - Set Start flag.
|
||||
REG_SIOCNT |= SIO_START;
|
||||
|
|
@ -113,8 +129,8 @@ IWRAM_CODE MAX_OPTIMIZE u32 sio_send_if_ready_master(u32 data, u8 is_32, u8* suc
|
|||
|
||||
IWRAM_CODE MAX_OPTIMIZE u32 sio_send_master(u32 data, u8 is_32) {
|
||||
// - Wait for SI to become LOW (slave ready). (Check timeout here!)
|
||||
REG_SIODATA32 = data;
|
||||
REG_SIODATA8 = (data & 0xFF);
|
||||
sio_write(data);
|
||||
|
||||
// - Set Start flag.
|
||||
REG_SIOCNT |= SIO_START;
|
||||
// - Wait for IRQ (or for Start bit to become zero).
|
||||
|
|
@ -141,7 +157,7 @@ IWRAM_CODE u8 sio_normal_inner_master() {
|
|||
|
||||
IWRAM_CODE void init_sio_normal(int is_master, int is_32) {
|
||||
u16 sio_cnt_val = 0;
|
||||
|
||||
|
||||
if(is_32)
|
||||
sio_cnt_val |= SIO_32BIT;
|
||||
else
|
||||
|
|
@ -151,28 +167,33 @@ IWRAM_CODE void init_sio_normal(int is_master, int is_32) {
|
|||
sio_cnt_val |= SIO_CLK_INT;
|
||||
else
|
||||
sio_cnt_val |= SIO_SO_HIGH;
|
||||
|
||||
|
||||
|
||||
REG_RCNT = R_NORMAL;
|
||||
REG_SIOCNT = sio_cnt_val;
|
||||
}
|
||||
|
||||
IWRAM_CODE void init_sio_multi(int is_master) {
|
||||
u16 sio_cnt_val = SIO_MULTI | SIO_57600;
|
||||
|
||||
if(is_master)
|
||||
sio_cnt_val |= SIO_CLK_INT;
|
||||
else
|
||||
sio_cnt_val |= SIO_SO_HIGH;
|
||||
|
||||
REG_RCNT = R_MULTI;
|
||||
REG_SIOCNT = sio_cnt_val;
|
||||
}
|
||||
|
||||
IWRAM_CODE int sio_normal(int data, int is_master, int is_32, u8* success) {
|
||||
// - Initialize data which is to be sent to master.
|
||||
if(is_32)
|
||||
REG_SIODATA32 = data;
|
||||
else
|
||||
REG_SIODATA8 = (data & 0xFF);
|
||||
|
||||
sio_write(data);
|
||||
|
||||
if(is_master)
|
||||
*success = sio_normal_inner_master();
|
||||
else
|
||||
sio_normal_inner_slave();
|
||||
|
||||
|
||||
// - Process received data.
|
||||
if(is_32)
|
||||
return REG_SIODATA32;
|
||||
else
|
||||
return (REG_SIODATA8 & 0xFF);
|
||||
return sio_read(is_32);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -144,12 +144,13 @@ void load_names_gen12(struct game_data_t* game_data, struct gen2_party* party_2,
|
|||
if(is_jp)
|
||||
language = JAPANESE_LANGUAGE;
|
||||
|
||||
convert_trainer_name_gen3_to_gen12(game_data->trainer_name, trainer_name, game_data->game_identifier.language, language);
|
||||
convert_trainer_name_gen3_to_gen12(game_data->trainer_name, trainer_name, game_data->game_identifier.language, language, 0);
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
if((trainer_name[i] == NO_ACTION_BYTE) || (trainer_name[i] == (NO_ACTION_BYTE-1)))
|
||||
trainer_name[i] = NO_ACTION_BYTE-2;
|
||||
trainer_name[size-1] = GEN2_EOL;
|
||||
u8 text_size = text_gen2_size(trainer_name, size-1);
|
||||
trainer_name[text_size] = GEN2_EOL;
|
||||
|
||||
if(!curr_gen)
|
||||
return;
|
||||
|
|
@ -174,9 +175,11 @@ void load_names_gen12(struct game_data_t* game_data, struct gen2_party* party_2,
|
|||
src_nickname = party_1->mons[i].nickname;
|
||||
}
|
||||
copy_bytes(src_ot_name, ot_names, size, 0, i*size);
|
||||
ot_names[(i*size)+size-1] = GEN2_EOL;
|
||||
text_size = text_gen2_size(&ot_names[i*size], size-1);
|
||||
ot_names[(i*size)+text_size] = GEN2_EOL;
|
||||
copy_bytes(src_nickname, nicknames, size, 0, i*size);
|
||||
nicknames[(i*size)+size-1] = GEN2_EOL;
|
||||
text_size = text_gen2_size(&nicknames[i*size], size-1);
|
||||
nicknames[(i*size)+text_size] = GEN2_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ void sanitize_name_general_to_general(const u8* src, u8* dst, const u8* default_
|
|||
size_t question_marks_count = question_marks_count_dst - question_marks_count_src;
|
||||
if(question_marks_count_src > question_marks_count_dst)
|
||||
question_marks_count = 0;
|
||||
if((question_marks_count >= (text_general_size(dst, dst_size, dst_terminator) >> 1)) || (!text_general_size(dst, dst_size, dst_terminator)))
|
||||
if((question_marks_count >= ((text_general_size(dst, dst_size, dst_terminator) + 1) >> 1)) || (!text_general_size(dst, dst_size, dst_terminator)))
|
||||
text_general_copy(default_name, dst, dst_size, dst_size, dst_terminator);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user