mirror of
https://github.com/Lorenzooone/Pokemon-Gen3-to-Gen-X.git
synced 2026-03-21 17:24:39 -05:00
Major Refactor
This commit is contained in:
parent
3c0d9d19f0
commit
879a0a530b
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -3,5 +3,6 @@ build/
|
||||||
*.gba
|
*.gba
|
||||||
*.sav
|
*.sav
|
||||||
*.py
|
*.py
|
||||||
__pychache__/
|
settings.sh
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
|
|
||||||
7
Makefile
7
Makefile
|
|
@ -4,7 +4,7 @@
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(DEVKITARM)/gba_rules
|
include $(DEVKITARM)/gba_rules
|
||||||
|
|
@ -29,7 +29,10 @@ INCLUDES := include
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ARCH := -mthumb -mthumb-interwork
|
ARCH := -mthumb -mthumb-interwork
|
||||||
|
|
||||||
CFLAGS := -g -Wall -save-temps -Os -s\
|
CFLAGS := -g -Wall -Wstrict-overflow=5 -Wextra\
|
||||||
|
-Wpointer-arith -Wpedantic -Wcast-qual -Wswitch-default\
|
||||||
|
-Wstrict-prototypes -Wmissing-prototypes\
|
||||||
|
-Wshadow -Wwrite-strings -save-temps -Os -s\
|
||||||
-mcpu=arm7tdmi -mtune=arm7tdmi\
|
-mcpu=arm7tdmi -mtune=arm7tdmi\
|
||||||
-fomit-frame-pointer\
|
-fomit-frame-pointer\
|
||||||
-ffast-math \
|
-ffast-math \
|
||||||
|
|
|
||||||
9
build_proper_warnings.sh
Executable file
9
build_proper_warnings.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
if [ -z "$DEVKITARM" ];
|
||||||
|
then
|
||||||
|
echo "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM";
|
||||||
|
else
|
||||||
|
make 2>&1 >/dev/null | grep ^$(pwd);
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include "bin_table_handler.h"
|
#include "bin_table_handler.h"
|
||||||
|
|
||||||
const u8* get_table_pointer(const u8* table, u16 entry){
|
const u8* get_table_pointer(const u8* table, u16 entry){
|
||||||
u16* table_16 = (u16*)table;
|
const u16* table_16 = (const u16*)table;
|
||||||
u16 initial_offset;
|
u16 initial_offset;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
u8 offset_table_pos = 2;
|
u8 offset_table_pos = 2;
|
||||||
|
|
@ -30,7 +30,7 @@ const u8* get_table_pointer(const u8* table, u16 entry){
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* search_table_for_index(const u8* table, u16 index){
|
const u8* search_table_for_index(const u8* table, u16 index){
|
||||||
u16* table_16 = (u16*)table;
|
const u16* table_16 = (const u16*)table;
|
||||||
u16 initial_offset;
|
u16 initial_offset;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
u8 offset_table_pos = 2;
|
u8 offset_table_pos = 2;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "sio_buffers.h"
|
#include "sio_buffers.h"
|
||||||
#include "vcount_basic.h"
|
#include "vcount_basic.h"
|
||||||
#include "print_system.h"
|
#include "print_system.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#define GEN2_ENTER_STATES_NUM 4
|
#define GEN2_ENTER_STATES_NUM 4
|
||||||
#define GEN2_START_STATES_NUM 5
|
#define GEN2_START_STATES_NUM 5
|
||||||
|
|
@ -17,6 +18,25 @@
|
||||||
|
|
||||||
#define NUMBER_OF_ENTITIES 2
|
#define NUMBER_OF_ENTITIES 2
|
||||||
|
|
||||||
|
void set_start_state(enum START_TRADE_STATE);
|
||||||
|
void init_received_gen3(void);
|
||||||
|
u16 get_pos_bytes_from_index(u16);
|
||||||
|
u16 get_index_from_pos_bytes(u8, u8);
|
||||||
|
u8 set_received_gen3(u16);
|
||||||
|
u16 get_first_not_received_gen3(void);
|
||||||
|
u16 get_not_received_length_gen3(u16);
|
||||||
|
int increment_last_tranfer(void);
|
||||||
|
void reset_transfer_data_between_sync(void);
|
||||||
|
void init_transfer_data(void);
|
||||||
|
u8 get_offer(u8, u8, u8);
|
||||||
|
u8 get_accept(u8, u8);
|
||||||
|
int communicate_buffer(u8, u8);
|
||||||
|
int check_if_continue(u8, const u8*, const u8*, u32, int, int, u8);
|
||||||
|
int process_data_arrived_gen1(u8, u8);
|
||||||
|
int process_data_arrived_gen2(u8, u8);
|
||||||
|
u32 prepare_out_data_gen3(void);
|
||||||
|
void process_in_data_gen3(u32);
|
||||||
|
|
||||||
const u8 gen2_start_trade_enter_room[NUMBER_OF_ENTITIES][GEN2_ENTER_STATES_NUM] = {
|
const u8 gen2_start_trade_enter_room[NUMBER_OF_ENTITIES][GEN2_ENTER_STATES_NUM] = {
|
||||||
{ENTER_TRADE_SLAVE, 0x61, 0xD1, 0x00},
|
{ENTER_TRADE_SLAVE, 0x61, 0xD1, 0x00},
|
||||||
{ENTER_TRADE_MASTER, 0x61, 0xD1, 0x00}
|
{ENTER_TRADE_MASTER, 0x61, 0xD1, 0x00}
|
||||||
|
|
@ -61,8 +81,8 @@ u8 syn_transmitted;
|
||||||
u8 has_transmitted_syn;
|
u8 has_transmitted_syn;
|
||||||
volatile u8 next_long_pause = 0;
|
volatile u8 next_long_pause = 0;
|
||||||
int last_transfer_counter;
|
int last_transfer_counter;
|
||||||
int buffer_counter;
|
u32 buffer_counter;
|
||||||
int buffer_counter_out;
|
u32 buffer_counter_out;
|
||||||
u8 start_state_updated;
|
u8 start_state_updated;
|
||||||
enum START_TRADE_STATE start_state;
|
enum START_TRADE_STATE start_state;
|
||||||
enum TRADING_STATE trading_state;
|
enum TRADING_STATE trading_state;
|
||||||
|
|
@ -135,7 +155,7 @@ u16 get_transferred(u8 index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_received_gen3() {
|
void init_received_gen3() {
|
||||||
for(int i = 0; i < ((sizeof(struct gen3_trade_data) >> 4)+1); i++)
|
for(u32 i = 0; i < ((sizeof(struct gen3_trade_data) >> 4)+1); i++)
|
||||||
received_gen3[i] = 0;
|
received_gen3[i] = 0;
|
||||||
buffer_counter = 0;
|
buffer_counter = 0;
|
||||||
own_end_gen3 = -1;
|
own_end_gen3 = -1;
|
||||||
|
|
@ -171,7 +191,7 @@ u8 set_received_gen3(u16 index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 get_first_not_received_gen3() {
|
u16 get_first_not_received_gen3() {
|
||||||
for(int i = 0; i < ((sizeof(struct gen3_trade_data) >> 4)+1); i++)
|
for(u32 i = 0; i < ((sizeof(struct gen3_trade_data) >> 4)+1); i++)
|
||||||
for(int j = 0; j < 8; j++) {
|
for(int j = 0; j < 8; j++) {
|
||||||
if(((i<<3) + j) >= (sizeof(struct gen3_trade_data)>>1))
|
if(((i<<3) + j) >= (sizeof(struct gen3_trade_data)>>1))
|
||||||
return sizeof(struct gen3_trade_data)>>1;
|
return sizeof(struct gen3_trade_data)>>1;
|
||||||
|
|
@ -188,7 +208,7 @@ u16 get_not_received_length_gen3(u16 index) {
|
||||||
int j_pos = index & 7;
|
int j_pos = index & 7;
|
||||||
int j = j_pos;
|
int j = j_pos;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
for(int i = i_pos; i < ((sizeof(struct gen3_trade_data) >> 4)+1); i++) {
|
for(u32 i = i_pos; i < ((sizeof(struct gen3_trade_data) >> 4)+1); i++) {
|
||||||
for(; j < 8; j++) {
|
for(; j < 8; j++) {
|
||||||
if(((i<<3) + j) >= (sizeof(struct gen3_trade_data)>>1))
|
if(((i<<3) + j) >= (sizeof(struct gen3_trade_data)>>1))
|
||||||
return total;
|
return total;
|
||||||
|
|
@ -243,7 +263,8 @@ void init_start_state() {
|
||||||
|
|
||||||
IWRAM_CODE u8 get_offer(u8 data, u8 trade_offer_start, u8 end_trade_value) {
|
IWRAM_CODE u8 get_offer(u8 data, u8 trade_offer_start, u8 end_trade_value) {
|
||||||
next_long_pause = 1;
|
next_long_pause = 1;
|
||||||
if(((data >= trade_offer_start) && (data < trade_offer_start + PARTY_SIZE)) || (data == end_trade_value)) {
|
u8 limit_trade_offer = trade_offer_start + PARTY_SIZE;
|
||||||
|
if(((data >= trade_offer_start) && (data < limit_trade_offer)) || (data == end_trade_value)) {
|
||||||
trade_offer_in = data - trade_offer_start;
|
trade_offer_in = data - trade_offer_start;
|
||||||
trading_state = RECEIVED_OFFER;
|
trading_state = RECEIVED_OFFER;
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +280,7 @@ IWRAM_CODE u8 get_accept(u8 data, u8 trade_offer_start) {
|
||||||
return trade_offer_start + trade_offer_out;
|
return trade_offer_start + trade_offer_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) void set_next_vcount_interrupt(void){
|
IWRAM_CODE MAX_OPTIMIZE void set_next_vcount_interrupt(void){
|
||||||
int next_stop = REG_VCOUNT + VCOUNT_WAIT_LINES;
|
int next_stop = REG_VCOUNT + VCOUNT_WAIT_LINES;
|
||||||
if(next_stop >= SCANLINES)
|
if(next_stop >= SCANLINES)
|
||||||
next_stop -= SCANLINES;
|
next_stop -= SCANLINES;
|
||||||
|
|
@ -300,7 +321,7 @@ IWRAM_CODE int communicate_buffer(u8 data, u8 is_master) {
|
||||||
in_buffer[buffer_counter + base_pos] = data;
|
in_buffer[buffer_counter + base_pos] = data;
|
||||||
last_transfer_counter = 0;
|
last_transfer_counter = 0;
|
||||||
buffer_counter++;
|
buffer_counter++;
|
||||||
if((buffer_counter == (transfer_sizes[sizes_index])) || ((!is_master) && (sizes_index == get_number_of_buffers()-1) && (buffer_counter == transfer_sizes[sizes_index]-base_pos_out))) {
|
if((buffer_counter == (transfer_sizes[sizes_index])) || ((!is_master) && (sizes_index == get_number_of_buffers()-1) && (buffer_counter == ((u32)(transfer_sizes[sizes_index]-base_pos_out))))) {
|
||||||
base_pos += transfer_sizes[sizes_index];
|
base_pos += transfer_sizes[sizes_index];
|
||||||
sizes_index++;
|
sizes_index++;
|
||||||
reset_transfer_data_between_sync();
|
reset_transfer_data_between_sync();
|
||||||
|
|
@ -321,7 +342,7 @@ IWRAM_CODE int communicate_buffer(u8 data, u8 is_master) {
|
||||||
return out_buffer[buffer_counter_out - 1 + base_pos];
|
return out_buffer[buffer_counter_out - 1 + base_pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE int check_if_continue(u8 data, const u8* sends, const u8* recvs, int size, int new_state, int new_send, u8 filter) {
|
IWRAM_CODE int check_if_continue(u8 data, const u8* sends, const u8* recvs, u32 size, int new_state, int new_send, u8 filter) {
|
||||||
if((filter) && (data >= 0x10))
|
if((filter) && (data >= 0x10))
|
||||||
data = data & 0xF0;
|
data = data & 0xF0;
|
||||||
if(data == recvs[buffer_counter]) {
|
if(data == recvs[buffer_counter]) {
|
||||||
|
|
@ -341,7 +362,7 @@ IWRAM_CODE int process_data_arrived_gen1(u8 data, u8 is_master) {
|
||||||
if(start_state != START_TRADE_DON)
|
if(start_state != START_TRADE_DON)
|
||||||
switch(start_state) {
|
switch(start_state) {
|
||||||
case START_TRADE_ENT:
|
case START_TRADE_ENT:
|
||||||
return check_if_continue(data, gen1_start_trade_enter_room[is_master], gen1_start_trade_enter_room_next[is_master], GEN1_ENTER_STATES_NUM, START_TRADE_WAI, (START_TRADE_BYTE_GEN1 | 1), 1);
|
return check_if_continue(data, gen1_start_trade_enter_room[is_master], gen1_start_trade_enter_room_next[is_master], GEN1_ENTER_STATES_NUM, START_TRADE_WAI, START_TRADE_BYTE_GEN1 | 1, 1);
|
||||||
case START_TRADE_STA:
|
case START_TRADE_STA:
|
||||||
return check_if_continue(data, gen1_start_trade_start_trade_procedure[is_master], gen1_start_trade_start_trade_procedure_next[is_master], GEN1_START_STATES_NUM, START_TRADE_SYN, SEND_NO_INFO, 1);
|
return check_if_continue(data, gen1_start_trade_start_trade_procedure[is_master], gen1_start_trade_start_trade_procedure_next[is_master], GEN1_START_STATES_NUM, START_TRADE_SYN, SEND_NO_INFO, 1);
|
||||||
case START_TRADE_PAR:
|
case START_TRADE_PAR:
|
||||||
|
|
@ -374,7 +395,7 @@ IWRAM_CODE int process_data_arrived_gen1(u8 data, u8 is_master) {
|
||||||
}
|
}
|
||||||
if((!is_master) && (filtered_data == START_TRADE_BYTE_GEN1)) {
|
if((!is_master) && (filtered_data == START_TRADE_BYTE_GEN1)) {
|
||||||
buffer_counter++;
|
buffer_counter++;
|
||||||
if(buffer_counter == MAX_WAIT_FOR_SYN) {
|
if(buffer_counter >= MAX_WAIT_FOR_SYN) {
|
||||||
buffer_counter = 0;
|
buffer_counter = 0;
|
||||||
last_filtered = 0;
|
last_filtered = 0;
|
||||||
init_transfer_data();
|
init_transfer_data();
|
||||||
|
|
@ -383,7 +404,7 @@ IWRAM_CODE int process_data_arrived_gen1(u8 data, u8 is_master) {
|
||||||
}
|
}
|
||||||
if((!is_master) && (filtered_data == CHOICE_BYTE_GEN1)) {
|
if((!is_master) && (filtered_data == CHOICE_BYTE_GEN1)) {
|
||||||
buffer_counter++;
|
buffer_counter++;
|
||||||
if(buffer_counter == MAX_WAIT_FOR_SYN) {
|
if(buffer_counter >= MAX_WAIT_FOR_SYN) {
|
||||||
buffer_counter = 0;
|
buffer_counter = 0;
|
||||||
last_filtered = 0;
|
last_filtered = 0;
|
||||||
set_start_state(START_TRADE_STA);
|
set_start_state(START_TRADE_STA);
|
||||||
|
|
@ -405,7 +426,7 @@ IWRAM_CODE int process_data_arrived_gen1(u8 data, u8 is_master) {
|
||||||
if(is_master) {
|
if(is_master) {
|
||||||
if(start_state == START_TRADE_UNK)
|
if(start_state == START_TRADE_UNK)
|
||||||
return gen1_start_trade_enter_room[is_master][0];
|
return gen1_start_trade_enter_room[is_master][0];
|
||||||
return (START_TRADE_BYTE_GEN1 | 1);
|
return START_TRADE_BYTE_GEN1 | 1;
|
||||||
}
|
}
|
||||||
return SEND_NO_INFO;
|
return SEND_NO_INFO;
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +612,7 @@ void process_in_data_gen3(u32 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) void slave_routine(void) {
|
IWRAM_CODE MAX_OPTIMIZE void slave_routine(void) {
|
||||||
if(!(REG_IF & IRQ_SERIAL)){
|
if(!(REG_IF & IRQ_SERIAL)){
|
||||||
REG_IF |= IRQ_SERIAL;
|
REG_IF |= IRQ_SERIAL;
|
||||||
int value;
|
int value;
|
||||||
|
|
@ -613,7 +634,7 @@ IWRAM_CODE __attribute__((optimize(3))) void slave_routine(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) void master_routine_gen3(void) {
|
IWRAM_CODE MAX_OPTIMIZE void master_routine_gen3(void) {
|
||||||
REG_IF |= IRQ_VCOUNT;
|
REG_IF |= IRQ_VCOUNT;
|
||||||
int data;
|
int data;
|
||||||
u8 success = 0;
|
u8 success = 0;
|
||||||
|
|
@ -629,7 +650,7 @@ IWRAM_CODE __attribute__((optimize(3))) void master_routine_gen3(void) {
|
||||||
set_next_vcount_interrupt();
|
set_next_vcount_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) void master_routine_gen12(void) {
|
IWRAM_CODE MAX_OPTIMIZE void master_routine_gen12(void) {
|
||||||
REG_IF |= IRQ_VCOUNT;
|
REG_IF |= IRQ_VCOUNT;
|
||||||
int data;
|
int data;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,22 +38,23 @@
|
||||||
enum START_TRADE_STATE {START_TRADE_UNK, START_TRADE_ENT, START_TRADE_STA, START_TRADE_END, START_TRADE_WAI, START_TRADE_PAR, START_TRADE_SYN, START_TRADE_DON, START_TRADE_NO_UPDATE};
|
enum START_TRADE_STATE {START_TRADE_UNK, START_TRADE_ENT, START_TRADE_STA, START_TRADE_END, START_TRADE_WAI, START_TRADE_PAR, START_TRADE_SYN, START_TRADE_DON, START_TRADE_NO_UPDATE};
|
||||||
enum TRADING_STATE {NO_INFO, HAVE_OFFER, RECEIVED_OFFER, HAVE_ACCEPT, RECEIVED_ACCEPT, DURING_TRADE, COMPLETED_TRADE};
|
enum TRADING_STATE {NO_INFO, HAVE_OFFER, RECEIVED_OFFER, HAVE_ACCEPT, RECEIVED_ACCEPT, DURING_TRADE, COMPLETED_TRADE};
|
||||||
|
|
||||||
void try_to_end_trade();
|
void try_to_end_trade(void);
|
||||||
void try_to_offer(u8);
|
void try_to_offer(u8);
|
||||||
void try_to_accept_offer();
|
void try_to_accept_offer(void);
|
||||||
void try_to_decline_offer();
|
void try_to_decline_offer(void);
|
||||||
int get_received_trade_offer();
|
int get_received_trade_offer(void);
|
||||||
int has_accepted_offer();
|
int has_accepted_offer(void);
|
||||||
void start_transfer(u8, u8);
|
void start_transfer(u8, u8);
|
||||||
void set_next_vcount_interrupt();
|
void set_next_vcount_interrupt(void);
|
||||||
void stop_transfer(u8);
|
void stop_transfer(u8);
|
||||||
int increment_last_tranfer();
|
int increment_last_tranfer(void);
|
||||||
void init_start_state();
|
void init_start_state(void);
|
||||||
enum TRADING_STATE get_trading_state();
|
enum TRADING_STATE get_trading_state(void);
|
||||||
enum START_TRADE_STATE get_start_state();
|
enum START_TRADE_STATE get_start_state(void);
|
||||||
enum START_TRADE_STATE get_start_state_raw();
|
enum START_TRADE_STATE get_start_state_raw(void);
|
||||||
u16 get_transferred(u8);
|
u16 get_transferred(u8);
|
||||||
void slave_routine(void);
|
void slave_routine(void);
|
||||||
void master_routine_gen12(void);
|
void master_routine_gen12(void);
|
||||||
|
void master_routine_gen3(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,24 @@
|
||||||
|
|
||||||
#include "optimized_swi.h"
|
#include "optimized_swi.h"
|
||||||
#include "party_handler.h"
|
#include "party_handler.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
static __attribute__((optimize(3), always_inline)) inline u8 get_nature_fast(u32 pid){
|
static u8 get_nature_fast(u32);
|
||||||
|
static u8 get_unown_letter_gen3_fast(u32);
|
||||||
|
static u8 get_unown_letter_gen2_fast(u16);
|
||||||
|
|
||||||
|
ALWAYS_INLINE MAX_OPTIMIZE u8 get_nature_fast(u32 pid){
|
||||||
// Make use of modulo properties to get this to positives
|
// Make use of modulo properties to get this to positives
|
||||||
while(pid >= 0x80000000)
|
while(pid >= 0x80000000)
|
||||||
pid -= 0x7FFFFFE9;
|
pid -= 0x7FFFFFE9;
|
||||||
return SWI_DivMod(pid, NUM_NATURES);
|
return SWI_DivMod(pid, NUM_NATURES);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((optimize(3), always_inline)) inline u8 get_unown_letter_gen3_fast(u32 pid){
|
ALWAYS_INLINE MAX_OPTIMIZE u8 get_unown_letter_gen3_fast(u32 pid){
|
||||||
return SWI_DivMod((pid & 3) + (((pid >> 8) & 3) << 2) + (((pid >> 16) & 3) << 4) + (((pid >> 24) & 3) << 6), NUM_UNOWN_LETTERS_GEN3);
|
return SWI_DivMod((pid & 3) + (((pid >> 8) & 3) << 2) + (((pid >> 16) & 3) << 4) + (((pid >> 24) & 3) << 6), NUM_UNOWN_LETTERS_GEN3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((optimize(3), always_inline)) inline u8 get_unown_letter_gen2_fast(u16 ivs){
|
ALWAYS_INLINE MAX_OPTIMIZE u8 get_unown_letter_gen2_fast(u16 ivs){
|
||||||
u8 atk_ivs = ((ivs>>4) & 0xF);
|
u8 atk_ivs = ((ivs>>4) & 0xF);
|
||||||
u8 def_ivs = ((ivs) & 0xF);
|
u8 def_ivs = ((ivs) & 0xF);
|
||||||
u8 spe_ivs = ((ivs>>12) & 0xF);
|
u8 spe_ivs = ((ivs>>12) & 0xF);
|
||||||
|
|
|
||||||
199
source/gen12_methods.c
Normal file
199
source/gen12_methods.c
Normal file
|
|
@ -0,0 +1,199 @@
|
||||||
|
#include <gba.h>
|
||||||
|
#include "gen12_methods.h"
|
||||||
|
#include "party_handler.h"
|
||||||
|
#include "text_handler.h"
|
||||||
|
#include "bin_table_handler.h"
|
||||||
|
#include "fast_pokemon_methods.h"
|
||||||
|
|
||||||
|
#include "gen3_to_1_conv_table_bin.h"
|
||||||
|
#include "gen1_to_3_conv_table_bin.h"
|
||||||
|
#include "pokemon_gender_bin.h"
|
||||||
|
#include "pokemon_names_bin.h"
|
||||||
|
#include "gen2_names_jap_bin.h"
|
||||||
|
#include "pokemon_stats_gen1_bin.h"
|
||||||
|
#include "pokemon_stats_bin.h"
|
||||||
|
|
||||||
|
u8 stat_index_conversion_gen2[] = {0, 1, 2, 5, 3, 4};
|
||||||
|
u8 gender_thresholds_gen12[TOTAL_GENDER_KINDS] = {8, 0, 2, 4, 12, 14, 16, 17, 0, 16};
|
||||||
|
|
||||||
|
const struct stats_gen_23* stats_table_gen2 = (const struct stats_gen_23*)pokemon_stats_bin;
|
||||||
|
const struct stats_gen_1* stats_table_gen1 = (const struct stats_gen_1*)pokemon_stats_gen1_bin;
|
||||||
|
|
||||||
|
u8 has_legal_moves_gen12(u8* moves, u8 is_gen2) {
|
||||||
|
u8 last_valid_move = LAST_VALID_GEN_1_MOVE;
|
||||||
|
if(is_gen2)
|
||||||
|
last_valid_move = LAST_VALID_GEN_2_MOVE;
|
||||||
|
|
||||||
|
u8 previous_moves[MOVES_SIZE];
|
||||||
|
u8 curr_slot = 0;
|
||||||
|
for(int i = 0; i < MOVES_SIZE; i++) {
|
||||||
|
if((moves[i] != 0) && (moves[i] <= last_valid_move)) {
|
||||||
|
for(int j = 0; j < curr_slot; j++)
|
||||||
|
if(moves[i] == previous_moves[j])
|
||||||
|
return 0;
|
||||||
|
previous_moves[curr_slot++] = moves[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(curr_slot)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 get_ivs_gen2(u16 ivs, u8 stat_index) {
|
||||||
|
u8 atk_ivs = (ivs >> 4) & 0xF;
|
||||||
|
u8 def_ivs = ivs & 0xF;
|
||||||
|
u8 spe_ivs = (ivs >> 12) & 0xF;
|
||||||
|
u8 spa_ivs = (ivs >> 8) & 0xF;
|
||||||
|
switch(stat_index) {
|
||||||
|
case HP_STAT_INDEX:
|
||||||
|
return ((atk_ivs & 1) << 3) | ((def_ivs & 1) << 2) | ((spe_ivs & 1) << 1) | (spa_ivs & 1);
|
||||||
|
case ATK_STAT_INDEX:
|
||||||
|
return atk_ivs;
|
||||||
|
case DEF_STAT_INDEX:
|
||||||
|
return def_ivs;
|
||||||
|
case SPE_STAT_INDEX:
|
||||||
|
return spe_ivs;
|
||||||
|
default:
|
||||||
|
return spa_ivs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 get_unown_letter_gen2(u16 ivs){
|
||||||
|
return get_unown_letter_gen2_fast(ivs);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 get_proper_exp_gen2(u16 mon_index, u8 level, u8* given_exp) {
|
||||||
|
s32 exp = (given_exp[0]<<0x10) + (given_exp[1]<<0x8) + (given_exp[2]<<0);
|
||||||
|
s32 min_exp = get_level_exp_mon_index(mon_index, level);
|
||||||
|
s32 max_exp = min_exp;
|
||||||
|
if(level == MAX_LEVEL)
|
||||||
|
exp = min_exp;
|
||||||
|
else
|
||||||
|
max_exp = get_level_exp_mon_index(mon_index, level+1)-1;
|
||||||
|
if(exp < min_exp)
|
||||||
|
exp = min_exp;
|
||||||
|
if(exp > max_exp)
|
||||||
|
exp = max_exp;
|
||||||
|
if(exp < 0)
|
||||||
|
exp = 0;
|
||||||
|
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
u8 is_shiny_gen2(u8 atk_ivs, u8 def_ivs, u8 spa_ivs, u8 spe_ivs) {
|
||||||
|
if((atk_ivs & 2) == 2 && def_ivs == 10 && spa_ivs == 10 && spe_ivs == 10)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 is_shiny_gen2_unfiltered(u16 ivs) {
|
||||||
|
return is_shiny_gen2((ivs >> 4) & 0xF, ivs & 0xF, (ivs >> 8) & 0xF, (ivs >> 12) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 is_shiny_gen2_raw(struct gen2_mon_data* src) {
|
||||||
|
return is_shiny_gen2_unfiltered(src->ivs);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 get_mon_index_gen1(int index) {
|
||||||
|
if(index > LAST_VALID_GEN_1_MON)
|
||||||
|
return 0;
|
||||||
|
return gen3_to_1_conv_table_bin[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u16 get_mon_index_gen2_1(int index) {
|
||||||
|
if(index > LAST_VALID_GEN_1_MON)
|
||||||
|
return 0;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 get_mon_index_gen2(int index, u8 is_egg) {
|
||||||
|
if(index > LAST_VALID_GEN_2_MON)
|
||||||
|
return 0;
|
||||||
|
if(is_egg)
|
||||||
|
return GEN2_EGG;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 get_mon_index_gen1_to_3(u8 index){
|
||||||
|
return gen1_to_3_conv_table_bin[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 calc_stats_gen1(u16 species, u8 stat_index, u8 level, u8 iv, u16 stat_exp) {
|
||||||
|
if(species > LAST_VALID_GEN_1_MON)
|
||||||
|
species = 0;
|
||||||
|
species = get_mon_index_gen1(species);
|
||||||
|
if(stat_index >= GEN1_STATS_TOTAL)
|
||||||
|
stat_index = GEN1_STATS_TOTAL-1;
|
||||||
|
u16 base = 5;
|
||||||
|
if(stat_index == HP_STAT_INDEX)
|
||||||
|
base = level + 10;
|
||||||
|
u16 stat_exp_contribution = Sqrt(stat_exp);
|
||||||
|
// Bulbapedia error...
|
||||||
|
//if((stat_exp_contribution * stat_exp_contribution) < stat_exp)
|
||||||
|
// stat_exp_contribution += 1;
|
||||||
|
return base + Div((((stats_table_gen1[species].stats[stat_index] + iv)*2) + (stat_exp_contribution >> 2)) * level, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 calc_stats_gen2(u16 species, u32 pid, u8 stat_index, u8 level, u8 iv, u16 stat_exp) {
|
||||||
|
if(species > LAST_VALID_GEN_2_MON)
|
||||||
|
species = 0;
|
||||||
|
if(stat_index >= GEN2_STATS_TOTAL)
|
||||||
|
stat_index = GEN2_STATS_TOTAL-1;
|
||||||
|
|
||||||
|
u16 mon_index = get_mon_index(species, pid, 0, 0);
|
||||||
|
|
||||||
|
stat_index = stat_index_conversion_gen2[stat_index];
|
||||||
|
u16 base = 5;
|
||||||
|
if(stat_index == HP_STAT_INDEX)
|
||||||
|
base = level + 10;
|
||||||
|
u16 stat_exp_contribution = Sqrt(stat_exp);
|
||||||
|
// Bulbapedia error...
|
||||||
|
//if((stat_exp_contribution * stat_exp_contribution) < stat_exp)
|
||||||
|
// stat_exp_contribution += 1;
|
||||||
|
return base + Div((((stats_table_gen2[mon_index].stats[stat_index] + iv)*2) + (stat_exp_contribution >> 2)) * level, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 get_gender_thresholds_gen12(u8 gender_kind) {
|
||||||
|
if(gender_kind >= TOTAL_GENDER_KINDS)
|
||||||
|
gender_kind = 0;
|
||||||
|
return gender_thresholds_gen12[gender_kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 get_pokemon_gender_kind_gen2(u8 index, u8 is_egg, u8 curr_gen) {
|
||||||
|
if(curr_gen == 1)
|
||||||
|
return pokemon_gender_bin[get_mon_index_gen2_1(index)];
|
||||||
|
return pokemon_gender_bin[get_mon_index_gen2(index, is_egg)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8* get_pokemon_name_gen2(int index, u8 is_egg, u8 is_jp, u8* buffer) {
|
||||||
|
if(is_jp)
|
||||||
|
return &(gen2_names_jap_bin[get_mon_index_gen2(index, is_egg)*STRING_GEN2_JP_CAP]);
|
||||||
|
u8 buffer_two[STRING_GEN2_INT_SIZE];
|
||||||
|
u16 mon_index = get_mon_index_gen2(index, is_egg);
|
||||||
|
if (mon_index == MR_MIME_SPECIES)
|
||||||
|
mon_index = MR_MIME_OLD_NAME_POS;
|
||||||
|
if (mon_index == UNOWN_SPECIES)
|
||||||
|
mon_index = UNOWN_REAL_NAME_POS;
|
||||||
|
text_generic_to_gen3(get_table_pointer(pokemon_names_bin, mon_index), buffer_two, NAME_SIZE, STRING_GEN2_INT_CAP, 0, 0);
|
||||||
|
text_gen3_to_gen12(buffer_two, buffer, STRING_GEN2_INT_CAP, STRING_GEN2_INT_CAP, 0, 0);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
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){
|
||||||
|
case M_INDEX:
|
||||||
|
case NIDORAN_M_GENDER_INDEX:
|
||||||
|
return M_GENDER;
|
||||||
|
case F_INDEX:
|
||||||
|
case NIDORAN_F_GENDER_INDEX:
|
||||||
|
return F_GENDER;
|
||||||
|
case U_INDEX:
|
||||||
|
return U_GENDER;
|
||||||
|
default:
|
||||||
|
if(atk_ivs >= get_gender_thresholds_gen12(gender_kind))
|
||||||
|
return M_GENDER;
|
||||||
|
return F_GENDER;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
source/gen12_methods.h
Normal file
24
source/gen12_methods.h
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef GEN12_METHODS__
|
||||||
|
#define GEN12_METHODS__
|
||||||
|
|
||||||
|
#include "party_handler.h"
|
||||||
|
|
||||||
|
u8 has_legal_moves_gen12(u8*, u8);
|
||||||
|
u8 get_ivs_gen2(u16, u8);
|
||||||
|
u8 get_unown_letter_gen2(u16);
|
||||||
|
s32 get_proper_exp_gen2(u16, u8, u8*);
|
||||||
|
u8 is_shiny_gen2(u8, u8, u8, u8);
|
||||||
|
u8 is_shiny_gen2_unfiltered(u16);
|
||||||
|
u8 is_shiny_gen2_raw(struct gen2_mon_data*);
|
||||||
|
u16 get_mon_index_gen1(int);
|
||||||
|
u16 get_mon_index_gen2_1(int);
|
||||||
|
u16 get_mon_index_gen2(int, u8);
|
||||||
|
u16 get_mon_index_gen1_to_3(u8);
|
||||||
|
u16 calc_stats_gen1(u16, u8, u8, u8, u16);
|
||||||
|
u16 calc_stats_gen2(u16, u32, u8, u8, u8, u16);
|
||||||
|
u8 get_gender_thresholds_gen12(u8);
|
||||||
|
u8 get_pokemon_gender_gen2(u8, u8, u8, u8);
|
||||||
|
u8 get_pokemon_gender_kind_gen2(u8, u8, u8);
|
||||||
|
const u8* get_pokemon_name_gen2(int, u8, u8, u8*);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "save.h"
|
#include "save.h"
|
||||||
#include "gen3_save.h"
|
#include "gen3_save.h"
|
||||||
|
#include "gen_converter.h"
|
||||||
#include "text_handler.h"
|
#include "text_handler.h"
|
||||||
|
|
||||||
#define MAGIC_NUMBER 0x08012025
|
#define MAGIC_NUMBER 0x08012025
|
||||||
|
|
@ -25,6 +26,16 @@
|
||||||
|
|
||||||
#define VALID_MAPS 36
|
#define VALID_MAPS 36
|
||||||
|
|
||||||
|
u32 read_section_id(int, int);
|
||||||
|
void read_game_data_trainer_info(int, struct game_data_t*);
|
||||||
|
void register_dex_entry(struct game_data_t*, struct gen3_mon_data_unenc*);
|
||||||
|
void handle_mail_trade(struct game_data_t*, u8, u8);
|
||||||
|
void process_party_data(struct game_data_t*);
|
||||||
|
void read_party(int, struct game_data_t*);
|
||||||
|
u32 read_slot_index(int);
|
||||||
|
u8 validate_slot(int);
|
||||||
|
u8 get_slot(void);
|
||||||
|
|
||||||
const u16 summable_bytes[SECTION_TOTAL] = {3884, 3968, 3968, 3968, 3848, 3968, 3968, 3968, 3968, 3968, 3968, 3968, 3968, 2000};
|
const u16 summable_bytes[SECTION_TOTAL] = {3884, 3968, 3968, 3968, 3848, 3968, 3968, 3968, 3968, 3968, 3968, 3968, 3968, 2000};
|
||||||
const u16 pokedex_extra_pos_1 [] = {0x938, 0x5F8, 0x988};
|
const u16 pokedex_extra_pos_1 [] = {0x938, 0x5F8, 0x988};
|
||||||
const u16 pokedex_extra_pos_2 [] = {0xC0C, 0xB98, 0xCA4};
|
const u16 pokedex_extra_pos_2 [] = {0xC0C, 0xB98, 0xCA4};
|
||||||
|
|
@ -51,7 +62,7 @@ void init_game_data(struct game_data_t* game_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 read_section_id(int slot, int section_pos) {
|
u32 read_section_id(int slot, int section_pos) {
|
||||||
if(slot != 0)
|
if(slot)
|
||||||
slot = 1;
|
slot = 1;
|
||||||
if(section_pos < 0)
|
if(section_pos < 0)
|
||||||
section_pos = 0;
|
section_pos = 0;
|
||||||
|
|
@ -62,7 +73,7 @@ u32 read_section_id(int slot, int section_pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_game_data_trainer_info(int slot, struct game_data_t* game_data) {
|
void read_game_data_trainer_info(int slot, struct game_data_t* game_data) {
|
||||||
if(slot != 0)
|
if(slot)
|
||||||
slot = 1;
|
slot = 1;
|
||||||
|
|
||||||
for(int i = 0; i < SECTION_TOTAL; i++)
|
for(int i = 0; i < SECTION_TOTAL; i++)
|
||||||
|
|
@ -97,7 +108,7 @@ void handle_mail_trade(struct game_data_t* game_data, u8 own_mon, u8 other_mon)
|
||||||
mail_id = get_mail_id_raw(&game_data[1].party_3_undec[other_mon]);
|
mail_id = get_mail_id_raw(&game_data[1].party_3_undec[other_mon]);
|
||||||
if((mail_id != GEN3_NO_MAIL) && (mail_id < PARTY_SIZE)) {
|
if((mail_id != GEN3_NO_MAIL) && (mail_id < PARTY_SIZE)) {
|
||||||
u8 is_mail_free[PARTY_SIZE] = {1,1,1,1,1,1};
|
u8 is_mail_free[PARTY_SIZE] = {1,1,1,1,1,1};
|
||||||
for(int i = 0; i < game_data[0].party_3.total; i++) {
|
for(u32 i = 0; i < game_data[0].party_3.total; i++) {
|
||||||
u8 inner_mail_id = get_mail_id_raw(&game_data[0].party_3_undec[i]);
|
u8 inner_mail_id = get_mail_id_raw(&game_data[0].party_3_undec[i]);
|
||||||
if((inner_mail_id != GEN3_NO_MAIL) && (inner_mail_id < PARTY_SIZE))
|
if((inner_mail_id != GEN3_NO_MAIL) && (inner_mail_id < PARTY_SIZE))
|
||||||
is_mail_free[inner_mail_id] = 0;
|
is_mail_free[inner_mail_id] = 0;
|
||||||
|
|
@ -110,7 +121,7 @@ void handle_mail_trade(struct game_data_t* game_data, u8 own_mon, u8 other_mon)
|
||||||
}
|
}
|
||||||
u8* dst = (u8*)&game_data[0].mails_3[target];
|
u8* dst = (u8*)&game_data[0].mails_3[target];
|
||||||
u8* src = (u8*)&game_data[1].mails_3[mail_id];
|
u8* src = (u8*)&game_data[1].mails_3[mail_id];
|
||||||
for(int i = 0; i < sizeof(struct mail_gen3); i++)
|
for(u32 i = 0; i < sizeof(struct mail_gen3); i++)
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
game_data[1].party_3_undec[other_mon].src->mail_id = target;
|
game_data[1].party_3_undec[other_mon].src->mail_id = target;
|
||||||
}
|
}
|
||||||
|
|
@ -123,11 +134,11 @@ u8 trade_mons(struct game_data_t* game_data, u8 own_mon, u8 other_mon, const u16
|
||||||
|
|
||||||
u8* dst = (u8*)&game_data[0].party_3.mons[own_mon];
|
u8* dst = (u8*)&game_data[0].party_3.mons[own_mon];
|
||||||
u8* src = (u8*)&game_data[1].party_3.mons[other_mon];
|
u8* src = (u8*)&game_data[1].party_3.mons[other_mon];
|
||||||
for(int i = 0; i < sizeof(struct gen3_mon); i++)
|
for(u32 i = 0; i < sizeof(struct gen3_mon); i++)
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
dst = (u8*)&game_data[0].party_3_undec[own_mon];
|
dst = (u8*)&game_data[0].party_3_undec[own_mon];
|
||||||
src = (u8*)&game_data[1].party_3_undec[other_mon];
|
src = (u8*)&game_data[1].party_3_undec[other_mon];
|
||||||
for(int i = 0; i < sizeof(struct gen3_mon_data_unenc); i++)
|
for(u32 i = 0; i < sizeof(struct gen3_mon_data_unenc); i++)
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
game_data[0].party_3_undec[own_mon].src = &game_data[0].party_3.mons[own_mon];
|
game_data[0].party_3_undec[own_mon].src = &game_data[0].party_3.mons[own_mon];
|
||||||
for(int i = 0; i < GIFT_RIBBONS; i++)
|
for(int i = 0; i < GIFT_RIBBONS; i++)
|
||||||
|
|
@ -164,14 +175,14 @@ void process_party_data(struct game_data_t* game_data) {
|
||||||
game_data->party_3.total = PARTY_SIZE;
|
game_data->party_3.total = PARTY_SIZE;
|
||||||
u8 curr_slot = 0;
|
u8 curr_slot = 0;
|
||||||
u8 found = 0;
|
u8 found = 0;
|
||||||
for(int i = 0; i < game_data->party_3.total; i++) {
|
for(u32 i = 0; i < game_data->party_3.total; i++) {
|
||||||
process_gen3_data(&game_data->party_3.mons[i], &game_data->party_3_undec[i], game_data->game_identifier.game_main_version, game_data->game_identifier.game_sub_version);
|
process_gen3_data(&game_data->party_3.mons[i], &game_data->party_3_undec[i], game_data->game_identifier.game_main_version, game_data->game_identifier.game_sub_version);
|
||||||
if(game_data->party_3_undec[i].is_valid_gen3)
|
if(game_data->party_3_undec[i].is_valid_gen3)
|
||||||
found = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
game_data->party_3.total = 0;
|
game_data->party_3.total = 0;
|
||||||
for(int i = 0; i < game_data->party_3.total; i++)
|
for(u32 i = 0; i < game_data->party_3.total; i++)
|
||||||
if(gen3_to_gen2(&game_data->party_2.mons[curr_slot], &game_data->party_3_undec[i], game_data->trainer_id)) {
|
if(gen3_to_gen2(&game_data->party_2.mons[curr_slot], &game_data->party_3_undec[i], game_data->trainer_id)) {
|
||||||
curr_slot++;
|
curr_slot++;
|
||||||
game_data->party_3_undec[i].is_valid_gen2 = 1;
|
game_data->party_3_undec[i].is_valid_gen2 = 1;
|
||||||
|
|
@ -180,7 +191,7 @@ void process_party_data(struct game_data_t* game_data) {
|
||||||
game_data->party_3_undec[i].is_valid_gen2 = 0;
|
game_data->party_3_undec[i].is_valid_gen2 = 0;
|
||||||
game_data->party_2.total = curr_slot;
|
game_data->party_2.total = curr_slot;
|
||||||
curr_slot = 0;
|
curr_slot = 0;
|
||||||
for(int i = 0; i < game_data->party_3.total; i++)
|
for(u32 i = 0; i < game_data->party_3.total; i++)
|
||||||
if(gen3_to_gen1(&game_data->party_1.mons[curr_slot], &game_data->party_3_undec[i], game_data->trainer_id)) {
|
if(gen3_to_gen1(&game_data->party_1.mons[curr_slot], &game_data->party_3_undec[i], game_data->trainer_id)) {
|
||||||
curr_slot++;
|
curr_slot++;
|
||||||
game_data->party_3_undec[i].is_valid_gen1 = 1;
|
game_data->party_3_undec[i].is_valid_gen1 = 1;
|
||||||
|
|
@ -191,7 +202,7 @@ void process_party_data(struct game_data_t* game_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_party(int slot, struct game_data_t* game_data) {
|
void read_party(int slot, struct game_data_t* game_data) {
|
||||||
if(slot != 0)
|
if(slot)
|
||||||
slot = 1;
|
slot = 1;
|
||||||
|
|
||||||
read_game_data_trainer_info(slot, game_data);
|
read_game_data_trainer_info(slot, game_data);
|
||||||
|
|
@ -214,14 +225,14 @@ void read_party(int slot, struct game_data_t* game_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 read_slot_index(int slot) {
|
u32 read_slot_index(int slot) {
|
||||||
if(slot != 0)
|
if(slot)
|
||||||
slot = 1;
|
slot = 1;
|
||||||
|
|
||||||
return read_int_save((slot * SAVE_SLOT_SIZE) + SAVE_SLOT_INDEX_POS);
|
return read_int_save((slot * SAVE_SLOT_SIZE) + SAVE_SLOT_INDEX_POS);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 validate_slot(int slot) {
|
u8 validate_slot(int slot) {
|
||||||
if(slot != 0)
|
if(slot)
|
||||||
slot = 1;
|
slot = 1;
|
||||||
|
|
||||||
u16 valid_sections = 0;
|
u16 valid_sections = 0;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ struct game_data_t {
|
||||||
void init_game_data(struct game_data_t*);
|
void init_game_data(struct game_data_t*);
|
||||||
void read_gen_3_data(struct game_data_t*);
|
void read_gen_3_data(struct game_data_t*);
|
||||||
void process_party_data(struct game_data_t* game_data);
|
void process_party_data(struct game_data_t* game_data);
|
||||||
struct game_data_t* get_own_game_data();
|
struct game_data_t* get_own_game_data(void);
|
||||||
u8 trade_mons(struct game_data_t*, u8, u8, const u16**, u8);
|
u8 trade_mons(struct game_data_t*, u8, u8, const u16**, u8);
|
||||||
u8 is_invalid_offer(struct game_data_t*, u8, u8);
|
u8 is_invalid_offer(struct game_data_t*, u8, u8);
|
||||||
|
|
||||||
|
|
|
||||||
960
source/gen_converter.c
Normal file
960
source/gen_converter.c
Normal file
|
|
@ -0,0 +1,960 @@
|
||||||
|
#include <gba.h>
|
||||||
|
#include "party_handler.h"
|
||||||
|
#include "gen12_methods.h"
|
||||||
|
#include "gen_converter.h"
|
||||||
|
#include "text_handler.h"
|
||||||
|
#include "version_identifier.h"
|
||||||
|
#include "bin_table_handler.h"
|
||||||
|
#include "gen3_save.h"
|
||||||
|
#include "rng.h"
|
||||||
|
#include "pid_iv_tid.h"
|
||||||
|
#include "fast_pokemon_methods.h"
|
||||||
|
#include "optimized_swi.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
|
#include "pokemon_moves_pp_bin.h"
|
||||||
|
#include "item_gen3_to_12_bin.h"
|
||||||
|
#include "item_gen12_to_3_bin.h"
|
||||||
|
#include "pokemon_types_gen1_bin.h"
|
||||||
|
#include "encounter_types_bin.h"
|
||||||
|
#include "egg_locations_bin.h"
|
||||||
|
#include "encounters_static_bin.h"
|
||||||
|
#include "encounters_roamers_bin.h"
|
||||||
|
#include "encounters_unown_bin.h"
|
||||||
|
#include "encounter_types_gen2_bin.h"
|
||||||
|
#include "special_encounters_gen2_bin.h"
|
||||||
|
|
||||||
|
#define MF_7_1_INDEX 2
|
||||||
|
#define UNOWN_EX_LETTER 26
|
||||||
|
#define UNOWN_I_LETTER 8
|
||||||
|
#define UNOWN_V_LETTER 21
|
||||||
|
|
||||||
|
u16 swap_endian_short(u16);
|
||||||
|
u32 swap_endian_int(u32);
|
||||||
|
u8 validate_converting_mon_of_gen1(u8, struct gen1_mon_data*);
|
||||||
|
u8 validate_converting_mon_of_gen2(u8, struct gen2_mon_data*, u8*);
|
||||||
|
u8 validate_converting_mon_of_gen3(struct gen3_mon*, struct gen3_mon_growth*, u8, u8, u8, u8, u8);
|
||||||
|
u8 convert_moves_of_gen3(struct gen3_mon_attacks*, u8, u8*, u8*, u8);
|
||||||
|
u8 convert_moves_to_gen3(struct gen3_mon_attacks*, struct gen3_mon_growth*, u8*, u8*, u8);
|
||||||
|
u8 convert_item_of_gen3(u16);
|
||||||
|
u16 convert_item_to_gen3(u16);
|
||||||
|
void convert_exp_nature_of_gen3(struct gen3_mon*, struct gen3_mon_growth*, u8*, u8*, u8);
|
||||||
|
u8 get_exp_nature(struct gen3_mon*, struct gen3_mon_growth*, u8, u8*);
|
||||||
|
void convert_evs_of_gen3(struct gen3_mon_evs*, u16*);
|
||||||
|
void convert_evs_to_gen3(struct gen3_mon_evs*, u16*);
|
||||||
|
u16 convert_ivs_of_gen3(struct gen3_mon_misc*, u16, u32, u8, u8, u8, u8);
|
||||||
|
void set_ivs(struct gen3_mon_misc*, u32);
|
||||||
|
void set_origin_pid_iv(struct gen3_mon*, struct gen3_mon_misc*, u16, u16, u8, u8, u8, u8);
|
||||||
|
u8 are_trainers_same(struct gen3_mon*, u8);
|
||||||
|
void fix_name_change_from_gen3(struct gen3_mon*, u16, u8*, u8, u8);
|
||||||
|
void fix_name_change_to_gen3(struct gen3_mon*, u8);
|
||||||
|
void convert_strings_of_gen3(struct gen3_mon*, u16, u8*, u8*, u8*, u8*, u8, u8);
|
||||||
|
void convert_strings_of_gen12(struct gen3_mon*, u8, u8*, u8*, u8);
|
||||||
|
|
||||||
|
u16 swap_endian_short(u16 shrt) {
|
||||||
|
return ((shrt & 0xFF00) >> 8) | ((shrt & 0xFF) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 swap_endian_int(u32 integer) {
|
||||||
|
return ((integer & 0xFF000000) >> 24) | ((integer & 0xFF) << 24) | ((integer & 0xFF0000) >> 8) | ((integer & 0xFF00) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 validate_converting_mon_of_gen1(u8 index, struct gen1_mon_data* src) {
|
||||||
|
|
||||||
|
// Check for matching index to species
|
||||||
|
if(index != src->species)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u8 conv_species = get_mon_index_gen1_to_3(src->species);
|
||||||
|
|
||||||
|
// Is this a valid mon
|
||||||
|
if((conv_species > LAST_VALID_GEN_1_MON) || (conv_species == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Does it have a valid movepool
|
||||||
|
if(!has_legal_moves_gen12(src->moves, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Check for valid types
|
||||||
|
u8 matched[2] = {0,0};
|
||||||
|
for(int i = 0; i < 2; i++) {
|
||||||
|
if((src->type[i] == pokemon_types_gen1_bin[(2*src->species)]) && (!matched[0]))
|
||||||
|
matched[0] = 1;
|
||||||
|
else if((src->type[i] == pokemon_types_gen1_bin[(2*src->species)+1]) && (!matched[1]))
|
||||||
|
matched[1] = 1;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 2; i++)
|
||||||
|
if(!matched[i])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 validate_converting_mon_of_gen2(u8 index, struct gen2_mon_data* src, u8* is_egg) {
|
||||||
|
if(index == GEN2_EGG)
|
||||||
|
*is_egg = 1;
|
||||||
|
else
|
||||||
|
*is_egg = 0;
|
||||||
|
|
||||||
|
// Check for matching index to species
|
||||||
|
if((!(*is_egg)) && (index != src->species))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Is this a valid mon
|
||||||
|
if((src->species > LAST_VALID_GEN_2_MON) || (src->species == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Does it have a valid movepool
|
||||||
|
if(!has_legal_moves_gen12(src->moves, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 validate_converting_mon_of_gen3(struct gen3_mon* src, struct gen3_mon_growth* growth, u8 is_shiny, u8 gender, u8 gender_kind, u8 is_egg, u8 is_gen2) {
|
||||||
|
u8 last_valid_mon = LAST_VALID_GEN_1_MON;
|
||||||
|
if(is_gen2)
|
||||||
|
last_valid_mon = LAST_VALID_GEN_2_MON;
|
||||||
|
|
||||||
|
// Bad egg checks
|
||||||
|
if(src->is_bad_egg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Item checks
|
||||||
|
if(has_mail(src, growth, is_egg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Validity checks
|
||||||
|
if((growth->species > last_valid_mon) || (growth->species == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// These Pokemon cannot be both female and shiny in gen 1/2
|
||||||
|
if(is_shiny && (gender == F_GENDER) && (gender_kind == MF_7_1_INDEX))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Unown ! and ? did not exist in gen 2
|
||||||
|
// Not only that, but only Unown I and V can be shiny
|
||||||
|
if(is_gen2 && (growth->species == UNOWN_SPECIES)) {
|
||||||
|
u8 letter = get_unown_letter_gen3(src->pid);
|
||||||
|
if(letter >= UNOWN_EX_LETTER)
|
||||||
|
return 0;
|
||||||
|
if(is_shiny && (letter != UNOWN_I_LETTER) && (letter != UNOWN_V_LETTER))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eggs cannot be traded to gen 1
|
||||||
|
if((!is_gen2) && is_egg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 convert_moves_of_gen3(struct gen3_mon_attacks* attacks, u8 pp_bonuses, u8* moves, u8* pps, u8 is_gen2) {
|
||||||
|
// Start converting moves
|
||||||
|
u16 last_valid_move = LAST_VALID_GEN_1_MOVE;
|
||||||
|
if(is_gen2)
|
||||||
|
last_valid_move = LAST_VALID_GEN_2_MOVE;
|
||||||
|
|
||||||
|
u8 used_slots = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < MOVES_SIZE; i++)
|
||||||
|
{
|
||||||
|
moves[i] = 0;
|
||||||
|
pps[i] = 0;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < MOVES_SIZE; i++) {
|
||||||
|
u16 move = attacks->moves[i];
|
||||||
|
if((move > 0) && (move <= last_valid_move)) {
|
||||||
|
u8 base_pp = pokemon_moves_pp_bin[move];
|
||||||
|
u8 bonus_pp = (pp_bonuses >> (2*i)) & 3;
|
||||||
|
u8 base_increase_pp = Div(base_pp, 5);
|
||||||
|
base_pp += (base_increase_pp * bonus_pp);
|
||||||
|
// Limit the PP to its maximum of 61
|
||||||
|
if(base_pp > 61)
|
||||||
|
base_pp = 61;
|
||||||
|
base_pp |= (bonus_pp << 6);
|
||||||
|
pps[used_slots] = base_pp;
|
||||||
|
moves[used_slots++] = move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return used_slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 convert_moves_to_gen3(struct gen3_mon_attacks* attacks, struct gen3_mon_growth* growth, u8* moves, u8* pps, u8 is_gen2) {
|
||||||
|
// Start converting moves
|
||||||
|
u8 last_valid_move = LAST_VALID_GEN_1_MOVE;
|
||||||
|
if(is_gen2)
|
||||||
|
last_valid_move = LAST_VALID_GEN_2_MOVE;
|
||||||
|
|
||||||
|
u8 used_slots = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < MOVES_SIZE; i++) {
|
||||||
|
u16 move = moves[i];
|
||||||
|
if((move > 0) && (move <= last_valid_move)) {
|
||||||
|
u8 base_pp = pokemon_moves_pp_bin[move];
|
||||||
|
u8 bonus_pp = (pps[i] >> 6) & 3;
|
||||||
|
u8 base_increase_pp = Div(base_pp, 5);
|
||||||
|
base_pp += (base_increase_pp * bonus_pp);
|
||||||
|
|
||||||
|
growth->pp_bonuses |= (bonus_pp)<<(2*i);
|
||||||
|
attacks->pp[used_slots] = base_pp;
|
||||||
|
attacks->moves[used_slots++] = move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return used_slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 convert_item_of_gen3(u16 item) {
|
||||||
|
if(item > LAST_VALID_GEN_3_ITEM)
|
||||||
|
item = 0;
|
||||||
|
item = item_gen3_to_12_bin[item];
|
||||||
|
if((item == GEN2_NO_ITEM) || (item == GEN2_MAIL))
|
||||||
|
item = 0;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 convert_item_to_gen3(u16 item) {
|
||||||
|
item = item_gen12_to_3_bin[item*2] + (item_gen12_to_3_bin[(item*2)+1]<<8);
|
||||||
|
if(item == GEN3_NO_ITEM)
|
||||||
|
item = 0;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert_exp_nature_of_gen3(struct gen3_mon* src, struct gen3_mon_growth* growth, u8* level_ptr, u8* exp_ptr, u8 is_gen2) {
|
||||||
|
if(((is_gen2) && (growth->species > LAST_VALID_GEN_2_MON)) || ((!is_gen2) && (growth->species > LAST_VALID_GEN_1_MON)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Level handling
|
||||||
|
u8 level = to_valid_level_gen3(src);
|
||||||
|
|
||||||
|
u16 mon_index = get_mon_index(growth->species, src->pid, 0, 0);
|
||||||
|
|
||||||
|
// Experience handling
|
||||||
|
s32 exp = get_proper_exp(src, growth, 0);
|
||||||
|
|
||||||
|
s32 max_exp = exp;
|
||||||
|
if(level < MAX_LEVEL)
|
||||||
|
max_exp = get_level_exp_mon_index(mon_index, level+1)-1;
|
||||||
|
|
||||||
|
// Save nature in experience, like the Gen I-VII conversion
|
||||||
|
u8 nature = get_nature(src->pid);
|
||||||
|
|
||||||
|
// Nature handling
|
||||||
|
u8 exp_nature = DivMod(exp, NUM_NATURES);
|
||||||
|
if(exp_nature > nature)
|
||||||
|
nature += NUM_NATURES;
|
||||||
|
exp += nature - exp_nature;
|
||||||
|
if (level < MAX_LEVEL)
|
||||||
|
while (exp > max_exp) {
|
||||||
|
level++;
|
||||||
|
if(level == MAX_LEVEL) {
|
||||||
|
exp = max_exp+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
max_exp = get_level_exp_mon_index(mon_index, level+1)-1;
|
||||||
|
}
|
||||||
|
if ((level == MAX_LEVEL) && (exp != get_level_exp_mon_index(mon_index, MAX_LEVEL))){
|
||||||
|
level--;
|
||||||
|
exp -= NUM_NATURES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store exp and level
|
||||||
|
*level_ptr = level;
|
||||||
|
for(int i = 0; i < 3; i++)
|
||||||
|
exp_ptr[2-i] = (exp >> (8*i))&0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 get_exp_nature(struct gen3_mon* dst, struct gen3_mon_growth* growth, u8 level, u8* given_exp) {
|
||||||
|
// Level handling
|
||||||
|
level = to_valid_level(level);
|
||||||
|
|
||||||
|
u16 mon_index = get_mon_index_gen2(growth->species, 0);
|
||||||
|
|
||||||
|
// Experience handling
|
||||||
|
s32 exp = get_proper_exp_gen2(mon_index, level, given_exp);
|
||||||
|
|
||||||
|
// Save nature in experience, like the Gen I-VII conversion
|
||||||
|
u8 nature = SWI_DivMod(exp, NUM_NATURES);
|
||||||
|
|
||||||
|
// Store exp and level
|
||||||
|
dst->level = level;
|
||||||
|
growth->exp = exp;
|
||||||
|
return nature;
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert_evs_of_gen3(struct gen3_mon_evs* evs, u16* old_evs) {
|
||||||
|
// Convert to Gen1/2 EVs
|
||||||
|
u16 evs_total = 0;
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN3; i++)
|
||||||
|
evs_total += evs->evs[i];
|
||||||
|
if(evs_total >= MAX_USABLE_EVS)
|
||||||
|
evs_total = MAX_EVS;
|
||||||
|
u16 new_evs = ((evs_total+1)>>1) * ((evs_total+1)>>1);
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN12; i++)
|
||||||
|
old_evs[i] = swap_endian_short(new_evs & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert_evs_to_gen3(struct gen3_mon_evs* evs, u16* UNUSED(old_evs)) {
|
||||||
|
// A direct conversion is possible, but it would be
|
||||||
|
// atrocious for competitive/high-level battling...
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN3; i++)
|
||||||
|
evs->evs[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 convert_ivs_of_gen3(struct gen3_mon_misc* misc, u16 species, u32 pid, u8 is_shiny, u8 gender, u8 gender_kind, u8 is_gen2) {
|
||||||
|
if(((is_gen2) && (species > LAST_VALID_GEN_2_MON)) || ((!is_gen2) && (species > LAST_VALID_GEN_1_MON)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Assign IVs
|
||||||
|
// Keep in mind: Unown letter, gender and shinyness
|
||||||
|
// Hidden Power calculations are too restrictive
|
||||||
|
u8 atk_ivs = misc->atk_ivs >> 1;
|
||||||
|
u8 def_ivs = misc->def_ivs >> 1;
|
||||||
|
u8 spa_ivs = (misc->spa_ivs + misc->spd_ivs) >> 2;
|
||||||
|
u8 spe_ivs = misc->spe_ivs >> 1;
|
||||||
|
|
||||||
|
// Handle roamers losing IVs when caught
|
||||||
|
u8 origin_game = (misc->origins_info>>7)&0xF;
|
||||||
|
if(((species >= RAIKOU_SPECIES) && (species <= SUICUNE_SPECIES)) && ((origin_game == FR_VERSION_ID) || (origin_game == LG_VERSION_ID))) {
|
||||||
|
u32 real_ivs = 0;
|
||||||
|
if(get_roamer_ivs(pid, misc->hp_ivs, misc->atk_ivs, &real_ivs)){
|
||||||
|
atk_ivs = ((real_ivs >> 5) & 0x1F) >> 1;
|
||||||
|
def_ivs = ((real_ivs >> 10) & 0x1F) >> 1;
|
||||||
|
spa_ivs = (((real_ivs >> 20) & 0x1F) + ((real_ivs >> 25) & 0x1F)) >> 2;
|
||||||
|
spe_ivs = ((real_ivs >> 15) & 0x1F) >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unown letter
|
||||||
|
if((is_gen2) && (species == UNOWN_SPECIES)) {
|
||||||
|
u8 letter = get_unown_letter_gen3(pid);
|
||||||
|
u8 min_iv_sum = letter * 10;
|
||||||
|
u16 max_iv_sum = ((letter+1) * 10)-1;
|
||||||
|
if(max_iv_sum >= 0x100)
|
||||||
|
max_iv_sum = 0xFF;
|
||||||
|
u8 iv_sum = ((spa_ivs & 0x6) >> 1) | ((spe_ivs & 0x6) << 1) | ((def_ivs & 0x6) << 3) | ((atk_ivs & 0x6) << 5);
|
||||||
|
if(iv_sum < min_iv_sum)
|
||||||
|
iv_sum = min_iv_sum;
|
||||||
|
if(iv_sum > max_iv_sum)
|
||||||
|
iv_sum = max_iv_sum;
|
||||||
|
atk_ivs = (atk_ivs & 0x9) | ((iv_sum >> 5) & 0x6);
|
||||||
|
def_ivs = (def_ivs & 0x9) | ((iv_sum >> 3) & 0x6);
|
||||||
|
spe_ivs = (spe_ivs & 0x9) | ((iv_sum >> 1) & 0x6);
|
||||||
|
spa_ivs = (spa_ivs & 0x9) | ((iv_sum << 1) & 0x6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gender
|
||||||
|
// TODO: Remake this to offer a more fair conversion
|
||||||
|
if(gender != U_GENDER && gender_kind != M_INDEX && gender_kind != F_INDEX) {
|
||||||
|
if(gender == F_GENDER && atk_ivs >= get_gender_thresholds_gen12(gender_kind))
|
||||||
|
atk_ivs = get_gender_thresholds_gen12(gender_kind) - 1;
|
||||||
|
else if(gender == M_GENDER && atk_ivs < get_gender_thresholds_gen12(gender_kind))
|
||||||
|
atk_ivs = get_gender_thresholds_gen12(gender_kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shinyness
|
||||||
|
if(is_shiny) {
|
||||||
|
atk_ivs = atk_ivs | 2;
|
||||||
|
def_ivs = 10;
|
||||||
|
spa_ivs = 10;
|
||||||
|
spe_ivs = 10;
|
||||||
|
}
|
||||||
|
if(!is_shiny && is_shiny_gen2(atk_ivs, def_ivs, spa_ivs, spe_ivs))
|
||||||
|
spe_ivs = 11;
|
||||||
|
|
||||||
|
return (atk_ivs << 4) | def_ivs | (spa_ivs << 8) | (spe_ivs << 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_ivs(struct gen3_mon_misc* misc, u32 ivs) {
|
||||||
|
misc->hp_ivs = (ivs >> 0) & 0x1F;
|
||||||
|
misc->atk_ivs = (ivs >> 5) & 0x1F;
|
||||||
|
misc->def_ivs = (ivs >> 10) & 0x1F;
|
||||||
|
misc->spe_ivs = (ivs >> 15) & 0x1F;
|
||||||
|
misc->spa_ivs = (ivs >> 20) & 0x1F;
|
||||||
|
misc->spd_ivs = (ivs >> 25) & 0x1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_misc* misc, u16 species, u16 wanted_ivs, u8 wanted_nature, u8 ot_gender, u8 is_egg, u8 no_restrictions) {
|
||||||
|
struct game_data_t* trainer_data = get_own_game_data();
|
||||||
|
u8 trainer_game_version = id_to_version(&trainer_data->game_identifier);
|
||||||
|
u8 trainer_gender = trainer_data->trainer_gender;
|
||||||
|
|
||||||
|
// Handle eggs separately
|
||||||
|
u32 ot_id = dst->ot_id;
|
||||||
|
if(is_egg)
|
||||||
|
ot_id = trainer_data->trainer_id;
|
||||||
|
|
||||||
|
// Prepare the TSV
|
||||||
|
u16 tsv = (ot_id & 0xFFFF) ^ (ot_id >> 16);
|
||||||
|
|
||||||
|
u8 chosen_version = FR_VERSION_ID;
|
||||||
|
if(!no_restrictions) {
|
||||||
|
chosen_version = trainer_game_version;
|
||||||
|
ot_gender = trainer_gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 encounter_type = (encounter_types_bin[species>>2]>>(2*(species&3)))&3;
|
||||||
|
u8 is_shiny = is_shiny_gen2_unfiltered(wanted_ivs);
|
||||||
|
u32 ivs = 0;
|
||||||
|
const u8* searchable_table = egg_locations_bin;
|
||||||
|
u8 find_in_table = 0;
|
||||||
|
|
||||||
|
// Get PID and IVs
|
||||||
|
switch(encounter_type) {
|
||||||
|
case STATIC_ENCOUNTER:
|
||||||
|
if(!is_shiny)
|
||||||
|
generate_static_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs);
|
||||||
|
else
|
||||||
|
generate_static_shiny_info(wanted_nature, tsv, &dst->pid, &ivs);
|
||||||
|
searchable_table = encounters_static_bin;
|
||||||
|
find_in_table = 1;
|
||||||
|
break;
|
||||||
|
case ROAMER_ENCOUNTER:
|
||||||
|
if(!is_shiny)
|
||||||
|
generate_static_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs);
|
||||||
|
else
|
||||||
|
generate_static_shiny_info(wanted_nature, tsv, &dst->pid, &ivs);
|
||||||
|
// Roamers only get the first byte of their IVs
|
||||||
|
ivs &= 0xFF;
|
||||||
|
searchable_table = encounters_roamers_bin;
|
||||||
|
find_in_table = 1;
|
||||||
|
break;
|
||||||
|
case UNOWN_ENCOUNTER:
|
||||||
|
if(!is_shiny)
|
||||||
|
generate_unown_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs);
|
||||||
|
else
|
||||||
|
generate_unown_shiny_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs);
|
||||||
|
searchable_table = encounters_unown_bin;
|
||||||
|
find_in_table = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(!is_shiny)
|
||||||
|
generate_egg_info(species, wanted_nature, wanted_ivs, tsv, 2, &dst->pid, &ivs);
|
||||||
|
else
|
||||||
|
generate_egg_shiny_info(species, wanted_nature, wanted_ivs, tsv, 2, &dst->pid, &ivs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set met location and origins info
|
||||||
|
u8 met_location = egg_locations_bin[chosen_version];
|
||||||
|
u8 met_level = 0;
|
||||||
|
|
||||||
|
if(find_in_table) {
|
||||||
|
u16 mon_index = get_mon_index(species, dst->pid, 0, 0);
|
||||||
|
const u8* possible_met_data = search_table_for_index(searchable_table, mon_index);
|
||||||
|
if(possible_met_data != NULL) {
|
||||||
|
u8 num_elems = possible_met_data[0];
|
||||||
|
u8 chosen_entry = 0;
|
||||||
|
for(int i = 0; i < num_elems; i++)
|
||||||
|
if(possible_met_data[1+(3*i)] == chosen_version)
|
||||||
|
chosen_entry = i;
|
||||||
|
chosen_version = possible_met_data[1+(3*chosen_entry)];
|
||||||
|
met_location = possible_met_data[2+(3*chosen_entry)];
|
||||||
|
met_level = possible_met_data[3+(3*chosen_entry)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
misc->met_location = met_location;
|
||||||
|
misc->origins_info = ((ot_gender&1)<<15) | ((POKEBALL_ID&0xF)<<11) | ((chosen_version&0xF)<<7) | ((met_level&0x7F)<<0);
|
||||||
|
|
||||||
|
// Set IVs
|
||||||
|
set_ivs(misc, ivs);
|
||||||
|
|
||||||
|
// Set ability
|
||||||
|
if(dst->pid & 1) {
|
||||||
|
u16 abilities = get_possible_abilities_pokemon(species, dst->pid, 0, 0);
|
||||||
|
u8 abilities_same = (abilities&0xFF) == ((abilities>>8)&0xFF);
|
||||||
|
if(!abilities_same)
|
||||||
|
misc->ability = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 are_trainers_same(struct gen3_mon* dst, u8 is_jp) {
|
||||||
|
struct game_data_t* trainer_data = get_own_game_data();
|
||||||
|
u8 trainer_is_jp = trainer_data->game_identifier.game_is_jp;
|
||||||
|
u32 trainer_id = trainer_data->trainer_id;
|
||||||
|
u8* trainer_name = trainer_data->trainer_name;
|
||||||
|
|
||||||
|
// Languages do not match
|
||||||
|
if(is_jp ^ trainer_is_jp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// IDs do not match
|
||||||
|
if((trainer_id & 0xFFFF) != (dst->ot_id & 0xFFFF))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Return whether the OT names are the same
|
||||||
|
return text_gen3_is_same(dst->ot_name, trainer_name, OT_NAME_GEN3_SIZE, OT_NAME_GEN3_SIZE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fix_name_change_from_gen3(struct gen3_mon* src, u16 species, u8* nickname, u8 is_egg, u8 is_gen2) {
|
||||||
|
u8 tmp_text_buffer[NAME_SIZE];
|
||||||
|
|
||||||
|
// Get the string to compare to
|
||||||
|
text_generic_to_gen3(get_pokemon_name(species, src->pid, is_egg, 0), tmp_text_buffer, NAME_SIZE, NICKNAME_GEN3_SIZE, 0, 0);
|
||||||
|
|
||||||
|
// If it's the same, update the nickname with the new one
|
||||||
|
if(text_gen3_is_same(src->nickname, tmp_text_buffer, NICKNAME_GEN3_SIZE, NICKNAME_GEN3_SIZE)) {
|
||||||
|
text_gen2_copy(get_pokemon_name_gen2(species, is_egg, 0, tmp_text_buffer), nickname, STRING_GEN2_INT_CAP, STRING_GEN2_INT_CAP);
|
||||||
|
// Gen 1 used the wrong dot symbol
|
||||||
|
if(!is_gen2)
|
||||||
|
text_gen2_replace(nickname, STRING_GEN2_INT_CAP, GEN2_DOT, GEN1_DOT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fix_name_change_to_gen3(struct gen3_mon* dst, u8 species) {
|
||||||
|
u8 tmp_text_buffer[STRING_GEN2_INT_CAP];
|
||||||
|
u8 tmp_text_buffer2[NICKNAME_GEN3_SIZE];
|
||||||
|
|
||||||
|
// Get the string to compare to
|
||||||
|
text_gen12_to_gen3(get_pokemon_name_gen2(species, 0, 0, tmp_text_buffer), tmp_text_buffer2, STRING_GEN2_INT_CAP, NICKNAME_GEN3_SIZE, 0, 0);
|
||||||
|
|
||||||
|
// If it's the same, update the nickname with the new one
|
||||||
|
if(text_gen3_is_same(dst->nickname, tmp_text_buffer2, NICKNAME_GEN3_SIZE, NICKNAME_GEN3_SIZE))
|
||||||
|
text_generic_to_gen3(get_pokemon_name(species, 0, 0, 0), dst->nickname, NAME_SIZE, NICKNAME_GEN3_SIZE, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
u8 gen2_buffer[STRING_GEN2_INT_SIZE];
|
||||||
|
u8 is_jp = (src->language == JAPANESE_LANGUAGE);
|
||||||
|
|
||||||
|
// Text conversions
|
||||||
|
text_gen2_terminator_fill(ot_name, STRING_GEN2_INT_SIZE);
|
||||||
|
text_gen2_terminator_fill(ot_name_jp, STRING_GEN2_JP_SIZE);
|
||||||
|
text_gen2_terminator_fill(nickname, STRING_GEN2_INT_SIZE);
|
||||||
|
text_gen2_terminator_fill(nickname_jp, STRING_GEN2_JP_SIZE);
|
||||||
|
|
||||||
|
text_gen3_to_gen12(src->ot_name, ot_name, OT_NAME_GEN3_SIZE, STRING_GEN2_INT_CAP, is_jp, 0);
|
||||||
|
text_gen3_to_gen12(src->ot_name, ot_name_jp, OT_NAME_GEN3_SIZE, STRING_GEN2_JP_CAP, is_jp, 1);
|
||||||
|
text_gen3_to_gen12(src->nickname, nickname, NICKNAME_GEN3_SIZE, STRING_GEN2_INT_CAP, is_jp, 0);
|
||||||
|
text_gen3_to_gen12(src->nickname, nickname_jp, NICKNAME_GEN3_SIZE, STRING_GEN2_JP_CAP, is_jp, 1);
|
||||||
|
|
||||||
|
// Fix text up
|
||||||
|
// "MR.MIME" gen 2 == "MR. MIME" gen 3
|
||||||
|
// Idk if something similar happens in Jap...
|
||||||
|
// Maybe there are some French things with accents...
|
||||||
|
if((species == MR_MIME_SPECIES) && !is_egg)
|
||||||
|
fix_name_change_from_gen3(src, species, nickname, is_egg, is_gen2);
|
||||||
|
|
||||||
|
// Put the "EGG" name
|
||||||
|
if(is_gen2 && is_egg) {
|
||||||
|
text_gen2_copy(get_pokemon_name_gen2(species, is_egg, 0, gen2_buffer), nickname, STRING_GEN2_INT_CAP, STRING_GEN2_INT_CAP);
|
||||||
|
text_gen2_copy(get_pokemon_name_gen2(species, is_egg, 1, gen2_buffer), nickname_jp, STRING_GEN2_JP_CAP, STRING_GEN2_JP_CAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle bad naming conversions (? >= half the name) and empty names
|
||||||
|
s32 question_marks_count = text_gen2_count_question(nickname, STRING_GEN2_INT_CAP) - text_gen3_count_question(src->nickname, NICKNAME_GEN3_SIZE);
|
||||||
|
if((question_marks_count >= (text_gen2_size(nickname, STRING_GEN2_INT_CAP) >> 1)) || (text_gen2_size(nickname, STRING_GEN2_INT_CAP) == 0))
|
||||||
|
text_gen2_copy(get_pokemon_name_gen2(species, is_egg, 0, gen2_buffer), nickname, STRING_GEN2_INT_CAP, STRING_GEN2_INT_CAP);
|
||||||
|
// For the japanese nickname too
|
||||||
|
question_marks_count = text_gen2_count_question(nickname_jp, STRING_GEN2_JP_CAP) - text_gen3_count_question(src->nickname, NICKNAME_GEN3_SIZE);
|
||||||
|
if((question_marks_count >= (text_gen2_size(nickname_jp, STRING_GEN2_JP_CAP) >> 1)) || (text_gen2_size(nickname_jp, STRING_GEN2_JP_CAP) == 0))
|
||||||
|
text_gen2_copy(get_pokemon_name_gen2(species, is_egg, 1, gen2_buffer), nickname_jp, STRING_GEN2_JP_CAP, STRING_GEN2_JP_CAP);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void convert_strings_of_gen12(struct gen3_mon* dst, u8 species, u8* ot_name, u8* nickname, u8 is_egg) {
|
||||||
|
u8 gen2_buffer[STRING_GEN2_INT_SIZE];
|
||||||
|
u8 is_jp = (dst->language == JAPANESE_LANGUAGE);
|
||||||
|
|
||||||
|
u8 name_cap = STRING_GEN2_INT_CAP;
|
||||||
|
if(is_jp)
|
||||||
|
name_cap = STRING_GEN2_JP_CAP;
|
||||||
|
|
||||||
|
// Text conversions
|
||||||
|
text_gen3_terminator_fill(dst->nickname, NICKNAME_GEN3_SIZE);
|
||||||
|
text_gen3_terminator_fill(dst->ot_name, OT_NAME_GEN3_SIZE);
|
||||||
|
|
||||||
|
text_gen12_to_gen3(nickname, dst->nickname, name_cap, NICKNAME_GEN3_SIZE, is_jp, is_jp);
|
||||||
|
text_gen12_to_gen3(ot_name, dst->ot_name, name_cap, OT_NAME_GEN3_SIZE, is_jp, is_jp);
|
||||||
|
|
||||||
|
// Handle Mew's special Japanese-only nature
|
||||||
|
if(species == MEW_SPECIES) {
|
||||||
|
dst->language = JAPANESE_LANGUAGE;
|
||||||
|
text_gen12_to_gen3(nickname, dst->nickname, name_cap, NICKNAME_JP_GEN3_SIZE, is_jp, 1);
|
||||||
|
text_gen12_to_gen3(ot_name, dst->ot_name, name_cap, OT_NAME_JP_GEN3_SIZE, is_jp, 1);
|
||||||
|
name_cap = STRING_GEN2_JP_CAP;
|
||||||
|
is_jp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix text up
|
||||||
|
// "MR.MIME" gen 2 == "MR. MIME" gen 3
|
||||||
|
// Idk if something similar happens in Jap...
|
||||||
|
// Maybe there are some French things with accents...
|
||||||
|
if((species == MR_MIME_SPECIES) && !is_egg && !is_jp)
|
||||||
|
fix_name_change_to_gen3(dst, species);
|
||||||
|
|
||||||
|
// Put the "EGG" name
|
||||||
|
if(is_egg) {
|
||||||
|
dst->language = JAPANESE_LANGUAGE;
|
||||||
|
text_gen12_to_gen3(get_pokemon_name_gen2(species, 1, 1, gen2_buffer), dst->nickname, STRING_GEN2_JP_CAP, NICKNAME_GEN3_SIZE, 1, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Handle bad naming conversions (? >= half the name) and empty names
|
||||||
|
s32 question_marks_count = text_gen3_count_question(dst->nickname, NICKNAME_GEN3_SIZE) - text_gen2_count_question(nickname, name_cap);
|
||||||
|
if((question_marks_count >= (text_gen3_size(dst->nickname, NICKNAME_GEN3_SIZE) >> 1)) || (text_gen3_size(dst->nickname, NICKNAME_GEN3_SIZE) == 0))
|
||||||
|
text_gen12_to_gen3(get_pokemon_name_gen2(species, 0, is_jp, gen2_buffer), dst->nickname, name_cap, NICKNAME_GEN3_SIZE, is_jp, is_jp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 gen3_to_gen2(struct gen2_mon* dst_data, struct gen3_mon_data_unenc* data_src, u32 trainer_id) {
|
||||||
|
|
||||||
|
struct gen3_mon* src = data_src->src;
|
||||||
|
struct gen2_mon_data* dst = &dst_data->data;
|
||||||
|
|
||||||
|
if(!data_src->is_valid_gen3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct gen3_mon_growth* growth = &data_src->growth;
|
||||||
|
struct gen3_mon_attacks* attacks = &data_src->attacks;
|
||||||
|
struct gen3_mon_evs* evs = &data_src->evs;
|
||||||
|
struct gen3_mon_misc* misc = &data_src->misc;
|
||||||
|
|
||||||
|
// Get shinyness and gender for checks
|
||||||
|
u8 is_shiny = is_shiny_gen3_raw(data_src, trainer_id);
|
||||||
|
u8 gender = get_pokemon_gender_gen3(growth->species, src->pid, 0, data_src->deoxys_form);
|
||||||
|
u8 gender_kind = get_pokemon_gender_kind_gen3(growth->species, src->pid, 0, data_src->deoxys_form);
|
||||||
|
|
||||||
|
// Check that the mon can be traded
|
||||||
|
if(!validate_converting_mon_of_gen3(src, growth, is_shiny, gender, gender_kind, data_src->is_egg, 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Reset data structure
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen2_mon); i++)
|
||||||
|
((u8*)dst_data)[i] = 0;
|
||||||
|
|
||||||
|
// Start setting data
|
||||||
|
dst->species = growth->species;
|
||||||
|
|
||||||
|
// Convert moves, and check if no valid moves were found
|
||||||
|
if(convert_moves_of_gen3(attacks, growth->pp_bonuses, dst->moves, dst->pps, 1) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Item handling
|
||||||
|
dst->item = convert_item_of_gen3(growth->item);
|
||||||
|
|
||||||
|
// OT handling
|
||||||
|
dst->ot_id = swap_endian_short(src->ot_id & 0xFFFF);
|
||||||
|
|
||||||
|
// Assign level and experience
|
||||||
|
convert_exp_nature_of_gen3(src, growth, &dst->level, dst->exp, 1);
|
||||||
|
|
||||||
|
// Convert EVs
|
||||||
|
u16 evs_container[EVS_TOTAL_GEN12];
|
||||||
|
convert_evs_of_gen3(evs, evs_container);
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN12; i++)
|
||||||
|
dst->evs[i] = evs_container[i];
|
||||||
|
|
||||||
|
// Assign IVs
|
||||||
|
dst->ivs = convert_ivs_of_gen3(misc, growth->species, src->pid, is_shiny, gender, gender_kind, 1);
|
||||||
|
|
||||||
|
// Is this really how it works...?
|
||||||
|
dst->pokerus = misc->pokerus;
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
dst->friendship = BASE_FRIENDSHIP;
|
||||||
|
dst->status = 0;
|
||||||
|
dst->unused = 0;
|
||||||
|
|
||||||
|
// Handle met location data
|
||||||
|
dst->time = 1;
|
||||||
|
dst->ot_gender = (misc->origins_info>>15)&1;
|
||||||
|
|
||||||
|
// Handle special mons which cannot breed
|
||||||
|
const struct special_met_data_gen2* met_data = NULL;
|
||||||
|
if(encounter_types_gen2_bin[dst->species>>3]&(1<<(dst->species&7))) {
|
||||||
|
met_data = (const struct special_met_data_gen2*)search_table_for_index(special_encounters_gen2_bin, dst->species);
|
||||||
|
if(met_data != NULL) {
|
||||||
|
dst->location = met_data->location;
|
||||||
|
dst->met_level = met_data->level;
|
||||||
|
if((dst->location == 0) && (dst->location == dst->met_level)) {
|
||||||
|
dst->time = 0;
|
||||||
|
dst->ot_gender = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(met_data == NULL) {
|
||||||
|
dst->met_level = 1;
|
||||||
|
dst->location = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra byte for egg data
|
||||||
|
dst_data->is_egg = data_src->is_egg;
|
||||||
|
|
||||||
|
// Stats calculations
|
||||||
|
// Curr HP should be 0 for eggs, otherwise they count as party members
|
||||||
|
if(!dst_data->is_egg)
|
||||||
|
dst->curr_hp = swap_endian_short(calc_stats_gen2(growth->species, src->pid, HP_STAT_INDEX, dst->level, get_ivs_gen2(dst->ivs, HP_STAT_INDEX), swap_endian_short(dst->evs[HP_STAT_INDEX])));
|
||||||
|
else
|
||||||
|
dst->curr_hp = 0;
|
||||||
|
for(int i = 0; i < GEN2_STATS_TOTAL; i++)
|
||||||
|
dst->stats[i] = swap_endian_short(calc_stats_gen2(growth->species, src->pid, i, dst->level, get_ivs_gen2(dst->ivs, i), swap_endian_short(dst->evs[i >= EVS_TOTAL_GEN12 ? EVS_TOTAL_GEN12-1 : i])));
|
||||||
|
|
||||||
|
// Store egg cycles
|
||||||
|
if(dst_data->is_egg)
|
||||||
|
dst->friendship = growth->friendship;
|
||||||
|
|
||||||
|
// Text conversions
|
||||||
|
convert_strings_of_gen3(src, growth->species, dst_data->ot_name, dst_data->ot_name_jp, dst_data->nickname, dst_data->nickname_jp, dst_data->is_egg, 1);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 gen3_to_gen1(struct gen1_mon* dst_data, struct gen3_mon_data_unenc* data_src, u32 trainer_id) {
|
||||||
|
|
||||||
|
struct gen3_mon* src = data_src->src;
|
||||||
|
struct gen1_mon_data* dst = &dst_data->data;
|
||||||
|
|
||||||
|
if(!data_src->is_valid_gen3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct gen3_mon_growth* growth = &data_src->growth;
|
||||||
|
struct gen3_mon_attacks* attacks = &data_src->attacks;
|
||||||
|
struct gen3_mon_evs* evs = &data_src->evs;
|
||||||
|
struct gen3_mon_misc* misc = &data_src->misc;
|
||||||
|
|
||||||
|
// Get shinyness and gender for checks
|
||||||
|
u8 is_shiny = is_shiny_gen3_raw(data_src, trainer_id);
|
||||||
|
u8 gender = get_pokemon_gender_gen3(growth->species, src->pid, 0, data_src->deoxys_form);
|
||||||
|
u8 gender_kind = get_pokemon_gender_kind_gen3(growth->species, src->pid, 0, data_src->deoxys_form);
|
||||||
|
|
||||||
|
// Check that the mon can be traded
|
||||||
|
if(!validate_converting_mon_of_gen3(src, growth, is_shiny, gender, gender_kind, data_src->is_egg, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Reset data structure
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen1_mon); i++)
|
||||||
|
((u8*)dst_data)[i] = 0;
|
||||||
|
|
||||||
|
// Start setting data
|
||||||
|
dst->species = get_mon_index_gen1(growth->species);
|
||||||
|
|
||||||
|
// Convert moves, and check if no valid moves were found
|
||||||
|
if(convert_moves_of_gen3(attacks, growth->pp_bonuses, dst->moves, dst->pps, 0) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Item handling
|
||||||
|
dst->item = convert_item_of_gen3(growth->item);
|
||||||
|
|
||||||
|
// Types handling
|
||||||
|
dst->type[0] = pokemon_types_gen1_bin[(2*dst->species)];
|
||||||
|
dst->type[1] = pokemon_types_gen1_bin[(2*dst->species) + 1];
|
||||||
|
|
||||||
|
// OT handling
|
||||||
|
dst->ot_id = swap_endian_short(src->ot_id & 0xFFFF);
|
||||||
|
|
||||||
|
// Assign level and experience
|
||||||
|
convert_exp_nature_of_gen3(src, growth, &dst->level, dst->exp, 0);
|
||||||
|
|
||||||
|
// Convert EVs
|
||||||
|
u16 evs_container[EVS_TOTAL_GEN12];
|
||||||
|
convert_evs_of_gen3(evs, evs_container);
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN12; i++)
|
||||||
|
dst->evs[i] = evs_container[i];
|
||||||
|
|
||||||
|
// Assign IVs
|
||||||
|
dst->ivs = convert_ivs_of_gen3(misc, growth->species, src->pid, is_shiny, gender, gender_kind, 0);
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
dst->bad_level = 0;
|
||||||
|
dst->status = 0;
|
||||||
|
|
||||||
|
// Stats calculations
|
||||||
|
dst->curr_hp = swap_endian_short(calc_stats_gen1(growth->species, HP_STAT_INDEX, dst->level, get_ivs_gen2(dst->ivs, HP_STAT_INDEX), swap_endian_short(dst->evs[HP_STAT_INDEX])));
|
||||||
|
for(int i = 0; i < GEN1_STATS_TOTAL; i++)
|
||||||
|
dst->stats[i] = swap_endian_short(calc_stats_gen1(growth->species, i, dst->level, get_ivs_gen2(dst->ivs, i), swap_endian_short(dst->evs[i])));
|
||||||
|
|
||||||
|
// Text conversions
|
||||||
|
convert_strings_of_gen3(src, growth->species, dst_data->ot_name, dst_data->ot_name_jp, dst_data->nickname, dst_data->nickname_jp, 0, 0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 gen2_to_gen3(struct gen2_mon_data* src, struct gen3_mon_data_unenc* data_dst, u8 index, u8* ot_name, u8* nickname, u8 is_jp) {
|
||||||
|
struct gen3_mon* dst = data_dst->src;
|
||||||
|
u8 no_restrictions = 1;
|
||||||
|
u8 is_egg = 0;
|
||||||
|
|
||||||
|
// Reset everything
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon); i++)
|
||||||
|
((u8*)(dst))[i] = 0;
|
||||||
|
|
||||||
|
data_dst->is_valid_gen3 = 0;
|
||||||
|
data_dst->is_valid_gen2 = 0;
|
||||||
|
|
||||||
|
// Check if valid
|
||||||
|
if(!validate_converting_mon_of_gen2(index, src, &is_egg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
data_dst->is_valid_gen3 = 1;
|
||||||
|
data_dst->is_valid_gen2 = 1;
|
||||||
|
|
||||||
|
// Set base data
|
||||||
|
dst->has_species = 1;
|
||||||
|
dst->mail_id = GEN3_NO_MAIL;
|
||||||
|
data_dst->is_egg = is_egg;
|
||||||
|
|
||||||
|
if(is_jp)
|
||||||
|
dst->language = JAPANESE_LANGUAGE;
|
||||||
|
else
|
||||||
|
dst->language = ENGLISH_LANGUAGE;
|
||||||
|
|
||||||
|
// Handle Nickname + OT conversion
|
||||||
|
convert_strings_of_gen12(dst, src->species, ot_name, nickname, is_egg);
|
||||||
|
|
||||||
|
// Handle OT ID, if same as the game owner, set it to the game owner's
|
||||||
|
dst->ot_id = swap_endian_short(src->ot_id);
|
||||||
|
|
||||||
|
if(are_trainers_same(dst, is_jp)) {
|
||||||
|
no_restrictions = 0;
|
||||||
|
dst->ot_id = get_own_game_data()->trainer_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dst->ot_id = generate_ot(dst->ot_id, dst->ot_name);
|
||||||
|
|
||||||
|
// Reset everything
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_growth); i++)
|
||||||
|
((u8*)(&data_dst->growth))[i] = 0;
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_attacks); i++)
|
||||||
|
((u8*)(&data_dst->attacks))[i] = 0;
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_evs); i++)
|
||||||
|
((u8*)(&data_dst->evs))[i] = 0;
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_misc); i++)
|
||||||
|
((u8*)(&data_dst->misc))[i] = 0;
|
||||||
|
|
||||||
|
// Set species, exp, level and item
|
||||||
|
data_dst->growth.species = src->species;
|
||||||
|
u8 wanted_nature = get_exp_nature(dst, &data_dst->growth, src->level, src->exp);
|
||||||
|
data_dst->growth.item = convert_item_to_gen3(src->item);
|
||||||
|
|
||||||
|
// Convert EVs
|
||||||
|
u16 evs_container[EVS_TOTAL_GEN12];
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN12; i++)
|
||||||
|
evs_container[i] = src->evs[i];
|
||||||
|
convert_evs_to_gen3(&data_dst->evs, evs_container);
|
||||||
|
|
||||||
|
// Handle cases in which the nature would be forced
|
||||||
|
if((dst->level == MAX_LEVEL) || (is_egg))
|
||||||
|
wanted_nature = SWI_DivMod(get_rng(), NUM_NATURES);
|
||||||
|
|
||||||
|
// Store egg cycles
|
||||||
|
if(is_egg) {
|
||||||
|
data_dst->growth.friendship = src->friendship;
|
||||||
|
data_dst->misc.is_egg = 1;
|
||||||
|
dst->use_egg_name = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data_dst->growth.friendship = BASE_FRIENDSHIP;
|
||||||
|
|
||||||
|
// Set the moves
|
||||||
|
convert_moves_to_gen3(&data_dst->attacks, &data_dst->growth, src->moves, src->pps, 1);
|
||||||
|
|
||||||
|
data_dst->misc.pokerus = src->pokerus;
|
||||||
|
|
||||||
|
// Special Mew handling
|
||||||
|
if(data_dst->growth.species == MEW_SPECIES)
|
||||||
|
data_dst->misc.obedience = 1;
|
||||||
|
|
||||||
|
// Set the PID-Origin-IVs data, they're all connected
|
||||||
|
set_origin_pid_iv(dst, &data_dst->misc, data_dst->growth.species, src->ivs, wanted_nature, src->ot_gender, is_egg, no_restrictions);
|
||||||
|
|
||||||
|
// Place all the substructures' data
|
||||||
|
place_and_encrypt_gen3_data(data_dst, dst);
|
||||||
|
|
||||||
|
// Calculate stats
|
||||||
|
recalc_stats_gen3(data_dst, dst);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 gen1_to_gen3(struct gen1_mon_data* src, struct gen3_mon_data_unenc* data_dst, u8 index, u8* ot_name, u8* nickname, u8 is_jp) {
|
||||||
|
struct gen3_mon* dst = data_dst->src;
|
||||||
|
u8 no_restrictions = 1;
|
||||||
|
|
||||||
|
// Reset everything
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon); i++)
|
||||||
|
((u8*)(dst))[i] = 0;
|
||||||
|
|
||||||
|
data_dst->is_valid_gen3 = 0;
|
||||||
|
data_dst->is_valid_gen1 = 0;
|
||||||
|
|
||||||
|
// Check if valid
|
||||||
|
if(!validate_converting_mon_of_gen1(index, src))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
data_dst->is_valid_gen3 = 1;
|
||||||
|
data_dst->is_valid_gen1 = 1;
|
||||||
|
|
||||||
|
// Set base data
|
||||||
|
dst->has_species = 1;
|
||||||
|
dst->mail_id = GEN3_NO_MAIL;
|
||||||
|
data_dst->is_egg = 0;
|
||||||
|
|
||||||
|
if(is_jp)
|
||||||
|
dst->language = JAPANESE_LANGUAGE;
|
||||||
|
else
|
||||||
|
dst->language = ENGLISH_LANGUAGE;
|
||||||
|
|
||||||
|
// Handle Nickname + OT conversion
|
||||||
|
convert_strings_of_gen12(dst, get_mon_index_gen1_to_3(src->species), ot_name, nickname, 0);
|
||||||
|
|
||||||
|
// Handle OT ID, if same as the game owner, set it to the game owner's
|
||||||
|
dst->ot_id = swap_endian_short(src->ot_id);
|
||||||
|
|
||||||
|
if(are_trainers_same(dst, is_jp)) {
|
||||||
|
no_restrictions = 0;
|
||||||
|
dst->ot_id = get_own_game_data()->trainer_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dst->ot_id = generate_ot(dst->ot_id, dst->ot_name);
|
||||||
|
|
||||||
|
// Reset everything
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_growth); i++)
|
||||||
|
((u8*)(&data_dst->growth))[i] = 0;
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_attacks); i++)
|
||||||
|
((u8*)(&data_dst->attacks))[i] = 0;
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_evs); i++)
|
||||||
|
((u8*)(&data_dst->evs))[i] = 0;
|
||||||
|
for(u32 i = 0; i < sizeof(struct gen3_mon_misc); i++)
|
||||||
|
((u8*)(&data_dst->misc))[i] = 0;
|
||||||
|
|
||||||
|
// Set species, exp, level and item
|
||||||
|
data_dst->growth.species = get_mon_index_gen1_to_3(src->species);
|
||||||
|
u8 wanted_nature = get_exp_nature(dst, &data_dst->growth, src->level, src->exp);
|
||||||
|
data_dst->growth.item = convert_item_to_gen3(src->item);
|
||||||
|
|
||||||
|
// Convert EVs
|
||||||
|
u16 evs_container[EVS_TOTAL_GEN12];
|
||||||
|
for(int i = 0; i < EVS_TOTAL_GEN12; i++)
|
||||||
|
evs_container[i] = src->evs[i];
|
||||||
|
convert_evs_to_gen3(&data_dst->evs, evs_container);
|
||||||
|
|
||||||
|
// Handle cases in which the nature would be forced
|
||||||
|
if(dst->level == MAX_LEVEL)
|
||||||
|
wanted_nature = SWI_DivMod(get_rng(), NUM_NATURES);
|
||||||
|
|
||||||
|
// Set base friendship
|
||||||
|
data_dst->growth.friendship = BASE_FRIENDSHIP;
|
||||||
|
|
||||||
|
// Set the moves
|
||||||
|
convert_moves_to_gen3(&data_dst->attacks, &data_dst->growth, src->moves, src->pps, 1);
|
||||||
|
|
||||||
|
data_dst->misc.pokerus = 0;
|
||||||
|
|
||||||
|
// Special Mew handling
|
||||||
|
if(data_dst->growth.species == MEW_SPECIES)
|
||||||
|
data_dst->misc.obedience = 1;
|
||||||
|
|
||||||
|
// Set the PID-Origin-IVs data, they're all connected
|
||||||
|
set_origin_pid_iv(dst, &data_dst->misc, data_dst->growth.species, src->ivs, wanted_nature, 0, 0, no_restrictions);
|
||||||
|
|
||||||
|
// Place all the substructures' data
|
||||||
|
place_and_encrypt_gen3_data(data_dst, dst);
|
||||||
|
|
||||||
|
// Calculate stats
|
||||||
|
recalc_stats_gen3(data_dst, dst);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
11
source/gen_converter.h
Normal file
11
source/gen_converter.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef GEN_CONVERTER__
|
||||||
|
#define GEN_CONVERTER__
|
||||||
|
|
||||||
|
#include "party_handler.h"
|
||||||
|
|
||||||
|
u8 gen3_to_gen2(struct gen2_mon*, struct gen3_mon_data_unenc*, u32);
|
||||||
|
u8 gen3_to_gen1(struct gen1_mon*, struct gen3_mon_data_unenc*, u32);
|
||||||
|
u8 gen2_to_gen3(struct gen2_mon_data*, struct gen3_mon_data_unenc*, u8, u8*, u8*, u8);
|
||||||
|
u8 gen1_to_gen3(struct gen1_mon_data*, struct gen3_mon_data_unenc*, u8, u8*, u8*, u8);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "graphics_handler.h"
|
#include "graphics_handler.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#define MAX_SIZE_POKEMON_SPRITE 0x400
|
#define MAX_SIZE_POKEMON_SPRITE 0x400
|
||||||
#define GRAPHICS_BUFFER_SHIFT 10
|
#define GRAPHICS_BUFFER_SHIFT 10
|
||||||
|
|
@ -10,7 +11,7 @@
|
||||||
void convert_3bpp_forward_odd(const u8*, u32*, u16);
|
void convert_3bpp_forward_odd(const u8*, u32*, u16);
|
||||||
void convert_3bpp_forward_even(const u8*, u32*, u16);
|
void convert_3bpp_forward_even(const u8*, u32*, u16);
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void load_pokemon_sprite_gfx(const u32* src, u32* dst, u8 is_3bpp, u8 zero_fill, u8 index, u8* colors){
|
IWRAM_CODE 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 zero = 0;
|
||||||
|
|
||||||
u32 buffer[2][MAX_SIZE_POKEMON_SPRITE>>2];
|
u32 buffer[2][MAX_SIZE_POKEMON_SPRITE>>2];
|
||||||
|
|
@ -70,7 +71,7 @@ void convert_xbpp(u8* src, u32* dst, u16 src_size, u8* colors, u8 is_forward, u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void convert_3bpp_forward_even(const u8* src, u32* dst, u16 src_size) {
|
IWRAM_CODE MAX_OPTIMIZE void convert_3bpp_forward_even(const u8* src, u32* dst, u16 src_size) {
|
||||||
// This is soooo slow, even with all of this. 50k cycles more than 4bpp
|
// This is soooo slow, even with all of this. 50k cycles more than 4bpp
|
||||||
u16 num_rows = Div(src_size, 3);
|
u16 num_rows = Div(src_size, 3);
|
||||||
if(DivMod(src_size, 3))
|
if(DivMod(src_size, 3))
|
||||||
|
|
@ -88,7 +89,7 @@ IWRAM_CODE __attribute__ ((optimize(3))) void convert_3bpp_forward_even(const u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void convert_3bpp_forward_odd(const u8* src, u32* dst, u16 src_size) {
|
IWRAM_CODE MAX_OPTIMIZE void convert_3bpp_forward_odd(const u8* src, u32* dst, u16 src_size) {
|
||||||
// This is soooo slow, even with all of this. 50k cycles more than 4bpp
|
// This is soooo slow, even with all of this. 50k cycles more than 4bpp
|
||||||
u16 num_rows = Div(src_size, 3);
|
u16 num_rows = Div(src_size, 3);
|
||||||
if(DivMod(src_size, 3))
|
if(DivMod(src_size, 3))
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "input_handler.h"
|
#include "input_handler.h"
|
||||||
#include "options_handler.h"
|
#include "options_handler.h"
|
||||||
#include "communicator.h"
|
#include "communicator.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
u8 handle_input_multiboot_menu(u16 keys) {
|
u8 handle_input_multiboot_menu(u16 keys) {
|
||||||
if(keys & KEY_A)
|
if(keys & KEY_A)
|
||||||
|
|
@ -9,7 +10,7 @@ u8 handle_input_multiboot_menu(u16 keys) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 handle_input_info_menu(struct game_data_t* game_data, u8* cursor_y_pos, u8 cursor_x_pos, u16 keys, u8* curr_mon, u8 curr_gen, u8* curr_page) {
|
u8 handle_input_info_menu(struct game_data_t* game_data, u8* cursor_y_pos, u8 cursor_x_pos, u16 keys, u8* curr_mon, u8 UNUSED(curr_gen), u8* curr_page) {
|
||||||
|
|
||||||
u8* options = get_options_trade(cursor_x_pos);
|
u8* options = get_options_trade(cursor_x_pos);
|
||||||
u8 num_options = get_options_num_trade(cursor_x_pos);
|
u8 num_options = get_options_num_trade(cursor_x_pos);
|
||||||
|
|
@ -87,7 +88,7 @@ u8 handle_input_info_menu(struct game_data_t* game_data, u8* cursor_y_pos, u8 cu
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 handle_input_trading_menu(u8* cursor_y_pos, u8* cursor_x_pos, u16 keys, u8 curr_gen, u8 is_own) {
|
u8 handle_input_trading_menu(u8* cursor_y_pos, u8* cursor_x_pos, u16 keys, u8 UNUSED(curr_gen), u8 is_own) {
|
||||||
|
|
||||||
u8* options[2];
|
u8* options[2];
|
||||||
u8 num_options[2];
|
u8 num_options[2];
|
||||||
|
|
@ -324,7 +325,7 @@ u8 handle_input_trade_options(u16 keys, u8* cursor_x_pos) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 handle_input_trade_setup(u16 keys, u8 curr_gen) {
|
u8 handle_input_trade_setup(u16 keys, u8 UNUSED(curr_gen)) {
|
||||||
|
|
||||||
if(keys & KEY_B) {
|
if(keys & KEY_B) {
|
||||||
if((get_start_state_raw() != START_TRADE_PAR) || (get_transferred(0) == 0)) {
|
if((get_start_state_raw() != START_TRADE_PAR) || (get_transferred(0) == 0)) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
|
|
||||||
#include "multiboot_handler.h"
|
#include "multiboot_handler.h"
|
||||||
|
|
@ -35,8 +33,28 @@
|
||||||
#define TRADE_CANCEL_SCREEN 1
|
#define TRADE_CANCEL_SCREEN 1
|
||||||
#define INFO_SCREEN 3
|
#define INFO_SCREEN 3
|
||||||
|
|
||||||
|
void vblank_update_function(void);
|
||||||
|
void find_optimal_ewram_settings(void);
|
||||||
|
u8 init_cursor_y_pos_main_menu(void);
|
||||||
|
void cursor_update_trading_menu(u8, u8);
|
||||||
|
void cursor_update_main_menu(u8);
|
||||||
|
void cursor_update_trade_options(u8);
|
||||||
|
void cursor_update_offer_options(u8, u8);
|
||||||
|
void offer_init(struct game_data_t*, u8, u8, u8*, u8*);
|
||||||
|
void waiting_init(void);
|
||||||
|
void invalid_init(u8);
|
||||||
|
void waiting_offer_init(u8, u8);
|
||||||
|
void waiting_accept_init(u8);
|
||||||
|
void check_bad_trade_received(struct game_data_t*, u8, u8, u8, u8, u8, u8*);
|
||||||
|
void trade_cancel_print_screen(u8);
|
||||||
|
void trade_options_init(u8, u8*);
|
||||||
|
void trade_menu_init(struct game_data_t*, u8, u8, u8, u8, u8, u8*, u8*);
|
||||||
|
void start_trade_init(struct game_data_t*, u8, u8, u8, u8, u8*);
|
||||||
void main_menu_init(struct game_data_t*, u8, u8, u8, u8*);
|
void main_menu_init(struct game_data_t*, u8, u8, u8, u8*);
|
||||||
|
void info_menu_init(struct game_data_t*, u8, u8, u8*);
|
||||||
void conclude_trade(struct game_data_t*, u8, u8, u8, u8*);
|
void conclude_trade(struct game_data_t*, u8, u8, u8, u8*);
|
||||||
|
void return_to_trade_menu(struct game_data_t*, u8, u8, u8, 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};
|
enum STATE {MAIN_MENU, MULTIBOOT, TRADING_MENU, INFO_MENU, START_TRADE, WAITING_DATA, TRADE_OPTIONS, NATURE_SETTING, OFFER_MENU, TRADING_ANIMATION};
|
||||||
enum STATE curr_state;
|
enum STATE curr_state;
|
||||||
|
|
@ -76,8 +94,8 @@ IWRAM_CODE void vblank_update_function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE void find_optimal_ewram_settings() {
|
IWRAM_CODE void find_optimal_ewram_settings() {
|
||||||
int size = ewram_speed_check_bin_size>>2;
|
u32 size = ewram_speed_check_bin_size>>2;
|
||||||
u32* ewram_speed_check = (u32*) ewram_speed_check_bin;
|
const u32* ewram_speed_check = (const u32*) ewram_speed_check_bin;
|
||||||
u32 test_data[size];
|
u32 test_data[size];
|
||||||
|
|
||||||
// Check for unsupported (DS)
|
// Check for unsupported (DS)
|
||||||
|
|
@ -89,7 +107,7 @@ IWRAM_CODE void find_optimal_ewram_settings() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Prepare data to test against
|
// Prepare data to test against
|
||||||
for(int i = 0; i < size; i++)
|
for(u32 i = 0; i < size; i++)
|
||||||
test_data[i] = ewram_speed_check[i];
|
test_data[i] = ewram_speed_check[i];
|
||||||
|
|
||||||
// Detetmine minimum number of stable waitcycles
|
// Detetmine minimum number of stable waitcycles
|
||||||
|
|
@ -97,8 +115,8 @@ IWRAM_CODE void find_optimal_ewram_settings() {
|
||||||
REG_MEMORY_CONTROLLER &= ~(0xF<<24);
|
REG_MEMORY_CONTROLLER &= ~(0xF<<24);
|
||||||
REG_MEMORY_CONTROLLER |= (15-i-MIN_WAITCYCLE)<<24;
|
REG_MEMORY_CONTROLLER |= (15-i-MIN_WAITCYCLE)<<24;
|
||||||
u8 failed = 0;
|
u8 failed = 0;
|
||||||
for(int j = 0; (!failed) && (j < size); j++)
|
for(u32 j = 0; (!failed) && (j < size); j++)
|
||||||
if(test_data[i] != ewram_speed_check[i])
|
if(test_data[j] != ewram_speed_check[j])
|
||||||
failed = 1;
|
failed = 1;
|
||||||
if(!failed)
|
if(!failed)
|
||||||
return;
|
return;
|
||||||
|
|
@ -296,9 +314,9 @@ int main(void)
|
||||||
input_counter = 0;
|
input_counter = 0;
|
||||||
find_optimal_ewram_settings();
|
find_optimal_ewram_settings();
|
||||||
init_text_system();
|
init_text_system();
|
||||||
|
init_enc_positions();
|
||||||
init_rng(0,0);
|
init_rng(0,0);
|
||||||
u16 keys;
|
u16 keys;
|
||||||
enum MULTIBOOT_RESULTS result;
|
|
||||||
struct game_data_t game_data[2];
|
struct game_data_t game_data[2];
|
||||||
|
|
||||||
init_game_data(&game_data[0]);
|
init_game_data(&game_data[0]);
|
||||||
|
|
@ -325,6 +343,7 @@ int main(void)
|
||||||
init_cursor();
|
init_cursor();
|
||||||
|
|
||||||
const u16** learnset_ptr = NULL;
|
const u16** learnset_ptr = NULL;
|
||||||
|
int result = 0;
|
||||||
u8 evolved = 0;
|
u8 evolved = 0;
|
||||||
u8 returned_val;
|
u8 returned_val;
|
||||||
u8 update = 0;
|
u8 update = 0;
|
||||||
|
|
@ -368,7 +387,7 @@ int main(void)
|
||||||
if(curr_state == WAITING_DATA) {
|
if(curr_state == WAITING_DATA) {
|
||||||
if(get_trading_state() == RECEIVED_OFFER) {
|
if(get_trading_state() == RECEIVED_OFFER) {
|
||||||
keys = 0;
|
keys = 0;
|
||||||
int result = get_received_trade_offer();
|
result = get_received_trade_offer();
|
||||||
if(result == TRADE_CANCELLED)
|
if(result == TRADE_CANCELLED)
|
||||||
conclude_trade(&game_data[0], target, region, master, &cursor_y_pos);
|
conclude_trade(&game_data[0], target, region, master, &cursor_y_pos);
|
||||||
else if(result == WANTS_TO_CANCEL)
|
else if(result == WANTS_TO_CANCEL)
|
||||||
|
|
@ -411,8 +430,7 @@ int main(void)
|
||||||
sio_stop_irq_slave();
|
sio_stop_irq_slave();
|
||||||
irqDisable(IRQ_SERIAL);
|
irqDisable(IRQ_SERIAL);
|
||||||
disable_cursor();
|
disable_cursor();
|
||||||
result = multiboot_normal((u16*)EWRAM, (u16*)(EWRAM + 0x3FF40));
|
print_multiboot(multiboot_normal((u16*)EWRAM, (u16*)(EWRAM + 0x3FF40)));
|
||||||
print_multiboot(result);
|
|
||||||
}
|
}
|
||||||
else if(returned_val > VIEW_OWN_PARTY && returned_val <= VIEW_OWN_PARTY + TOTAL_GENS) {
|
else if(returned_val > VIEW_OWN_PARTY && returned_val <= VIEW_OWN_PARTY + TOTAL_GENS) {
|
||||||
curr_gen = returned_val - VIEW_OWN_PARTY;
|
curr_gen = returned_val - VIEW_OWN_PARTY;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,14 @@
|
||||||
#define SUMMARY_LINE_MAX_SIZE 18
|
#define SUMMARY_LINE_MAX_SIZE 18
|
||||||
#define PRINTABLE_INVALID_STRINGS 3
|
#define PRINTABLE_INVALID_STRINGS 3
|
||||||
|
|
||||||
|
void print_pokemon_base_info(u8, struct gen3_mon_data_unenc*, u8);
|
||||||
|
void print_bottom_info(void);
|
||||||
|
void print_pokemon_page1(struct gen3_mon_data_unenc*);
|
||||||
|
void print_pokemon_page2(struct gen3_mon_data_unenc*);
|
||||||
|
void print_pokemon_page3(struct gen3_mon_data_unenc*);
|
||||||
|
void print_pokemon_page4(struct gen3_mon_data_unenc*);
|
||||||
|
void print_pokemon_page5(struct gen3_mon_data_unenc*);
|
||||||
|
|
||||||
const char* person_strings[] = {"You", "Other"};
|
const char* person_strings[] = {"You", "Other"};
|
||||||
const char* game_strings[] = {"RS", "FRLG", "E"};
|
const char* game_strings[] = {"RS", "FRLG", "E"};
|
||||||
const char* unidentified_string = "Unidentified";
|
const char* unidentified_string = "Unidentified";
|
||||||
|
|
@ -32,6 +40,8 @@ const char* offer_strings[] = {" Sending ", "Receiving"};
|
||||||
const char* invalid_strings[][PRINTABLE_INVALID_STRINGS] = {{" TRADE REJECTED!", "The Pokémon offered by the", "other player has issues!"}, {" TRADE REJECTED!", "The trade would leave you", "with no usable Pokémon!"}};
|
const char* invalid_strings[][PRINTABLE_INVALID_STRINGS] = {{" TRADE REJECTED!", "The Pokémon offered by the", "other player has issues!"}, {" TRADE REJECTED!", "The trade would leave you", "with no usable Pokémon!"}};
|
||||||
|
|
||||||
const u8 ribbon_print_pos[NUM_LINES*2] = {0,1,2,3,4,5,6,7,8,9,14,15,13,16,10,0xFF,11,0xFF,12,0xFF};
|
const u8 ribbon_print_pos[NUM_LINES*2] = {0,1,2,3,4,5,6,7,8,9,14,15,13,16,10,0xFF,11,0xFF,12,0xFF};
|
||||||
|
typedef void (*print_info_functions_t)(struct gen3_mon_data_unenc*);
|
||||||
|
print_info_functions_t print_info_functions[PAGES_TOTAL] = {print_pokemon_page1, print_pokemon_page2, print_pokemon_page3, print_pokemon_page4, print_pokemon_page5};
|
||||||
|
|
||||||
void print_game_info(struct game_data_t* game_data, int index) {
|
void print_game_info(struct game_data_t* game_data, int index) {
|
||||||
PRINT_FUNCTION("\n Game: ");
|
PRINT_FUNCTION("\n Game: ");
|
||||||
|
|
@ -402,10 +412,6 @@ void print_pokemon_page5(struct gen3_mon_data_unenc* mon) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*print_info_functions_t)(struct gen3_mon_data_unenc*);
|
|
||||||
|
|
||||||
print_info_functions_t print_info_functions[PAGES_TOTAL] = {print_pokemon_page1, print_pokemon_page2, print_pokemon_page3, print_pokemon_page4, print_pokemon_page5};
|
|
||||||
|
|
||||||
void print_pokemon_pages(u8 update, u8 load_sprites, struct gen3_mon_data_unenc* mon, u8 page_num) {
|
void print_pokemon_pages(u8 update, u8 load_sprites, struct gen3_mon_data_unenc* mon, u8 page_num) {
|
||||||
if(!update)
|
if(!update)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ void print_pokemon_pages(u8, u8, struct gen3_mon_data_unenc*, u8);
|
||||||
void print_main_menu(u8, u8, u8, u8);
|
void print_main_menu(u8, u8, u8, u8);
|
||||||
void print_multiboot_mid_process(u8);
|
void print_multiboot_mid_process(u8);
|
||||||
void print_multiboot(enum MULTIBOOT_RESULTS);
|
void print_multiboot(enum MULTIBOOT_RESULTS);
|
||||||
void print_start_trade();
|
void print_start_trade(void);
|
||||||
void print_waiting();
|
void print_waiting(void);
|
||||||
void print_invalid(u8);
|
void print_invalid(u8);
|
||||||
void print_offer_screen(struct game_data_t*, u8, u8);
|
void print_offer_screen(struct game_data_t*, u8, u8);
|
||||||
void print_offer_options_screen(struct game_data_t*, u8, u8);
|
void print_offer_options_screen(struct game_data_t*, u8, u8);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
#ifndef OPTIMIZED_SWI__
|
#ifndef OPTIMIZED_SWI__
|
||||||
#define OPTIMIZED_SWI__
|
#define OPTIMIZED_SWI__
|
||||||
|
|
||||||
static __attribute__((optimize(3), always_inline)) inline s32 SWI_DivMod(const uint32_t dividend, const uint32_t divisor)
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
|
static s32 SWI_DivMod(const uint32_t, const uint32_t);
|
||||||
|
static s32 SWI_Div(const uint32_t, const uint32_t);
|
||||||
|
static s32 SWI_DivDivMod(const uint32_t, const uint32_t, int* mod);
|
||||||
|
|
||||||
|
ALWAYS_INLINE MAX_OPTIMIZE s32 SWI_DivMod(const uint32_t dividend, const uint32_t divisor)
|
||||||
{
|
{
|
||||||
register uint32_t divid_ asm("r0") = (uint32_t)dividend;
|
register uint32_t divid_ asm("r0") = (uint32_t)dividend;
|
||||||
register uint32_t divis_ asm("r1") = (uint32_t)divisor;
|
register uint32_t divis_ asm("r1") = (uint32_t)divisor;
|
||||||
|
|
@ -15,7 +21,7 @@ static __attribute__((optimize(3), always_inline)) inline s32 SWI_DivMod(const u
|
||||||
return divis_;
|
return divis_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((optimize(3), always_inline)) inline s32 SWI_Div(const uint32_t dividend, const uint32_t divisor)
|
ALWAYS_INLINE MAX_OPTIMIZE s32 SWI_Div(const uint32_t dividend, const uint32_t divisor)
|
||||||
{
|
{
|
||||||
register uint32_t divid_ asm("r0") = (uint32_t)dividend;
|
register uint32_t divid_ asm("r0") = (uint32_t)dividend;
|
||||||
register uint32_t divis_ asm("r1") = (uint32_t)divisor;
|
register uint32_t divis_ asm("r1") = (uint32_t)divisor;
|
||||||
|
|
@ -29,7 +35,7 @@ static __attribute__((optimize(3), always_inline)) inline s32 SWI_Div(const uint
|
||||||
return divid_;
|
return divid_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __attribute__((optimize(3), always_inline)) inline s32 SWI_DivDivMod(const uint32_t dividend, const uint32_t divisor, int* mod)
|
ALWAYS_INLINE MAX_OPTIMIZE s32 SWI_DivDivMod(const uint32_t dividend, const uint32_t divisor, int* mod)
|
||||||
{
|
{
|
||||||
register uint32_t divid_ asm("r0") = (uint32_t)dividend;
|
register uint32_t divid_ asm("r0") = (uint32_t)dividend;
|
||||||
register uint32_t divis_ asm("r1") = (uint32_t)divisor;
|
register uint32_t divis_ asm("r1") = (uint32_t)divisor;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "options_handler.h"
|
#include "options_handler.h"
|
||||||
|
|
||||||
u8 options_main[3];
|
void set_valid_options_main(struct game_data_t*);
|
||||||
|
void fill_options_main_array(struct game_data_t*);
|
||||||
|
int prepare_trade_options_num(u8*);
|
||||||
|
void fill_trade_options(u8*, struct game_data_t*, u8);
|
||||||
|
|
||||||
|
u8 options_main[MAIN_OPTIONS_NUM];
|
||||||
u8 valid_options_main;
|
u8 valid_options_main;
|
||||||
u8 options_trade[2][PARTY_SIZE];
|
u8 options_trade[2][PARTY_SIZE];
|
||||||
u8 num_options_trade[2];
|
u8 num_options_trade[2];
|
||||||
|
|
@ -12,7 +17,7 @@ u8 is_valid_for_gen(struct game_data_t* game_data, u8 gen) {
|
||||||
if(gen == 2)
|
if(gen == 2)
|
||||||
return (game_data->party_2.total > 0);
|
return (game_data->party_2.total > 0);
|
||||||
u8 found = 0;
|
u8 found = 0;
|
||||||
for(int i = 0; i < game_data->party_3.total; i++)
|
for(u32 i = 0; i < game_data->party_3.total; i++)
|
||||||
if(game_data->party_3_undec[i].is_valid_gen3) {
|
if(game_data->party_3_undec[i].is_valid_gen3) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -72,11 +77,13 @@ u8 get_number_of_higher_ordered_options(u8* options, u8 curr_option, u8 limit) {
|
||||||
u8 get_number_of_lower_ordered_options(u8* options, u8 curr_option, u8 limit) {
|
u8 get_number_of_lower_ordered_options(u8* options, u8 curr_option, u8 limit) {
|
||||||
u8 curr_num = 0;
|
u8 curr_num = 0;
|
||||||
u8 lowest_found = curr_option;
|
u8 lowest_found = curr_option;
|
||||||
for(int i = limit-1; i >= 0; i--)
|
u8 start = limit-1;
|
||||||
if(options[i] < lowest_found) {
|
if(limit)
|
||||||
curr_num++;
|
for(int i = start; i >= 0; i--)
|
||||||
lowest_found = options[i];
|
if(options[i] < lowest_found) {
|
||||||
}
|
curr_num++;
|
||||||
|
lowest_found = options[i];
|
||||||
|
}
|
||||||
return curr_num;
|
return curr_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ u8 get_number_of_lower_ordered_options(u8*, u8, u8);
|
||||||
|
|
||||||
u8 is_valid_for_gen(struct game_data_t*, u8);
|
u8 is_valid_for_gen(struct game_data_t*, u8);
|
||||||
|
|
||||||
u8* get_options_main();
|
u8* get_options_main(void);
|
||||||
u8 get_valid_options_main();
|
u8 get_valid_options_main(void);
|
||||||
void prepare_main_options(struct game_data_t*);
|
void prepare_main_options(struct game_data_t*);
|
||||||
|
|
||||||
u8* get_options_trade(int);
|
u8* get_options_trade(int);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef PARTY_HANDLER__
|
#ifndef PARTY_HANDLER__
|
||||||
#define PARTY_HANDLER__
|
#define PARTY_HANDLER__
|
||||||
|
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#define TOTAL_GENS 3
|
#define TOTAL_GENS 3
|
||||||
#define FIRST_GEN 1
|
#define FIRST_GEN 1
|
||||||
|
|
||||||
|
|
@ -27,8 +29,12 @@
|
||||||
#define M_GENDER 0
|
#define M_GENDER 0
|
||||||
#define F_GENDER 1
|
#define F_GENDER 1
|
||||||
#define U_GENDER 2
|
#define U_GENDER 2
|
||||||
|
#define M_INDEX 1
|
||||||
|
#define F_INDEX 6
|
||||||
|
#define U_INDEX 7
|
||||||
#define NIDORAN_M_GENDER_INDEX 8
|
#define NIDORAN_M_GENDER_INDEX 8
|
||||||
#define NIDORAN_F_GENDER_INDEX 9
|
#define NIDORAN_F_GENDER_INDEX 9
|
||||||
|
#define TOTAL_GENDER_KINDS 10
|
||||||
|
|
||||||
#define NO_POKERUS 0
|
#define NO_POKERUS 0
|
||||||
#define HAS_POKERUS 1
|
#define HAS_POKERUS 1
|
||||||
|
|
@ -63,6 +69,7 @@
|
||||||
#define RAIKOU_SPECIES 243
|
#define RAIKOU_SPECIES 243
|
||||||
#define SUICUNE_SPECIES 245
|
#define SUICUNE_SPECIES 245
|
||||||
#define DEOXYS_SPECIES 410
|
#define DEOXYS_SPECIES 410
|
||||||
|
#define EGG_SPECIES 412
|
||||||
|
|
||||||
#define DEOXYS_FORMS_POS 442
|
#define DEOXYS_FORMS_POS 442
|
||||||
#define MR_MIME_OLD_NAME_POS 445
|
#define MR_MIME_OLD_NAME_POS 445
|
||||||
|
|
@ -133,7 +140,7 @@ struct mail_gen3 {
|
||||||
u16 species;
|
u16 species;
|
||||||
u16 item;
|
u16 item;
|
||||||
u16 unk;
|
u16 unk;
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct special_met_data_gen2 {
|
struct special_met_data_gen2 {
|
||||||
u8 location;
|
u8 location;
|
||||||
|
|
@ -219,7 +226,7 @@ struct gen3_mon {
|
||||||
u8 mail_id;
|
u8 mail_id;
|
||||||
u16 curr_hp;
|
u16 curr_hp;
|
||||||
u16 stats[GEN2_STATS_TOTAL];
|
u16 stats[GEN2_STATS_TOTAL];
|
||||||
} __attribute__ ((packed)) __attribute__ ((aligned(4)));
|
} PACKED ALIGNED(4);
|
||||||
|
|
||||||
struct gen2_mon_data {
|
struct gen2_mon_data {
|
||||||
u8 species;
|
u8 species;
|
||||||
|
|
@ -241,7 +248,7 @@ struct gen2_mon_data {
|
||||||
u8 unused;
|
u8 unused;
|
||||||
u16 curr_hp;
|
u16 curr_hp;
|
||||||
u16 stats[GEN2_STATS_TOTAL];
|
u16 stats[GEN2_STATS_TOTAL];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen2_mon {
|
struct gen2_mon {
|
||||||
struct gen2_mon_data data;
|
struct gen2_mon_data data;
|
||||||
|
|
@ -267,7 +274,7 @@ struct gen1_mon_data {
|
||||||
u8 pps[MOVES_SIZE];
|
u8 pps[MOVES_SIZE];
|
||||||
u8 level;
|
u8 level;
|
||||||
u16 stats[GEN1_STATS_TOTAL];
|
u16 stats[GEN1_STATS_TOTAL];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen1_mon {
|
struct gen1_mon {
|
||||||
struct gen1_mon_data data;
|
struct gen1_mon_data data;
|
||||||
|
|
@ -292,11 +299,22 @@ struct gen1_party {
|
||||||
struct gen1_mon mons[PARTY_SIZE];
|
struct gen1_mon mons[PARTY_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void init_enc_positions(void);
|
||||||
|
|
||||||
void process_gen3_data(struct gen3_mon*, struct gen3_mon_data_unenc*, u8, u8);
|
void process_gen3_data(struct gen3_mon*, struct gen3_mon_data_unenc*, u8, u8);
|
||||||
u8 gen3_to_gen2(struct gen2_mon*, struct gen3_mon_data_unenc*, u32);
|
|
||||||
u8 gen3_to_gen1(struct gen1_mon*, struct gen3_mon_data_unenc*, u32);
|
u8 get_index_key(u32);
|
||||||
u8 gen2_to_gen3(struct gen2_mon_data*, struct gen3_mon_data_unenc*, u8, u8*, u8*, u8);
|
u8 get_nature(u32);
|
||||||
u8 gen1_to_gen3(struct gen1_mon_data*, struct gen3_mon_data_unenc*, u8, u8*, u8*, u8);
|
u16 get_mon_index(int, u32, u8, u8);
|
||||||
|
u8 get_unown_letter_gen3(u32);
|
||||||
|
const u8* get_pokemon_name(int, u32, u8, u8);
|
||||||
|
u8 has_mail(struct gen3_mon*, struct gen3_mon_growth*, u8);
|
||||||
|
s32 get_proper_exp(struct gen3_mon*, struct gen3_mon_growth*, u8);
|
||||||
|
u8 to_valid_level(u8);
|
||||||
|
u16 get_possible_abilities_pokemon(int, u32, u8, u8);
|
||||||
|
u8 get_pokemon_gender_gen3(int, u32, u8, u8);
|
||||||
|
u16 calc_stats_gen3(u16, u32, u8, u8, u8, u8, u8);
|
||||||
|
void place_and_encrypt_gen3_data(struct gen3_mon_data_unenc*, struct gen3_mon*);
|
||||||
|
|
||||||
const u8* get_pokemon_name_raw(struct gen3_mon_data_unenc*);
|
const u8* get_pokemon_name_raw(struct gen3_mon_data_unenc*);
|
||||||
u16 get_mon_index_raw(struct gen3_mon_data_unenc*);
|
u16 get_mon_index_raw(struct gen3_mon_data_unenc*);
|
||||||
|
|
@ -327,11 +345,10 @@ const u8* get_move_name_gen3(struct gen3_mon_attacks*, u8);
|
||||||
const u8* get_ability_name_raw(struct gen3_mon_data_unenc*);
|
const u8* get_ability_name_raw(struct gen3_mon_data_unenc*);
|
||||||
const u8* get_ribbon_name(struct gen3_mon_misc*, u8);
|
const u8* get_ribbon_name(struct gen3_mon_misc*, u8);
|
||||||
const u8* get_ribbon_rank_name(struct gen3_mon_misc*, u8);
|
const u8* get_ribbon_rank_name(struct gen3_mon_misc*, u8);
|
||||||
u32 get_proper_exp_raw(struct gen3_mon_data_unenc*);
|
s32 get_proper_exp_raw(struct gen3_mon_data_unenc*);
|
||||||
u32 get_level_exp_mon_index(u16, u8);
|
s32 get_level_exp_mon_index(u16, u8);
|
||||||
u8 get_pokemon_gender_gen2(u8, u8, u8, u8);
|
|
||||||
u8 get_pokemon_gender_kind_gen3(int, u32, u8, u8);
|
u8 get_pokemon_gender_kind_gen3(int, u32, u8, u8);
|
||||||
u8 get_pokemon_gender_kind_gen2(u8, u8, u8);
|
void recalc_stats_gen3(struct gen3_mon_data_unenc*, struct gen3_mon*);
|
||||||
void clean_mail_gen3(struct mail_gen3*, struct gen3_mon* mon);
|
void clean_mail_gen3(struct mail_gen3*, struct gen3_mon* mon);
|
||||||
u8 trade_evolve(struct gen3_mon*, struct gen3_mon_data_unenc*, const u16**, u8);
|
u8 trade_evolve(struct gen3_mon*, struct gen3_mon_data_unenc*, const u16**, u8);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "pid_iv_tid.h"
|
#include "pid_iv_tid.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "party_handler.h"
|
#include "gen12_methods.h"
|
||||||
#include "text_handler.h"
|
#include "text_handler.h"
|
||||||
#include "fast_pokemon_methods.h"
|
#include "fast_pokemon_methods.h"
|
||||||
#include "optimized_swi.h"
|
#include "optimized_swi.h"
|
||||||
#include "print_system.h"
|
#include "print_system.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#include "shiny_unown_banned_tsv_bin.h"
|
#include "shiny_unown_banned_tsv_bin.h"
|
||||||
#include "shiny_unown_banned_tsv_letter_table_bin.h"
|
#include "shiny_unown_banned_tsv_letter_table_bin.h"
|
||||||
|
|
||||||
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
|
|
||||||
|
|
||||||
#define TEST_WORST_CASE 0
|
#define TEST_WORST_CASE 0
|
||||||
|
|
||||||
|
|
@ -18,6 +17,19 @@
|
||||||
#define NUM_DIFFERENT_PSV (0x10000>>3)
|
#define NUM_DIFFERENT_PSV (0x10000>>3)
|
||||||
#define NUM_DIFFERENT_UNOWN_PSV (0x10000>>5)
|
#define NUM_DIFFERENT_UNOWN_PSV (0x10000>>5)
|
||||||
|
|
||||||
|
static u8 is_bad_tsv(u16);
|
||||||
|
static void get_letter_valid_natures(u16, u8, u8*);
|
||||||
|
static u32 get_prev_seed(u32);
|
||||||
|
static u32 get_next_seed(u32);
|
||||||
|
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 _generate_static_info(u8, u16, u16, u32*, u32*, u32);
|
||||||
|
void _generate_static_shiny_info(u8, u16, u32*, u32*, u32);
|
||||||
|
void _generate_unown_info(u8, u8, u8, u16, u32*, u32*, u32);
|
||||||
|
u8 search_specific_low_pid(u32, u32*, u32*);
|
||||||
|
u8 search_unown_pid_masks(u32, u8, u32*, u32*);
|
||||||
|
void _generate_unown_shiny_info(u8, u16, u8, u32*, u32*, u32);
|
||||||
|
|
||||||
// Nidoran M is special, it has to have 0x8000 set in the lower PID
|
// Nidoran M is special, it has to have 0x8000 set in the lower PID
|
||||||
u8 gender_useful_atk_ivs[] = {3, 4, 1, 2, 2, 1, 4, 4, 4, 4};
|
u8 gender_useful_atk_ivs[] = {3, 4, 1, 2, 2, 1, 4, 4, 4, 4};
|
||||||
u16 gender_values[] = {0x7F, 0, 0x1F, 0x3F, 0xBF, 0xDF, 0, 0, 0x7FFF, 0};
|
u16 gender_values[] = {0x7F, 0, 0x1F, 0x3F, 0xBF, 0xDF, 0, 0, 0x7FFF, 0};
|
||||||
|
|
@ -39,17 +51,17 @@ void init_unown_tsv() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE __attribute__ ((optimize(3))) u8 is_bad_tsv(u16 tsv) {
|
ALWAYS_INLINE MAX_OPTIMIZE u8 is_bad_tsv(u16 tsv) {
|
||||||
tsv = (tsv >> 3) << 3;
|
tsv = (tsv >> 3) << 3;
|
||||||
const u32* shiny_unown_banned_tsv_bin_32 = (const u32*)shiny_unown_banned_tsv_bin;
|
const u32* shiny_unown_banned_tsv_bin_32 = (const u32*)shiny_unown_banned_tsv_bin;
|
||||||
for(int i = 0; i < (shiny_unown_banned_tsv_bin_size >> 2); i++) {
|
for(u32 i = 0; i < (shiny_unown_banned_tsv_bin_size >> 2); i++) {
|
||||||
if(tsv == (shiny_unown_banned_tsv_bin_32[i] & 0xFFFF))
|
if(tsv == (shiny_unown_banned_tsv_bin_32[i] & 0xFFFF))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE __attribute__ ((optimize(3))) void get_letter_valid_natures(u16 tsv, u8 letter, u8* valid_natures) {
|
ALWAYS_INLINE MAX_OPTIMIZE void get_letter_valid_natures(u16 tsv, u8 letter, u8* valid_natures) {
|
||||||
tsv = (tsv >> 3) << 3;
|
tsv = (tsv >> 3) << 3;
|
||||||
for(int i = 0; i < NUM_NATURES; i++)
|
for(int i = 0; i < NUM_NATURES; i++)
|
||||||
valid_natures[i] = 1;
|
valid_natures[i] = 1;
|
||||||
|
|
@ -58,7 +70,7 @@ ALWAYS_INLINE __attribute__ ((optimize(3))) void get_letter_valid_natures(u16 ts
|
||||||
if(letter_kind == 0xF)
|
if(letter_kind == 0xF)
|
||||||
return;
|
return;
|
||||||
const u32* shiny_unown_banned_tsv_bin_32 = (const u32*)shiny_unown_banned_tsv_bin;
|
const u32* shiny_unown_banned_tsv_bin_32 = (const u32*)shiny_unown_banned_tsv_bin;
|
||||||
for(int i = 0; i < (shiny_unown_banned_tsv_bin_size >> 2); i++) {
|
for(u32 i = 0; i < (shiny_unown_banned_tsv_bin_size >> 2); i++) {
|
||||||
if(tsv == (shiny_unown_banned_tsv_bin_32[i] & 0xFFFF)) {
|
if(tsv == (shiny_unown_banned_tsv_bin_32[i] & 0xFFFF)) {
|
||||||
u8 letter_kind_table = (shiny_unown_banned_tsv_bin_32[i]>>0x14)&0xF;
|
u8 letter_kind_table = (shiny_unown_banned_tsv_bin_32[i]>>0x14)&0xF;
|
||||||
u8 letter_dist_table = (shiny_unown_banned_tsv_bin_32[i]>>0x10)&0xF;
|
u8 letter_dist_table = (shiny_unown_banned_tsv_bin_32[i]>>0x10)&0xF;
|
||||||
|
|
@ -73,15 +85,15 @@ ALWAYS_INLINE __attribute__ ((optimize(3))) void get_letter_valid_natures(u16 ts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE __attribute__ ((optimize(3))) u32 get_prev_seed(u32 seed) {
|
ALWAYS_INLINE MAX_OPTIMIZE u32 get_prev_seed(u32 seed) {
|
||||||
return (seed-0x6073) * 0xEEB9EB65;
|
return (seed-0x6073) * 0xEEB9EB65;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE __attribute__ ((optimize(3))) u32 get_next_seed(u32 seed) {
|
ALWAYS_INLINE MAX_OPTIMIZE u32 get_next_seed(u32 seed) {
|
||||||
return ((seed*0x41C64E6D)+0x6073);
|
return ((seed*0x41C64E6D)+0x6073);
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) u32 generate_ot(u16 tid, u8* name) {
|
IWRAM_CODE MAX_OPTIMIZE u32 generate_ot(u16 tid, u8* name) {
|
||||||
// Worst case: ANY
|
// Worst case: ANY
|
||||||
// This should NOT be random...
|
// This should NOT be random...
|
||||||
// All Pokémon from a trainer should have the same TID/SID!
|
// All Pokémon from a trainer should have the same TID/SID!
|
||||||
|
|
@ -108,7 +120,7 @@ IWRAM_CODE __attribute__ ((optimize(3))) u32 generate_ot(u16 tid, u8* name) {
|
||||||
return (sid << 0x10) | tid;
|
return (sid << 0x10) | tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void _generate_egg_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 gender, u8 gender_kind, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
IWRAM_CODE MAX_OPTIMIZE void _generate_egg_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 gender, u8 gender_kind, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
||||||
// Worst case: 0, 0x2113, 0, 0, 0, 34
|
// Worst case: 0, 0x2113, 0, 0, 0, 34
|
||||||
u8 atk_ivs = ((((wanted_ivs>>4) & 0xF)<<(4-gender_useful_atk_ivs[gender_kind])) & 0xF)<<1;
|
u8 atk_ivs = ((((wanted_ivs>>4) & 0xF)<<(4-gender_useful_atk_ivs[gender_kind])) & 0xF)<<1;
|
||||||
u8 def_ivs = ((wanted_ivs) & 0xF)<<1;
|
u8 def_ivs = ((wanted_ivs) & 0xF)<<1;
|
||||||
|
|
@ -201,11 +213,11 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_egg_info(u8 wanted_natur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void generate_egg_info(u8 index, u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 curr_gen, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE void generate_egg_info(u8 index, u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 curr_gen, u32* dst_pid, u32* dst_ivs) {
|
||||||
_generate_egg_info(wanted_nature, wanted_ivs, tsv, get_pokemon_gender_gen2(index, (wanted_ivs>>4)&0xF, 0, curr_gen), get_pokemon_gender_kind_gen2(index, 0, curr_gen), dst_pid, dst_ivs, get_rng());
|
_generate_egg_info(wanted_nature, wanted_ivs, tsv, get_pokemon_gender_gen2(index, (wanted_ivs>>4)&0xF, 0, curr_gen), get_pokemon_gender_kind_gen2(index, 0, curr_gen), dst_pid, dst_ivs, get_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void _generate_egg_shiny_info(u8 wanted_nature, u16 tsv, u8 gender, u8 gender_kind, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
IWRAM_CODE MAX_OPTIMIZE void _generate_egg_shiny_info(u8 wanted_nature, u16 tsv, u8 gender, u8 gender_kind, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
||||||
// Worst case: ANY
|
// Worst case: ANY
|
||||||
u16 lower_pid = start_seed &0xFFFF;
|
u16 lower_pid = start_seed &0xFFFF;
|
||||||
|
|
||||||
|
|
@ -251,11 +263,11 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_egg_shiny_info(u8 wanted
|
||||||
*dst_pid = pid;
|
*dst_pid = pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void generate_egg_shiny_info(u8 index, u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 curr_gen, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE void generate_egg_shiny_info(u8 index, u8 wanted_nature, u16 wanted_ivs, u16 tsv, u8 curr_gen, u32* dst_pid, u32* dst_ivs) {
|
||||||
_generate_egg_shiny_info(wanted_nature, tsv, get_pokemon_gender_gen2(index, (wanted_ivs>>4)&0xF, 0, curr_gen), get_pokemon_gender_kind_gen2(index, 0, curr_gen), dst_pid, dst_ivs, get_rng());
|
_generate_egg_shiny_info(wanted_nature, tsv, get_pokemon_gender_gen2(index, (wanted_ivs>>4)&0xF, 0, curr_gen), get_pokemon_gender_kind_gen2(index, 0, curr_gen), dst_pid, dst_ivs, get_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void _generate_static_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
IWRAM_CODE MAX_OPTIMIZE void _generate_static_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
||||||
// Worst case: 6, 12706, 0xA30E, 0
|
// Worst case: 6, 12706, 0xA30E, 0
|
||||||
u8 atk_ivs = ((wanted_ivs>>4) & 0xF)<<1;
|
u8 atk_ivs = ((wanted_ivs>>4) & 0xF)<<1;
|
||||||
u8 def_ivs = ((wanted_ivs) & 0xF)<<1;
|
u8 def_ivs = ((wanted_ivs) & 0xF)<<1;
|
||||||
|
|
@ -320,11 +332,11 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_static_info(u8 wanted_na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void generate_static_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE void generate_static_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
||||||
_generate_static_info(wanted_nature, wanted_ivs, tsv, dst_pid, dst_ivs, get_rng());
|
_generate_static_info(wanted_nature, wanted_ivs, tsv, dst_pid, dst_ivs, get_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void _generate_static_shiny_info(u8 wanted_nature, u16 tsv, u32* dst_pid, u32* dst_ivs, u32 given_seed) {
|
IWRAM_CODE MAX_OPTIMIZE void _generate_static_shiny_info(u8 wanted_nature, u16 tsv, u32* dst_pid, u32* dst_ivs, u32 given_seed) {
|
||||||
// Worst case: 0, 0x2088, (base_increment = 1, initial_pos = 0x6D0, set TEST_WORST_CASE to 1 to test it, with seed 0x36810000)
|
// Worst case: 0, 0x2088, (base_increment = 1, initial_pos = 0x6D0, set TEST_WORST_CASE to 1 to test it, with seed 0x36810000)
|
||||||
s32 base_increment;
|
s32 base_increment;
|
||||||
u16 initial_pos;
|
u16 initial_pos;
|
||||||
|
|
@ -411,11 +423,11 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_static_shiny_info(u8 wan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void generate_static_shiny_info(u8 wanted_nature, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE void generate_static_shiny_info(u8 wanted_nature, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
||||||
_generate_static_shiny_info(wanted_nature, tsv, dst_pid, dst_ivs, get_rng());
|
_generate_static_shiny_info(wanted_nature, tsv, dst_pid, dst_ivs, get_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void _generate_unown_info(u8 wanted_nature, u8 letter, u8 rest_of_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
IWRAM_CODE MAX_OPTIMIZE void _generate_unown_info(u8 wanted_nature, u8 letter, u8 rest_of_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs, u32 start_seed) {
|
||||||
// Worst case: 15, 4, 0xCE, 0xA021, 0x1AA
|
// Worst case: 15, 4, 0xCE, 0xA021, 0x1AA
|
||||||
u8 atk_ivs = (((rest_of_ivs>>0)&1) | (((rest_of_ivs>>0)&2)<<2))<<1;
|
u8 atk_ivs = (((rest_of_ivs>>0)&1) | (((rest_of_ivs>>0)&2)<<2))<<1;
|
||||||
u8 def_ivs = (((rest_of_ivs>>2)&1) | (((rest_of_ivs>>2)&2)<<2))<<1;
|
u8 def_ivs = (((rest_of_ivs>>2)&1) | (((rest_of_ivs>>2)&2)<<2))<<1;
|
||||||
|
|
@ -472,7 +484,7 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_unown_info(u8 wanted_nat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void generate_unown_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE void generate_unown_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
||||||
u8 atk_ivs = ((wanted_ivs>>4) & 0xF);
|
u8 atk_ivs = ((wanted_ivs>>4) & 0xF);
|
||||||
u8 def_ivs = ((wanted_ivs) & 0xF);
|
u8 def_ivs = ((wanted_ivs) & 0xF);
|
||||||
u8 spe_ivs = ((wanted_ivs>>12) & 0xF);
|
u8 spe_ivs = ((wanted_ivs>>12) & 0xF);
|
||||||
|
|
@ -482,9 +494,9 @@ IWRAM_CODE __attribute__ ((optimize(3))) void generate_unown_info(u8 wanted_natu
|
||||||
_generate_unown_info(wanted_nature, letter, rest_of_ivs, tsv, dst_pid, dst_ivs, get_rng());
|
_generate_unown_info(wanted_nature, letter, rest_of_ivs, tsv, dst_pid, dst_ivs, get_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) u8 search_unown_with_mask(u32 mask, u16 new_high, u16 new_low, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE u8 search_specific_low_pid(u32 pid, u32* dst_pid, u32* dst_ivs) {
|
||||||
new_high = new_high ^ (mask>>16);
|
u16 new_high = pid >> 16;
|
||||||
new_low = new_low ^ (mask&0xFFFF);
|
u16 new_low = pid & 0xFFFF;
|
||||||
for(int u = 0; u < NUM_SEEDS; u++) {
|
for(int u = 0; u < NUM_SEEDS; u++) {
|
||||||
u32 seed = (new_high<<16) | u;
|
u32 seed = (new_high<<16) | u;
|
||||||
|
|
||||||
|
|
@ -504,7 +516,29 @@ IWRAM_CODE __attribute__ ((optimize(3))) u8 search_unown_with_mask(u32 mask, u16
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void _generate_unown_shiny_info(u8 wanted_nature, u16 tsv, u8 letter, u32* dst_pid, u32* dst_ivs, u32 given_seed) {
|
IWRAM_CODE MAX_OPTIMIZE u8 search_unown_pid_masks(u32 pid, u8 wanted_nature, u32* dst_pid, u32* dst_ivs) {
|
||||||
|
for(int i = 0; i < 0x20; i++)
|
||||||
|
for(int j = 0; j < 0x80; j++) {
|
||||||
|
u32 mask = 0;
|
||||||
|
if(j&1)
|
||||||
|
mask +=4;
|
||||||
|
if(j&2)
|
||||||
|
mask += 0x40000;
|
||||||
|
for(int k = 0; k < 5; k++)
|
||||||
|
if((j>>(2+k))&1)
|
||||||
|
mask += 0x10001 << (3+k);
|
||||||
|
for(int k = 0; k < 5; k++)
|
||||||
|
if((i>>k)&1)
|
||||||
|
mask += 0x01000100 << (3+k);
|
||||||
|
u8 xor_mod_change = get_nature_fast(pid ^ mask);
|
||||||
|
if(xor_mod_change == wanted_nature)
|
||||||
|
if(search_specific_low_pid(pid ^ mask, dst_pid, dst_ivs))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWRAM_CODE MAX_OPTIMIZE void _generate_unown_shiny_info(u8 wanted_nature, u16 tsv, u8 letter, u32* dst_pid, u32* dst_ivs, u32 given_seed) {
|
||||||
// Worst case: 5, 0x4FF8, 5, 0x8FC00000
|
// Worst case: 5, 0x4FF8, 5, 0x8FC00000
|
||||||
u16 high_pid;
|
u16 high_pid;
|
||||||
u16 low_pid;
|
u16 low_pid;
|
||||||
|
|
@ -578,26 +612,9 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_unown_shiny_info(u8 want
|
||||||
new_high = (new_high & 0x0303) | ((new_low) & 0xFCFC);
|
new_high = (new_high & 0x0303) | ((new_low) & 0xFCFC);
|
||||||
new_low = (new_low & 0x0303) | ((old_new_high) & 0xFCFC);
|
new_low = (new_low & 0x0303) | ((old_new_high) & 0xFCFC);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = (new_high<<16) | new_low;
|
if(search_unown_pid_masks((new_high<<16) | new_low, wanted_nature, dst_pid, dst_ivs))
|
||||||
for(int i = 0; i < 0x20; i++)
|
return;
|
||||||
for(int j = 0; j < 0x80; j++) {
|
|
||||||
u32 mask = 0;
|
|
||||||
if(j&1)
|
|
||||||
mask +=4;
|
|
||||||
if(j&2)
|
|
||||||
mask += 0x40000;
|
|
||||||
for(int k = 0; k < 5; k++)
|
|
||||||
if((j>>(2+k))&1)
|
|
||||||
mask += 0x10001 << (3+k);
|
|
||||||
for(int k = 0; k < 5; k++)
|
|
||||||
if((i>>k)&1)
|
|
||||||
mask += 0x01000100 << (3+k);
|
|
||||||
u8 xor_mod_change = get_nature_fast(pid ^ mask);
|
|
||||||
if(xor_mod_change == wanted_nature)
|
|
||||||
if(search_unown_with_mask(mask, new_high, new_low, dst_pid, dst_ivs))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pos + base_increment < 0)
|
if(pos + base_increment < 0)
|
||||||
|
|
@ -617,7 +634,7 @@ IWRAM_CODE __attribute__ ((optimize(3))) void _generate_unown_shiny_info(u8 want
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) void generate_unown_shiny_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE void generate_unown_shiny_info(u8 wanted_nature, u16 wanted_ivs, u16 tsv, u32* dst_pid, u32* dst_ivs) {
|
||||||
u8 letter = get_unown_letter_gen2_fast(wanted_ivs);
|
u8 letter = get_unown_letter_gen2_fast(wanted_ivs);
|
||||||
u8 valid_natures[NUM_NATURES];
|
u8 valid_natures[NUM_NATURES];
|
||||||
get_letter_valid_natures(tsv, letter, valid_natures);
|
get_letter_valid_natures(tsv, letter, valid_natures);
|
||||||
|
|
@ -627,10 +644,10 @@ IWRAM_CODE __attribute__ ((optimize(3))) void generate_unown_shiny_info(u8 wante
|
||||||
if(wanted_nature >= NUM_NATURES)
|
if(wanted_nature >= NUM_NATURES)
|
||||||
wanted_nature -= NUM_NATURES;
|
wanted_nature -= NUM_NATURES;
|
||||||
}
|
}
|
||||||
return _generate_unown_shiny_info(wanted_nature, letter, tsv, dst_pid, dst_ivs, get_rng());
|
_generate_unown_shiny_info(wanted_nature, letter, tsv, dst_pid, dst_ivs, get_rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__ ((optimize(3))) u8 get_roamer_ivs(u32 pid, u8 hp_ivs, u8 atk_ivs, u32* dst_ivs) {
|
IWRAM_CODE MAX_OPTIMIZE u8 get_roamer_ivs(u32 pid, u8 hp_ivs, u8 atk_ivs, u32* dst_ivs) {
|
||||||
atk_ivs &= 7;
|
atk_ivs &= 7;
|
||||||
|
|
||||||
for(u32 l = 0; l < NUM_SEEDS; l++) {
|
for(u32 l = 0; l < NUM_SEEDS; l++) {
|
||||||
|
|
@ -655,11 +672,13 @@ IWRAM_CODE __attribute__ ((optimize(3))) u8 get_roamer_ivs(u32 pid, u8 hp_ivs, u
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !(TEST_WORST_CASE)
|
||||||
|
void worst_case_conversion_tester(u32* UNUSED(counter)) {
|
||||||
|
#else
|
||||||
void worst_case_conversion_tester(u32* counter) {
|
void worst_case_conversion_tester(u32* counter) {
|
||||||
#if TEST_WORST_CASE
|
|
||||||
|
|
||||||
int curr_counter = *counter;
|
u32 curr_counter = *counter;
|
||||||
int max_counter = 0;
|
u32 max_counter = 0;
|
||||||
u32 pid, ivs;
|
u32 pid, ivs;
|
||||||
|
|
||||||
curr_counter = *counter;
|
curr_counter = *counter;
|
||||||
|
|
@ -730,4 +749,4 @@ void worst_case_conversion_tester(u32* counter) {
|
||||||
PRINT_FUNCTION("Max time 4 s: 0x\x04\n", max_counter);
|
PRINT_FUNCTION("Max time 4 s: 0x\x04\n", max_counter);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
#ifndef PID_IV_TID__
|
#ifndef PID_IV_TID__
|
||||||
#define PID_IV_TID__
|
#define PID_IV_TID__
|
||||||
|
|
||||||
#include <gba.h>
|
|
||||||
|
|
||||||
void worst_case_conversion_tester(u32*);
|
void worst_case_conversion_tester(u32*);
|
||||||
void init_unown_tsv();
|
void init_unown_tsv(void);
|
||||||
|
|
||||||
u8 get_roamer_ivs(u32, u8, u8, u32*);
|
u8 get_roamer_ivs(u32, u8, u8, u32*);
|
||||||
void generate_unown_shiny_info(u8, u16, u16, u32*, u32*);
|
void generate_unown_shiny_info(u8, u16, u16, u32*, u32*);
|
||||||
|
|
@ -15,4 +13,4 @@ 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_egg_info(u8, u8, u16, u16, u8, u32*, u32*);
|
||||||
u32 generate_ot(u16, u8*);
|
u32 generate_ot(u16, u8*);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,13 @@
|
||||||
#include "text_handler.h"
|
#include "text_handler.h"
|
||||||
#include "graphics_handler.h"
|
#include "graphics_handler.h"
|
||||||
#include "sprite_handler.h"
|
#include "sprite_handler.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#include "text_gen3_to_general_int_bin.h"
|
#include "text_gen3_to_general_int_bin.h"
|
||||||
#include "amiga_font_c_bin.h"
|
#include "amiga_font_c_bin.h"
|
||||||
#include "jp_font_c_bin.h"
|
#include "jp_font_c_bin.h"
|
||||||
#include "window_graphics_bin.h"
|
#include "window_graphics_bin.h"
|
||||||
|
|
||||||
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
|
|
||||||
|
|
||||||
#define BASE_COLOUR RGB8(58,110,165)
|
#define BASE_COLOUR RGB8(58,110,165)
|
||||||
#define FONT_COLOUR RGB5(31,31,31)
|
#define FONT_COLOUR RGB5(31,31,31)
|
||||||
#define WINDOW_COLOUR_1 RGB5(15,15,15)
|
#define WINDOW_COLOUR_1 RGB5(15,15,15)
|
||||||
|
|
@ -39,6 +38,22 @@
|
||||||
|
|
||||||
#define NUM_DIGITS 12
|
#define NUM_DIGITS 12
|
||||||
|
|
||||||
|
void set_arrangements(u8);
|
||||||
|
void process_arrangements(void);
|
||||||
|
void enable_screens(void);
|
||||||
|
void set_screens_positions(void);
|
||||||
|
static void base_flush(void);
|
||||||
|
void new_line(void);
|
||||||
|
u8 write_char(u16);
|
||||||
|
void write_above_char(u16);
|
||||||
|
int sub_printf(u8*);
|
||||||
|
int sub_printf_gen3(u8*, u8, u8);
|
||||||
|
int prepare_base_10(int, u8*);
|
||||||
|
int prepare_base_16(int, u8*);
|
||||||
|
int digits_print(u8*, int, u8, u8);
|
||||||
|
int write_base_10(int, int, u8);
|
||||||
|
int write_base_16(int, int, u8);
|
||||||
|
|
||||||
u8 x_pos;
|
u8 x_pos;
|
||||||
u8 y_pos;
|
u8 y_pos;
|
||||||
u16* screen;
|
u16* screen;
|
||||||
|
|
@ -151,8 +166,8 @@ void init_text_system() {
|
||||||
convert_1bpp((u8*)buffer, (u32*)JP_FONT_POS, FONT_1BPP_SIZE, colors, 0);
|
convert_1bpp((u8*)buffer, (u32*)JP_FONT_POS, FONT_1BPP_SIZE, colors, 0);
|
||||||
|
|
||||||
// Set window tiles
|
// Set window tiles
|
||||||
for(int i = 0; i < (window_graphics_bin_size>>2); i++)
|
for(u32 i = 0; i < (window_graphics_bin_size>>2); i++)
|
||||||
*((u32*)(FONT_POS+(2*TILE_SIZE)+(i<<2))) = ((u32*)window_graphics_bin)[i];
|
*((u32*)(FONT_POS+(2*TILE_SIZE)+(i<<2))) = ((const u32*)window_graphics_bin)[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_updated_screen() {
|
void set_updated_screen() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef PRINT_SYSTEM__
|
#ifndef PRINT_SYSTEM__
|
||||||
#define PRINT_SYSTEM__
|
#define PRINT_SYSTEM__
|
||||||
|
|
||||||
#include "gba.h"
|
|
||||||
|
|
||||||
#define PRINT_FUNCTION fast_printf
|
#define PRINT_FUNCTION fast_printf
|
||||||
#define X_LIMIT (SCREEN_WIDTH>>3)
|
#define X_LIMIT (SCREEN_WIDTH>>3)
|
||||||
#define Y_LIMIT (SCREEN_HEIGHT>>3)
|
#define Y_LIMIT (SCREEN_HEIGHT>>3)
|
||||||
|
|
@ -25,25 +23,25 @@
|
||||||
|
|
||||||
int fast_printf(const char *, ...);
|
int fast_printf(const char *, ...);
|
||||||
|
|
||||||
void init_numbers();
|
void init_numbers(void);
|
||||||
void default_reset_screen();
|
void default_reset_screen(void);
|
||||||
void reset_screen(u8);
|
void reset_screen(u8);
|
||||||
void set_text_x(u8);
|
void set_text_x(u8);
|
||||||
void set_text_y(u8);
|
void set_text_y(u8);
|
||||||
void enable_screen(u8);
|
void enable_screen(u8);
|
||||||
void disable_screen(u8);
|
void disable_screen(u8);
|
||||||
void disable_all_screens_but_current();
|
void disable_all_screens_but_current(void);
|
||||||
void set_bg_pos(u8, int, int);
|
void set_bg_pos(u8, int, int);
|
||||||
u16* get_screen(u8 bg_num);
|
u16* get_screen(u8 bg_num);
|
||||||
u8 get_screen_num();
|
u8 get_screen_num(void);
|
||||||
void set_screen(u8);
|
void set_screen(u8);
|
||||||
void init_text_system();
|
void init_text_system(void);
|
||||||
void prepare_flush();
|
void prepare_flush(void);
|
||||||
void set_updated_screen();
|
void set_updated_screen(void);
|
||||||
void flush_screens();
|
void flush_screens(void);
|
||||||
void wait_for_vblank_if_needed();
|
void wait_for_vblank_if_needed(void);
|
||||||
u8 get_bg_priority(u8);
|
u8 get_bg_priority(u8);
|
||||||
u8 get_curr_priority();
|
u8 get_curr_priority(void);
|
||||||
u8 get_loaded_priority();
|
u8 get_loaded_priority(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
12
source/rng.c
12
source/rng.c
|
|
@ -1,18 +1,20 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
|
|
||||||
|
|
||||||
#define FACTOR_0 0x4C957F2D
|
#define FACTOR_0 0x4C957F2D
|
||||||
#define FACTOR_1 0x5851F42D
|
#define FACTOR_1 0x5851F42D
|
||||||
#define INCREMENT_0 1
|
#define INCREMENT_0 1
|
||||||
#define INCREMENT_1 0
|
#define INCREMENT_1 0
|
||||||
|
|
||||||
|
static void u64_add(u32*, u32*, u32, u32);
|
||||||
|
void u64_mul(u32*, u32*, u32, u32);
|
||||||
|
|
||||||
static u32 curr_seed_0;
|
static u32 curr_seed_0;
|
||||||
static u32 curr_seed_1;
|
static u32 curr_seed_1;
|
||||||
static u8 advances_enabled;
|
static u8 advances_enabled;
|
||||||
|
|
||||||
ALWAYS_INLINE __attribute__((optimize(3))) void u64_add(u32* src0_0_p, u32* src0_1_p, u32 src1_0, u32 src1_1)
|
ALWAYS_INLINE MAX_OPTIMIZE void u64_add(u32* src0_0_p, u32* src0_1_p, u32 src1_0, u32 src1_1)
|
||||||
{
|
{
|
||||||
u32 src0_0 = *src0_0_p;
|
u32 src0_0 = *src0_0_p;
|
||||||
u32 src0_1 = *src0_1_p;
|
u32 src0_1 = *src0_1_p;
|
||||||
|
|
@ -25,7 +27,7 @@ ALWAYS_INLINE __attribute__((optimize(3))) void u64_add(u32* src0_0_p, u32* src0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((target("arm"), noinline)) void u64_mul(u32* src0_0_p, u32* src0_1_p, u32 src1_0, u32 src1_1)
|
IWRAM_CODE ARM_TARGET MAX_OPTIMIZE void u64_mul(u32* src0_0_p, u32* src0_1_p, u32 src1_0, u32 src1_1)
|
||||||
{
|
{
|
||||||
register uint32_t src0_0_ asm("r0") = (uint32_t)(*src0_0_p);
|
register uint32_t src0_0_ asm("r0") = (uint32_t)(*src0_0_p);
|
||||||
register uint32_t src0_1_ asm("r1") = (uint32_t)(*src0_1_p);
|
register uint32_t src0_1_ asm("r1") = (uint32_t)(*src0_1_p);
|
||||||
|
|
@ -83,4 +85,4 @@ u32 get_rng() {
|
||||||
void advance_rng() {
|
void advance_rng() {
|
||||||
if(advances_enabled)
|
if(advances_enabled)
|
||||||
get_rng();
|
get_rng();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
source/rng.h
12
source/rng.h
|
|
@ -1,13 +1,11 @@
|
||||||
#ifndef RNG__
|
#ifndef RNG__
|
||||||
#define RNG__
|
#define RNG__
|
||||||
|
|
||||||
#include <gba.h>
|
|
||||||
|
|
||||||
void init_rng(u32, u32);
|
void init_rng(u32, u32);
|
||||||
void disable_advances();
|
void disable_advances(void);
|
||||||
void enable_advances();
|
void enable_advances(void);
|
||||||
u32 get_rng();
|
u32 get_rng(void);
|
||||||
void advance_rng();
|
void advance_rng(void);
|
||||||
void increase_rng(u32, u32);
|
void increase_rng(u32, u32);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#define timeout 0x1000
|
#define timeout 0x1000
|
||||||
#define BANK_SIZE 0x10000
|
#define BANK_SIZE 0x10000
|
||||||
|
|
||||||
|
void bank_check(u32);
|
||||||
|
|
||||||
u8 current_bank;
|
u8 current_bank;
|
||||||
|
|
||||||
void init_bank(){
|
void init_bank(){
|
||||||
|
|
@ -117,4 +119,4 @@ int is_flash_correct(u8* data, int size, int has_banks) {
|
||||||
else if(size > BANK_SIZE)
|
else if(size > BANK_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@ int is_flash_correct(u8* data, int size, int has_banks);
|
||||||
u32 read_int_save(u32);
|
u32 read_int_save(u32);
|
||||||
u16 read_short_save(u32);
|
u16 read_short_save(u32);
|
||||||
void copy_save_to_ram(u32, u8*, int);
|
void copy_save_to_ram(u32, u8*, int);
|
||||||
void init_bank();
|
void init_bank(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "sio.h"
|
#include "sio.h"
|
||||||
#include "vcount_basic.h"
|
#include "vcount_basic.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#define BLANK_LINES_WAIT 13
|
#define BLANK_LINES_WAIT 13
|
||||||
|
|
||||||
|
|
@ -50,7 +51,7 @@ void sio_normal_inner_slave() {
|
||||||
REG_SIOCNT |= SIO_SO_HIGH;
|
REG_SIOCNT |= SIO_SO_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) void sio_handle_irq_slave(int next_data) {
|
IWRAM_CODE MAX_OPTIMIZE void sio_handle_irq_slave(int next_data) {
|
||||||
REG_SIOCNT |= SIO_SO_HIGH;
|
REG_SIOCNT |= SIO_SO_HIGH;
|
||||||
|
|
||||||
REG_SIODATA32 = next_data;
|
REG_SIODATA32 = next_data;
|
||||||
|
|
@ -65,7 +66,7 @@ IWRAM_CODE __attribute__((optimize(3))) void sio_handle_irq_slave(int next_data)
|
||||||
REG_SIOCNT &= ~SIO_SO_HIGH;
|
REG_SIOCNT &= ~SIO_SO_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) int sio_read(u8 is_32) {
|
IWRAM_CODE MAX_OPTIMIZE int sio_read(u8 is_32) {
|
||||||
u32 data = REG_SIODATA8;
|
u32 data = REG_SIODATA8;
|
||||||
if(is_32)
|
if(is_32)
|
||||||
data = REG_SIODATA32;
|
data = REG_SIODATA32;
|
||||||
|
|
@ -94,7 +95,7 @@ void sio_normal_prepare_irq_slave(int data) {
|
||||||
REG_SIOCNT &= ~SIO_SO_HIGH;
|
REG_SIOCNT &= ~SIO_SO_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) u32 sio_send_if_ready_master(u32 data, u8 is_32, u8* success) {
|
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!)
|
// - Wait for SI to become LOW (slave ready). (Check timeout here!)
|
||||||
REG_SIODATA32 = data;
|
REG_SIODATA32 = data;
|
||||||
REG_SIODATA8 = (data & 0xFF);
|
REG_SIODATA8 = (data & 0xFF);
|
||||||
|
|
@ -110,7 +111,7 @@ IWRAM_CODE __attribute__((optimize(3))) u32 sio_send_if_ready_master(u32 data, u
|
||||||
return sio_read(is_32);
|
return sio_read(is_32);
|
||||||
}
|
}
|
||||||
|
|
||||||
IWRAM_CODE __attribute__((optimize(3))) u32 sio_send_master(u32 data, u8 is_32) {
|
IWRAM_CODE MAX_OPTIMIZE u32 sio_send_master(u32 data, u8 is_32) {
|
||||||
// - Wait for SI to become LOW (slave ready). (Check timeout here!)
|
// - Wait for SI to become LOW (slave ready). (Check timeout here!)
|
||||||
REG_SIODATA32 = data;
|
REG_SIODATA32 = data;
|
||||||
REG_SIODATA8 = (data & 0xFF);
|
REG_SIODATA8 = (data & 0xFF);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ int sio_normal(int, int, int, u8*);
|
||||||
void sio_normal_prepare_irq_slave(int);
|
void sio_normal_prepare_irq_slave(int);
|
||||||
int timed_sio_normal_master(int, int, int);
|
int timed_sio_normal_master(int, int, int);
|
||||||
void sio_handle_irq_slave(int);
|
void sio_handle_irq_slave(int);
|
||||||
void sio_stop_irq_slave();
|
void sio_stop_irq_slave(void);
|
||||||
int sio_read(u8);
|
int sio_read(u8);
|
||||||
u32 sio_send_if_ready_master(u32, u8, u8*);
|
u32 sio_send_if_ready_master(u32, u8, u8*);
|
||||||
u32 sio_send_master(u32 data, u8 is_32);
|
u32 sio_send_master(u32 data, u8 is_32);
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,39 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "sio_buffers.h"
|
#include "sio_buffers.h"
|
||||||
#include "text_handler.h"
|
#include "text_handler.h"
|
||||||
#include "options_handler.h"
|
#include "options_handler.h"
|
||||||
#include "party_handler.h"
|
#include "party_handler.h"
|
||||||
|
#include "gen_converter.h"
|
||||||
#include "gen3_save.h"
|
#include "gen3_save.h"
|
||||||
|
|
||||||
#include "default_gift_ribbons_bin.h"
|
#include "default_gift_ribbons_bin.h"
|
||||||
|
|
||||||
|
#define EACH_DIFFERENT 1
|
||||||
|
|
||||||
|
void prepare_number_of_sizes(void);
|
||||||
|
u8 get_number_of_buffers(void);
|
||||||
|
void copy_bytes(const void*, void*, int, u8, u8);
|
||||||
|
void prepare_random_data_gen12(struct random_data_t*);
|
||||||
|
void prepare_patch_set(u8*, u8*, u32, int, u32, int);
|
||||||
|
void apply_patch_set(u8*, u8*, u32, int, u32, int);
|
||||||
|
void prepare_mail_gen2(u8*, int, u8*, u8, u32);
|
||||||
|
#if !(EACH_DIFFERENT)
|
||||||
|
void buffer_loader(struct game_data_t*, u32*, u16*, u8);
|
||||||
|
#else
|
||||||
|
void load_names_gen12(struct game_data_t*, u8*, u8*, u8*, u8, u8);
|
||||||
|
void load_party_info_gen2(struct game_data_t*, struct gen2_party_info*);
|
||||||
|
void load_party_info_gen1(struct game_data_t*, struct gen1_party_info*);
|
||||||
|
void prepare_gen2_trade_data(struct game_data_t*, u32*, u8, u16*);
|
||||||
|
void prepare_gen1_trade_data(struct game_data_t*, u32*, u8, u16*);
|
||||||
|
#endif
|
||||||
|
void prepare_gen3_trade_data(struct game_data_t*, u32*, u16*);
|
||||||
|
void read_gen12_trade_data(struct game_data_t*, u32*, u8, u8);
|
||||||
|
void read_gen3_trade_data(struct game_data_t* game_data, u32* buffer);
|
||||||
|
|
||||||
u32 communication_buffers[2][BUFFER_SIZE>>2];
|
u32 communication_buffers[2][BUFFER_SIZE>>2];
|
||||||
u16 buffer_sizes[NUM_SIZES];
|
u16 buffer_sizes[NUM_SIZES];
|
||||||
u8 number_of_sizes;
|
u8 number_of_sizes;
|
||||||
|
|
||||||
#define EACH_DIFFERENT 1
|
|
||||||
|
|
||||||
u32* get_communication_buffer(u8 requested) {
|
u32* get_communication_buffer(u8 requested) {
|
||||||
if(!requested)
|
if(!requested)
|
||||||
return communication_buffers[OWN_BUFFER];
|
return communication_buffers[OWN_BUFFER];
|
||||||
|
|
@ -43,8 +63,8 @@ u16 get_buffer_size(int index) {
|
||||||
return buffer_sizes[index];
|
return buffer_sizes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_bytes(void* src, void* dst, int size, u8 src_offset, u8 dst_offset) {
|
void copy_bytes(const void* src, void* dst, int size, u8 src_offset, u8 dst_offset) {
|
||||||
u8* src_data = (u8*)src;
|
const u8* src_data = (const u8*)src;
|
||||||
u8* dst_data = (u8*)dst;
|
u8* dst_data = (u8*)dst;
|
||||||
for(int i = 0; i < size; i++)
|
for(int i = 0; i < size; i++)
|
||||||
dst_data[dst_offset+i] = src_data[src_offset+i];
|
dst_data[dst_offset+i] = src_data[src_offset+i];
|
||||||
|
|
@ -55,14 +75,14 @@ void prepare_random_data_gen12(struct random_data_t* random_data) {
|
||||||
random_data->data[i] = DEFAULT_FILLER;
|
random_data->data[i] = DEFAULT_FILLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare_patch_set(u8* buffer, u8* patch_set_buffer, int size, int start_pos, int patch_set_size, int base_pos) {
|
void prepare_patch_set(u8* buffer, u8* patch_set_buffer, u32 size, int start_pos, u32 patch_set_size, int base_pos) {
|
||||||
int cursor_data = base_pos;
|
u32 cursor_data = base_pos;
|
||||||
|
|
||||||
for(int i = 0; i < patch_set_size; i++)
|
for(u32 i = 0; i < patch_set_size; i++)
|
||||||
patch_set_buffer[i] = 0;
|
patch_set_buffer[i] = 0;
|
||||||
|
|
||||||
u32 base = start_pos;
|
u32 base = start_pos;
|
||||||
for(int i = 0; i < size; i++) {
|
for(u32 i = 0; i < size; i++) {
|
||||||
if(buffer[start_pos + i] == NO_ACTION_BYTE) {
|
if(buffer[start_pos + i] == NO_ACTION_BYTE) {
|
||||||
buffer[start_pos + i] = 0xFF;
|
buffer[start_pos + i] = 0xFF;
|
||||||
patch_set_buffer[cursor_data++] = start_pos + i + 1 -base;
|
patch_set_buffer[cursor_data++] = start_pos + i + 1 -base;
|
||||||
|
|
@ -87,9 +107,9 @@ void prepare_patch_set(u8* buffer, u8* patch_set_buffer, int size, int start_pos
|
||||||
patch_set_buffer[cursor_data] = 0xFF;
|
patch_set_buffer[cursor_data] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_patch_set(u8* buffer, u8* patch_set_buffer, int size, int start_pos, int patch_set_size, int base_pos) {
|
void apply_patch_set(u8* buffer, u8* patch_set_buffer, u32 size, int start_pos, u32 patch_set_size, int base_pos) {
|
||||||
u32 base = 0;
|
u32 base = 0;
|
||||||
for(int i = base_pos; i < patch_set_size; i++) {
|
for(u32 i = base_pos; i < patch_set_size; i++) {
|
||||||
if(patch_set_buffer[i]) {
|
if(patch_set_buffer[i]) {
|
||||||
if(patch_set_buffer[i] == 0xFF) {
|
if(patch_set_buffer[i] == 0xFF) {
|
||||||
base += NO_ACTION_BYTE-1;
|
base += NO_ACTION_BYTE-1;
|
||||||
|
|
@ -434,8 +454,8 @@ u8 are_checksum_same_gen3(struct gen3_trade_data* td) {
|
||||||
u32 checksum = 0;
|
u32 checksum = 0;
|
||||||
for(int i = 0; i < PARTY_SIZE; i++) {
|
for(int i = 0; i < PARTY_SIZE; i++) {
|
||||||
u32* mail_buf = (u32*)&td->mails_3[i];
|
u32* mail_buf = (u32*)&td->mails_3[i];
|
||||||
for(int i = 0; i < (sizeof(struct mail_gen3)>>2); i++)
|
for(u32 j = 0; j < (sizeof(struct mail_gen3)>>2); j++)
|
||||||
checksum += mail_buf[i];
|
checksum += mail_buf[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(td->checksum_mail != checksum)
|
if(td->checksum_mail != checksum)
|
||||||
|
|
@ -444,7 +464,7 @@ u8 are_checksum_same_gen3(struct gen3_trade_data* td) {
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
|
|
||||||
u32* party_buf = (u32*)&td->party_3;
|
u32* party_buf = (u32*)&td->party_3;
|
||||||
for(int i = 0; i < (sizeof(struct gen3_party)>>2); i++)
|
for(u32 i = 0; i < (sizeof(struct gen3_party)>>2); i++)
|
||||||
checksum += party_buf[i];
|
checksum += party_buf[i];
|
||||||
|
|
||||||
if(td->checksum_party != checksum)
|
if(td->checksum_party != checksum)
|
||||||
|
|
@ -453,7 +473,7 @@ u8 are_checksum_same_gen3(struct gen3_trade_data* td) {
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
u32* buffer = (u32*)td;
|
u32* buffer = (u32*)td;
|
||||||
|
|
||||||
for(int i = 0; i < ((sizeof(struct gen3_trade_data) - 4)>>2); i++)
|
for(u32 i = 0; i < ((sizeof(struct gen3_trade_data) - 4)>>2); i++)
|
||||||
checksum += buffer[i];
|
checksum += buffer[i];
|
||||||
|
|
||||||
if(td->final_checksum != checksum)
|
if(td->final_checksum != checksum)
|
||||||
|
|
@ -469,7 +489,7 @@ void prepare_gen3_trade_data(struct game_data_t* game_data, u32* buffer, u16* si
|
||||||
for(int i = 0; i < PARTY_SIZE; i++) {
|
for(int i = 0; i < PARTY_SIZE; i++) {
|
||||||
copy_bytes(&game_data->mails_3[i], &td->mails_3[i], sizeof(struct mail_gen3), 0, 0);
|
copy_bytes(&game_data->mails_3[i], &td->mails_3[i], sizeof(struct mail_gen3), 0, 0);
|
||||||
u32* mail_buf = (u32*)&td->mails_3[i];
|
u32* mail_buf = (u32*)&td->mails_3[i];
|
||||||
for(int i = 0; i < (sizeof(struct mail_gen3)>>2); i++)
|
for(u32 j = 0; j < (sizeof(struct mail_gen3)>>2); j++)
|
||||||
checksum += mail_buf[i];
|
checksum += mail_buf[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -478,7 +498,7 @@ void prepare_gen3_trade_data(struct game_data_t* game_data, u32* buffer, u16* si
|
||||||
|
|
||||||
copy_bytes(&game_data->party_3, &td->party_3, sizeof(struct gen3_party), 0, 0);
|
copy_bytes(&game_data->party_3, &td->party_3, sizeof(struct gen3_party), 0, 0);
|
||||||
u32* party_buf = (u32*)&td->party_3;
|
u32* party_buf = (u32*)&td->party_3;
|
||||||
for(int i = 0; i < (sizeof(struct gen3_party)>>2); i++)
|
for(u32 i = 0; i < (sizeof(struct gen3_party)>>2); i++)
|
||||||
checksum += party_buf[i];
|
checksum += party_buf[i];
|
||||||
|
|
||||||
td->checksum_party = checksum;
|
td->checksum_party = checksum;
|
||||||
|
|
@ -498,7 +518,7 @@ void prepare_gen3_trade_data(struct game_data_t* game_data, u32* buffer, u16* si
|
||||||
|
|
||||||
td->trainer_id = game_data->trainer_id;
|
td->trainer_id = game_data->trainer_id;
|
||||||
|
|
||||||
for(int i = 0; i < ((sizeof(struct gen3_trade_data) - 4)>>2); i++)
|
for(u32 i = 0; i < ((sizeof(struct gen3_trade_data) - 4)>>2); i++)
|
||||||
checksum += buffer[i];
|
checksum += buffer[i];
|
||||||
|
|
||||||
td->final_checksum = checksum;
|
td->final_checksum = checksum;
|
||||||
|
|
@ -559,13 +579,13 @@ void read_gen12_trade_data(struct game_data_t* game_data, u32* buffer, u8 curr_g
|
||||||
game_data->game_identifier.game_is_jp = is_jp;
|
game_data->game_identifier.game_is_jp = is_jp;
|
||||||
|
|
||||||
for(int i = 0; i < PARTY_SIZE; i++)
|
for(int i = 0; i < PARTY_SIZE; i++)
|
||||||
for(int j = 0; j < sizeof(struct mail_gen3); j++)
|
for(u32 j = 0; j < sizeof(struct mail_gen3); j++)
|
||||||
((u8*)(&game_data->mails_3[i]))[j] = 0;
|
((u8*)(&game_data->mails_3[i]))[j] = 0;
|
||||||
|
|
||||||
for(int i = 0; i < sizeof(struct gen3_party); i++)
|
for(u32 i = 0; i < sizeof(struct gen3_party); i++)
|
||||||
((u8*)(&game_data->party_3))[i] = 0;
|
((u8*)(&game_data->party_3))[i] = 0;
|
||||||
|
|
||||||
copy_bytes((u8*)default_gift_ribbons_bin, game_data->giftRibbons, GIFT_RIBBONS, 0, 0);
|
copy_bytes(default_gift_ribbons_bin, game_data->giftRibbons, GIFT_RIBBONS, 0, 0);
|
||||||
game_data->trainer_gender = 0;
|
game_data->trainer_gender = 0;
|
||||||
|
|
||||||
apply_patch_set(patch_target, patch_set, target_size-(names_size + MON_INDEX_SIZE), names_size + MON_INDEX_SIZE, PATCH_SET_SIZE, PATCH_SET_BASE_POS);
|
apply_patch_set(patch_target, patch_set, target_size-(names_size + MON_INDEX_SIZE), names_size + MON_INDEX_SIZE, PATCH_SET_SIZE, PATCH_SET_BASE_POS);
|
||||||
|
|
@ -584,7 +604,7 @@ void read_gen12_trade_data(struct game_data_t* game_data, u32* buffer, u8 curr_g
|
||||||
game_data->party_3.total = PARTY_SIZE;
|
game_data->party_3.total = PARTY_SIZE;
|
||||||
|
|
||||||
u8 found = 0;
|
u8 found = 0;
|
||||||
for(int i = 0; i < game_data->party_3.total; i++) {
|
for(u32 i = 0; i < game_data->party_3.total; i++) {
|
||||||
game_data->party_3_undec[i].src = &game_data->party_3.mons[i];
|
game_data->party_3_undec[i].src = &game_data->party_3.mons[i];
|
||||||
u8 conversion_success = 0;
|
u8 conversion_success = 0;
|
||||||
if(curr_gen == 2)
|
if(curr_gen == 2)
|
||||||
|
|
@ -624,7 +644,7 @@ void read_gen3_trade_data(struct game_data_t* game_data, u32* buffer) {
|
||||||
game_data->party_3.total = PARTY_SIZE;
|
game_data->party_3.total = PARTY_SIZE;
|
||||||
|
|
||||||
u8 found = 0;
|
u8 found = 0;
|
||||||
for(int i = 0; i < game_data->party_3.total; i++) {
|
for(u32 i = 0; i < game_data->party_3.total; i++) {
|
||||||
process_gen3_data(&game_data->party_3.mons[i], &game_data->party_3_undec[i], game_data->game_identifier.game_main_version, game_data->game_identifier.game_sub_version);
|
process_gen3_data(&game_data->party_3.mons[i], &game_data->party_3_undec[i], game_data->game_identifier.game_main_version, game_data->game_identifier.game_sub_version);
|
||||||
if(game_data->party_3_undec[i].is_valid_gen3)
|
if(game_data->party_3_undec[i].is_valid_gen3)
|
||||||
found = 1;
|
found = 1;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "party_handler.h"
|
#include "party_handler.h"
|
||||||
#include "gen3_save.h"
|
#include "gen3_save.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
// We oversize it to have some wiggle room
|
// We oversize it to have some wiggle room
|
||||||
#define BUFFER_SIZE 0x500
|
#define BUFFER_SIZE 0x500
|
||||||
|
|
@ -38,20 +39,20 @@
|
||||||
|
|
||||||
struct random_data_t {
|
struct random_data_t {
|
||||||
u8 data[RANDOM_DATA_SIZE];
|
u8 data[RANDOM_DATA_SIZE];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen2_party_info {
|
struct gen2_party_info {
|
||||||
u8 num_mons;
|
u8 num_mons;
|
||||||
u8 mons_index[MON_INDEX_SIZE];
|
u8 mons_index[MON_INDEX_SIZE];
|
||||||
u16 trainer_id;
|
u16 trainer_id;
|
||||||
struct gen2_mon_data mons_data[PARTY_SIZE];
|
struct gen2_mon_data mons_data[PARTY_SIZE];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen1_party_info {
|
struct gen1_party_info {
|
||||||
u8 num_mons;
|
u8 num_mons;
|
||||||
u8 mons_index[MON_INDEX_SIZE];
|
u8 mons_index[MON_INDEX_SIZE];
|
||||||
struct gen1_mon_data mons_data[PARTY_SIZE];
|
struct gen1_mon_data mons_data[PARTY_SIZE];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct trainer_data_gen2_int {
|
struct trainer_data_gen2_int {
|
||||||
u8 trainer_name[STRING_GEN2_INT_SIZE];
|
u8 trainer_name[STRING_GEN2_INT_SIZE];
|
||||||
|
|
@ -59,7 +60,7 @@ struct trainer_data_gen2_int {
|
||||||
u8 ot_names[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
u8 ot_names[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
||||||
u8 nicknames[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
u8 nicknames[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
||||||
u8 safety_bytes[SAFETY_BYTES_NUM];
|
u8 safety_bytes[SAFETY_BYTES_NUM];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct trainer_data_gen2_jp {
|
struct trainer_data_gen2_jp {
|
||||||
u8 trainer_name[STRING_GEN2_JP_SIZE];
|
u8 trainer_name[STRING_GEN2_JP_SIZE];
|
||||||
|
|
@ -67,7 +68,7 @@ struct trainer_data_gen2_jp {
|
||||||
u8 ot_names[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
u8 ot_names[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
||||||
u8 nicknames[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
u8 nicknames[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
||||||
u8 safety_bytes[SAFETY_BYTES_NUM];
|
u8 safety_bytes[SAFETY_BYTES_NUM];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct trainer_data_gen1_int {
|
struct trainer_data_gen1_int {
|
||||||
u8 trainer_name[STRING_GEN2_INT_SIZE];
|
u8 trainer_name[STRING_GEN2_INT_SIZE];
|
||||||
|
|
@ -75,7 +76,7 @@ struct trainer_data_gen1_int {
|
||||||
u8 ot_names[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
u8 ot_names[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
||||||
u8 nicknames[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
u8 nicknames[PARTY_SIZE][STRING_GEN2_INT_SIZE];
|
||||||
u8 safety_bytes[SAFETY_BYTES_NUM];
|
u8 safety_bytes[SAFETY_BYTES_NUM];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct trainer_data_gen1_jp {
|
struct trainer_data_gen1_jp {
|
||||||
u8 trainer_name[STRING_GEN2_JP_SIZE];
|
u8 trainer_name[STRING_GEN2_JP_SIZE];
|
||||||
|
|
@ -83,22 +84,22 @@ struct trainer_data_gen1_jp {
|
||||||
u8 ot_names[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
u8 ot_names[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
||||||
u8 nicknames[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
u8 nicknames[PARTY_SIZE][STRING_GEN2_JP_SIZE];
|
||||||
u8 safety_bytes[SAFETY_BYTES_NUM];
|
u8 safety_bytes[SAFETY_BYTES_NUM];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct patch_set_trainer_data_gen12 {
|
struct patch_set_trainer_data_gen12 {
|
||||||
u8 patch_set[PATCH_SET_SIZE];
|
u8 patch_set[PATCH_SET_SIZE];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct party_mail_data_gen2_int {
|
struct party_mail_data_gen2_int {
|
||||||
u8 gen2_mail_data[MAIL_GEN2_INT_SIZE];
|
u8 gen2_mail_data[MAIL_GEN2_INT_SIZE];
|
||||||
u8 patch_set[MAIL_PATCH_SET_INT_SIZE];
|
u8 patch_set[MAIL_PATCH_SET_INT_SIZE];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct party_mail_data_gen2_jp {
|
struct party_mail_data_gen2_jp {
|
||||||
// Need to look into it, again for the size...
|
// Need to look into it, again for the size...
|
||||||
u8 gen2_mail_data[MAIL_GEN2_JP_SIZE];
|
u8 gen2_mail_data[MAIL_GEN2_JP_SIZE];
|
||||||
u8 patch_set[MAIL_PATCH_SET_JP_SIZE];
|
u8 patch_set[MAIL_PATCH_SET_JP_SIZE];
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen2_trade_data_int {
|
struct gen2_trade_data_int {
|
||||||
struct random_data_t random_data;
|
struct random_data_t random_data;
|
||||||
|
|
@ -106,7 +107,7 @@ struct gen2_trade_data_int {
|
||||||
struct patch_set_trainer_data_gen12 patch_set;
|
struct patch_set_trainer_data_gen12 patch_set;
|
||||||
u8 useless_sync[USELESS_SYNC_BYTES];
|
u8 useless_sync[USELESS_SYNC_BYTES];
|
||||||
struct party_mail_data_gen2_int mail;
|
struct party_mail_data_gen2_int mail;
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen2_trade_data_jp {
|
struct gen2_trade_data_jp {
|
||||||
struct random_data_t random_data;
|
struct random_data_t random_data;
|
||||||
|
|
@ -114,19 +115,19 @@ struct gen2_trade_data_jp {
|
||||||
struct patch_set_trainer_data_gen12 patch_set;
|
struct patch_set_trainer_data_gen12 patch_set;
|
||||||
u8 useless_sync[USELESS_SYNC_BYTES];
|
u8 useless_sync[USELESS_SYNC_BYTES];
|
||||||
struct party_mail_data_gen2_jp mail;
|
struct party_mail_data_gen2_jp mail;
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen1_trade_data_int {
|
struct gen1_trade_data_int {
|
||||||
struct random_data_t random_data;
|
struct random_data_t random_data;
|
||||||
struct trainer_data_gen1_int trainer_info;
|
struct trainer_data_gen1_int trainer_info;
|
||||||
struct patch_set_trainer_data_gen12 patch_set;
|
struct patch_set_trainer_data_gen12 patch_set;
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen1_trade_data_jp {
|
struct gen1_trade_data_jp {
|
||||||
struct random_data_t random_data;
|
struct random_data_t random_data;
|
||||||
struct trainer_data_gen1_jp trainer_info;
|
struct trainer_data_gen1_jp trainer_info;
|
||||||
struct patch_set_trainer_data_gen12 patch_set;
|
struct patch_set_trainer_data_gen12 patch_set;
|
||||||
} __attribute__ ((packed));
|
} PACKED;
|
||||||
|
|
||||||
struct gen3_trade_data {
|
struct gen3_trade_data {
|
||||||
struct mail_gen3 mails_3[PARTY_SIZE];
|
struct mail_gen3 mails_3[PARTY_SIZE];
|
||||||
|
|
@ -142,15 +143,15 @@ struct gen3_trade_data {
|
||||||
u8 extra_tmp_padding[NUM_EXTRA_PADDING_BYTES_GEN3];
|
u8 extra_tmp_padding[NUM_EXTRA_PADDING_BYTES_GEN3];
|
||||||
u32 trainer_id;
|
u32 trainer_id;
|
||||||
u32 final_checksum;
|
u32 final_checksum;
|
||||||
} __attribute__ ((packed)) __attribute__((aligned(4)));
|
} PACKED ALIGNED(4);
|
||||||
|
|
||||||
void load_comm_buffer(struct game_data_t*, int, u8);
|
void load_comm_buffer(struct game_data_t*, int, u8);
|
||||||
void read_comm_buffer(struct game_data_t*, int, u8);
|
void read_comm_buffer(struct game_data_t*, int, u8);
|
||||||
|
|
||||||
u8 are_checksum_same_gen3(struct gen3_trade_data*);
|
u8 are_checksum_same_gen3(struct gen3_trade_data*);
|
||||||
u32* get_communication_buffer(u8);
|
u32* get_communication_buffer(u8);
|
||||||
u8 get_number_of_buffers();
|
u8 get_number_of_buffers(void);
|
||||||
u16 get_buffer_size(int);
|
u16 get_buffer_size(int);
|
||||||
u16* get_buffer_sizes();
|
u16* get_buffer_sizes(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,20 @@
|
||||||
#define OFF_SCREEN_SPRITE SCREEN_HEIGHT
|
#define OFF_SCREEN_SPRITE SCREEN_HEIGHT
|
||||||
|
|
||||||
u8 check_for_same_address(const u8*);
|
u8 check_for_same_address(const u8*);
|
||||||
|
u32 get_vram_pos(void);
|
||||||
|
void set_updated_shadow_oam(void);
|
||||||
|
void inc_inner_sprite_counter(void);
|
||||||
|
u8 get_sprite_counter(void);
|
||||||
|
void inc_sprite_counter(void);
|
||||||
|
void set_attributes(u16, u16, u16);
|
||||||
|
u8 get_first_variable_palette(void);
|
||||||
|
u8 get_3bpp_palette(int);
|
||||||
|
void set_palette_3bpp(u8*, int, int);
|
||||||
|
u16 get_item_icon_tile(void);
|
||||||
|
u16 get_mail_icon_tile(void);
|
||||||
|
void set_item_icon(u16, u16);
|
||||||
|
void set_mail_icon(u16, u16);
|
||||||
|
void raw_update_cursor_x(u16);
|
||||||
|
|
||||||
const u16* sprite_cursor_gfx = (const u16*)sprite_cursor_bin;
|
const u16* sprite_cursor_gfx = (const u16*)sprite_cursor_bin;
|
||||||
const u16* item_icon_gfx = (const u16*)item_icon_bin;
|
const u16* item_icon_gfx = (const u16*)item_icon_bin;
|
||||||
|
|
@ -64,7 +78,7 @@ IWRAM_CODE void update_normal_oam() {
|
||||||
if(updated_shadow_oam) {
|
if(updated_shadow_oam) {
|
||||||
u32* oam_ptr = (u32*)OAM;
|
u32* oam_ptr = (u32*)OAM;
|
||||||
u32* shadow_oam_ptr = (u32*)shadow_oam;
|
u32* shadow_oam_ptr = (u32*)shadow_oam;
|
||||||
for(int i = 0; i < ((sizeof(OBJATTR)*OAM_ENTITIES)>>2); i++)
|
for(u32 i = 0; i < ((sizeof(OBJATTR)*OAM_ENTITIES)>>2); i++)
|
||||||
oam_ptr[i] = shadow_oam_ptr[i];
|
oam_ptr[i] = shadow_oam_ptr[i];
|
||||||
updated_shadow_oam = 0;
|
updated_shadow_oam = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -124,12 +138,12 @@ void set_palette_3bpp(u8* colors, int index, int palette) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_cursor(){
|
void init_cursor(){
|
||||||
sprite_pointers[__sprite_counter] = (u8*)sprite_cursor_gfx;
|
sprite_pointers[__sprite_counter] = (const u8*)sprite_cursor_gfx;
|
||||||
u16* vram_pos = (u16*)get_vram_pos();
|
u16* vram_pos = (u16*)get_vram_pos();
|
||||||
for(int i = 0; i < (sprite_cursor_bin_size>>1); i++)
|
for(u32 i = 0; i < (sprite_cursor_bin_size>>1); i++)
|
||||||
vram_pos[i] = sprite_cursor_gfx[i];
|
vram_pos[i] = sprite_cursor_gfx[i];
|
||||||
vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE);
|
vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE);
|
||||||
for(int i = 0; i < (sprite_cursor_bin_size>>1); i++)
|
for(u32 i = 0; i < (sprite_cursor_bin_size>>1); i++)
|
||||||
vram_pos[i] = sprite_cursor_gfx[i];
|
vram_pos[i] = sprite_cursor_gfx[i];
|
||||||
for(int i = 0; i < TOTAL_BG; i++) {
|
for(int i = 0; i < TOTAL_BG; i++) {
|
||||||
set_attributes(OFF_SCREEN_SPRITE, 0, (32*__sprite_counter) | ((3-i)<<10));
|
set_attributes(OFF_SCREEN_SPRITE, 0, (32*__sprite_counter) | ((3-i)<<10));
|
||||||
|
|
@ -143,18 +157,18 @@ void init_cursor(){
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_oam_palette(){
|
void init_oam_palette(){
|
||||||
for(int i = 0; i < (sprite_palettes_bin_size>>1); i++)
|
for(u32 i = 0; i < (sprite_palettes_bin_size>>1); i++)
|
||||||
SPRITE_PALETTE[i] = sprite_palettes_bin_16[i];
|
SPRITE_PALETTE[i] = sprite_palettes_bin_16[i];
|
||||||
for(int i = 0; i < (item_icon_palette_bin_size>>1); i++)
|
for(u32 i = 0; i < (item_icon_palette_bin_size>>1); i++)
|
||||||
SPRITE_PALETTE[i+(sprite_palettes_bin_size>>1)] = item_icon_palette_bin_16[i];
|
SPRITE_PALETTE[i+(sprite_palettes_bin_size>>1)] = item_icon_palette_bin_16[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_item_icon(){
|
void init_item_icon(){
|
||||||
u16* vram_pos = (u16*)(get_vram_pos() + sprite_cursor_bin_size);
|
u16* vram_pos = (u16*)(get_vram_pos() + sprite_cursor_bin_size);
|
||||||
for(int i = 0; i < (item_icon_bin_size>>1); i++)
|
for(u32 i = 0; i < (item_icon_bin_size>>1); i++)
|
||||||
vram_pos[i] = item_icon_gfx[i];
|
vram_pos[i] = item_icon_gfx[i];
|
||||||
vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE + sprite_cursor_bin_size);
|
vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE + sprite_cursor_bin_size);
|
||||||
for(int i = 0; i < (item_icon_bin_size>>1); i++)
|
for(u32 i = 0; i < (item_icon_bin_size>>1); i++)
|
||||||
vram_pos[i] = item_icon_gfx[i];
|
vram_pos[i] = item_icon_gfx[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,30 +32,24 @@
|
||||||
#define BASE_X_CURSOR_INCREMENT_OFFER_OPTIONS 64
|
#define BASE_X_CURSOR_INCREMENT_OFFER_OPTIONS 64
|
||||||
#define BASE_Y_CURSOR_INCREMENT_OFFER_OPTIONS 16
|
#define BASE_Y_CURSOR_INCREMENT_OFFER_OPTIONS 16
|
||||||
|
|
||||||
void init_sprite_counter();
|
void init_sprites(void);
|
||||||
u8 get_sprite_counter();
|
void init_sprite_counter(void);
|
||||||
void inc_sprite_counter();
|
void init_oam_palette(void);
|
||||||
u32 get_vram_pos();
|
void init_item_icon(void);
|
||||||
void init_oam_palette();
|
|
||||||
void set_attributes(u16, u16, u16);
|
|
||||||
|
|
||||||
void init_sprites();
|
|
||||||
void init_item_icon();
|
|
||||||
void set_item_icon(u16, u16);
|
|
||||||
void set_pokemon_sprite(const u8*, u8, u8, u8, u8, u16, u16);
|
void set_pokemon_sprite(const u8*, u8, u8, u8, u8, u16, u16);
|
||||||
void set_party_sprite_counter();
|
void set_party_sprite_counter(void);
|
||||||
void init_cursor();
|
void init_cursor(void);
|
||||||
void update_cursor_y(u16);
|
void update_cursor_y(u16);
|
||||||
void update_cursor_base_x(u16);
|
void update_cursor_base_x(u16);
|
||||||
void move_sprites(u8 counter);
|
void move_sprites(u8 counter);
|
||||||
void move_cursor_x(u8 counter);
|
void move_cursor_x(u8 counter);
|
||||||
void disable_cursor();
|
void disable_cursor(void);
|
||||||
void disable_all_cursors();
|
void disable_all_cursors(void);
|
||||||
void reset_sprites(u8);
|
void reset_sprites(u8);
|
||||||
void disable_all_sprites();
|
void disable_all_sprites(void);
|
||||||
void enable_all_sprites();
|
void enable_all_sprites(void);
|
||||||
void update_normal_oam();
|
void update_normal_oam(void);
|
||||||
void reset_sprites_to_cursor();
|
void reset_sprites_to_cursor(void);
|
||||||
void reset_sprites_to_party();
|
void reset_sprites_to_party(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <gba.h>
|
#include <gba.h>
|
||||||
#include "text_handler.h"
|
#include "text_handler.h"
|
||||||
#include "bin_table_handler.h"
|
#include "bin_table_handler.h"
|
||||||
|
#include "useful_qualifiers.h"
|
||||||
|
|
||||||
#include "trainer_names_bin.h"
|
#include "trainer_names_bin.h"
|
||||||
#include "text_gen3_to_gen12_int_bin.h"
|
#include "text_gen3_to_gen12_int_bin.h"
|
||||||
|
|
@ -19,6 +20,15 @@
|
||||||
#define GENERIC_TO_UPPER 0x20
|
#define GENERIC_TO_UPPER 0x20
|
||||||
#define GEN12_TRAINER 0x5D
|
#define GEN12_TRAINER 0x5D
|
||||||
|
|
||||||
|
u8 text_general_count_question(const u8*, u8, u8, u8);
|
||||||
|
u8 text_general_size(const u8*, u8, u8);
|
||||||
|
void text_general_conversion(const u8*, u8*, u8, u8, u8, u8, const u8*);
|
||||||
|
u8 text_general_is_same(const u8*, const u8*, u8, u8, u8);
|
||||||
|
void text_general_copy(const u8*, u8*, u8, u8, u8);
|
||||||
|
void text_general_concat(const u8*, const u8*, u8*, u8, u8, u8, u8);
|
||||||
|
void text_general_replace(u8*, u8, u8, u8, u8);
|
||||||
|
void text_general_terminator_fill(u8*, u8, u8);
|
||||||
|
|
||||||
u8 text_general_count_question(const u8* src, u8 src_size, u8 terminator, u8 question) {
|
u8 text_general_count_question(const u8* src, u8 src_size, u8 terminator, u8 question) {
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for(int i = 0; i < src_size; i++) {
|
for(int i = 0; i < src_size; i++) {
|
||||||
|
|
@ -205,14 +215,14 @@ u8 text_gen2_size(const u8* src, u8 src_size) {
|
||||||
return text_general_size(src, src_size, GEN2_EOL);
|
return text_general_size(src, src_size, GEN2_EOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_generic_to_gen3(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 jp_src, u8 jp_dst) {
|
void text_generic_to_gen3(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 UNUSED(jp_src), u8 jp_dst) {
|
||||||
if(jp_dst)
|
if(jp_dst)
|
||||||
text_general_conversion(src, dst, src_size, dst_size, GENERIC_EOL, GEN3_EOL, text_general_to_gen3_jp_bin);
|
text_general_conversion(src, dst, src_size, dst_size, GENERIC_EOL, GEN3_EOL, text_general_to_gen3_jp_bin);
|
||||||
else
|
else
|
||||||
text_general_conversion(src, dst, src_size, dst_size, GENERIC_EOL, GEN3_EOL, text_general_to_gen3_int_bin);
|
text_general_conversion(src, dst, src_size, dst_size, GENERIC_EOL, GEN3_EOL, text_general_to_gen3_int_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_gen3_to_generic(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 jp_src, u8 jp_dst) {
|
void text_gen3_to_generic(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 jp_src, u8 UNUSED(jp_dst)) {
|
||||||
if(jp_src)
|
if(jp_src)
|
||||||
text_general_conversion(src, dst, src_size, dst_size, GEN3_EOL, GENERIC_EOL, text_gen3_to_general_jp_bin);
|
text_general_conversion(src, dst, src_size, dst_size, GEN3_EOL, GENERIC_EOL, text_gen3_to_general_jp_bin);
|
||||||
else
|
else
|
||||||
|
|
@ -230,7 +240,7 @@ void text_gen3_to_gen12(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 jp_
|
||||||
text_general_conversion(src, dst, src_size, dst_size, GEN3_EOL, GEN2_EOL, text_gen3_to_gen12_int_bin);
|
text_general_conversion(src, dst, src_size, dst_size, GEN3_EOL, GEN2_EOL, text_gen3_to_gen12_int_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void text_gen12_to_gen3(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 jp_src, u8 jp_dst) {
|
void text_gen12_to_gen3(const u8* src, u8* dst, u8 src_size, u8 dst_size, u8 jp_src, u8 UNUSED(jp_dst)) {
|
||||||
if(src[0] == GEN12_TRAINER)
|
if(src[0] == GEN12_TRAINER)
|
||||||
text_gen3_copy(get_table_pointer(trainer_names_bin, jp_src), dst, src_size, dst_size);
|
text_gen3_copy(get_table_pointer(trainer_names_bin, jp_src), dst, src_size, dst_size);
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
11
source/useful_qualifiers.h
Normal file
11
source/useful_qualifiers.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef USEFUL_QUALIFIERS__
|
||||||
|
#define USEFUL_QUALIFIERS__
|
||||||
|
|
||||||
|
#define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||||
|
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
|
||||||
|
#define MAX_OPTIMIZE __attribute__((optimize(3)))
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
#define ARM_TARGET __attribute__((target("arm"),noinline))
|
||||||
|
#define ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef WINDOW_HANDLER__
|
#ifndef WINDOW_HANDLER__
|
||||||
#define WINDOW_HANDLER__
|
#define WINDOW_HANDLER__
|
||||||
|
|
||||||
#include "gba.h"
|
|
||||||
|
|
||||||
#define TOTAL_Y_SIZE (SCREEN_HEIGHT>>3)
|
#define TOTAL_Y_SIZE (SCREEN_HEIGHT>>3)
|
||||||
#define TOTAL_X_SIZE (SCREEN_WIDTH>>3)
|
#define TOTAL_X_SIZE (SCREEN_WIDTH>>3)
|
||||||
|
|
||||||
|
|
@ -36,19 +34,19 @@
|
||||||
#define OFFER_OPTIONS_WINDOW_X_SIZE (TOTAL_X_SIZE - OFFER_OPTIONS_WINDOW_X - 1)
|
#define OFFER_OPTIONS_WINDOW_X_SIZE (TOTAL_X_SIZE - OFFER_OPTIONS_WINDOW_X - 1)
|
||||||
#define OFFER_OPTIONS_WINDOW_Y_SIZE (TOTAL_Y_SIZE - OFFER_OPTIONS_WINDOW_Y - 1)
|
#define OFFER_OPTIONS_WINDOW_Y_SIZE (TOTAL_Y_SIZE - OFFER_OPTIONS_WINDOW_Y - 1)
|
||||||
|
|
||||||
void init_trade_options_window();
|
void init_trade_options_window(void);
|
||||||
void clear_trade_options_window();
|
void clear_trade_options_window(void);
|
||||||
|
|
||||||
void init_offer_window();
|
void init_offer_window(void);
|
||||||
void clear_offer_window();
|
void clear_offer_window(void);
|
||||||
|
|
||||||
void init_message_window();
|
void init_message_window(void);
|
||||||
void clear_message_window();
|
void clear_message_window(void);
|
||||||
|
|
||||||
void init_offer_options_window();
|
void init_offer_options_window(void);
|
||||||
void clear_offer_options_window();
|
void clear_offer_options_window(void);
|
||||||
|
|
||||||
void init_waiting_window();
|
void init_waiting_window(void);
|
||||||
void clear_waiting_window();
|
void clear_waiting_window(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user