mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-09-08 17:07:33 -05:00
Adding LinkWirelessMultiboot_demo
This commit is contained in:
289
examples/LinkWirelessMultiboot_demo/Makefile
Normal file
289
examples/LinkWirelessMultiboot_demo/Makefile
Normal file
@@ -0,0 +1,289 @@
|
||||
# === SETUP ===========================================================
|
||||
|
||||
# --- No implicit rules ---
|
||||
.SUFFIXES:
|
||||
|
||||
# --- Paths ---
|
||||
export TONCLIB := $(DEVKITPRO)/libtonc
|
||||
|
||||
# === TONC RULES ======================================================
|
||||
#
|
||||
# Yes, this is almost, but not quite, completely like to
|
||||
# DKP's base_rules and gba_rules
|
||||
#
|
||||
|
||||
export PATH := $(DEVKITARM)/bin:$(PATH)
|
||||
|
||||
|
||||
# --- Executable names ---
|
||||
|
||||
PREFIX ?= arm-none-eabi-
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AS := $(PREFIX)as
|
||||
export AR := $(PREFIX)ar
|
||||
export NM := $(PREFIX)nm
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
|
||||
# LD defined in Makefile
|
||||
|
||||
|
||||
# === LINK / TRANSLATE ================================================
|
||||
|
||||
%.gba : %.elf
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
@gbafix $@ -t$(TITLE)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.mb.elf :
|
||||
@echo Linking multiboot
|
||||
$(LD) -specs=gba_mb.specs $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
$(NM) -Sn $@ > $(basename $(notdir $@)).map
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.elf :
|
||||
@echo Linking cartridge
|
||||
$(LD) -specs=gba.specs $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
$(NM) -Sn $@ > $(basename $(notdir $@)).map
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.a :
|
||||
@echo $(notdir $@)
|
||||
@rm -f $@
|
||||
$(AR) -crs $@ $^
|
||||
|
||||
|
||||
# === OBJECTIFY =======================================================
|
||||
|
||||
%.iwram.o : %.iwram.cpp
|
||||
@echo $(notdir $<)
|
||||
$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(IARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
%.iwram.o : %.iwram.c
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(IARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.cpp
|
||||
@echo $(notdir $<)
|
||||
$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(RARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.c
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(RARCH) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.s
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
%.o : %.S
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# canned command sequence for binary data
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
define bin2o
|
||||
bin2s $< | $(AS) -o $(@)
|
||||
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(<F) | tr . _)`.h
|
||||
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(<F) | tr . _)`.h
|
||||
echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(<F) | tr . _)`.h
|
||||
endef
|
||||
# =====================================================================
|
||||
|
||||
# === PROJECT DETAILS =================================================
|
||||
# PROJ : Base project name
|
||||
# TITLE : Title for ROM header (12 characters)
|
||||
# LIBS : Libraries to use, formatted as list for linker flags
|
||||
# BUILD : Directory for build process temporaries. Should NOT be empty!
|
||||
# SRCDIRS : List of source file directories
|
||||
# DATADIRS : List of data file directories
|
||||
# INCDIRS : List of header file directories
|
||||
# LIBDIRS : List of library directories
|
||||
# General note: use `.' for the current dir, don't leave the lists empty.
|
||||
|
||||
export PROJ ?= $(notdir $(CURDIR))
|
||||
TITLE := $(PROJ)
|
||||
|
||||
LIBS := -ltonc -lugba -lgba-sprite-engine
|
||||
|
||||
BUILD := build
|
||||
SRCDIRS := src ../_lib ../../lib \
|
||||
src/scenes \
|
||||
src/utils
|
||||
|
||||
DATADIRS :=
|
||||
INCDIRS := src
|
||||
LIBDIRS := $(TONCLIB) $(PWD)/../_lib/libugba $(PWD)/../_lib/libgba-sprite-engine
|
||||
|
||||
# --- switches ---
|
||||
|
||||
bMB := 0 # Multiboot build
|
||||
bTEMPS := 0 # Save gcc temporaries (.i and .S files)
|
||||
bDEBUG2 := 0 # Generate debug info (bDEBUG2? Not a full DEBUG flag. Yet)
|
||||
|
||||
# === BUILD FLAGS =====================================================
|
||||
# This is probably where you can stop editing
|
||||
# NOTE: I've noticed that -fgcse and -ftree-loop-optimize sometimes muck
|
||||
# up things (gcse seems fond of building masks inside a loop instead of
|
||||
# outside them for example). Removing them sometimes helps
|
||||
|
||||
# --- Architecture ---
|
||||
|
||||
ARCH := -mthumb-interwork -mthumb
|
||||
RARCH := -mthumb-interwork -mthumb
|
||||
IARCH := -mthumb-interwork -marm -mlong-calls
|
||||
|
||||
# --- Main flags ---
|
||||
|
||||
CFLAGS := -mcpu=arm7tdmi -mtune=arm7tdmi -Ofast
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += $(INCLUDE)
|
||||
CFLAGS += -ffast-math -fno-strict-aliasing
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := $(ARCH) $(INCLUDE)
|
||||
LDFLAGS := $(ARCH) -Wl,-Map,$(PROJ).map
|
||||
|
||||
# --- switched additions ----------------------------------------------
|
||||
|
||||
# --- Multiboot ? ---
|
||||
ifeq ($(strip $(bMB)), 1)
|
||||
TARGET := $(PROJ).mb
|
||||
else
|
||||
TARGET := $(PROJ)
|
||||
endif
|
||||
|
||||
# --- Save temporary files ? ---
|
||||
ifeq ($(strip $(bTEMPS)), 1)
|
||||
CFLAGS += -save-temps
|
||||
CXXFLAGS += -save-temps
|
||||
endif
|
||||
|
||||
# --- Debug info ? ---
|
||||
|
||||
ifeq ($(strip $(bDEBUG)), 1)
|
||||
CFLAGS += -DDEBUG -g
|
||||
CXXFLAGS += -DDEBUG -g
|
||||
ASFLAGS += -DDEBUG -g
|
||||
LDFLAGS += -g
|
||||
else
|
||||
CFLAGS += -DNDEBUG
|
||||
CXXFLAGS += -DNDEBUG
|
||||
ASFLAGS += -DNDEBUG
|
||||
endif
|
||||
|
||||
# --- Custom vars ? ---
|
||||
|
||||
GAMETITLE=test-multi-link
|
||||
GAMEMAKER=AGB
|
||||
GAMECODE=AZCE # Megaman Zero (SRAM - 64kb)
|
||||
ENV ?= development
|
||||
|
||||
ifeq ($(ENV), debug)
|
||||
CXXFLAGS += -DENV_DEBUG=true -DENV_DEVELOPMENT=true
|
||||
else ifeq ($(ENV), development)
|
||||
CXXFLAGS += -DENV_DEVELOPMENT=true
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
# CXXFLAGS += -DCUSTOM_VAR_DEFINE
|
||||
|
||||
# === BUILD PROC ======================================================
|
||||
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
|
||||
# Still in main dir:
|
||||
# * Define/export some extra variables
|
||||
# * Invoke this file again from the build dir
|
||||
# PONDER: what happens if BUILD == "" ?
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export VPATH := \
|
||||
$(foreach dir, $(SRCDIRS) , $(CURDIR)/$(dir)) \
|
||||
$(foreach dir, $(DATADIRS), $(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
# --- List source and data files ---
|
||||
|
||||
CFILES := $(foreach dir, $(SRCDIRS) , $(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir, $(SRCDIRS) , $(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir, $(SRCDIRS) , $(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir, $(DATADIRS), $(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
# --- Set linker depending on C++ file existence ---
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
# --- Define object file list ---
|
||||
export OFILES := $(addsuffix .o, $(BINFILES)) \
|
||||
$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) \
|
||||
$(SFILES:.S=.o)
|
||||
|
||||
# --- Create include and library search paths ---
|
||||
export INCLUDE := $(foreach dir,$(INCDIRS),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := -L$(CURDIR) $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
# --- Create BUILD if necessary, and run this makefile from there ---
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
arm-none-eabi-nm -Sn $(OUTPUT).elf > $(BUILD)/$(TARGET).map
|
||||
|
||||
all : $(BUILD)
|
||||
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -rf $(BUILD) $(TARGET).elf $(TARGET).gba $(TARGET).sav
|
||||
|
||||
else # If we're here, we should be in the BUILD dir
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
# --- Main targets ----
|
||||
|
||||
$(OUTPUT).gba : $(OUTPUT).elf
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
endif # End BUILD switch
|
||||
|
||||
# --- More targets ----------------------------------------------------
|
||||
|
||||
.PHONY: clean rebuild start
|
||||
|
||||
rebuild: clean $(BUILD)
|
||||
|
||||
start:
|
||||
start "$(TARGET).gba"
|
||||
|
||||
restart: rebuild start
|
||||
|
||||
# EOF
|
||||
45
examples/LinkWirelessMultiboot_demo/src/main.cpp
Normal file
45
examples/LinkWirelessMultiboot_demo/src/main.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <tonc.h>
|
||||
#include "../../../lib/LinkRawWireless.hpp"
|
||||
#include "../../_lib/interrupt.h"
|
||||
#include "scenes/MultibootScene.h"
|
||||
#include "utils/SceneUtils.h"
|
||||
|
||||
void setUpInterrupts();
|
||||
void printTutorial();
|
||||
static std::shared_ptr<GBAEngine> engine{new GBAEngine()};
|
||||
static std::unique_ptr<MultibootScene> multibootScene{
|
||||
new MultibootScene(engine)};
|
||||
|
||||
LinkRawWireless* linkRawWireless = new LinkRawWireless();
|
||||
|
||||
int main() {
|
||||
setUpInterrupts();
|
||||
|
||||
engine->setScene(multibootScene.get());
|
||||
|
||||
while (true) {
|
||||
engine->update();
|
||||
|
||||
VBlankIntrWait();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void ISR_reset() {
|
||||
RegisterRamReset(RESET_REG | RESET_VRAM);
|
||||
SoftReset();
|
||||
}
|
||||
|
||||
inline void setUpInterrupts() {
|
||||
interrupt_init();
|
||||
|
||||
interrupt_set_handler(INTR_VBLANK, [] {});
|
||||
interrupt_enable(INTR_VBLANK);
|
||||
|
||||
// A+B+START+SELECT
|
||||
REG_KEYCNT = 0b1100000000001111;
|
||||
interrupt_set_handler(INTR_KEYPAD, ISR_reset);
|
||||
interrupt_enable(INTR_KEYPAD);
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
#include "MultibootScene.h"
|
||||
|
||||
#include <libgba-sprite-engine/background/text_stream.h>
|
||||
#include <tonc.h>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "../../../../lib/LinkRawWireless.hpp"
|
||||
#include "utils/InputHandler.h"
|
||||
#include "utils/SceneUtils.h"
|
||||
|
||||
MultibootScene::MultibootScene(std::shared_ptr<GBAEngine> engine)
|
||||
: Scene(engine) {}
|
||||
|
||||
static std::unique_ptr<InputHandler> aHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
static std::unique_ptr<InputHandler> bHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
static std::unique_ptr<InputHandler> upHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
static std::unique_ptr<InputHandler> downHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
static std::unique_ptr<InputHandler> lHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
static std::unique_ptr<InputHandler> rHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
static std::unique_ptr<InputHandler> selectHandler =
|
||||
std::unique_ptr<InputHandler>(new InputHandler());
|
||||
|
||||
static std::vector<std::string> logLines;
|
||||
static u32 currentLogLine = 0;
|
||||
static bool useVerboseLog = true;
|
||||
|
||||
#define MAX_LINES 20
|
||||
#define DRAW_LINE 0
|
||||
|
||||
void printScrollableText(u32 currentLine,
|
||||
std::vector<std::string> lines,
|
||||
bool withCursor = false) {
|
||||
for (u32 i = 0; i < MAX_LINES; i++) {
|
||||
u32 lastLineIndex = MAX_LINES - 1;
|
||||
u32 index = max(currentLine, lastLineIndex) - lastLineIndex + i;
|
||||
if (index < lines.size()) {
|
||||
std::string cursor = currentLine == index ? "> " : " ";
|
||||
TextStream::instance().setText((withCursor ? cursor : "") + lines[index],
|
||||
DRAW_LINE + i, -3);
|
||||
} else {
|
||||
TextStream::instance().setText(" ",
|
||||
DRAW_LINE + i, -3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print() {
|
||||
printScrollableText(currentLogLine, logLines);
|
||||
}
|
||||
|
||||
void scrollBack() {
|
||||
if (currentLogLine <= 0)
|
||||
return;
|
||||
currentLogLine--;
|
||||
print();
|
||||
}
|
||||
|
||||
void scrollForward() {
|
||||
if (currentLogLine < MAX_LINES - 1)
|
||||
currentLogLine = min(MAX_LINES - 1, logLines.size() - 1);
|
||||
if (currentLogLine == logLines.size() - 1)
|
||||
return;
|
||||
currentLogLine++;
|
||||
print();
|
||||
}
|
||||
|
||||
void scrollPageUp() {
|
||||
currentLogLine = max(currentLogLine - MAX_LINES, 0);
|
||||
print();
|
||||
}
|
||||
|
||||
void scrollPageDown() {
|
||||
currentLogLine = min(currentLogLine + MAX_LINES, logLines.size() - 1);
|
||||
print();
|
||||
}
|
||||
|
||||
void scrollToTop() {
|
||||
currentLogLine = 0;
|
||||
print();
|
||||
}
|
||||
|
||||
void scrollToBottom() {
|
||||
currentLogLine = logLines.size() - 1;
|
||||
print();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
logLines.clear();
|
||||
currentLogLine = 0;
|
||||
print();
|
||||
}
|
||||
|
||||
void log(std::string string) {
|
||||
logLines.push_back(string);
|
||||
scrollPageDown();
|
||||
}
|
||||
|
||||
std::vector<Background*> MultibootScene::backgrounds() {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<Sprite*> MultibootScene::sprites() {
|
||||
std::vector<Sprite*> sprites;
|
||||
return sprites;
|
||||
}
|
||||
|
||||
void MultibootScene::load() {
|
||||
SCENE_init();
|
||||
BACKGROUND_enable(true, false, false, false);
|
||||
|
||||
linkRawWireless->logger = [](std::string string) {
|
||||
if (useVerboseLog)
|
||||
log(string);
|
||||
};
|
||||
|
||||
log("---");
|
||||
log("LinkWirelessMultiboot demo");
|
||||
log("");
|
||||
log("A: send ROM");
|
||||
log("B: toggle log level");
|
||||
log("UP/DOWN: scroll up/down");
|
||||
log("L/R: scroll page up/down");
|
||||
log("UP+L/DOWN+R: scroll to top/bottom");
|
||||
log("SELECT: clear");
|
||||
log("---");
|
||||
log("");
|
||||
toggleLogLevel();
|
||||
}
|
||||
|
||||
void MultibootScene::tick(u16 keys) {
|
||||
if (engine->isTransitioning())
|
||||
return;
|
||||
|
||||
processKeys(keys);
|
||||
processButtons();
|
||||
|
||||
__qran_seed += keys;
|
||||
__qran_seed += REG_RCNT;
|
||||
__qran_seed += REG_SIOCNT;
|
||||
}
|
||||
|
||||
void MultibootScene::processKeys(u16 keys) {
|
||||
aHandler->setIsPressed(keys & KEY_A);
|
||||
bHandler->setIsPressed(keys & KEY_B);
|
||||
upHandler->setIsPressed(keys & KEY_UP);
|
||||
downHandler->setIsPressed(keys & KEY_DOWN);
|
||||
lHandler->setIsPressed(keys & KEY_L);
|
||||
rHandler->setIsPressed(keys & KEY_R);
|
||||
selectHandler->setIsPressed(keys & KEY_SELECT);
|
||||
}
|
||||
|
||||
void MultibootScene::processButtons() {
|
||||
if (bHandler->hasBeenPressedNow())
|
||||
toggleLogLevel();
|
||||
|
||||
if (aHandler->hasBeenPressedNow()) {
|
||||
// TODO: IMPLEMENT
|
||||
print();
|
||||
}
|
||||
|
||||
if (lHandler->hasBeenPressedNow()) {
|
||||
if (upHandler->getIsPressed())
|
||||
scrollToTop();
|
||||
else
|
||||
scrollPageUp();
|
||||
}
|
||||
|
||||
if (rHandler->hasBeenPressedNow()) {
|
||||
if (downHandler->getIsPressed())
|
||||
scrollToBottom();
|
||||
else
|
||||
scrollPageDown();
|
||||
}
|
||||
|
||||
if (upHandler->getIsPressed())
|
||||
scrollBack();
|
||||
|
||||
if (downHandler->getIsPressed())
|
||||
scrollForward();
|
||||
|
||||
if (selectHandler->hasBeenPressedNow())
|
||||
clear();
|
||||
}
|
||||
|
||||
void MultibootScene::toggleLogLevel() {
|
||||
if (useVerboseLog) {
|
||||
useVerboseLog = false;
|
||||
log("! setting log level to NORMAL");
|
||||
} else {
|
||||
useVerboseLog = true;
|
||||
log("! setting log level to VERBOSE");
|
||||
}
|
||||
log("");
|
||||
}
|
||||
|
||||
void MultibootScene::logOperation(std::string name,
|
||||
std::function<bool()> operation) {
|
||||
log("> " + name + "...");
|
||||
bool success = operation();
|
||||
log(success ? "< success :)" : "< failure :(");
|
||||
log("");
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef MULTIBOOT_SCENE_H
|
||||
#define MULTIBOOT_SCENE_H
|
||||
|
||||
#include <libgba-sprite-engine/background/background.h>
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
#include <libgba-sprite-engine/scene.h>
|
||||
#include <libgba-sprite-engine/sprites/sprite.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class MultibootScene : public Scene {
|
||||
public:
|
||||
MultibootScene(std::shared_ptr<GBAEngine> engine);
|
||||
|
||||
std::vector<Background*> backgrounds() override;
|
||||
std::vector<Sprite*> sprites() override;
|
||||
|
||||
void load() override;
|
||||
void tick(u16 keys) override;
|
||||
|
||||
private:
|
||||
struct CommandMenuOption {
|
||||
std::string name;
|
||||
u8 command;
|
||||
};
|
||||
int lastSelectedCommandIndex = 0;
|
||||
|
||||
void processKeys(u16 keys);
|
||||
void processButtons();
|
||||
void toggleLogLevel();
|
||||
void logOperation(std::string name, std::function<bool()> operation);
|
||||
};
|
||||
|
||||
#endif // MULTIBOOT_SCENE_H
|
||||
39
examples/LinkWirelessMultiboot_demo/src/utils/InputHandler.h
Normal file
39
examples/LinkWirelessMultiboot_demo/src/utils/InputHandler.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef INPUT_HANDLER_H
|
||||
#define INPUT_HANDLER_H
|
||||
|
||||
#include <libgba-sprite-engine/gba_engine.h>
|
||||
|
||||
class InputHandler {
|
||||
public:
|
||||
InputHandler() {
|
||||
this->isPressed = false;
|
||||
this->isWaiting = true;
|
||||
}
|
||||
|
||||
inline bool getIsPressed() { return isPressed; }
|
||||
|
||||
inline bool hasBeenPressedNow() { return isNewPressEvent; }
|
||||
inline bool hasBeenReleasedNow() { return isNewReleaseEvent; }
|
||||
|
||||
inline bool getHandledFlag() { return handledFlag; }
|
||||
inline void setHandledFlag(bool value) { handledFlag = value; }
|
||||
|
||||
inline void setIsPressed(bool isPressed) {
|
||||
bool isNewPressEvent = !this->isWaiting && !this->isPressed && isPressed;
|
||||
bool isNewReleaseEvent = !this->isWaiting && this->isPressed && !isPressed;
|
||||
this->isPressed = isPressed;
|
||||
this->isWaiting = this->isWaiting && isPressed;
|
||||
|
||||
this->isNewPressEvent = isNewPressEvent;
|
||||
this->isNewReleaseEvent = isNewReleaseEvent;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool isPressed = false;
|
||||
bool isNewPressEvent = false;
|
||||
bool isNewReleaseEvent = false;
|
||||
bool handledFlag = false;
|
||||
bool isWaiting = false;
|
||||
};
|
||||
|
||||
#endif // INPUT_HANDLER_H
|
||||
52
examples/LinkWirelessMultiboot_demo/src/utils/SceneUtils.h
Normal file
52
examples/LinkWirelessMultiboot_demo/src/utils/SceneUtils.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef SCENE_UTILS_H
|
||||
#define SCENE_UTILS_H
|
||||
|
||||
#include <libgba-sprite-engine/background/text_stream.h>
|
||||
#include <tonc_memdef.h>
|
||||
#include <tonc_memmap.h>
|
||||
#include <string>
|
||||
|
||||
const u32 TEXT_MIDDLE_COL = 12;
|
||||
|
||||
inline std::string asStr(u16 data) {
|
||||
return std::to_string(data);
|
||||
}
|
||||
|
||||
inline void BACKGROUND_enable(bool bg0, bool bg1, bool bg2, bool bg3) {
|
||||
REG_DISPCNT = bg0 ? REG_DISPCNT | DCNT_BG0 : REG_DISPCNT & ~DCNT_BG0;
|
||||
REG_DISPCNT = bg1 ? REG_DISPCNT | DCNT_BG1 : REG_DISPCNT & ~DCNT_BG1;
|
||||
REG_DISPCNT = bg2 ? REG_DISPCNT | DCNT_BG2 : REG_DISPCNT & ~DCNT_BG2;
|
||||
REG_DISPCNT = bg3 ? REG_DISPCNT | DCNT_BG3 : REG_DISPCNT & ~DCNT_BG3;
|
||||
}
|
||||
|
||||
inline void SPRITE_disable() {
|
||||
REG_DISPCNT = REG_DISPCNT & ~DCNT_OBJ;
|
||||
}
|
||||
|
||||
inline void SCENE_init() {
|
||||
TextStream::instance().clear();
|
||||
TextStream::instance().scroll(0, 0);
|
||||
TextStream::instance().setMosaic(false);
|
||||
|
||||
BACKGROUND_enable(false, false, false, false);
|
||||
SPRITE_disable();
|
||||
}
|
||||
|
||||
inline void SCENE_write(std::string text, u32 row) {
|
||||
TextStream::instance().setText(text, row,
|
||||
TEXT_MIDDLE_COL - text.length() / 2);
|
||||
}
|
||||
|
||||
inline void SCENE_wait(u32 verticalLines) {
|
||||
u32 count = 0;
|
||||
u32 vCount = REG_VCOUNT;
|
||||
|
||||
while (count < verticalLines) {
|
||||
if (REG_VCOUNT != vCount) {
|
||||
count++;
|
||||
vCount = REG_VCOUNT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SCENE_UTILS_H
|
||||
@@ -86,3 +86,8 @@ mv backup.gba LinkWireless_demo.gba
|
||||
sed -i -e "s/#define LINK_WIRELESS_PUT_ISR_IN_IWRAM/\/\/ #define LINK_WIRELESS_PUT_ISR_IN_IWRAM/g" ../../lib/LinkWireless.hpp
|
||||
sed -i -e "s/#define PROFILING_ENABLED/\/\/ #define PROFILING_ENABLED/g" ../../lib/LinkWireless.hpp
|
||||
cd ..
|
||||
|
||||
cd LinkWirelessMultiboot_demo/
|
||||
make rebuild
|
||||
cp LinkWirelessMultiboot_demo.gba ../
|
||||
cd ..
|
||||
|
||||
Reference in New Issue
Block a user