From b7ebdb3c288f404e148b0ace9b25e9b6d070fa81 Mon Sep 17 00:00:00 2001 From: Trevor Boddy Date: Mon, 15 Aug 2022 15:59:52 -0400 Subject: [PATCH] init uhhhh uhhhhhhhh uh uh uhu hhhhh --- Makefile | 145 +++++++++++++ README.md | 5 +- bible.txt | 32 +++ boot/rom_head.c | 43 ++++ boot/sega.s | 462 ++++++++++++++++++++++++++++++++++++++++++ build.sh | 3 + compile.sh | 2 + res/bg/1_1.png | Bin 0 -> 5062 bytes res/chrome/frame1.png | Bin 0 -> 4594 bytes res/chrome/frame2.png | Bin 0 -> 4615 bytes res/chrome/frame3.png | Bin 0 -> 4612 bytes res/font.png | Bin 0 -> 3338 bytes res/player/player.png | Bin 0 -> 2142 bytes res/resources.res | 12 ++ res/tiles/1_1.png | Bin 0 -> 4862 bytes res/tiles/1_2.png | Bin 0 -> 4858 bytes run.sh | 1 + src/background.h | 47 +++++ src/chrome.h | 76 +++++++ src/controls.h | 21 ++ src/global.h | 25 +++ src/main.c | 51 +++++ src/player.h | 32 +++ src/tiles.h | 84 ++++++++ 24 files changed, 1038 insertions(+), 3 deletions(-) create mode 100644 Makefile create mode 100644 bible.txt create mode 100644 boot/rom_head.c create mode 100644 boot/sega.s create mode 100755 build.sh create mode 100755 compile.sh create mode 100644 res/bg/1_1.png create mode 100644 res/chrome/frame1.png create mode 100644 res/chrome/frame2.png create mode 100644 res/chrome/frame3.png create mode 100644 res/font.png create mode 100644 res/player/player.png create mode 100644 res/resources.res create mode 100644 res/tiles/1_1.png create mode 100644 res/tiles/1_2.png create mode 100755 run.sh create mode 100644 src/background.h create mode 100644 src/chrome.h create mode 100644 src/controls.h create mode 100644 src/global.h create mode 100644 src/main.c create mode 100644 src/player.h create mode 100644 src/tiles.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f9f0227 --- /dev/null +++ b/Makefile @@ -0,0 +1,145 @@ +# Sample Makefile for Marsdev (SGDK version) + +# Default paths, can be overridden by setting MARSDEV before calling make +MARSDEV ?= ${HOME}/mars +MARSBIN = $(MARSDEV)/m68k-elf/bin +TOOLSBIN = $(MARSDEV)/bin + +# GCC and Binutils +CC = $(MARSBIN)/m68k-elf-gcc +CXX = $(MARSBIN)/m68k-elf-g++ +AS = $(MARSBIN)/m68k-elf-as +LD = $(MARSBIN)/m68k-elf-ld +NM = $(MARSBIN)/m68k-elf-nm +OBJC = $(MARSBIN)/m68k-elf-objcopy +# SGDK Tools +BINTOS = $(TOOLSBIN)/bintos +PCMTORAW = $(TOOLSBIN)/pcmtoraw +RESCOMP = $(TOOLSBIN)/rescomp +WAVTORAW = $(TOOLSBIN)/wavtoraw +XGMTOOL = $(TOOLSBIN)/xgmtool +# Use rescomp jar for SGDK > 1.33 +ifneq ("$(wildcard $(TOOLSBIN)/rescomp.jar)","") + RESCOMP = java -jar $(TOOLSBIN)/rescomp.jar + WAVTORAW = @echo "wavtoraw no longer available!" ## + PCMTORAW = @echo "pcmtoraw no longer available!" ## +endif + +# Some files needed are in a versioned directory +GCC_VER := $(shell $(CC) -dumpversion) + +# Need the LTO plugin so NM can dump our symbol table +PLUGIN = $(MARSDEV)/m68k-elf/libexec/gcc/m68k-elf/$(GCC_VER) +LTO_SO = liblto_plugin.so +ifeq ($(OS),Windows_NT) + LTO_SO = liblto_plugin-0.dll +endif + +# Includes: Local + GCC + SGDK + Newlib +INCS = -Isrc -Ires -Iinc +INCS += -I$(MARSDEV)/m68k-elf/lib/gcc/m68k-elf/$(GCC_VER)/include +INCS += -I$(MARSDEV)/m68k-elf/include +INCS += -I$(MARSDEV)/m68k-elf/m68k-elf/include + +# Libraries: GCC + Newlib (SGDK libs are with release/debug targets) +# If you plan on using Newlib, uncomment the line with -lnosys +LIBS = -L$(MARSDEV)/m68k-elf/lib/gcc/m68k-elf/$(GCC_VER) -lgcc +#LIBS += -L$(MARSDEV)/m68k-elf/m68k-elf/lib -lnosys + +# Force libgcc math routines to be available at link time +LIBS += -u __modsi3 -u __divsi3 -u __mulsi3 -u __umodsi3 -u __udivsi3 -u __umulsi3 + +# Any C or C++ standard should be fine here as long as GCC support it +CCFLAGS = -m68000 -Wall -Wextra -std=c99 -ffreestanding -fcommon +CXXFLAGS = -m68000 -Wall -Wextra -std=c++17 -ffreestanding + +# Extra options set by debug or release target +OPTIONS = +ASFLAGS = -m68000 --register-prefix-optional +LDFLAGS = -T $(MARSDEV)/ldscripts/sgdk.ld -nostdlib -fcommon + +RESS = $(wildcard res/*.res) +CS = $(wildcard src/*.c) +CPPS = $(wildcard src/*.cpp) +SS = $(wildcard src/*.s) + +OBJS = $(RESS:.res=.o) +OBJS += $(CS:.c=.o) +OBJS += $(CPPS:.cpp=.o) +OBJS += $(SS:.s=.o) + +ASMO = $(RESS:.res=.o) +ASMO += $(CS:%.c=asmout/%.s) + +.SECONDARY: out.elf + +.PHONY: all release asm debug + +all: release + +release: OPTIONS = -O3 -fno-web -fno-gcse -fno-unit-at-a-time -fomit-frame-pointer +release: OPTIONS += -fshort-enums -flto -fuse-linker-plugin +release: LIBS += -L$(MARSDEV)/m68k-elf/lib -lmd +release: out.bin symbol.txt + +asm: OPTIONS = -O3 -fno-web -fno-gcse -fno-unit-at-a-time -fomit-frame-pointer +asm: OPTIONS += -fshort-enums +asm: LIBS += -L$(MARSDEV)/m68k-elf/lib -lmd +asm: asm-dir $(ASMO) + +# Gens-KMod, BlastEm and UMDK support GDB tracing, enabled by this target +debug: OPTIONS = -g -Og -DDEBUG -DKDEBUG -fno-web -fno-gcse -fno-unit-at-a-time -fshort-enums +debug: LIBS += -L$(MARSDEV)/m68k-elf/lib -lmd-debug +debug: out.bin symbol.txt + +# This generates a symbol table that is very helpful in debugging crashes, +# even with an optimized release build! +# Cross reference symbol.txt with the addresses displayed in the crash handler +symbol.txt: out.bin + $(NM) --plugin=$(PLUGIN)/$(LTO_SO) -n out.elf > symbol.txt + +boot/sega.o: boot/rom_head.bin + @echo "AS $<" + @$(AS) $(ASFLAGS) boot/sega.s -o $@ + +boot/rom_head.bin: boot/rom_head.c + @echo "CC $<" + @$(CC) $(CFLAGS) $(INCS) -nostdlib -Wl,--oformat=binary $< -o $@ + +%.bin: %.elf + @echo "Stripping ELF header..." + @$(OBJC) -O binary $< temp.bin + @dd if=temp.bin of=$@ bs=8192 conv=sync + @rm -f temp.bin + +%.elf: boot/sega.o $(OBJS) + $(CC) -o $@ $(LDFLAGS) boot/sega.o $(OBJS) $(LIBS) + +%.o: %.c + @echo "CC $<" + @$(CC) $(CCFLAGS) $(OPTIONS) $(INCS) -c $< -o $@ + +%.o: %.cpp + @echo "CXX $<" + @$(CXX) $(CXXFLAGS) $(OPTIONS) $(INCS) -c $< -o $@ + +%.o: %.s + @echo "AS $<" + @$(AS) $(ASFLAGS) $< -o $@ + +%.s: %.res + $(RESCOMP) $< $@ + +# For asm target +asm-dir: + mkdir -p asmout/src + +asmout/%.s: %.c + $(CC) $(CCFLAGS) $(OPTIONS) $(INCS) -S $< -o $@ + +.PHONY: clean + +clean: + rm -f $(OBJS) out.bin out.elf symbol.txt + rm -f boot/sega.o boot/rom_head.o boot/rom_head.bin + rm -rf asmout diff --git a/README.md b/README.md index 099a64a..ae3c8ab 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,2 @@ -# 2hustation3 - -vanguard-type thing for the genesis \ No newline at end of file +# eohp +touhou pride jam 4 entry diff --git a/bible.txt b/bible.txt new file mode 100644 index 0000000..615e1c1 --- /dev/null +++ b/bible.txt @@ -0,0 +1,32 @@ +########## +# THEMES # +########## + - + +############ +# GAMEPLAY # +############ + - The player controls a ship which automatically flies forward through scrolling levels. + - It has a limited amount of fuel that constantly depletes. + - Fuel is replenished by destroying enemies + +########## +# LEVELS # +########## + - Tunnel 1 + - Mountain Zone + - Rainbow Zone + - Styx Zone + - Rainbow Zone 2 + - Stripe Zone + - Rainbow Zone 3 + - Bleak Zone + - Last Zone + - Tunnel 2 + - Mountain Zone + - Stripe Zone + - Styx Zone + - Rainbow Zone + - Bleak Zone + - Last Zone + - At the end of each tunnel the player must defeat a boss guarded by two moving force fields with holes in them. \ No newline at end of file diff --git a/boot/rom_head.c b/boot/rom_head.c new file mode 100644 index 0000000..87678c3 --- /dev/null +++ b/boot/rom_head.c @@ -0,0 +1,43 @@ +#include "types.h" + +__attribute__((externally_visible)) +const struct +{ + char console[16]; /* Console Name (16) */ + char copyright[16]; /* Copyright Information (16) */ + char title_local[48]; /* Domestic Name (48) */ + char title_int[48]; /* Overseas Name (48) */ + char serial[14]; /* Serial Number (2, 12) */ + u16 checksum; /* Checksum (2) */ + char IOSupport[16]; /* I/O Support (16) */ + u32 rom_start; /* ROM Start Address (4) */ + u32 rom_end; /* ROM End Address (4) */ + u32 ram_start; /* Start of Backup RAM (4) */ + u32 ram_end; /* End of Backup RAM (4) */ + char sram_sig[2]; /* "RA" for save ram (2) */ + u16 sram_type; /* 0xF820 for save ram on odd bytes (2) */ + u32 sram_start; /* SRAM start address - normally 0x200001 (4) */ + u32 sram_end; /* SRAM end address - start + 2*sram_size (4) */ + char modem_support[12]; /* Modem Support (24) */ + char notes[40]; /* Memo (40) */ + char region[16]; /* Country Support (16) */ +} rom_header = { + "SEGA MEGA DRIVE ", + "TBODDY ", + "th station ", + "th station ", + "GM 00000000-00", + 0x0000, + "JD ", + 0x00000000, + 0x00100000, + 0x00FF0000, + 0x00FFFFFF, + " ", + 0x0000, + 0x00200000, + 0x002001FF, + " ", + "th station ", + "JUE " +}; diff --git a/boot/sega.s b/boot/sega.s new file mode 100644 index 0000000..56302b8 --- /dev/null +++ b/boot/sega.s @@ -0,0 +1,462 @@ +.section .text.keepboot + +*------------------------------------------------------- +* +* Sega startup code for the GNU Assembler +* Translated from: +* Sega startup code for the Sozobon C compiler +* Written by Paul W. Lee +* Modified by Charles Coty +* Modified by Stephane Dallongeville +* +*------------------------------------------------------- + + .globl _hard_reset + + .org 0x00000000 + +_Start_Of_Rom: +_Vecteurs_68K: + dc.l 0x00000000 /* Stack address */ + dc.l _Entry_Point /* Program start address */ + dc.l _Bus_Error + dc.l _Address_Error + dc.l _Illegal_Instruction + dc.l _Zero_Divide + dc.l _Chk_Instruction + dc.l _Trapv_Instruction + dc.l _Privilege_Violation + dc.l _Trace + dc.l _Line_1010_Emulation + dc.l _Line_1111_Emulation + dc.l _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception + dc.l _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception + dc.l _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception + dc.l _Error_Exception, _INT, _EXTINT, _INT + dc.l _HINT + dc.l _INT + dc.l _VINT + dc.l _INT + dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT + dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT + dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT + dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT + + .incbin "boot/rom_head.bin" + +_Entry_Point: + move #0x2700,%sr + tst.l 0xa10008 + bne.s SkipJoyDetect + + tst.w 0xa1000c + +SkipJoyDetect: + bne.s SkipSetup + + lea Table,%a5 + movem.w (%a5)+,%d5-%d7 + movem.l (%a5)+,%a0-%a4 +* Check Version Number + move.b -0x10ff(%a1),%d0 + andi.b #0x0f,%d0 + beq.s WrongVersion + +* Sega Security Code (SEGA) + move.l #0x53454741,0x2f00(%a1) +WrongVersion: + move.w (%a4),%d0 + moveq #0x00,%d0 + movea.l %d0,%a6 + move %a6,%usp + move.w %d7,(%a1) + move.w %d7,(%a2) + +* Jump to initialisation process now... + + jmp _start_entry + +SkipSetup: + jmp _reset_entry + + +Table: + dc.w 0x8000,0x3fff,0x0100 + dc.l 0xA00000,0xA11100,0xA11200,0xC00000,0xC00004 + + +*------------------------------------------------ +* +* interrupt functions +* +*------------------------------------------------ + +registersDump: + move.l %d0,registerState+0 + move.l %d1,registerState+4 + move.l %d2,registerState+8 + move.l %d3,registerState+12 + move.l %d4,registerState+16 + move.l %d5,registerState+20 + move.l %d6,registerState+24 + move.l %d7,registerState+28 + move.l %a0,registerState+32 + move.l %a1,registerState+36 + move.l %a2,registerState+40 + move.l %a3,registerState+44 + move.l %a4,registerState+48 + move.l %a5,registerState+52 + move.l %a6,registerState+56 + move.l %a7,registerState+60 + rts + +busAddressErrorDump: + move.w 4(%sp),ext1State + move.l 6(%sp),addrState + move.w 10(%sp),ext2State + move.w 12(%sp),srState + move.l 14(%sp),pcState + jmp registersDump + +exception4WDump: + move.w 4(%sp),srState + move.l 6(%sp),pcState + move.w 10(%sp),ext1State + jmp registersDump + +exceptionDump: + move.w 4(%sp),srState + move.l 6(%sp),pcState + jmp registersDump + + +_Bus_Error: + jsr busAddressErrorDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l busErrorCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Address_Error: + jsr busAddressErrorDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l addressErrorCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Illegal_Instruction: + jsr exception4WDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l illegalInstCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Zero_Divide: + jsr exceptionDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l zeroDivideCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Chk_Instruction: + jsr exception4WDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l chkInstCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Trapv_Instruction: + jsr exception4WDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l trapvInstCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Privilege_Violation: + jsr exceptionDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l privilegeViolationCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Trace: + jsr exceptionDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l traceCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Line_1010_Emulation: +_Line_1111_Emulation: + jsr exceptionDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l line1x1xCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_Error_Exception: + jsr exceptionDump + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l errorExceptionCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_INT: + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l intCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_EXTINT: + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l eintCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_HINT: + movem.l %d0-%d1/%a0-%a1,-(%sp) + move.l hintCB, %a0 + jsr (%a0) + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + +_VINT: + movem.l %d0-%d1/%a0-%a1,-(%sp) + ori.w #0x0001, intTrace /* in V-Int */ + addq.l #1, vtimer /* increment frame counter (more a vint counter) */ + btst #3, VBlankProcess+1 /* PROCESS_XGM_TASK ? (use VBlankProcess+1 as btst is a byte operation) */ + beq.s _no_xgm_task + + jsr XGM_doVBlankProcess /* do XGM vblank task */ + +_no_xgm_task: + btst #1, VBlankProcess+1 /* PROCESS_BITMAP_TASK ? (use VBlankProcess+1 as btst is a byte operation) */ + beq.s _no_bmp_task + + jsr BMP_doVBlankProcess /* do BMP vblank task */ + +_no_bmp_task: + move.l vintCB, %a0 /* load user callback */ + jsr (%a0) /* call user callback */ + andi.w #0xFFFE, intTrace /* out V-Int */ + movem.l (%sp)+,%d0-%d1/%a0-%a1 + rte + + +*------------------------------------------------ +* +* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg +* +* Permission is granted to anyone to use this software for any purpose +* on any computer system, and to redistribute it freely, with the +* following restrictions: +* 1) No charge may be made other than reasonable charges for reproduction. +* 2) Modified versions must be clearly marked as such. +* 3) The authors are not responsible for any harmful consequences +* of using this software, even if they result from defects in it. +* +*------------------------------------------------ + +ldiv: + move.l 4(%a7),%d0 + bpl ld1 + neg.l %d0 +ld1: + move.l 8(%a7),%d1 + bpl ld2 + neg.l %d1 + eor.b #0x80,4(%a7) +ld2: + bsr i_ldiv /* d0 = d0/d1 */ + tst.b 4(%a7) + bpl ld3 + neg.l %d0 +ld3: + rts + +lmul: + move.l 4(%a7),%d0 + bpl lm1 + neg.l %d0 +lm1: + move.l 8(%a7),%d1 + bpl lm2 + neg.l %d1 + eor.b #0x80,4(%a7) +lm2: + bsr i_lmul /* d0 = d0*d1 */ + tst.b 4(%a7) + bpl lm3 + neg.l %d0 +lm3: + rts + +lrem: + move.l 4(%a7),%d0 + bpl lr1 + neg.l %d0 +lr1: + move.l 8(%a7),%d1 + bpl lr2 + neg.l %d1 +lr2: + bsr i_ldiv /* d1 = d0%d1 */ + move.l %d1,%d0 + tst.b 4(%a7) + bpl lr3 + neg.l %d0 +lr3: + rts + +ldivu: + move.l 4(%a7),%d0 + move.l 8(%a7),%d1 + bsr i_ldiv + rts + +lmulu: + move.l 4(%a7),%d0 + move.l 8(%a7),%d1 + bsr i_lmul + rts + +lremu: + move.l 4(%a7),%d0 + move.l 8(%a7),%d1 + bsr i_ldiv + move.l %d1,%d0 + rts +* +* A in d0, B in d1, return A*B in d0 +* +i_lmul: + move.l %d3,%a2 /* save d3 */ + move.w %d1,%d2 + mulu %d0,%d2 /* d2 = Al * Bl */ + + move.l %d1,%d3 + swap %d3 + mulu %d0,%d3 /* d3 = Al * Bh */ + + swap %d0 + mulu %d1,%d0 /* d0 = Ah * Bl */ + + add.l %d3,%d0 /* d0 = (Ah*Bl + Al*Bh) */ + swap %d0 + clr.w %d0 /* d0 = (Ah*Bl + Al*Bh) << 16 */ + + add.l %d2,%d0 /* d0 = A*B */ + move.l %a2,%d3 /* restore d3 */ + rts +* +*A in d0, B in d1, return A/B in d0, A%B in d1 +* +i_ldiv: + tst.l %d1 + bne nz1 + +* divide by zero +* divu #0,%d0 /* cause trap */ + move.l #0x80000000,%d0 + move.l %d0,%d1 + rts +nz1: + move.l %d3,%a2 /* save d3 */ + cmp.l %d1,%d0 + bhi norm + beq is1 +* AB and B is not 0 +norm: + cmp.l #1,%d1 + bne not1 +* B==1, so ret A, rem 0 + clr.l %d1 + move.l %a2,%d3 /* restore d3 */ + rts +* check for A short (implies B short also) +not1: + cmp.l #0xffff,%d0 + bhi slow +* A short and B short -- use 'divu' + divu %d1,%d0 /* d0 = REM:ANS */ + swap %d0 /* d0 = ANS:REM */ + clr.l %d1 + move.w %d0,%d1 /* d1 = REM */ + clr.w %d0 + swap %d0 + move.l %a2,%d3 /* restore d3 */ + rts +* check for B short +slow: + cmp.l #0xffff,%d1 + bhi slower +* A long and B short -- use special stuff from gnu + move.l %d0,%d2 + clr.w %d2 + swap %d2 + divu %d1,%d2 /* d2 = REM:ANS of Ahi/B */ + clr.l %d3 + move.w %d2,%d3 /* d3 = Ahi/B */ + swap %d3 + + move.w %d0,%d2 /* d2 = REM << 16 + Alo */ + divu %d1,%d2 /* d2 = REM:ANS of stuff/B */ + + move.l %d2,%d1 + clr.w %d1 + swap %d1 /* d1 = REM */ + + clr.l %d0 + move.w %d2,%d0 + add.l %d3,%d0 /* d0 = ANS */ + move.l %a2,%d3 /* restore d3 */ + rts +* A>B, B > 1 +slower: + move.l #1,%d2 + clr.l %d3 +moreadj: + cmp.l %d0,%d1 + bhs adj + add.l %d2,%d2 + add.l %d1,%d1 + bpl moreadj +* we shifted B until its >A or sign bit set +* we shifted #1 (d2) along with it +adj: + cmp.l %d0,%d1 + bhi ltuns + or.l %d2,%d3 + sub.l %d1,%d0 +ltuns: + lsr.l #1,%d1 + lsr.l #1,%d2 + bne adj +* d3=answer, d0=rem + move.l %d0,%d1 + move.l %d3,%d0 + move.l %a2,%d3 /* restore d3 */ + rts diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..d0c2e7c --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +rm res/resources.o res/resources.h out.bin out.elf symbol.txt +make +./blastem/blastem out.bin \ No newline at end of file diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..6e24737 --- /dev/null +++ b/compile.sh @@ -0,0 +1,2 @@ +rm out.bin out.elf symbol.txt +make \ No newline at end of file diff --git a/res/bg/1_1.png b/res/bg/1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7ecb2c65e26dfd004307c2c7d1961b01a22feda8 GIT binary patch literal 5062 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 literal 0 HcmV?d00001 diff --git a/res/chrome/frame1.png b/res/chrome/frame1.png new file mode 100644 index 0000000000000000000000000000000000000000..b8b00cfeba0848e4c2cb9ad328e0596a72432a9e GIT binary patch literal 4594 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 literal 0 HcmV?d00001 diff --git a/res/chrome/frame2.png b/res/chrome/frame2.png new file mode 100644 index 0000000000000000000000000000000000000000..f266ebc9f79d88c60e74c0f75c8e1c388766d445 GIT binary patch literal 4615 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 literal 0 HcmV?d00001 diff --git a/res/tiles/1_2.png b/res/tiles/1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5896b2c42854cb8be40780af36b9e6c3e4043596 GIT binary patch literal 4858 zcmb_f2UrtXyADm7DChzLmTYhVf%F7Oq$$1gQxv4=B$+^#G)Sn@ZCJ2SrHSAo2m%7a zQpHt@uoM*qQAAOYDlSEl>P-;&_ulL7-RIt$=b6koGw*r7_I`6_PTSj>Nl7S5Kp+q) z3v*)!-dUP|hzarj)!>^QArOf^nvs#cF^$8f1Hll8`RT;uKzk=I`KHXHzm}e;kQ8)~ zyXg6gxs0*vf`r85eNIUp#GB)#M?MHEOV_yEGRCQAlW>AtBuT%?2_M~TZm)@Uxf|U& zC%WrwODOi$U|U~s#7tXoCZ{7~vAGJOZLFC*d@@zan*p~&Kx^RuFPf{`sUXJtnr%{wEn z8pag~>j02+%42JVyD6eaZtgbH6wzrGcsBgbHd!zo0qGWr;}Y&Z6@HyE9qYC5YRS=Q zh2&d(M)aK^1SN!-86>>v{WAS@>C1!mmR&ai@yPfrvD3nLMPv5%b{RQqTBU5$e~{vE zH0o^p zSxM>4i)!0GZ}0CH5QuyTZlZ13b+=ps3O{)}-Sg@I>}q+0d0C(MEvqO;i?~pe-y%&# zAc`&zA-fh(CkZzPAo7*>mF|c&1RYma6u&GXj=3l)LM82#yC(LN%ZZQA&b@zjx=ttZ zeqN(*dQ-5wsU-7_{_}^YJ~8bLo3i6Rr|6ibt01-%Hh5%b1ewJtZiSmTiU3(XrRvvy#BJg#8qoeO2@7 z500&BvI)l$LM*oq5p!avvJ)Q#be(_P@re1DNUP%#J(8Iwb5~D2+&bbqTQ%#j za3BO<7u9e1;p!Y}+s3eyJMN#7>5#@IoP#x~G=(?qX~LVTz7>jZ#{t!-W0y}`D{#ci z&Q)Cqjth>RPw36PeuJ9zE=R6N#W}68!hw-|sP4IQxox?AlHBiShVGxCf+ccgTBVyx zJ4$xm>M!l3V?TL++8v;BROYDiqV%F*O~&%2YwaaNpE+?l^Xanbdg&WFJUZME$v!O~ zhgAF$`(*npClw}@Cq@0QR9~w$_sG9vU*}$Dx}3V8A%&Ncl*(#yiX|w5ie|W?pKG5u zb=`h4+w+4D;-O}b?)6}|GPAR}LpNoM5(}L3%k9Rq4QrT@0Rb8SLe8RE=p!<4VUT5PZ!D;HcRDg zsMrv{k*Y|?>UjO(rxQ^*$8P!K&A_QsudutN7*fho!-|u*TGBHzh5iG5xAt=iw`nA& zq^P9WH))FaHomFTI!J|VgR$vONyh{u9?FP`5TawF%c7Z%MqScfp38#VqhB&}$FB zUDtN!-b#f~^S%-L*Y-mXC-cU)y{l{}>7IJ}Kt_41S<%j3+;l;Fn&bH{MDAk8^NzO} z$vQoI>wQc7FI6Vg^s$GkH&h|Gg`6hJmWViC6!spIh-< znORm6R1^43pi!Vb>Uk78DotpYNQy{~sI!Q_XpKmx6jLng#PO3iH&wwgTP%zdvnQu^ zz8$_`pwucJEAevsf=-*3wafv7sB~2Lz31YaRSsDv*xZydt5geRe7-MM5ThVdZ<}p* z=CYIisKqaw!P*Dc)jXfv&I|ij-J|eF8rMEFyEG3rE_$uXo1s`jdwRVy4XgD^b55hUpHvCXC(XI#xD_*IUIwsh9({^?pBdh^G}Uqb z^$xsjk}SA)bgyK9ey?mz!Ki9yrh1^#1fq8tyg;{m(f^>%OG8gxV@_ex&DG?<&_TTy znYZhQ4DUu&AKN4v=rn#HdHcPrC8N#=+m-q5frs~F&2%qpUut}l3^xllJL?mZ+KYc# zu29bK7xyo0ZrbH@bFRo>q2O)t(er6Lkp@{D(vU@W%f0yJ+;{0?w2Rucx*6fs*L)AX zUB*s%G1D`+74z;RRg%NUIx=Znv@)t+a|S+}6rXKI1bgP!O@vpyJM$v(T7A`W!0q0; zs(1O#Ppgw2!9Ny~57~Jt1-_sC7&$)7ieb9nAxu%n3op9`GF4wPYn1D{{I!QC$B&B4 zEleUq43F9`+0OvI%Jt8H+zI@jokga!hx%F*c^W5IuJCG|67T7EXqp6QUEmJdUoU3s#=`CViDVExk2Vo&1a=gE$qGd;^J%U5IdFK3uf zYMQRZTrsPwstfyY)?g&!+2W%aa#wDpo!ufeoEqByx$&LVa?iu!%?q5x#Uav(Z4g5N z!|OQ$tWS_W;m97rTPm9;x*-tK>j=oUXZu#PH&48RKmv~>Bc*G^V%&x4uEH+!f)g8{ z_vB+fiHwfrhpZ?C(~1y6o)d>64|Ko!qP6MBGst1)+}zyLPjeByQudPqQguRm^&k%~ zK&szEGe7G+I}j7mbob7e_H$o!v&LSth9e*@6vh3;6R&UcUUyOU)=nn8vx2mmX|YLG z_X!jIpa9CsG4!4*_eT00tp;L)yQ_|lKFj)%Zq)@oD9*3?I6E$=LFd0Ti?hvLIS`2C zR{kLXNlo7dfrz@%oLsmrHr7Nki-7@gWl^Fav$4ZV-`2zyP@bG>AcGa)?2CuvK0n zZ_K}pgh5v!TpvByKE6Syi;X?hh~)=DwGn7I8HGYYwFw9cKmy1lk|q>`!l02T91@L# zqfkUFfr!IF*M2abIX?=O=wNKRW{fw}gL!kgY$6gF7#N5M#3ERJUPv^7KtQ4}NDKzf zL%=z~OfC=vXL6LkF&Kj!vLB7jrLmY$J|jS4`E&JPJXgQQz+kV_GC6B`;$;jO1hA24 z1d1QiDv&~6$FcqW=&QylWF$xj86cC(;bGD1SYDcJY}Vo5rDZVI(HyQx0MDbf*uIPA zI0dsoqyxxd`TLPUlK`GY3$qJOKD{WlgU z28%#J)ocJVjmhWT!?&}x1T+S?pdO4@Hw+x51;=2WFeoBgi-_k{bY;1@YOb!=dl0ge& zJs8hb1dT=^0w4jSL&Z?x6daiV$5C;3I6&1Q!Esn^st#2fL!lCYZ|jX&WPg4Q`Rl*x znZhFTIMy>q#9#?n3Rwq)Q^`629HinfZ~{r2%u_9y0N?;EJcWSy#%AY7th`9Dw}@~_= BG_SIZE_F) bgPos.y = 0; +} + + +// loop + +void loadBg(){ + drawBg(); +} + +void updateBg(){ + // scrollBg(); +} \ No newline at end of file diff --git a/src/chrome.h b/src/chrome.h new file mode 100644 index 0000000..38f6241 --- /dev/null +++ b/src/chrome.h @@ -0,0 +1,76 @@ +// chrome + +#define CHROME_I 32 + +static void loadChromeI(){ + VDP_loadTileSet(frame1.tileset, CHROME_I, DMA); + VDP_loadTileSet(frame2.tileset, CHROME_I + 1, DMA); + VDP_loadTileSet(frame3.tileset, CHROME_I + 2, DMA); +} + +static void drawFrame(){ + VDP_fillTileMapRect(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, CHROME_I), 0, 0, WIN_W_T, GAME_Y_T - 1); + VDP_fillTileMapRect(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, CHROME_I + 1), 0, GAME_Y_T - 1, WIN_W_T, 1); +} + + +// score + +#define SCORE_X 3 +#define SCORE_Y 2 +#define SCORE_LENGTH 6 + +u32 lastScore; +char scoreStr[SCORE_LENGTH]; + +static void loadScore(){ + VDP_drawText("hi", 1, 1); + VDP_drawText("000000", SCORE_X, 1); + VDP_drawText("sc", 1, 2); + intToStr(score, scoreStr, SCORE_LENGTH); + VDP_drawText(scoreStr, SCORE_X, SCORE_Y); +} + +static void updateScore(){ + if(lastScore != score){ + intToStr(score, scoreStr, SCORE_LENGTH); + VDP_drawText(scoreStr, SCORE_X, SCORE_Y); + lastScore = score; + } + score++; +} + + +// lives + +#define LIVES_Y 4 + +static void loadLives(){ + VDP_drawText("ENERGY 69", 1, LIVES_Y); +} + + +// dialogue + +#define DIALOGUE_Y 24 + +static void loadDialogue(){ + VDP_drawText("FLANDRE", 1, DIALOGUE_Y); + VDP_drawText("\"Are you morbid?", 1, DIALOGUE_Y + 1); + VDP_drawText("Are you morbid?\"", 1, DIALOGUE_Y + 2); +} + + +// loop + +void loadChrome(){ + // loadChromeI(); + // drawFrame(); + // loadScore(); + // loadLives(); + // loadDialogue(); +} + +void updateChrome(){ + // updateScore(); +} \ No newline at end of file diff --git a/src/controls.h b/src/controls.h new file mode 100644 index 0000000..53b7d5f --- /dev/null +++ b/src/controls.h @@ -0,0 +1,21 @@ +// controls + +struct controls { + bool left, right, up, down, a, b, c, start; +}; + +struct controls ctrl; + +void updateControls(u16 joy, u16 changed, u16 state){ + if(joy == JOY_1){ + if(changed){} + ctrl.left = (state & BUTTON_LEFT); + ctrl.right = (state & BUTTON_RIGHT); + ctrl.up = (state & BUTTON_UP); + ctrl.down = (state & BUTTON_DOWN); + ctrl.a = (state & BUTTON_A); + ctrl.b = (state & BUTTON_B); + ctrl.c = (state & BUTTON_C); + ctrl.start = (state & BUTTON_START); + } +} \ No newline at end of file diff --git a/src/global.h b/src/global.h new file mode 100644 index 0000000..5fc4b7f --- /dev/null +++ b/src/global.h @@ -0,0 +1,25 @@ +// globals + +#define WIN_W_T 32 +#define WIN_H_T 28 + +#define WIN_W WIN_W_T * 8 +#define WIN_H WIN_H_T * 8 + +#define GAME_W_T WIN_W_T +#define GAME_H_T WIN_H_T + +#define GAME_W GAME_W_T * 8 +#define GAME_H GAME_H_T * 8 + +#define GAME_X_T 0 +#define GAME_Y_T 0 + +#define GAME_X 0 +#define GAME_Y 0 + +#define CLOCK_LIMIT 32000 + +s16 clock; + +u32 score; \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..1fd341d --- /dev/null +++ b/src/main.c @@ -0,0 +1,51 @@ +// main + +#include +#include + +#include "global.h" +#include "controls.h" +#include "background.h" +#include "tiles.h" +#include "player.h" +#include "chrome.h" + +// game loop + +static void loadInternals(){ + JOY_init(); + JOY_setEventHandler(&updateControls); + SPR_init(127, 0, 0); + VDP_setScreenWidth256(); + VDP_setPalette(PAL1, tile1_1.palette -> data); + VDP_setPalette(PAL2, bg1_1.palette -> data); + VDP_loadFont(font.tileset, DMA); + VDP_setTextPalette(1); +} + +static void loadGame(){ + loadBg(); + loadTiles(); + loadChrome(); +} + +static void updateGame(){ + updateBg(); + updateChrome(); + updateTiles(); + clock++; + if(clock >= CLOCK_LIMIT) clock -= CLOCK_LIMIT; +} + +// main loop + +int main(){ + loadInternals(); + loadGame(); + while(1){ + updateGame(); + SPR_update(); + SYS_doVBlankProcess(); + } + return(0); +} \ No newline at end of file diff --git a/src/player.h b/src/player.h new file mode 100644 index 0000000..4e3e7c9 --- /dev/null +++ b/src/player.h @@ -0,0 +1,32 @@ +// player + +#define PLAYER_OFF FIX16(16) +#define PLAYER_INIT_X FIX16(32) +#define PLAYER_INIT_Y FIX16(32) + +struct playerStruct { + Vect2D_f16 pos; + Sprite* image; +}; +struct playerStruct player; + + +// spawn + +static void spawnPlayer(){ + player.pos.x = 0; + player.pos.y = 0; + player.image = SPR_addSprite(&reimu, + fix16ToInt(fix16Sub(player.pos.x, PLAYER_OFF)), + fix16ToInt(fix16Sub(player.pos.y, PLAYER_OFF)), + TILE_ATTR(PAL1, 0, 0, 0)); +} + + +// loop + +void loadPlayer(){} + +void updatePlayer(){ + spawnPlayer(); +} \ No newline at end of file diff --git a/src/tiles.h b/src/tiles.h new file mode 100644 index 0000000..a1515dc --- /dev/null +++ b/src/tiles.h @@ -0,0 +1,84 @@ +// tiles + +#define TILE_I 128 +#define TILE_W 128 + +#define TILE_COUNT 3072 +u16 tileMap[TILE_COUNT]; + +u16 tileC; + +static void loadTilesI(){ + VDP_loadTileSet(tile1_1.tileset, TILE_I, DMA); +} + + +static void spawnTileRows(s16 y1, s16 y2, bool trig){ + tileC = 0; + for(u16 y = 0; y < GAME_H_T; y++) for(u16 x = 0; x < TILE_W; x++){ + if((y == y1 && tileMap[tileC - TILE_W] > 0 && random() % 4 < 3) || (y == y2 && tileMap[tileC + TILE_W] > 0 && trig)) tileMap[tileC] = 1; + tileC++; + } +} + +static void spawnTiles(){ + + // initial ceiling and floor + tileC = 0; + for(u16 y = 0; y < GAME_H_T; y++) for(u16 x = 0; x < TILE_W; x++){ + tileMap[tileC] = 0; + if(y == 0 || y == 23) tileMap[tileC] = 1; + tileC++; + } + + // first go around + spawnTileRows(1, 22, random() % 4 < 3); + + // second go around + spawnTileRows(2, 21, random() % 4 < 2); + + // third go around + spawnTileRows(3, 20, random() % 4 < 1); + + // draw small + tileC = 0; + for(u16 y = 0; y < GAME_H_T; y++) for(u16 x = 0; x < TILE_W; x++){ + if(tileMap[tileC] > 0) + VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, TILE_I), x, y + 4); + tileC++; + } + + + // if(tileMap[tileC] > 0 && x % 2 == 0 && y % 2 == 0) VDP_drawImageEx(BG_A, &tile1_2, TILE_ATTR_FULL(PAL1, 0, 0, 0, TILE_I + 1), x, y + 4, 0, DMA); + // if(x % 2 == 0 && tileC % 256 < 128 && tileMap[tileC] > 0){ + // VDP_drawImageEx(BG_A, &tile1_2, TILE_ATTR_FULL(PAL1, 0, 0, 0, TILE_I + 1), x, 4, 0, DMA); + // } + // tileC++; + // } + // } + +} + +#define TILE_SPEED -1 +#define TILE_LIMIT -TILE_W * 8 +s16 tilePos[GAME_H_T]; +static void scrollTiles(){ + for(u16 y = 0; y < GAME_H_T; y++){ + tilePos[y] += TILE_SPEED; + if(tilePos[y] <= TILE_LIMIT) tilePos[y] = 0; + } + VDP_setHorizontalScrollTile(BG_A, 4, tilePos, GAME_H_T, DMA); +} + + +// loop + +void loadTiles(){ + // loadTilesI(); + // VDP_setScrollingMode(HSCROLL_TILE, VSCROLL_PLANE); + // spawnTiles(); +} + +void updateTiles(){ + // scrollTiles(); +} \ No newline at end of file