Add Nintendo DS build

This commit is contained in:
Lorenzooone 2023-04-09 01:27:03 +02:00
parent 305aafdcb5
commit 173c63cd75
37 changed files with 825 additions and 143 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
build/
*.elf
*.nds
*.NDS
*.gba
*.GBA
*.sav

277
Makefile.arm9 Normal file
View File

@ -0,0 +1,277 @@
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileContributor: Antonio Niño Díaz, 2023
BLOCKSDS ?= /opt/blocksds/core
BLOCKSDSEXT ?= /opt/blocksds/external
# User config
# ===========
NAME := Pokemon_Gen3_to_GenX
GAME_TITLE := Pokémon Gen 3 to Gen X
GAME_SUBTITLE := Test NDS Port
GAME_AUTHOR := Lorenzooone
GAME_ICON := icon.bmp
# DLDI and internal SD slot of DSi
# --------------------------------
# Root folder of the SD image
SDROOT := sdroot
# Name of the generated image it "DSi-1.sd" for no$gba in DSi mode
SDIMAGE := image.bin
# Source code paths
# -----------------
SOURCEDIRS := source
INCLUDEDIRS := include
GFXDIRS := graphics
BINDIRS := data
AUDIODIRS := audio
NITROFATDIR :=
# Defines passed to all files
# ---------------------------
DEFINES :=
# Libraries
# ---------
LIBS := -lmm9 -lnds9 -lc
LIBDIRS := $(BLOCKSDS)/libs/maxmod \
$(BLOCKSDS)/libs/libnds
# Build artifacts
# ---------------
BUILDDIR := build
ELF := build/$(NAME).elf
DUMP := build/$(NAME).dump
NITROFAT_IMG := build/nitrofat.bin
MAP := build/$(NAME).map
SOUNDBANKDIR := $(BUILDDIR)/maxmod
ROM := $(NAME).nds
# Tools
# -----
PREFIX := arm-none-eabi-
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
OBJDUMP := $(PREFIX)objdump
MKDIR := mkdir
RM := rm -rf
# Verbose flag
# ------------
ifeq ($(VERBOSE),1)
V :=
else
V := @
endif
# Source files
# ------------
ifneq ($(BINDIRS),)
SOURCES_BIN := $(shell find -L $(BINDIRS) -name "*.bin")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(BINDIRS))
endif
ifneq ($(GFXDIRS),)
SOURCES_PNG := $(shell find -L $(GFXDIRS) -name "*.png")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(GFXDIRS))
endif
ifneq ($(AUDIODIRS),)
SOURCES_AUDIO := $(shell find -L $(AUDIODIRS) -regex '.*\.\(it\|mod\|s3m\|wav\|xm\)')
ifneq ($(SOURCES_AUDIO),)
INCLUDEDIRS += $(SOUNDBANKDIR)
endif
endif
SOURCES_S := $(shell find -L $(SOURCEDIRS) -name "*.s")
SOURCES_C := $(shell find -L $(SOURCEDIRS) -name "*.c")
SOURCES_CPP := $(shell find -L $(SOURCEDIRS) -name "*.cpp")
# Compiler and linker flags
# -------------------------
DEFINES += -D__NDS__ -DARM9
ARCH := -march=armv5te -mtune=arm946e-s
WARNFLAGS := -Wall
ifeq ($(SOURCES_CPP),)
LD := $(CC)
else
LD := $(CXX)
endif
INCLUDEFLAGS := $(foreach path,$(INCLUDEDIRS),-I$(path)) \
$(foreach path,$(LIBDIRS),-I$(path)/include)
LIBDIRSFLAGS := $(foreach path,$(LIBDIRS),-L$(path)/lib)
ASFLAGS += -x assembler-with-cpp $(DEFINES) $(ARCH) \
-mthumb -mthumb-interwork $(INCLUDEFLAGS) \
-ffunction-sections -fdata-sections
CFLAGS += -std=gnu11 $(WARNFLAGS) $(DEFINES) $(ARCH) \
-mthumb -mthumb-interwork $(INCLUDEFLAGS) -O2 \
-Wall -Wstrict-overflow=5 -Wextra\
-Wpointer-arith -Wpedantic -Wcast-qual -Wswitch-default\
-Wstrict-prototypes -Wmissing-prototypes\
-Wshadow -Wwrite-strings \
-ffunction-sections -fdata-sections \
-fomit-frame-pointer
CXXFLAGS += -std=gnu++14 $(WARNFLAGS) $(DEFINES) $(ARCH) \
-mthumb -mthumb-interwork $(INCLUDEFLAGS) -O2 \
-ffunction-sections -fdata-sections \
-fno-exceptions -fno-rtti \
-fomit-frame-pointer
LDFLAGS := -mthumb -mthumb-interwork $(LIBDIRSFLAGS) \
-Wl,-Map,$(MAP) -Wl,--gc-sections -nostdlib \
-T$(BLOCKSDS)/sys/crts/ds_arm9.mem \
-T$(BLOCKSDS)/sys/crts/ds_arm9.ld \
-Wl,--no-warn-rwx-segments \
-Wl,--start-group $(LIBS) -lgcc -Wl,--end-group
# Intermediate build files
# ------------------------
OBJS_ASSETS := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_PNG)))
HEADERS_ASSETS := $(patsubst %.bin,%_bin.h,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN))) \
$(patsubst %.png,%.h,$(addprefix $(BUILDDIR)/,$(SOURCES_PNG)))
ifneq ($(SOURCES_AUDIO),)
OBJS_ASSETS += $(SOUNDBANKDIR)/soundbank.c.o
HEADERS_ASSETS += $(SOUNDBANKDIR)/soundbank.h
endif
OBJS_SOURCES := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_S))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_C))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_CPP)))
OBJS := $(OBJS_ASSETS) $(OBJS_SOURCES)
DEPS := $(OBJS:.o=.d)
# Targets
# -------
.PHONY: all clean dump dldipatch sdimage
all: $(ROM)
ifneq ($(strip $(NITROFATDIR)),)
# Additional arguments for ndstool
NDSTOOL_FAT := -F $(NITROFAT_IMG)
$(NITROFAT_IMG): $(NITROFATDIR)
@echo " MKFATIMG $@ $(NITROFATDIR)"
$(V)$(BLOCKSDS)/tools/mkfatimg/mkfatimg -t $(NITROFATDIR) $@ 0
# Make the NDS ROM depend on the filesystem image only if it is needed
$(ROM): $(NITROFAT_IMG)
endif
# Combine the title strings
ifeq ($(strip $(GAME_SUBTITLE)),)
GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_AUTHOR)
else
GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_SUBTITLE);$(GAME_AUTHOR)
endif
$(ROM): $(ELF)
@echo " NDSTOOL $@"
$(V)$(BLOCKSDS)/tools/ndstool/ndstool -c $@ \
-7 $(BLOCKSDS)/sys/default_arm7/arm7.elf -9 $(ELF) \
-b $(GAME_ICON) "$(GAME_FULL_TITLE)" \
$(NDSTOOL_FAT)
$(ELF): $(OBJS)
@echo " LD $@"
$(V)$(LD) -o $@ $(OBJS) $(BLOCKSDS)/sys/crts/ds_arm9_crt0.o $(LDFLAGS)
$(DUMP): $(ELF)
@echo " OBJDUMP $@"
$(V)$(OBJDUMP) -h -C -S $< > $@
dump: $(DUMP)
clean:
@echo " CLEAN"
$(V)$(RM) $(ROM) $(DUMP) $(BUILDDIR) $(SDIMAGE)
sdimage:
@echo " MKFATIMG $(SDIMAGE) $(SDROOT)"
$(V)$(BLOCKSDS)/tools/mkfatimg/mkfatimg -t $(SDROOT) $(SDIMAGE) 0
dldipatch: $(ROM)
@echo " DLDITOOL $(ROM)"
$(V)$(BLOCKSDS)/tools/dlditool/dlditool \
$(BLOCKSDS)/tools/dldi/r4tfv2.dldi $(ROM)
# Rules
# -----
$(BUILDDIR)/%.s.o : %.s
@echo " AS $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(ASFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.c.o : %.c
@echo " CC $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.cpp.o : %.cpp
@echo " CXX $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.bin.o $(BUILDDIR)/%_bin.h : %.bin
@echo " BIN2C $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $< $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.bin.o $(BUILDDIR)/$*_bin.c
$(BUILDDIR)/%.png.o $(BUILDDIR)/%.h : %.png %.grit
@echo " GRIT $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/grit/grit $< -ftc -W1 -o$(BUILDDIR)/$*
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.png.o $(BUILDDIR)/$*.c
$(V)touch $(BUILDDIR)/$*.png.o $(BUILDDIR)/$*.h
$(SOUNDBANKDIR)/soundbank.h: $(SOURCES_AUDIO)
@echo " MMUTIL $^"
@$(MKDIR) -p $(@D)
@$(BLOCKSDS)/tools/mmutil/mmutil $^ -d \
-o$(SOUNDBANKDIR)/soundbank.bin -h$(SOUNDBANKDIR)/soundbank.h
$(SOUNDBANKDIR)/soundbank.c.o: $(SOUNDBANKDIR)/soundbank.h
@echo " BIN2C soundbank.bin"
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $(SOUNDBANKDIR)/soundbank.bin \
$(SOUNDBANKDIR)
@echo " CC.9 soundbank_bin.c"
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(SOUNDBANKDIR)/soundbank.c.o \
$(SOUNDBANKDIR)/soundbank_bin.c
# All assets must be built before the source code
# -----------------------------------------------
$(SOURCES_S) $(SOURCES_C) $(SOURCES_CPP): $(HEADERS_ASSETS)
# Include dependency files if they exist
# --------------------------------------
-include $(DEPS)

BIN
icon.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

88
include/base_include.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef BASE_INCLUDE__
#define BASE_INCLUDE__
#ifndef __NDS__
// GBA defines and all
#include <gba.h>
#include "useful_qualifiers.h"
#define ROM 0x8000000
ALWAYS_INLINE MAX_OPTIMIZE void __set_next_vcount_interrupt_gba(int scanline) {
REG_DISPSTAT = (REG_DISPSTAT &0xFF) | (scanline<<8);
}
ALWAYS_INLINE MAX_OPTIMIZE int __get_next_vcount_interrupt(void) {
return REG_DISPSTAT >> 8;
}
#define __set_next_vcount_interrupt(x) __set_next_vcount_interrupt_gba(x)
#define SCANLINE_IRQ_BIT LCDC_VCNT
#define REG_WAITCNT *(vu16*)(REG_BASE + 0x204) // Wait state Control
#define SRAM_READING_VALID_WAITCYCLES 3
#define NON_SRAM_MASK 0xFFFC
#define BASE_WAITCNT_VAL 0x4314
#define TIMEOUT_INCREASE 0
#define OVRAM_START ((uintptr_t)OBJ_BASE_ADR)
#define TILE_1D_MAP 0
#define ACTIVATE_SCREEN_HW 0
#define EWRAM_SIZE 0x0003FF40
#define DIV_SWI_VAL "0x06"
#define VRAM_0 VRAM
#define HAS_SIO
#define CLOCK_SPEED 16777216
#define SCANLINES 0xE4
#define SAME_ON_BOTH_SCREENS 0
#ifndef __GBA__
#define __GBA__
#endif
#define CONSOLE_LETTER 'G'
#else
// NDS defines and all
#include <nds.h>
#include "useful_qualifiers.h"
#include "nds_functions.h"
#define ROM GBAROM
ALWAYS_INLINE MAX_OPTIMIZE int __get_next_vcount_interrupt(void) {
return (REG_DISPSTAT >> 8) | ((REG_DISPSTAT & 0x80) << 1);
}
#define __set_next_vcount_interrupt(x) SetYtrigger(x)
#define SCANLINE_IRQ_BIT DISP_YTRIGGER_IRQ
#define REG_WAITCNT REG_EXMEMCNT // Wait state Control
#define SRAM_READING_VALID_WAITCYCLES 3
#define NON_SRAM_MASK 0xFFFC
#define EXMEMCNT_MASK_SLOT2_CLOCKRATE (3<<5)
#define EXMEMCNT_SLOT2_CLOCKRATE_1 (1<<5)
#define BASE_WAITCNT_VAL EXMEMCNT_SLOT2_CLOCKRATE_1
#define TIMEOUT_INCREASE 2
#define OVRAM_START ((uintptr_t)SPRITE_GFX)
#define OVRAM_START_SUB ((uintptr_t)SPRITE_GFX_SUB)
#define OBJ_ON DISPLAY_SPR_ACTIVE
#define OBJ_1D_MAP (1<<6)
#define TILE_1D_MAP (1<<4)
#define ACTIVATE_SCREEN_HW (1<<16)
#define EWRAM 0x2000000
#define EWRAM_SIZE 0x00400000
#define VRAM_0_SUB BG_GFX_SUB
#define ARM9_CLOCK_SPEED 67108864
#define ARM7_CLOCK_SPEED 33554432
#define ARM7_GBA_CLOCK_SPEED 16777216
#define CLOCK_SPEED ARM9_CLOCK_SPEED
#define SCANLINES 0x107
#define SAME_ON_BOTH_SCREENS 1
#define CONSOLE_LETTER 'D'
// Define SWIs back
#define Div(x, y) swiDivide(x, y)
#define DivMod(x, y) swiRemainder(x, y)
#define Sqrt(x) swiSqrt(x)
#define LZ77UnCompWram(x, y) swiDecompressLZSSWram(x, y)
#define CpuFastSet(x, y, z) swiFastCopy(x, y, z)
#define VBlankIntrWait() swiWaitForVBlank()
#define Halt() Halt_ARM9()
#define DIV_SWI_VAL "0x09"
#endif
#define VBLANK_SCANLINES SCREEN_HEIGHT
#endif

15
include/nds_functions.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef NDS_FUNCTIONS__
#define NDS_FUNCTIONS__
#ifdef __NDS__
typedef struct {
u16 attr0;
u16 attr1;
u16 attr2;
u16 dummy;
} ALIGN(4) OBJATTR;
void Halt_ARM9(void);
#endif
#endif

View File

@ -1,6 +1,7 @@
#ifndef OPTIMIZED_SWI__
#define OPTIMIZED_SWI__
#include "base_include.h"
#include "useful_qualifiers.h"
static s32 SWI_DivMod(const uint32_t, const uint32_t);
@ -14,7 +15,7 @@ ALWAYS_INLINE MAX_OPTIMIZE s32 SWI_DivMod(const uint32_t dividend, const uint32_
register uint32_t abs_divis_ asm("r3");
asm volatile(
"swi 0x06;" : "=r"(divid_), "=r"(divis_), "=r"(abs_divis_) :
"swi "DIV_SWI_VAL";" : "=r"(divid_), "=r"(divis_), "=r"(abs_divis_) :
"r"(divid_), "r"(divis_), "r"(abs_divis_) :
);
@ -28,7 +29,7 @@ ALWAYS_INLINE MAX_OPTIMIZE s32 SWI_Div(const uint32_t dividend, const uint32_t d
register uint32_t abs_divis_ asm("r3");
asm volatile(
"swi 0x06;" : "=r"(divid_), "=r"(divis_), "=r"(abs_divis_) :
"swi "DIV_SWI_VAL";" : "=r"(divid_), "=r"(divis_), "=r"(abs_divis_) :
"r"(divid_), "r"(divis_), "r"(abs_divis_) :
);
@ -42,7 +43,7 @@ ALWAYS_INLINE MAX_OPTIMIZE s32 SWI_DivDivMod(const uint32_t dividend, const uint
register uint32_t abs_divis_ asm("r3");
asm volatile(
"swi 0x06;" : "=r"(divid_), "=r"(divis_), "=r"(abs_divis_) :
"swi "DIV_SWI_VAL";" : "=r"(divid_), "=r"(divis_), "=r"(abs_divis_) :
"r"(divid_), "r"(divis_), "r"(abs_divis_) :
);

View File

@ -46,6 +46,9 @@ void swap_buffer_screen(u8, u8);
void disable_all_screens_but_current(void);
void set_bg_pos(u8, int, int);
screen_t* get_screen(u8 bg_num);
#ifdef __NDS__
screen_t* get_screen_sub(u8 bg_num);
#endif
u8 get_screen_num(void);
void set_screen(u8);
void init_text_system(void);

View File

@ -49,10 +49,12 @@
#define BASE_X_CURSOR_MAIN_MENU 2
#define BASE_Y_CURSOR_MAIN_MENU 8
#define BASE_Y_CURSOR_INCREMENT_MAIN_MENU 16
#define BOTTOM_Y_CURSOR_MAIN_MENU_VALUE ((((Y_LIMIT-1)<<3)-BASE_Y_CURSOR_MAIN_MENU)/BASE_Y_CURSOR_INCREMENT_MAIN_MENU)
#define BASE_X_CURSOR_BASE_SETTINGS_MENU 2
#define BASE_Y_CURSOR_BASE_SETTINGS_MENU 8
#define BASE_Y_CURSOR_INCREMENT_BASE_SETTINGS_MENU 16
#define BOTTOM_Y_CURSOR_BASE_SETTINGS_MENU_VALUE ((((Y_LIMIT-3)<<3)-BASE_Y_CURSOR_BASE_SETTINGS_MENU)/BASE_Y_CURSOR_INCREMENT_BASE_SETTINGS_MENU)
#define BASE_X_CURSOR_GEN12_SETTINGS_MENU 2
#define BASE_Y_CURSOR_GEN12_SETTINGS_MENU 8
@ -65,6 +67,7 @@
#define BASE_X_CURSOR_CLOCK_SETTINGS_MENU 2
#define BASE_Y_CURSOR_CLOCK_SETTINGS_MENU 8
#define BASE_Y_CURSOR_INCREMENT_CLOCK_SETTINGS_MENU 8
#define BOTTOM_Y_CURSOR_CLOCK_SETTINGS_MENU_VALUE ((((Y_LIMIT-8)<<3)-BASE_Y_CURSOR_CLOCK_SETTINGS_MENU)/BASE_Y_CURSOR_INCREMENT_CLOCK_SETTINGS_MENU)
#define BASE_X_CURSOR_CLOCK_WARNING 2
#define BASE_Y_CURSOR_CLOCK_WARNING 64

View File

@ -2,11 +2,10 @@
#define TIMING_BASIC__
#define FPS 60
#define CLOCK_SPEED 16777216
#define NS_PER_SECOND 1000000000
#define NS_PER_CYCLE ((NS_PER_SECOND/CLOCK_SPEED)+((NS_PER_SECOND%CLOCK_SPEED) == 0 ? 0 : 1))
#define CYCLES_PER_SCANLINE 1232
#define NS_PER_SCANLINE (CYCLES_PER_SCANLINE*NS_PER_CYCLE)
#define NS_PER_CYCLE ((NS_PER_SECOND + CLOCK_SPEED - 1)/CLOCK_SPEED)
#define NS_PER_SCANLINE ((NS_PER_SECOND + (FPS*SCANLINES) - 1)/(FPS*SCANLINES))
#define CYCLES_PER_SCANLINE ((NS_PER_SCANLINE + NS_PER_CYCLE - 1)/NS_PER_CYCLE)
#define GBA_CLOCK_SPEED 16777216

View File

@ -4,7 +4,12 @@
#define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
#define MAX_OPTIMIZE __attribute__((optimize(3)))
#ifndef PACKED
#define PACKED __attribute__((packed))
#endif
#ifndef IWRAM_CODE
#define IWRAM_CODE
#endif
#define ARM_TARGET __attribute__((target("arm"),noinline))
#define ALIGNED(x) __attribute__((aligned(x)))

View File

@ -1,7 +0,0 @@
#ifndef VCOUNT_BASIC__
#define VCOUNT_BASIC__
#define SCANLINES 0xE4
#define VBLANK_SCANLINES SCREEN_HEIGHT
#endif

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "party_handler.h"
#include "sprite_handler.h"
#include "animations_handler.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "bin_table_handler.h"
#include <stddef.h>

View File

@ -1,8 +1,7 @@
#include <gba.h>
#include "base_include.h"
#include "communicator.h"
#include "sio.h"
#include "sio_buffers.h"
#include "vcount_basic.h"
#include "party_handler.h"
#include "useful_qualifiers.h"
#include <stddef.h>
@ -347,7 +346,7 @@ MAX_OPTIMIZE void set_next_vcount_interrupt(void){
int next_stop = REG_VCOUNT + VCOUNT_WAIT_LINES;
if(next_stop >= SCANLINES)
next_stop -= SCANLINES;
REG_DISPSTAT = (REG_DISPSTAT &0xFF) | (next_stop<<8);
__set_next_vcount_interrupt(next_stop);
}
IWRAM_CODE int communicate_buffer(u8 data, u8 is_master) {
@ -811,6 +810,7 @@ IWRAM_CODE void process_in_data_gen3(u32 data) {
}
IWRAM_CODE MAX_OPTIMIZE void slave_routine(void) {
#ifdef HAS_SIO
if(!(REG_IF & IRQ_SERIAL)){
REG_IF |= IRQ_SERIAL;
int value;
@ -830,10 +830,12 @@ IWRAM_CODE MAX_OPTIMIZE void slave_routine(void) {
//PRINT_FUNCTION("0x\x0D - 0x\x0D\n", value, 2, data, 2);
//sio_handle_irq_slave(process_data_arrived_gen12(sio_read(SIO_8), 0));
}
#endif
}
IWRAM_CODE MAX_OPTIMIZE void master_routine_gen3(void) {
REG_IF |= IRQ_VCOUNT;
#ifdef HAS_SIO
int data;
u8 success = 0;
@ -845,11 +847,13 @@ IWRAM_CODE MAX_OPTIMIZE void master_routine_gen3(void) {
prepared_value = prepare_out_data_gen3();
}
#endif
set_next_vcount_interrupt();
}
IWRAM_CODE MAX_OPTIMIZE void master_routine_gen12(void) {
REG_IF |= IRQ_VCOUNT;
#ifdef HAS_SIO
int data;
if(!skip_sends) {
@ -870,6 +874,7 @@ IWRAM_CODE MAX_OPTIMIZE void master_routine_gen12(void) {
else
skip_sends--;
#endif
set_next_vcount_interrupt();
}
@ -891,48 +896,58 @@ void start_transfer(u8 is_master, u8 curr_gen)
stored_curr_gen = curr_gen;
if(curr_gen != 3) {
if(!is_master) {
#ifdef HAS_SIO
init_sio_normal(SIO_SLAVE, SIO_8);
irqSet(IRQ_SERIAL, slave_routine);
irqEnable(IRQ_SERIAL);
sio_normal_prepare_irq_slave(SEND_NO_INFO);
#endif
}
else{
set_next_vcount_interrupt();
#ifdef HAS_SIO
init_sio_normal(SIO_MASTER, SIO_8);
#endif
irqSet(IRQ_VCOUNT, master_routine_gen12);
prepared_value = ENTER_TRADE_MASTER;
irqEnable(IRQ_VCOUNT);
REG_DISPSTAT |= LCDC_VCNT;
REG_DISPSTAT |= SCANLINE_IRQ_BIT;
}
}
else {
init_received_gen3();
set_start_state(START_TRADE_PAR);
if(!is_master) {
#ifdef HAS_SIO
init_sio_normal(SIO_SLAVE, SIO_32);
irqSet(IRQ_SERIAL, slave_routine);
irqEnable(IRQ_SERIAL);
sio_normal_prepare_irq_slave(SEND_0_INFO);
#endif
}
else {
set_next_vcount_interrupt();
#ifdef HAS_SIO
init_sio_normal(SIO_MASTER, SIO_32);
#endif
irqSet(IRQ_VCOUNT, master_routine_gen3);
prepared_value = SEND_0_INFO;
irqEnable(IRQ_VCOUNT);
REG_DISPSTAT |= LCDC_VCNT;
REG_DISPSTAT |= SCANLINE_IRQ_BIT;
}
}
}
void base_stop_transfer(u8 is_master) {
if(!is_master) {
#ifdef HAS_SIO
irqDisable(IRQ_SERIAL);
sio_stop_irq_slave();
#endif
}
else{
irqDisable(IRQ_VCOUNT);
REG_DISPSTAT &= ~LCDC_VCNT;
REG_DISPSTAT &= ~SCANLINE_IRQ_BIT;
}
}

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "config_settings.h"
#include "version_identifier.h"
#include "party_handler.h"
@ -39,7 +39,7 @@ static u16 applied_ball;
static u8 egg_met_location;
static u8 first_set_egg_met_location;
const struct version_t version = { .main_version = 1, .sub_version = 1, .revision_version = 0, .revision_letter = ' '};
const struct version_t version = { .main_version = 1, .sub_version = 1, .revision_version = 0, .revision_letter = CONSOLE_LETTER};
const u8* egg_valid_met_locations[NUMBER_OF_GAMES+FIRST_VERSION_ID] = {valid_egg_locations_rs_bin, valid_egg_locations_rs_bin, valid_egg_locations_rs_bin, valid_egg_locations_e_bin, valid_egg_locations_frlg_bin, valid_egg_locations_frlg_bin};
void set_default_settings() {

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "gen12_methods.h"
#include "party_handler.h"
#include "text_handler.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "gen3_clock_events_t.h"
#include "gen3_save.h"
#include "party_handler.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "save.h"
#include "gen3_save.h"
#include "gen3_clock_events.h"
@ -77,6 +77,8 @@ static u8 get_next_slot(u8);
void replace_party_entry(struct game_data_t*, struct gen3_mon_data_unenc*, u8);
void trade_reorder_party_entries(struct game_data_t*, struct gen3_mon_data_unenc*, u8);
u32 calc_checksum_save_buffer(u32*, u16);
static void start_gen3_save_data_transfer(void);
static void end_gen3_save_data_transfer(void);
const u16 summable_bytes[SECTION_TOTAL] = {3884, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, 3848, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, MAX_SECTION_SIZE, 2000};
const u16 summable_bytes_section0[NUM_MAIN_GAME_ID] = {0x890, 0xF24, 0xF2C};
@ -807,48 +809,76 @@ IWRAM_CODE u8 has_cartridge_been_removed(){
return retval;
}
ALWAYS_INLINE void start_gen3_save_data_transfer() {
#ifdef __NDS__
disableSleep();
#endif
}
ALWAYS_INLINE void end_gen3_save_data_transfer() {
#ifdef __NDS__
enableSleep();
#endif
}
u8 read_gen_3_data(struct game_data_t* game_data, struct game_data_priv_t* game_data_priv){
unload_cartridge();
start_gen3_save_data_transfer();
init_bank();
game_data_priv->game_is_suspended = 0;
u8 slot = get_slot(&game_data->game_identifier);
in_use_slot = slot;
if(slot == INVALID_SLOT)
if(slot == INVALID_SLOT) {
end_gen3_save_data_transfer();
return 0;
}
read_party(slot, game_data, game_data_priv);
own_game_data_ptr = game_data;
if(game_data_priv->game_is_suspended)
if(game_data_priv->game_is_suspended) {
end_gen3_save_data_transfer();
return 0;
}
end_gen3_save_data_transfer();
load_cartridge();
return 1;
}
u8 pre_write_gen_3_data(struct game_data_t* game_data, struct game_data_priv_t* game_data_priv, u8 is_full){
unload_cartridge();
start_gen3_save_data_transfer();
init_bank();
u8 base_slot = in_use_slot;
if(base_slot == INVALID_SLOT)
if(base_slot == INVALID_SLOT) {
end_gen3_save_data_transfer();
return 0;
}
if(is_full) {
if(!pre_update_save(game_data, game_data_priv, base_slot, FULL_SAVE))
if(!pre_update_save(game_data, game_data_priv, base_slot, FULL_SAVE)) {
end_gen3_save_data_transfer();
return 0;
}
if(!validate_slot(get_next_slot(base_slot), &game_data->game_identifier))
if(!validate_slot(get_next_slot(base_slot), &game_data->game_identifier)) {
end_gen3_save_data_transfer();
return 0;
}
}
else {
if(!pre_update_save(game_data, game_data_priv, base_slot, NON_PARTY_SAVE))
if(!pre_update_save(game_data, game_data_priv, base_slot, NON_PARTY_SAVE)) {
end_gen3_save_data_transfer();
return 0;
}
}
end_gen3_save_data_transfer();
load_cartridge();
return 1;
@ -856,18 +886,26 @@ u8 pre_write_gen_3_data(struct game_data_t* game_data, struct game_data_priv_t*
u8 pre_write_updated_moves_gen_3_data(struct game_data_t* game_data, struct game_data_priv_t* game_data_priv){
unload_cartridge();
start_gen3_save_data_transfer();
init_bank();
u8 base_slot = in_use_slot;
if(base_slot == INVALID_SLOT)
if(base_slot == INVALID_SLOT) {
end_gen3_save_data_transfer();
return 0;
}
if(!pre_update_save(game_data, game_data_priv, base_slot, PARTY_ONLY_SAVE))
if(!pre_update_save(game_data, game_data_priv, base_slot, PARTY_ONLY_SAVE)) {
end_gen3_save_data_transfer();
return 0;
}
if(!validate_slot(get_next_slot(base_slot), &game_data->game_identifier))
if(!validate_slot(get_next_slot(base_slot), &game_data->game_identifier)) {
end_gen3_save_data_transfer();
return 0;
}
end_gen3_save_data_transfer();
load_cartridge();
return 1;
@ -875,17 +913,23 @@ u8 pre_write_updated_moves_gen_3_data(struct game_data_t* game_data, struct game
u8 complete_write_gen_3_data(struct game_data_t* game_data){
unload_cartridge();
start_gen3_save_data_transfer();
init_bank();
u8 base_slot = in_use_slot;
if(base_slot == INVALID_SLOT)
if(base_slot == INVALID_SLOT) {
end_gen3_save_data_transfer();
return 0;
}
if(!complete_save(base_slot, game_data))
if(!complete_save(base_slot, game_data)) {
end_gen3_save_data_transfer();
return 0;
}
in_use_slot = get_next_slot(in_use_slot);
end_gen3_save_data_transfer();
load_cartridge();
return 1;

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "party_handler.h"
#include "gen12_methods.h"
#include "gen_converter.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "graphics_handler.h"
#include "useful_qualifiers.h"
#include "print_system.h"

View File

@ -1,5 +1,6 @@
#include <gba.h>
#include "base_include.h"
#include "input_handler.h"
#include "sprite_handler.h"
#include "options_handler.h"
#include "communicator.h"
#include "gen3_clock_events.h"
@ -256,7 +257,7 @@ u8 handle_input_main_menu(u8* cursor_y_pos, u16 keys, u8* update, u8* target, u8
(*cursor_y_pos) += 1;
}
else if(keys & KEY_UP) {
(*cursor_y_pos) = 9;
(*cursor_y_pos) = BOTTOM_Y_CURSOR_MAIN_MENU_VALUE;
}
break;
case 1:
@ -323,15 +324,15 @@ u8 handle_input_main_menu(u8* cursor_y_pos, u16 keys, u8* update, u8* target, u8
if(keys & KEY_A)
return START_MULTIBOOT;
else if((keys & KEY_DOWN) && (PRINT_INFO_ALWAYS || (!get_is_cartridge_loaded())) && ENABLED_PRINT_INFO)
(*cursor_y_pos) = 6;
(*cursor_y_pos) = (BOTTOM_Y_CURSOR_MAIN_MENU_VALUE - 3);
else if(keys & KEY_DOWN)
(*cursor_y_pos) = 7;
(*cursor_y_pos) = (BOTTOM_Y_CURSOR_MAIN_MENU_VALUE - 2);
else if((keys & KEY_UP) && get_valid_options_main())
(*cursor_y_pos) -= 1;
else if(keys & KEY_UP)
(*cursor_y_pos) = 9;
(*cursor_y_pos) = BOTTOM_Y_CURSOR_MAIN_MENU_VALUE;
break;
case 6:
case (BOTTOM_Y_CURSOR_MAIN_MENU_VALUE - 3):
if(keys & KEY_A)
return START_PRINT_READ_INFO;
else if(keys & KEY_DOWN)
@ -339,19 +340,19 @@ u8 handle_input_main_menu(u8* cursor_y_pos, u16 keys, u8* update, u8* target, u8
else if(keys & KEY_UP)
(*cursor_y_pos) = 4;
break;
case 7:
case (BOTTOM_Y_CURSOR_MAIN_MENU_VALUE - 2):
if(keys & KEY_A)
return START_SWAP_CARTRIDGE;
else if((keys & KEY_DOWN) && get_valid_options_main())
(*cursor_y_pos) += 1;
else if(keys & KEY_DOWN)
(*cursor_y_pos) = 9;
(*cursor_y_pos) = BOTTOM_Y_CURSOR_MAIN_MENU_VALUE;
else if((keys & KEY_UP) && (PRINT_INFO_ALWAYS || (!get_is_cartridge_loaded())) && ENABLED_PRINT_INFO)
(*cursor_y_pos) -= 1;
else if(keys & KEY_UP)
(*cursor_y_pos) = 4;
break;
case 8:
case (BOTTOM_Y_CURSOR_MAIN_MENU_VALUE - 1):
if(keys & KEY_A)
return VIEW_OWN_PARTY + curr_gen;
else if(keys & KEY_DOWN)
@ -359,7 +360,7 @@ u8 handle_input_main_menu(u8* cursor_y_pos, u16 keys, u8* update, u8* target, u8
else if(keys & KEY_UP)
(*cursor_y_pos) -= 1;
break;
case 9:
case BOTTOM_Y_CURSOR_MAIN_MENU_VALUE:
if(keys & KEY_A)
return START_SETTINGS_MENU;
else if((keys & KEY_DOWN) && get_valid_options_main())
@ -369,7 +370,7 @@ u8 handle_input_main_menu(u8* cursor_y_pos, u16 keys, u8* update, u8* target, u8
else if((keys & KEY_UP) && get_valid_options_main())
(*cursor_y_pos) -= 1;
else if(keys & KEY_UP)
(*cursor_y_pos) = 7;
(*cursor_y_pos) = (BOTTOM_Y_CURSOR_MAIN_MENU_VALUE - 2);
break;
default:
break;
@ -597,7 +598,7 @@ u8 handle_input_base_settings_menu(u16 keys, u8* cursor_y_pos, u8* update, struc
switch(*cursor_y_pos) {
case 0:
if(keys & KEY_UP)
*cursor_y_pos = 8;
*cursor_y_pos = BOTTOM_Y_CURSOR_BASE_SETTINGS_MENU_VALUE;
else if(keys & KEY_DOWN)
*cursor_y_pos += 1;
else if((keys & KEY_RIGHT) || (keys & KEY_A)) {
@ -661,9 +662,9 @@ u8 handle_input_base_settings_menu(u16 keys, u8* cursor_y_pos, u8* update, struc
*cursor_y_pos -= 3;
}
else if(keys & KEY_DOWN)
*cursor_y_pos = 8;
*cursor_y_pos = BOTTOM_Y_CURSOR_BASE_SETTINGS_MENU_VALUE;
break;
case 8:
case BOTTOM_Y_CURSOR_BASE_SETTINGS_MENU_VALUE:
if(keys & KEY_A)
return ENTER_CHEATS_MENU;
else if(keys & KEY_UP)
@ -747,7 +748,7 @@ u8 handle_input_clock_menu(u16 keys, struct clock_events_t* clock_events, struct
switch(*cursor_y_pos) {
case 0:
if(keys & KEY_UP)
*cursor_y_pos = 11;
*cursor_y_pos = BOTTOM_Y_CURSOR_CLOCK_SETTINGS_MENU_VALUE;
else if(keys & KEY_DOWN)
*cursor_y_pos += 2;
else if((keys & KEY_RIGHT) || (keys & KEY_A) || (keys & KEY_LEFT)) {
@ -836,7 +837,7 @@ u8 handle_input_clock_menu(u16 keys, struct clock_events_t* clock_events, struct
if(keys & KEY_UP)
*cursor_y_pos -= 1;
else if(keys & KEY_DOWN)
*cursor_y_pos += 2;
*cursor_y_pos = BOTTOM_Y_CURSOR_CLOCK_SETTINGS_MENU_VALUE;
else if((keys & KEY_RIGHT) || (keys & KEY_A)) {
if(time_change->s < MAX_SECONDS-1)
time_change->s += 1;
@ -852,11 +853,11 @@ u8 handle_input_clock_menu(u16 keys, struct clock_events_t* clock_events, struct
*update = 1;
}
break;
case 11:
case BOTTOM_Y_CURSOR_CLOCK_SETTINGS_MENU_VALUE:
if(keys & KEY_A)
return 1;
else if(keys & KEY_UP)
*cursor_y_pos -= 2;
*cursor_y_pos = 9;
else if(keys & KEY_DOWN)
*cursor_y_pos = 0;
break;

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "multiboot_handler.h"
#include "graphics_handler.h"
#include "party_handler.h"
@ -18,7 +18,6 @@
#include "communicator.h"
#include "gen_converter.h"
#include "sio.h"
#include "vcount_basic.h"
#include "animations_handler.h"
#include <stddef.h>
#include "optimized_swi.h"
@ -130,6 +129,7 @@ IWRAM_CODE void vblank_update_function() {
// Handle trading animation
if(curr_state == TRADING_ANIMATION)
advance_trade_animation();
#ifdef HAS_SIO
// Handle slave communications
if((REG_SIOCNT & SIO_IRQ) && (!(REG_SIOCNT & SIO_START)))
slave_routine();
@ -140,12 +140,13 @@ IWRAM_CODE void vblank_update_function() {
REG_IF &= ~IRQ_SERIAL;
slave_routine();
}
#endif
// Handle master communications
if(REG_DISPSTAT & LCDC_VCNT) {
u16 next_vcount_irq = (REG_DISPSTAT >> 8);
if(REG_DISPSTAT & SCANLINE_IRQ_BIT) {
int next_vcount_irq = __get_next_vcount_interrupt();
if(next_vcount_irq < VBLANK_SCANLINES)
next_vcount_irq += SCANLINES;
u16 curr_vcount = REG_VCOUNT + 2;
int curr_vcount = REG_VCOUNT + 2;
if(curr_vcount < VBLANK_SCANLINES)
curr_vcount += SCANLINES;
if(next_vcount_irq <= curr_vcount)
@ -154,6 +155,7 @@ IWRAM_CODE void vblank_update_function() {
}
IWRAM_CODE void find_optimal_ewram_settings() {
#ifdef __GBA__
size_t size = ewram_speed_check_bin_size>>2;
const u32* ewram_speed_check = (const u32*)ewram_speed_check_bin;
u32 test_data[size];
@ -184,6 +186,7 @@ IWRAM_CODE void find_optimal_ewram_settings() {
if(!failed)
return;
}
#endif
}
void disable_all_irqs() {
@ -709,7 +712,7 @@ void crash_on_cartridge_removed() {
prepare_crash_screen(CARTRIDGE_REMOVED);
base_stop_transfer(0);
base_stop_transfer(1);
u8 curr_vcount = REG_VCOUNT + 1 + 1;
int curr_vcount = REG_VCOUNT + 1 + 1;
if(curr_vcount >= SCANLINES)
curr_vcount -= SCANLINES;
while(REG_VCOUNT != curr_vcount);
@ -759,8 +762,10 @@ void complete_cartridge_loading(struct game_data_t* game_data, struct game_data_
int main(void)
{
#ifdef __GBA__
RegisterRamReset(RESET_SIO|RESET_SOUND|RESET_OTHER);
disable_all_irqs();
#endif
curr_state = MAIN_MENU;
counter = 0;
input_counter = 0;
@ -770,7 +775,7 @@ int main(void)
init_enc_positions();
init_rng(0,0);
init_save_data();
u16 keys;
u32 keys;
struct game_data_t game_data[2];
struct game_data_priv_t game_data_priv;
struct saved_time_t time_change;
@ -782,8 +787,12 @@ int main(void)
init_numbers();
init_unown_tsv();
#ifdef HAS_SIO
sio_stop_irq_slave();
#endif
#ifdef __GBA__
irqInit();
#endif
irqSet(IRQ_VBLANK, vblank_update_function);
irqEnable(IRQ_VBLANK);
@ -990,8 +999,10 @@ int main(void)
cursor_update_main_menu(cursor_y_pos);
if(returned_val == START_MULTIBOOT) {
curr_state = MULTIBOOT;
#ifdef HAS_SIO
sio_stop_irq_slave();
irqDisable(IRQ_SERIAL);
#endif
disable_cursor();
init_save_data();
print_multiboot(multiboot_normal((u16*)EWRAM, (u16*)(EWRAM + MULTIBOOT_MAX_SIZE)));

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "menu_text_handler.h"
#include "gen3_clock_events.h"
#include "text_handler.h"
@ -16,11 +16,8 @@
#define NUM_LINES 10
#define MAIN_MENU_DISTANCE_FROM_BORDER 2
#define ROM 0x8000000
#define ROM_SIZE 0x1000000
#define EWRAM_SIZE 0x3FF40
#define SUMMARY_LINE_MAX_SIZE 18
#define PRINTABLE_INVALID_STRINGS 3
@ -150,11 +147,11 @@ void print_game_info(struct game_data_t* game_data, int index) {
const char* chosen_str = maingame_strings[game_data[index].game_identifier.game_main_version];
switch(game_data[index].game_identifier.game_main_version) {
case RS_MAIN_GAME_CODE:
if(game_data[index].game_identifier.game_sub_version != UNDETERMINED)
if(!game_data[index].game_identifier.game_sub_version_undetermined)
chosen_str = subgame_rs_strings[game_data[index].game_identifier.game_sub_version];
break;
case FRLG_MAIN_GAME_CODE:
if(game_data[index].game_identifier.game_sub_version != UNDETERMINED)
if(!game_data[index].game_identifier.game_sub_version_undetermined)
chosen_str = subgame_frlg_strings[game_data[index].game_identifier.game_sub_version];
break;
case E_MAIN_GAME_CODE:
@ -838,8 +835,14 @@ void print_learnable_moves_menu(struct gen3_mon_data_unenc* mon, u16 index) {
}
}
PRINT_FUNCTION("Ability: \x01", get_ability_name_raw(mon));
PRINT_FUNCTION("\nHidden Power: \x01 \x03", get_hidden_power_type_name_gen3(&mon->misc), get_hidden_power_power_gen3(&mon->misc));
PRINT_FUNCTION("\nWhich move will be forgotten?\n");
PRINT_FUNCTION("\nHidden Power: \x01 \x03\n", get_hidden_power_type_name_gen3(&mon->misc), get_hidden_power_power_gen3(&mon->misc));
base_y = get_text_y();
u8 offset_text_y = 0;
if(base_y < (((BASE_Y_CURSOR_LEARN_MOVE_MENU)>>3)-(3)))
offset_text_y = 1;
set_text_y(((BASE_Y_CURSOR_LEARN_MOVE_MENU)>>3)-(3 + offset_text_y));
PRINT_FUNCTION("Which move will be forgotten?");
set_text_y(((BASE_Y_CURSOR_LEARN_MOVE_MENU)>>3)-2);
set_text_x((BASE_X_CURSOR_LEARN_MOVE_MENU>>3)+2);
PRINT_FUNCTION("MOVES");
set_text_x(X_LIMIT-11+(BASE_X_CURSOR_LEARN_MOVE_MENU>>3)+2);

View File

@ -1,9 +1,10 @@
#include <gba.h>
#include "base_include.h"
#include "multiboot_handler.h"
#include "sio.h"
#include "menu_text_handler.h"
#include "print_system.h"
#include "timing_basic.h"
#include "useful_qualifiers.h"
#define MULTIBOOT_WAIT_TIME_NS 36000
#define MULTIBOOT_VCOUNTWAIT (((MULTIBOOT_WAIT_TIME_NS/NS_PER_SCANLINE) + ((MULTIBOOT_WAIT_TIME_NS%NS_PER_SCANLINE) == 0 ? 0 : 1))+1)
@ -16,7 +17,12 @@ int multiboot_normal_send(int data) {
return timed_sio_normal_master(data, SIO_32, MULTIBOOT_VCOUNTWAIT) >> 0x10;
}
#ifdef HAS_SIO
enum MULTIBOOT_RESULTS multiboot_normal (u16* data, u16* end) {
#else
enum MULTIBOOT_RESULTS multiboot_normal (u16* UNUSED(data), u16* UNUSED(end)) {
#endif
#ifdef HAS_SIO
int response;
u8 clientMask = 0;
int attempts, sends, halves;
@ -94,5 +100,6 @@ enum MULTIBOOT_RESULTS multiboot_normal (u16* data, u16* end) {
if(MultiBoot(&mp, MODE32_NORMAL))
return MB_SWI_FAILURE;
#endif
return MB_SUCCESS;
}

13
source/nds_functions.c Normal file
View File

@ -0,0 +1,13 @@
#include "base_include.h"
#include "useful_qualifiers.h"
#include "nds_functions.h"
#ifdef __NDS__
ARM_TARGET MAX_OPTIMIZE void Halt_ARM9() {
register uint32_t destroyed asm("r0");
asm volatile(
"mov r0, #0; mcr p15, 0, r0, c7, c0, 4;" : "=r"(destroyed) :
"r"(destroyed) :
);
}
#endif

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "party_handler.h"
#include "options_handler.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "party_handler.h"
#include "text_handler.h"
#include "sprite_handler.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "pid_iv_tid.h"
#include "rng.h"
#include "gen12_methods.h"

View File

@ -1,5 +1,5 @@
#include "base_include.h"
#include <stdarg.h>
#include <gba.h>
#include "optimized_swi.h"
#include "print_system.h"
#include "text_handler.h"
@ -15,17 +15,22 @@
#include "window_graphics_bin.h"
#define VRAM_SIZE 0x10000
#define VRAM_END (VRAM+VRAM_SIZE)
#define VRAM_END (((uintptr_t)VRAM_0)+VRAM_SIZE)
#define PALETTE 0xF
#define PALETTE_SIZE 0x10
#define PALETTE_BASE 0x5000000
#define FONT_TILES 0x100
#define FONT_SIZE (FONT_TILES*TILE_SIZE)
#define FONT_1BPP_SIZE (FONT_SIZE>>2)
#define FONT_POS (VRAM + 0)
#define FONT_POS (((uintptr_t)VRAM_0) + 0)
#define JP_FONT_POS (FONT_POS + FONT_SIZE)
#define NUMBERS_POS (VRAM_END - (10000*2))
#define ARRANGEMENT_POS (JP_FONT_POS+FONT_SIZE)
#ifdef __NDS__
#define FONT_POS_SUB (((uintptr_t)VRAM_0_SUB) + 0)
#define JP_FONT_POS_SUB (FONT_POS_SUB + FONT_SIZE)
#define ARRANGEMENT_POS_SUB (JP_FONT_POS_SUB+FONT_SIZE)
#endif
#define X_OFFSET_POS 0
#define Y_OFFSET_POS 1
@ -56,6 +61,9 @@ u8 is_screen_disabled(u8);
u8 x_pos;
u8 y_pos;
screen_t* screen;
#ifdef __NDS__
screen_t* screen_sub;
#endif
u8 screen_num;
u8 loaded_screen_num;
@ -68,7 +76,10 @@ u8 screen_positions[TOTAL_BG][2];
IWRAM_CODE void set_arrangements(u8 bg_num){
if(bg_num >= TOTAL_BG)
bg_num = TOTAL_BG-1;
BGCTRL[bg_num] = get_bg_priority(bg_num) | ((((uintptr_t)get_screen(bg_num))-VRAM)>>3);
BGCTRL[bg_num] = get_bg_priority(bg_num) | ((((uintptr_t)get_screen(bg_num))-((uintptr_t)VRAM_0))>>3);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
BGCTRL_SUB[bg_num] = get_bg_priority(bg_num) | ((((uintptr_t)get_screen(bg_num))-((uintptr_t)VRAM_0))>>3);
#endif
}
IWRAM_CODE void process_arrangements() {
@ -84,16 +95,28 @@ IWRAM_CODE void swap_buffer_screen_internal(u8 bg_num) {
if(bg_num >= TOTAL_BG)
bg_num = TOTAL_BG-1;
buffer_screen[bg_num] ^= 1;
if(bg_num == screen_num)
if(bg_num == screen_num) {
screen = get_screen(bg_num);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub = get_screen_sub(bg_num);
#endif
}
}
IWRAM_CODE void enable_screens() {
for(int i = 0; i < TOTAL_BG; i++)
if(enabled_screen[i])
if(enabled_screen[i]) {
REG_DISPCNT |= (0x100)<<i;
else
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_DISPCNT_SUB |= (0x100)<<i;
#endif
}
else {
REG_DISPCNT &= ~((0x100)<<i);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_DISPCNT_SUB &= ~((0x100)<<i);
#endif
}
}
u8 is_screen_disabled(u8 bg_num) {
@ -108,6 +131,10 @@ IWRAM_CODE void set_screens_positions() {
for(int i = 0; i < TOTAL_BG; i++) {
BG_OFFSET[i].x = screen_positions[i][X_OFFSET_POS];
BG_OFFSET[i].y = screen_positions[i][Y_OFFSET_POS];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
BG_OFFSET_SUB[i].x = screen_positions[i][X_OFFSET_POS];
BG_OFFSET_SUB[i].y = screen_positions[i][Y_OFFSET_POS];
#endif
}
}
@ -137,16 +164,27 @@ void init_numbers() {
}
void set_text_palettes() {
BG_COLORS[0]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_COLORS[(PALETTE*PALETTE_SIZE)]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_COLORS[(PALETTE*PALETTE_SIZE)+1]=get_full_colour(FONT_COLOUR_POS);
BG_COLORS[(PALETTE*PALETTE_SIZE)+2]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_COLORS[(PALETTE*PALETTE_SIZE)+3]=get_full_colour(WINDOW_COLOUR_1_POS);
BG_COLORS[(PALETTE*PALETTE_SIZE)+4]=get_full_colour(WINDOW_COLOUR_2_POS);
BG_PALETTE[0]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_PALETTE[(PALETTE*PALETTE_SIZE)]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_PALETTE[(PALETTE*PALETTE_SIZE)+1]=get_full_colour(FONT_COLOUR_POS);
BG_PALETTE[(PALETTE*PALETTE_SIZE)+2]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_PALETTE[(PALETTE*PALETTE_SIZE)+3]=get_full_colour(WINDOW_COLOUR_1_POS);
BG_PALETTE[(PALETTE*PALETTE_SIZE)+4]=get_full_colour(WINDOW_COLOUR_2_POS);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
BG_PALETTE_SUB[0]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_PALETTE_SUB[(PALETTE*PALETTE_SIZE)]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_PALETTE_SUB[(PALETTE*PALETTE_SIZE)+1]=get_full_colour(FONT_COLOUR_POS);
BG_PALETTE_SUB[(PALETTE*PALETTE_SIZE)+2]=get_full_colour(BACKGROUND_COLOUR_POS);
BG_PALETTE_SUB[(PALETTE*PALETTE_SIZE)+3]=get_full_colour(WINDOW_COLOUR_1_POS);
BG_PALETTE_SUB[(PALETTE*PALETTE_SIZE)+4]=get_full_colour(WINDOW_COLOUR_2_POS);
#endif
}
void init_text_system() {
REG_DISPCNT = 0;
REG_DISPCNT = 0 | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_DISPCNT_SUB = 0 | TILE_1D_MAP | ACTIVATE_SCREEN_HW;
#endif
screens_flush = 0;
for(int i = 0; i < TOTAL_BG; i++) {
enabled_screen[i] = 0;
@ -161,6 +199,10 @@ void init_text_system() {
// This is for the first frame
for(size_t i = 0; i < (TILE_SIZE>>2); i++)
*((u32*)(FONT_POS+(i<<2))) = 0x22222222;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
for(size_t i = 0; i < (TILE_SIZE>>2); i++)
*((u32*)(FONT_POS_SUB+(i<<2))) = 0x22222222;
#endif
default_reset_screen();
enable_screen(0);
@ -170,6 +212,9 @@ void init_text_system() {
u8 colors[] = {2, 1};
LZ77UnCompWram(amiga_font_c_bin, buffer);
convert_1bpp((u8*)buffer, (u32*)FONT_POS, FONT_1BPP_SIZE, colors, 1);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
convert_1bpp((u8*)buffer, (u32*)FONT_POS_SUB, FONT_1BPP_SIZE, colors, 1);
#endif
PRINT_FUNCTION("\n Loading...");
base_flush();
@ -177,14 +222,25 @@ void init_text_system() {
// Set empty tile
for(size_t i = 0; i < (TILE_SIZE>>2); i++)
*((u32*)(FONT_POS+TILE_SIZE+(i<<2))) = 0;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
for(size_t i = 0; i < (TILE_SIZE>>2); i++)
*((u32*)(FONT_POS_SUB+TILE_SIZE+(i<<2))) = 0;
#endif
// Load japanese font
LZ77UnCompWram(jp_font_c_bin, buffer);
convert_1bpp((u8*)buffer, (u32*)JP_FONT_POS, FONT_1BPP_SIZE, colors, 0);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
convert_1bpp((u8*)buffer, (u32*)JP_FONT_POS_SUB, FONT_1BPP_SIZE, colors, 0);
#endif
// Set window tiles
for(size_t i = 0; i < (window_graphics_bin_size>>2); i++)
*((u32*)(FONT_POS+(2*TILE_SIZE)+(i<<2))) = ((const u32*)window_graphics_bin)[i];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
for(size_t i = 0; i < (window_graphics_bin_size>>2); i++)
*((u32*)(FONT_POS_SUB+(2*TILE_SIZE)+(i<<2))) = ((const u32*)window_graphics_bin)[i];
#endif
}
void set_updated_screen() {
@ -266,28 +322,45 @@ void set_bg_pos(u8 bg_num, int x, int y){
}
u8 get_screen_num(){
return screen_num;
return screen_num;
}
screen_t* get_screen(u8 bg_num){
if(bg_num >= TOTAL_BG)
bg_num = TOTAL_BG-1;
return (screen_t*)(ARRANGEMENT_POS+(SCREEN_SIZE*(bg_num+(TOTAL_BG*buffer_screen[bg_num]))));
return (screen_t*)(ARRANGEMENT_POS+(SCREEN_SIZE*(bg_num+(TOTAL_BG*buffer_screen[bg_num]))));
}
#ifdef __NDS__
screen_t* get_screen_sub(u8 bg_num){
if(bg_num >= TOTAL_BG)
bg_num = TOTAL_BG-1;
return (screen_t*)(ARRANGEMENT_POS_SUB+(SCREEN_SIZE*(bg_num+(TOTAL_BG*buffer_screen[bg_num]))));
}
#endif
void set_screen(u8 bg_num){
if(bg_num >= TOTAL_BG)
bg_num = TOTAL_BG-1;
screen_num = bg_num;
screen = get_screen(bg_num);
#ifdef __NDS__
screen_sub = get_screen_sub(bg_num);
#endif
}
void reset_screen(u8 blank_fill){
set_updated_screen();
*((u32*)screen) = (PALETTE<<28) | (PALETTE<<12) | 0;
if(blank_fill)
*((u32*)screen) =(PALETTE<<28) | (PALETTE<<12) | 0x00010001;
*((u32*)screen) = (PALETTE<<28) | (PALETTE<<12) | 0x00010001;
CpuFastSet(screen, screen, CPUFASTSET_FILL | (SCREEN_SIZE>>2));
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
*((u32*)screen_sub) = (PALETTE<<28) | (PALETTE<<12) | 0;
if(blank_fill)
*((u32*)screen_sub) = (PALETTE<<28) | (PALETTE<<12) | 0x00010001;
CpuFastSet(screen_sub, screen_sub, CPUFASTSET_FILL | (SCREEN_SIZE>>2));
#endif
x_pos = 0;
y_pos = 0;
}
@ -327,6 +400,9 @@ void new_line(){
u8 write_char(u16 character) {
screen[x_pos+(y_pos*X_SIZE)] = character | (PALETTE << 12);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[x_pos+(y_pos*X_SIZE)] = character | (PALETTE << 12);
#endif
x_pos++;
if(x_pos >= X_LIMIT) {
new_line();
@ -340,6 +416,9 @@ void write_above_char(u16 character) {
if(!y_pos)
y_pos_altered = Y_SIZE-1;
screen[x_pos+(y_pos_altered*X_SIZE)] = character | (PALETTE << 12);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[x_pos+(y_pos_altered*X_SIZE)] = character | (PALETTE << 12);
#endif
}
int sub_printf(u8* string) {

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "rng.h"
#include "useful_qualifiers.h"

View File

@ -1,11 +1,9 @@
#include <gba.h>
#include "base_include.h"
#include "save.h"
#include <stddef.h>
#include "useful_qualifiers.h"
#include "timing_basic.h"
#define REG_WAITCNT *(vu16*)(REG_BASE + 0x204) // Wait state Control
#define IS_FLASH 1
#define SAVE_POS SRAM
@ -16,7 +14,7 @@
#define FLASH_TERM_CMD *((vu8*)(SAVE_POS+0x5555)) = 0xF0;
#define FLASH_ENTER_MAN_CMD BASE_FLASH_CMD *((vu8*)(SAVE_POS+0x5555)) = 0x90;
#define FLASH_EXIT_MAN_CMD BASE_FLASH_CMD FLASH_TERM_CMD FLASH_TERM_CMD
#define TIMEOUT (50000*((CLOCK_SPEED/GBA_CLOCK_SPEED) + ((CLOCK_SPEED%GBA_CLOCK_SPEED) == 0 ? 0 : 1)))
#define TIMEOUT (50000*(((CLOCK_SPEED + GBA_CLOCK_SPEED - 1)/GBA_CLOCK_SPEED) + TIMEOUT_INCREASE))
#define ERASE_TIMEOUT (TIMEOUT)
#define ERASED_BYTE 0xFF
#define BANK_SIZE 0x10000
@ -41,7 +39,8 @@ u8 current_bank;
u8 is_macronix;
IWRAM_CODE void init_bank(){
REG_WAITCNT |= 3;
REG_WAITCNT &= NON_SRAM_MASK;
REG_WAITCNT |= SRAM_READING_VALID_WAITCYCLES;
current_bank = NUM_BANKS;
is_macronix = 0;
#if IS_FLASH
@ -76,7 +75,7 @@ IWRAM_CODE void erase_sector(uintptr_t address) {
address <<= SECTOR_SIZE_BITS;
u8 failed = 1;
vu8* save_data = (vu8*)SAVE_POS;
for(int i = 0; failed && (i < 3); i++) {
for(size_t i = 0; failed && (i < 3); i++) {
#if IS_FLASH
FLASH_ERASE_SECTOR_BASE_CMD
save_data[address] = ERASE_SECTOR_FINAL_CMD;

View File

@ -1,6 +1,5 @@
#include <gba.h>
#include "base_include.h"
#include "sio.h"
#include "vcount_basic.h"
#include "useful_qualifiers.h"
#define BLANK_LINES_WAIT 13
@ -8,6 +7,7 @@
void sio_normal_inner_slave(void);
u8 sio_normal_inner_master(void);
#ifdef HAS_SIO
IWRAM_CODE int timed_sio_normal_master(int data, int is_32, int vCountWait) {
u8 curr_vcount, target_vcount;
@ -175,3 +175,4 @@ IWRAM_CODE int sio_normal(int data, int is_master, int is_32, u8* success) {
else
return (REG_SIODATA8 & 0xFF);
}
#endif

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "sio_buffers.h"
#include "text_handler.h"
#include "options_handler.h"

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "sprite_handler.h"
#include "graphics_handler.h"
#include "print_system.h"
@ -22,18 +22,27 @@
#define CURSOR_SPRITE_PALETTE_INDEX 9
#define SPRITE_SIZE (SPRITE_BASE_SIZE_MULTIPLIER*SPRITE_ALT_DISTANCE)
#define OVRAM_START ((uintptr_t)OBJ_BASE_ADR)
#define OVRAM_SIZE 0x8000
#define OVRAM_END (OVRAM_START+OVRAM_SIZE)
#ifdef __NDS__
#define OVRAM_END_SUB (OVRAM_START_SUB+OVRAM_SIZE)
#endif
#define POSSIBLE_SPRITES (OVRAM_SIZE/SPRITE_SIZE)
#define OAM_ENTITIES 0x80
#define OAM_DATA ((OBJATTR *)OAM)
#ifdef __NDS__
#define OAM_DATA_SUB ((OBJATTR *)OAM_SUB)
#endif
#define DISABLE_SPRITE (1<<9)
#define OFF_SCREEN_SPRITE SCREEN_HEIGHT
u8 check_for_same_address(const u8*);
uintptr_t get_vram_pos(void);
#ifdef __NDS__
uintptr_t get_vram_pos_sub(void);
#endif
void set_updated_shadow_oam(void);
void inc_inner_sprite_counter(void);
u8 get_sprite_counter(void);
@ -81,10 +90,17 @@ void set_updated_shadow_oam() {
IWRAM_CODE void update_normal_oam() {
if(updated_shadow_oam) {
u32* oam_ptr = (u32*)OAM;
u32* oam_ptr = (u32*)OAM_DATA;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
u32* oam_ptr_sub = (u32*)OAM_DATA_SUB;
#endif
u32* shadow_oam_ptr = (u32*)shadow_oam;
for(size_t i = 0; i < ((sizeof(OBJATTR)*OAM_ENTITIES)>>2); i++)
for(size_t i = 0; i < ((sizeof(OBJATTR)*OAM_ENTITIES)>>2); i++) {
oam_ptr[i] = shadow_oam_ptr[i];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
oam_ptr_sub[i] = shadow_oam_ptr[i];
#endif
}
updated_shadow_oam = 0;
}
loaded_inner_sprite_counter = __inner_sprite_counter;
@ -98,10 +114,16 @@ void set_party_sprite_counter(){
void enable_sprites_rendering(){
REG_DISPCNT |= OBJ_ON | OBJ_1D_MAP;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_DISPCNT_SUB |= OBJ_ON | OBJ_1D_MAP;
#endif
}
void disable_sprites_rendering(){
REG_DISPCNT &= ~(OBJ_ON);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_DISPCNT_SUB &= ~(OBJ_ON);
#endif
}
void init_sprites(){
@ -137,6 +159,15 @@ uintptr_t get_vram_pos(){
return vram_pos;
}
#ifdef __NDS__
uintptr_t get_vram_pos_sub(){
uintptr_t vram_pos = OVRAM_START_SUB+(__sprite_counter*SPRITE_SIZE);
if(vram_pos >= OVRAM_END_SUB)
vram_pos = OVRAM_END_SUB - SPRITE_SIZE;
return vram_pos;
}
#endif
u8 get_3bpp_palette(int index) {
return (index>>1) + get_first_variable_palette();
}
@ -151,6 +182,12 @@ void set_palette_3bpp(u8* colors, int index, int palette) {
SPRITE_PALETTE[base+i+(new_palette<<4)] = SPRITE_PALETTE[colors[i]+(palette<<4)];
else
SPRITE_PALETTE[i+(new_palette<<4)] = SPRITE_PALETTE[colors[i]+(palette<<4)];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
if(i)
SPRITE_PALETTE_SUB[base+i+(new_palette<<4)] = SPRITE_PALETTE_SUB[colors[i]+(palette<<4)];
else
SPRITE_PALETTE_SUB[i+(new_palette<<4)] = SPRITE_PALETTE_SUB[colors[i]+(palette<<4)];
#endif
}
}
@ -160,6 +197,11 @@ void init_cursor(){
u16* vram_pos = (u16*)(get_vram_pos() + (SPRITE_ALT_DISTANCE*i));
for(size_t j = 0; j < (sprite_cursor_bin_size>>1); j++)
vram_pos[j] = sprite_cursor_gfx[j];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
vram_pos = (u16*)(get_vram_pos_sub() + (SPRITE_ALT_DISTANCE*i));
for(size_t j = 0; j < (sprite_cursor_bin_size>>1); j++)
vram_pos[j] = sprite_cursor_gfx[j];
#endif
}
for(int i = 0; i < TOTAL_BG; i++) {
set_attributes(OFF_SCREEN_SPRITE, 0, (SPRITE_TILE_SIZE*__sprite_counter) | ((3-i)<<10) | ((sprite_palettes_bin_size>>5)<<12));
@ -174,6 +216,9 @@ void init_cursor(){
void set_cursor_palette() {
SPRITE_PALETTE[(sprite_palettes_bin_size>>1)+CURSOR_SPRITE_PALETTE_INDEX] = get_full_colour(SPRITE_COLOUR_POS);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
SPRITE_PALETTE_SUB[(sprite_palettes_bin_size>>1)+CURSOR_SPRITE_PALETTE_INDEX] = get_full_colour(SPRITE_COLOUR_POS);
#endif
}
void init_oam_palette(){
@ -181,6 +226,12 @@ void init_oam_palette(){
SPRITE_PALETTE[i] = sprite_palettes_bin_16[i];
for(size_t i = 0; i < (item_icon_palette_bin_size>>1); i++)
SPRITE_PALETTE[i+(sprite_palettes_bin_size>>1)] = item_icon_palette_bin_16[i];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
for(size_t i = 0; i < (sprite_palettes_bin_size>>1); i++)
SPRITE_PALETTE_SUB[i] = sprite_palettes_bin_16[i];
for(size_t i = 0; i < (item_icon_palette_bin_size>>1); i++)
SPRITE_PALETTE_SUB[i+(sprite_palettes_bin_size>>1)] = item_icon_palette_bin_16[i];
#endif
set_cursor_palette();
}
@ -189,6 +240,11 @@ void init_item_icon(){
u16* vram_pos = (u16*)(get_vram_pos() + sprite_cursor_bin_size + (SPRITE_ALT_DISTANCE*i));
for(size_t j = 0; j < (item_icon_bin_size>>1); j++)
vram_pos[j] = item_icon_gfx[j];
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
vram_pos = (u16*)(get_vram_pos_sub() + sprite_cursor_bin_size + (SPRITE_ALT_DISTANCE*i));
for(size_t j = 0; j < (item_icon_bin_size>>1); j++)
vram_pos[j] = item_icon_gfx[j];
#endif
}
}
@ -232,6 +288,9 @@ void set_pokemon_sprite(const u8* address, u8 palette, u8 info, u8 display_item,
if(position == POSSIBLE_SPRITES) {
u8 colors[8];
load_pokemon_sprite_gfx((const u32*)address, (u32*)get_vram_pos(), is_3bpp, zero_fill, __sprite_counter-(cursor_sprite+1), colors);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
load_pokemon_sprite_gfx((const u32*)address, (u32*)get_vram_pos_sub(), is_3bpp, zero_fill, __sprite_counter-(cursor_sprite+1), colors);
#endif
if(is_3bpp)
set_palette_3bpp(colors, __sprite_counter-(cursor_sprite+1), palette);
position = __sprite_counter;
@ -251,15 +310,22 @@ void update_cursor_y(u16 cursor_y){
}
IWRAM_CODE void raw_update_cursor_x(u16 cursor_x){
OAM[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x;
OAM_DATA[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
OAM_DATA_SUB[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x;
#endif
shadow_oam[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x;
}
IWRAM_CODE void raw_update_sprite_y(u8 index, u8 new_y){
if(index >= OAM_ENTITIES)
index = OAM_ENTITIES-1;
OAM[index].attr0 &= ~0xFF;
OAM[index].attr0 |= new_y;
OAM_DATA[index].attr0 &= ~0xFF;
OAM_DATA[index].attr0 |= new_y;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
OAM_DATA_SUB[index].attr0 &= ~0xFF;
OAM_DATA_SUB[index].attr0 |= new_y;
#endif
shadow_oam[index].attr0 &= ~0xFF;
shadow_oam[index].attr0 |= new_y;
}
@ -268,11 +334,20 @@ IWRAM_CODE void fade_all_sprites_to_white(u16 fading_fraction){
REG_BLDCNT &= ~(3<<6);
REG_BLDCNT |= (1<<4) | (2<<6);
REG_BLDY = fading_fraction;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_BLDCNT_SUB &= ~(3<<6);
REG_BLDCNT_SUB |= (1<<4) | (2<<6);
REG_BLDY_SUB = fading_fraction;
#endif
}
IWRAM_CODE void remove_fade_all_sprites(){
REG_BLDCNT &= ~((1<<4) | (2<<6));
REG_BLDY = 0;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
REG_BLDCNT_SUB &= ~((1<<4) | (2<<6));
REG_BLDY_SUB = 0;
#endif
}
void update_cursor_base_x(u16 cursor_x){
@ -342,10 +417,16 @@ IWRAM_CODE void move_sprites(u8 counter){
if(loaded_inner_sprite_counter > OAM_ENTITIES)
limit = OAM_ENTITIES;
for(int i = inner_cursor_sprite+1; i < limit; i++) {
u16 obj_attr_2 = OAM[i].attr2 & ~SPRITE_BASE_TILE_SIZE;
u16 obj_attr_2 = OAM_DATA[i].attr2 & ~SPRITE_BASE_TILE_SIZE;
if(counter_kind)
obj_attr_2 |= SPRITE_BASE_TILE_SIZE;
OAM[i].attr2 = obj_attr_2;
OAM_DATA[i].attr2 = obj_attr_2;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
obj_attr_2 = OAM_DATA_SUB[i].attr2 & ~SPRITE_BASE_TILE_SIZE;
if(counter_kind)
obj_attr_2 |= SPRITE_BASE_TILE_SIZE;
OAM_DATA_SUB[i].attr2 = obj_attr_2;
#endif
}
}

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "text_handler.h"
#include "bin_table_handler.h"
#include "useful_qualifiers.h"

View File

@ -1,17 +1,13 @@
#include <gba.h>
#include "base_include.h"
#include "version_identifier.h"
#include "save.h"
#include "text_handler.h"
#include "party_handler.h"
#include "gen3_save.h"
#define REG_WAITCNT *(vu16*)(REG_BASE + 0x204) // Wait state Control
#define ROM 0x8000000
#define GAME_STRING_POS (ROM+0xA0)
#define GAME_STRING_POS (((uintptr_t)ROM)+0xA0)
#define GAME_STRING_SIZE 0xC
#define LANGUAGE_ID_POS (ROM+0xAF)
#define LANGUAGE_ID_POS (((uintptr_t)ROM)+0xAF)
#define JAPANESE_ID 0x4A
#define ENGLISH_ID_0 0x45
#define ENGLISH_ID_1 0x50
@ -48,10 +44,9 @@ u8 is_trainer_name_japanese(u8* buffer) {
void get_game_id(struct game_identity* identifier) {
u8 tmp_buffer[GAME_STRING_SIZE+1];
REG_WAITCNT = 0x4314;
REG_WAITCNT = BASE_WAITCNT_VAL;
text_generic_copy((u8*)GAME_STRING_POS, tmp_buffer, GAME_STRING_SIZE, GAME_STRING_SIZE+1);
u8 language_char = *((u8*)LANGUAGE_ID_POS);
REG_WAITCNT = 0;
for(int i = 0; i < NUMBER_OF_GAMES; i++)
if(text_generic_is_same((const u8*)game_identifier_strings[i], tmp_buffer, GAME_STRING_SIZE, GAME_STRING_SIZE)) {
identifier->game_main_version = main_identifiers[i];

View File

@ -1,4 +1,4 @@
#include <gba.h>
#include "base_include.h"
#include "print_system.h"
#include "window_handler.h"
@ -132,11 +132,16 @@ void clear_offer_options_window() {
void create_window(u8 x, u8 y, u8 x_size, u8 y_size, u8 screen_num) {
set_updated_screen();
screen_t* screen = get_screen(screen_num);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_t* screen_sub = get_screen_sub(screen_num);
#endif
u8 fill_x = x_size == TOTAL_X_SIZE;
u8 fill_y = y_size == TOTAL_Y_SIZE;
if(2+x+x_size > X_SIZE)
x_size = 0;
x_size = X_SIZE - (x + 1);
if(2+y+y_size > Y_SIZE)
y_size = 0;
y_size = Y_SIZE - (y + 1);
if((!x_size) || (!y_size))
return;
@ -155,25 +160,64 @@ void create_window(u8 x, u8 y, u8 x_size, u8 y_size, u8 screen_num) {
if(end_y >= Y_SIZE)
end_y -= Y_SIZE;
for(int i = 0; i < x_size; i++) {
screen[x+(start_y*X_SIZE)+i] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE;
screen[x+(end_y*X_SIZE)+i] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE | VSWAP_TILE;
if(!fill_y) {
for(int i = 0; i < x_size; i++) {
screen[x+(start_y*X_SIZE)+i] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE;
screen[x+(end_y*X_SIZE)+i] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE | VSWAP_TILE;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[x+(start_y*X_SIZE)+i] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE;
screen_sub[x+(end_y*X_SIZE)+i] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE | VSWAP_TILE;
#endif
}
if(fill_x) {
screen[x+(start_y*X_SIZE)+x_size] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE;
screen[x+(end_y*X_SIZE)+x_size] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE | VSWAP_TILE;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[x+(start_y*X_SIZE)+x_size] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE;
screen_sub[x+(end_y*X_SIZE)+x_size] = (PALETTE<<12) | HORIZONTAL_WINDOW_TILE | VSWAP_TILE;
#endif
}
}
for(int i = 0; i < y_size; i++) {
screen[start_x+((y+i)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE;
screen[end_x+((y+i)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE | HSWAP_TILE;
if(!fill_x) {
for(int i = 0; i < y_size; i++) {
screen[start_x+((y+i)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE;
screen[end_x+((y+i)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE | HSWAP_TILE;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[start_x+((y+i)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE;
screen_sub[end_x+((y+i)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE | HSWAP_TILE;
#endif
}
if(fill_y) {
screen[start_x+((y+y_size)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE;
screen[end_x+((y+y_size)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE | HSWAP_TILE;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[start_x+((y+y_size)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE;
screen_sub[end_x+((y+y_size)*X_SIZE)] = (PALETTE<<12) | VERTICAL_WINDOW_TILE | HSWAP_TILE;
#endif
}
}
screen[start_x+(start_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE;
screen[end_x+(start_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | HSWAP_TILE;
screen[start_x+(end_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | VSWAP_TILE;
screen[end_x+(end_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | HSWAP_TILE | VSWAP_TILE;
if((!fill_x) && (!fill_y)) {
screen[start_x+(start_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE;
screen[end_x+(start_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | HSWAP_TILE;
screen[start_x+(end_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | VSWAP_TILE;
screen[end_x+(end_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | HSWAP_TILE | VSWAP_TILE;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[start_x+(start_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE;
screen_sub[end_x+(start_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | HSWAP_TILE;
screen_sub[start_x+(end_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | VSWAP_TILE;
screen_sub[end_x+(end_y*X_SIZE)] = (PALETTE<<12) | ANGLE_WINDOW_TILE | HSWAP_TILE | VSWAP_TILE;
#endif
}
}
void reset_window(u8 x, u8 y, u8 x_size, u8 y_size, u8 screen_num){
set_updated_screen();
screen_t* screen = get_screen(screen_num);
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_t* screen_sub = get_screen_sub(screen_num);
#endif
for(int i = 0; i < y_size; i++) {
u8 inside_y = y + i;
@ -184,6 +228,9 @@ void reset_window(u8 x, u8 y, u8 x_size, u8 y_size, u8 screen_num){
if(inside_x >= X_SIZE)
inside_x -= X_SIZE;
screen[inside_x+(inside_y*X_SIZE)] = (PALETTE<<12) | 0;
#if defined (__NDS__) && (SAME_ON_BOTH_SCREENS)
screen_sub[inside_x+(inside_y*X_SIZE)] = (PALETTE<<12) | 0;
#endif
}
}
}