From dbc46b2e3c282680e7d08bc428e1c2b9c9ce1119 Mon Sep 17 00:00:00 2001 From: Starport75 Date: Tue, 11 Apr 2023 10:35:49 -0500 Subject: [PATCH] Initial commit --- .gitignore | 6 ++ Makefile | 187 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 25 ++++++ graphics/metr.grit | 4 + graphics/metr.png | Bin 0 -> 1702 bytes source/main.c | 45 +++++++++++ 6 files changed, 267 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 graphics/metr.grit create mode 100644 graphics/metr.png create mode 100644 source/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43000fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +build/ +*.log +*.sav +*.gba +*.lnk +*.elf diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aabac37 --- /dev/null +++ b/Makefile @@ -0,0 +1,187 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITARM)/gba_rules + +#--------------------------------------------------------------------------------- +# the LIBGBA path is defined in gba_rules, but we have to define LIBTONC ourselves +#--------------------------------------------------------------------------------- +LIBTONC := $(DEVKITPRO)/libtonc + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +# DATA is a list of directories containing binary data +# GRAPHICS is a list of directories containing files to be processed by grit +# +# All directories are specified relative to the project directory where +# the makefile is found +# +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +INCLUDES := include +DATA := +MUSIC := +GRAPHICS := graphics + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb -mthumb-interwork + +CFLAGS := -g -Wall -O2\ + -mcpu=arm7tdmi -mtune=arm7tdmi\ + $(ARCH) + +CFLAGS += $(INCLUDE) + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := -g $(ARCH) +LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lmm -ltonc + + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib. +# the LIBGBA path should remain in this list if you want to use maxmod +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBGBA) $(LIBTONC) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- + + +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +ifneq ($(strip $(MUSIC)),) + export AUDIOFILES := $(foreach dir,$(notdir $(wildcard $(MUSIC)/*.*)),$(CURDIR)/$(MUSIC)/$(dir)) + BINFILES += soundbank.bin +endif + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) + +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES_GRAPHICS := $(PNGFILES:.png=.o) + +export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) $(OFILES_GRAPHICS) + +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(PNGFILES:.png=.h) + +export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba + + +#--------------------------------------------------------------------------------- +else + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- + +$(OUTPUT).gba : $(OUTPUT).elf + +$(OUTPUT).elf : $(OFILES) + +$(OFILES_SOURCES) : $(HFILES) + +#--------------------------------------------------------------------------------- +# The bin2o rule should be copied and modified +# for each extension used in the data directories +#--------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------- +# rule to build soundbank from music files +#--------------------------------------------------------------------------------- +soundbank.bin soundbank.h : $(AUDIOFILES) +#--------------------------------------------------------------------------------- + @mmutil $^ -osoundbank.bin -hsoundbank.h + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .bin extension +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +# This rule creates assembly source files using grit +# grit takes an image file and a .grit describing how the file is to be processed +# add additional rules like this for each image extension +# you use in the graphics folders +#--------------------------------------------------------------------------------- +%.s %.h: %.png %.grit +#--------------------------------------------------------------------------------- + @echo "grit $(notdir $<)" + @grit $< -fts -o$* + +# make likes to delete intermediate files. This prevents it from deleting the +# files generated by grit after building the GBA ROM. +.SECONDARY: + +-include $(DEPSDIR)/*.d +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 0000000..823bd2b --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +## Quickstart + +> _"I want to make GBA homebrew, where do I begin?"_ + + +1) [Install devkitARM](https://devkitpro.org/wiki/Getting_Started) for your system. + +2) [Read Tonc](https://www.coranac.com/tonc/text/) to learn all about GBA programming! + * You can skip _"Setting up a development environment"_ because we did that in step 1. + +3) Clone this repo and run `make` in your terminal. + * If you used the graphical installer on Windows for step 1, you should use the _MSYS2_ terminal for this step. + + +## About this repo + +This is a minimal GBA example project using libtonc instead of libgba. + +The commit history exists to document the process of converting a _libgba_ example to a _libtonc_ example. + +### Why? + +devkitPro provides two general-purpose libraries: _libgba_ and _libtonc_. Of the two, I recommend _libtonc_, because it has better documentation and more features (it's part of the accompanying material to the excellent Tonc tutorial). + +The trouble here is that all the GBA examples are using _libgba_, and converting the _libgba_ template to use _libtonc_ is non-trivial for those who are just getting started. \ No newline at end of file diff --git a/graphics/metr.grit b/graphics/metr.grit new file mode 100644 index 0000000..478da4e --- /dev/null +++ b/graphics/metr.grit @@ -0,0 +1,4 @@ +# +# Metroid : 4bpp, not compressed. Only use the first 64 columns. +# +-gB4 -ar64 diff --git a/graphics/metr.png b/graphics/metr.png new file mode 100644 index 0000000000000000000000000000000000000000..c9822b07eb7abcffa5743729528c0bc75d8556c3 GIT binary patch literal 1702 zcmeHG>r)d~6h9CiArOtk77*0nV;UT-i&_Z^aaACswYY!?w%UaF0%OhUU=2cX!2x3h zT!nVR_+ZtJ#A7?7J?GqWe&;u5 z?%9vUDTIPa0ss&yW1|wdo8UIe=W%Bz|KR5UJiu10iY5qRh;sp`CBWdAS;|inIZc`X zmIfPB=`>L88Gv-ET)e?xAW70_G*T30GMUU~b7f^EP1E)D^$f#UtyY$0Z8n?TZXX)@ z7n?(r03c&P*ccW*#)kx;0L)x900w{sumdL|5lAF}Ab_HPVW3t6j&p^9B!Qy9YzCSJ zh5?oZyE9${A_+(kKu|z2z|^3|0VjYUfuw*kgP8`J0fq(EK8F9E@J>em%YWDbKA$fV ziTwTjB@&5LDn$@PCX=Bk8XFsnVOUB^idwBsOH0FXT(8$Vd5YfSyGcsJmvbpD83}QT zfIhcw;s#@tGHU56{n3|Ye-@uZe4>|DuSQE9ju!Fau&$Wx`m*VtG-ap{U%K9IO}EW% zXt-?Is%zbodDcGPx$pz!XMYcgcve?gB|rN#t#IO$eqPIi9;Mk@^&!{erytdEYDtyRFI2(Y z%qe;{LlubXN)LDjSGH#JqrV%^<b6|E;D_2bP5Q&Vlk7FieQ6nC+B5~%p;gHq zj5lsGY@7haZ7~mn-YGm@XQvY@$)k(qJBd^2dB^(%vSN;CAQkLmPDjOwnI)GN+{xuS zLH{;sL^qrC&Ga4)xOB)RQl+3NsfxfpJLK4cHijt;;roqY7Y(WI!N=y+Dovf98~H~( znI8}SfyL;xXyYy)^siVfXjVr^doxk2lNTb}Hl=s@Dz53DTz!i)_4h|ryP{_vcVBZ8 z=L~!1G+&or&HA>^o2M^0vwL*e^rF73eTiKcBG$&ZM0RM-A$1LW%JJ3SDeGc;+GpCl zw86K6cf;$acQTs_3O-sn<6`%skP6MMwGRg-&&9QV{D7@L=gZ1%We$H2 z#u}4atg0FAo$Yd>Wb^if@MAr4AJ^K!)v1U5MhDlo4%VE`YGNzgLLXPGYcZdSH+EL! zj>yIx+4nNlaAn&Ix$?`fj0?gQ{nH4|>gu^k4T4T~U~;)nPsfs?%b6LyD;MnBA$V{D z!H_p5_u`XTI^o^E>Aa#} + +// This file is autogenerated from the file in the graphics folder +#include "metr.h" + +OBJ_ATTR obj_buffer[128]; +OBJ_AFFINE *obj_aff_buffer = (OBJ_AFFINE*)obj_buffer; + +void load_sprite(void) +{ + // Load tiles and palette of sprite into video and palete RAM + memcpy32(&tile_mem[4][0], metrTiles, metrTilesLen / 4); + memcpy32(pal_obj_mem, metrPal, metrPalLen / 4); + + oam_init(obj_buffer, 128); + + OBJ_ATTR *metr = &obj_buffer[0]; + obj_set_attr(metr, + ATTR0_SQUARE, // Square, regular sprite + ATTR1_SIZE_64, // 64x64 pixels, + ATTR2_PALBANK(0) | 0); // palette index 0, tile index 0 + + // Set position + obj_set_pos(metr, 176, 96); + + oam_copy(oam_mem, obj_buffer, 1); // Update first OAM object +} + +int main(void) +{ + irq_init(NULL); + irq_enable(II_VBLANK); + + tte_init_chr4c_default(0, BG_CBB(0) | BG_SBB(31)); + tte_set_pos(92, 68); + tte_write("Hello World!"); + + load_sprite(); + + REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ | DCNT_OBJ_1D; + + while (1) { + VBlankIntrWait(); + } +}