here you go
|
@ -0,0 +1,13 @@
|
||||||
|
.DS_Store
|
||||||
|
**/.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
**/Thumbs.db
|
||||||
|
out.bin
|
||||||
|
out.elf
|
||||||
|
symbol.txt
|
||||||
|
blastem/
|
||||||
|
boot/rom_head.bin
|
||||||
|
boot/sega.o
|
||||||
|
res/resources.o
|
||||||
|
res/resources.h
|
||||||
|
dist/
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
||||||
|
**sweetsdigger**
|
||||||
|
|
||||||
|
touhou pride jam 3 entry\
|
||||||
|
arcade thing for sega genesis influenced by jeff minter's gridrunner and ZUN's highly responsive to prayers
|
||||||
|
|
||||||
|
written with [sgdk](https://github.com/Stephane-D/SGDK)\
|
||||||
|
builds with [marsdev](https://github.com/andwn/marsdev) on mac and linux
|
|
@ -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 ",
|
||||||
|
"SWEETSDIGGER ",
|
||||||
|
"SWEETSDIGGER ",
|
||||||
|
"GM 00000000-00",
|
||||||
|
0x0000,
|
||||||
|
"JD ",
|
||||||
|
0x00000000,
|
||||||
|
0x00100000,
|
||||||
|
0x00FF0000,
|
||||||
|
0x00FFFFFF,
|
||||||
|
" ",
|
||||||
|
0x0000,
|
||||||
|
0x00200000,
|
||||||
|
0x002001FF,
|
||||||
|
" ",
|
||||||
|
"SWEETSDIGGER ",
|
||||||
|
"JUE "
|
||||||
|
};
|
|
@ -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
|
||||||
|
* A<B, so ret 0, rem A
|
||||||
|
move.l %d0,%d1
|
||||||
|
clr.l %d0
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* A==B, so ret 1, rem 0
|
||||||
|
is1:
|
||||||
|
moveq.l #1,%d0
|
||||||
|
clr.l %d1
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* A>B 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
|
|
@ -0,0 +1,3 @@
|
||||||
|
rm res/resources.o res/resources.h out.bin out.elf symbol.txt
|
||||||
|
make
|
||||||
|
./blastem/blastem out.bin
|
|
@ -0,0 +1,2 @@
|
||||||
|
rm out.bin out.elf symbol.txt
|
||||||
|
make
|
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.0 KiB |
|
@ -0,0 +1,94 @@
|
||||||
|
IMAGE font "chrome/font.png" BEST NONE
|
||||||
|
|
||||||
|
IMAGE full "full.png" FAST
|
||||||
|
IMAGE half "half.png" FAST
|
||||||
|
IMAGE least "least.png" FAST
|
||||||
|
|
||||||
|
IMAGE ground1 "bg/ground1.png" FAST
|
||||||
|
IMAGE ground2 "bg/ground2.png" FAST
|
||||||
|
IMAGE ground3 "bg/ground3.png" FAST
|
||||||
|
IMAGE ground4 "bg/ground4.png" FAST
|
||||||
|
IMAGE ground5 "bg/ground5.png" FAST
|
||||||
|
IMAGE ground6 "bg/ground6.png" FAST
|
||||||
|
IMAGE ground7 "bg/ground7.png" FAST
|
||||||
|
IMAGE ground8 "bg/ground8.png" FAST
|
||||||
|
|
||||||
|
IMAGE frame1 "chrome/frame1.png" FAST
|
||||||
|
IMAGE frame2 "chrome/frame2.png" FAST
|
||||||
|
IMAGE frame3 "chrome/frame3.png" FAST
|
||||||
|
IMAGE frame4 "chrome/frame4.png" FAST
|
||||||
|
IMAGE frame5 "chrome/frame5.png" FAST
|
||||||
|
IMAGE bossBar "chrome/bossbar.png" FAST
|
||||||
|
IMAGE chromePlayer "chrome/player.png" FAST
|
||||||
|
IMAGE chromeStage "chrome/stage.png" FAST
|
||||||
|
IMAGE chromeHard "chrome/hard.png" FAST
|
||||||
|
IMAGE chromeEasy "chrome/easy.png" FAST
|
||||||
|
IMAGE chromeEnemy "chrome/enemy.png" FAST
|
||||||
|
|
||||||
|
SPRITE imgPlayer "player/player.png" 3 4 FAST 20
|
||||||
|
SPRITE imgBullet "player/bullet.png" 2 2 FAST
|
||||||
|
|
||||||
|
SPRITE imgYin1 "enemies/yin1.png" 1 1 FAST 5
|
||||||
|
|
||||||
|
SPRITE imgGumdropRed "enemies/gumdropred.png" 2 2 FAST 20
|
||||||
|
SPRITE imgGumdropGreen "enemies/gumdropgreen.png" 2 2 FAST 20
|
||||||
|
SPRITE imgGumdropBlue "enemies/gumdropblue.png" 2 2 FAST 20
|
||||||
|
SPRITE imgGumdropYellow "enemies/gumdropyellow.png" 2 2 FAST 20
|
||||||
|
|
||||||
|
SPRITE imgPeppermintRed "enemies/peppermintred.png" 2 2 FAST 30
|
||||||
|
SPRITE imgPeppermintGreen "enemies/peppermintgreen.png" 2 2 FAST 10
|
||||||
|
SPRITE imgPeppermintBlue "enemies/peppermintblue.png" 2 2 FAST 10
|
||||||
|
SPRITE imgPeppermintYellow "enemies/peppermintyellow.png" 2 2 FAST 10
|
||||||
|
|
||||||
|
SPRITE imgSpider "enemies/spider.png" 2 2 FAST 20
|
||||||
|
|
||||||
|
IMAGE cake "enemies/cake.png" FAST
|
||||||
|
IMAGE parfait "enemies/parfait.png" FAST
|
||||||
|
IMAGE waffle "enemies/waffle.png" FAST
|
||||||
|
IMAGE roll "enemies/roll.png" FAST
|
||||||
|
|
||||||
|
SPRITE imgSmallRedBullet "bullets/smallred.png" 1 1 FAST 5
|
||||||
|
SPRITE imgSmallBlueBullet "bullets/smallblue.png" 1 1 FAST 5
|
||||||
|
SPRITE imgSmallPinkBullet "bullets/smallpink.png" 1 1 FAST 5
|
||||||
|
|
||||||
|
SPRITE imgBigRedBullet "bullets/bigred.png" 2 2 FAST 5
|
||||||
|
SPRITE imgBigBlueBullet "bullets/bigblue.png" 2 2 FAST 5
|
||||||
|
SPRITE imgBigPinkBullet "bullets/bigpink.png" 2 2 FAST 5
|
||||||
|
|
||||||
|
SPRITE imgExplosionPlayer "explosions/player.png" 3 3 FAST 5
|
||||||
|
|
||||||
|
IMAGE girl "chrome/girl.png" FAST
|
||||||
|
|
||||||
|
|
||||||
|
IMAGE startTop "start/top.png" FAST
|
||||||
|
IMAGE startGradient "start/gradient.png" FAST
|
||||||
|
IMAGE startBottom "start/bottom.png" FAST
|
||||||
|
IMAGE startLogo "start/logo.png" FAST
|
||||||
|
IMAGE startLogoV "start/logov.png" FAST
|
||||||
|
IMAGE startAbout "start/about.png" FAST
|
||||||
|
IMAGE startAbout2 "start/about2.png" FAST
|
||||||
|
|
||||||
|
SPRITE startBoddy1 "start/boddy.png" 7 4 FAST 5
|
||||||
|
SPRITE startBoddy2 "start/boddy2.png" 7 4 FAST 5
|
||||||
|
|
||||||
|
XGM bgmStart "bgm/start.vgm" 0
|
||||||
|
XGM bgmStage1 "bgm/stage1.vgm" 0
|
||||||
|
XGM bgmStage2 "bgm/stage2.vgm" 0
|
||||||
|
|
||||||
|
WAV sfxMenuSelect "sfx/menuselect.wav" 5
|
||||||
|
WAV sfxMenuChoose "sfx/menuchoose.wav" 5
|
||||||
|
WAV sfxStartGame "sfx/startgame.wav" 5
|
||||||
|
WAV sfxZoneOver "sfx/zoneover.wav" 5
|
||||||
|
|
||||||
|
WAV sfxPlayerHit "sfx/playerhit.wav" 5
|
||||||
|
WAV sfxPlayerShot "sfx/playershot.wav" 5
|
||||||
|
|
||||||
|
WAV sfxBullet1 "sfx/bullet1.wav" 5
|
||||||
|
|
||||||
|
WAV sfxExplosion1 "sfx/explosion1.wav" 5
|
||||||
|
WAV sfxExplosion2 "sfx/explosion2.wav" 5
|
||||||
|
WAV sfxExplosion3 "sfx/explosion3.wav" 5
|
||||||
|
|
||||||
|
WAV sfxGameOver "sfx/gameover.wav" 5
|
||||||
|
WAV sfxBeatGame "sfx/beatgame.wav" 5
|
||||||
|
|
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 4.0 KiB |
|
@ -0,0 +1,48 @@
|
||||||
|
#include <genesis.h>
|
||||||
|
#include <resources.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "background.h"
|
||||||
|
|
||||||
|
|
||||||
|
void resetBackground(){
|
||||||
|
for(s8 y = 0; y < BG_TILES_HEIGHT; y++){
|
||||||
|
for(s8 x = 0; x < BG_TILES_WIDTH; x++){
|
||||||
|
if(x % 8 == 0 && y % 8 == 0){
|
||||||
|
if(currentZone < 5) VDP_drawImageEx(BG_B, &ground1, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone == 5) VDP_drawImageEx(BG_B, &ground2, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone > 5 && currentZone < 10) VDP_drawImageEx(BG_B, &ground3, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone == 10) VDP_drawImageEx(BG_B, &ground4, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone > 10 && currentZone < 15) VDP_drawImageEx(BG_B, &ground5, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone == 15) VDP_drawImageEx(BG_B, &ground6, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone > 15 && currentZone < 20) VDP_drawImageEx(BG_B, &ground7, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
else if(currentZone == 20) VDP_drawImageEx(BG_B, &ground8, TILE_ATTR_FULL(PAL1, 0, 0, 0, 16), x, y, 0, DMA_QUEUE);
|
||||||
|
}
|
||||||
|
VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, 11), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stage
|
||||||
|
|
||||||
|
void loadBackgroundStage(){
|
||||||
|
for(s8 i = 0; i < BG_SCROLL_WIDTH; i++){
|
||||||
|
backgroundSpeeds[i] = i < 8 ? BG_SCROLL_WIDTH - i - 2 : i - 1;
|
||||||
|
backgroundSpeeds[i]--;
|
||||||
|
}
|
||||||
|
VDP_setScrollingMode(HSCROLL_PLANE, VSCROLL_2TILE);
|
||||||
|
resetBackground();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBackgroundStage(){
|
||||||
|
for(s8 i = 0; i < BG_SCROLL_WIDTH; i++) backgroundScrolls[i] -= fix16ToRoundedInt(FIX16(backgroundSpeeds[i] / 2)) - 1;
|
||||||
|
VDP_setVerticalScrollTile(BG_B, 0, backgroundScrolls, BG_SCROLL_WIDTH, DMA_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop
|
||||||
|
|
||||||
|
void updateBackground(){
|
||||||
|
if(gameStarting) loadBackgroundStage();
|
||||||
|
else updateBackgroundStage();
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#define BG_TILES_WIDTH 32
|
||||||
|
#define BG_TILES_HEIGHT 32
|
||||||
|
#define BG_SCROLL_WIDTH 16
|
||||||
|
|
||||||
|
s16 backgroundY;
|
||||||
|
s16 backgroundScrolls[BG_SCROLL_WIDTH],
|
||||||
|
backgroundSpeeds[BG_SCROLL_WIDTH];
|
||||||
|
|
||||||
|
void loadBackgroundStage(),
|
||||||
|
loadBackgroundBoss(),
|
||||||
|
loadBackgroundTiles(),
|
||||||
|
resetBackground(),
|
||||||
|
updateBackgroundStage(),
|
||||||
|
updateBackgroundBoss(),
|
||||||
|
updateBackground();
|
|
@ -0,0 +1,565 @@
|
||||||
|
#include <genesis.h>
|
||||||
|
#include <resources.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "enemies.h"
|
||||||
|
#include "explosion.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "chrome.h"
|
||||||
|
#include "boss.h"
|
||||||
|
|
||||||
|
|
||||||
|
// shooting
|
||||||
|
|
||||||
|
void bossPatternOne(){
|
||||||
|
if(bossClock % 10 == 0 && bossClock % 60 <= 50){
|
||||||
|
if(bossClock % 60 == 0) bossInt1 = random() % 1024;
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 120 < 60 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 1,
|
||||||
|
.angle = bossInt1,
|
||||||
|
.speed = FIX16(5)
|
||||||
|
};
|
||||||
|
for(s8 b = 0; b < 6; b++){
|
||||||
|
if(bSpawn.angle % 1024 >= 0 && bSpawn.angle % 1024 <= 512) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 170;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1 += bossClock % 120 < 60 ? 32 : -32;
|
||||||
|
if(bossClock % 30 == 0) spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
if(bossClock % 20 == 10){
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 4, 96, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 4, 16, FALSE);
|
||||||
|
bSpawn.type = 4;
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternTwo(){
|
||||||
|
if(bossClock % 60 == 0){
|
||||||
|
bossInt1 = 240 + random() % 32;
|
||||||
|
bossInt2 = bossClock % 120 == 0 ? 48 : -48;
|
||||||
|
bossInt3 = bossInt2 / 2;
|
||||||
|
}
|
||||||
|
if(bossClock % 8 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 120 < 60 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 4,
|
||||||
|
.angle = bossInt1 - bossInt2,
|
||||||
|
.speed = FIX16(5.5)
|
||||||
|
};
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 3; b++){
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.speed = fix16Add(bSpawn.speed, FIX16(1.5));
|
||||||
|
bSpawn.angle += bossInt3;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1 += bossInt2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternThree(){
|
||||||
|
if(bossClock % 60 < 18 && bossClock % 6 == 0){
|
||||||
|
if(bossClock % 60 == 0){
|
||||||
|
bossInt1 = 3;
|
||||||
|
bossInt2 = bossClock % 120 == 0 ? 68 : -68;
|
||||||
|
bossInt3 = bossClock % 120 == 0 ? 224 : 288;
|
||||||
|
bossFix1 = FIX16(bossClock % 120 < 60 ? 208 : 48);
|
||||||
|
}
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = bossFix1,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 3,
|
||||||
|
.angle = bossInt3,
|
||||||
|
.speed = FIX16(bossInt1)
|
||||||
|
};
|
||||||
|
if(bossClock % 60 == 0) spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 4; b++){
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += bossInt2;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1++;
|
||||||
|
}
|
||||||
|
else if(bossClock % 60 >= 30 && bossClock % 5 == 0){
|
||||||
|
if(bossClock % 60 == 30){
|
||||||
|
bossFix1 = FIX16(32 + random() % 192);
|
||||||
|
spawnExplosion(fix16ToInt(bossFix1), fix16ToInt(BOSS_B_Y), FALSE);
|
||||||
|
}
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = bossFix1,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 2
|
||||||
|
};
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 4, 96, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 4, 16, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternFour(){
|
||||||
|
if(bossClock % 60 <= 10 && bossClock % 5 == 0){
|
||||||
|
if(bossClock % 60 == 0) bossInt1 = 4;
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.speed = FIX16(bossInt1)
|
||||||
|
};
|
||||||
|
bSpawn.angle = bossClock % 60 == 5 ? 32 : 0;
|
||||||
|
bSpawn.type = bossClock % 60 == 0 ? 3 : 4;
|
||||||
|
for(s8 b = 0; b < (bossClock % 60 == 5 ? 5 : 6); b++){
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
if(b > 0) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1++;
|
||||||
|
} else if(bossClock % 60 >= 30 && bossClock % 5 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 10 == 0 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 1
|
||||||
|
};
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 4, 96, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 4, 16, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternFive(){
|
||||||
|
if(bossClock % 60 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.angle = random() % 1024,
|
||||||
|
.speed = FIX16(4),
|
||||||
|
.type = 4
|
||||||
|
};
|
||||||
|
for(s8 b = 0; b < 16; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 0 && bSpawn.angle % 1024 < 512){
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
}
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
} else if(bossClock % 60 >= 30 && bossClock % 60 < 45 && bossClock % 5 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = bossClock % 60 >= 38 ? 3 : 4
|
||||||
|
};
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 5, 128, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 5, 16, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
if(bossClock % 60 >= 30 && bossClock % 5 == 3){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 30 < 15 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = bossClock % 15 > 6 ? 1 : 2
|
||||||
|
};
|
||||||
|
if(bossClock % 15 == 0){
|
||||||
|
bossFix1 = bSpawn.x;
|
||||||
|
bossFix2 = bSpawn.y;
|
||||||
|
}
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bossFix1, bossFix2, 4, 32, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bossFix1, bossFix2, 4, 16, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternSix(){
|
||||||
|
if(bossClock % 5 == 0 && bossClock % 120 < 110){
|
||||||
|
if(bossClock % 120 == 0){
|
||||||
|
bossInt1 = 0 + random() % 32;
|
||||||
|
bossInt2 = 512 - random() % 32;
|
||||||
|
bossInt3 = 1;
|
||||||
|
}
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.angle = bossInt1,
|
||||||
|
.speed = FIX16(7),
|
||||||
|
.type = bossClock % 240 < 120 ? 4 : 2
|
||||||
|
};
|
||||||
|
if(bossClock % 10 == 0) spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 2; b++){
|
||||||
|
if(bSpawn.angle % 1024 < 512) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 512;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bSpawn.x = FIX16(208);
|
||||||
|
bSpawn.angle = bossInt2;
|
||||||
|
if(bossClock % 10 == 5) spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 2; b++){
|
||||||
|
if((bSpawn.angle < 0 && abs(bSpawn.angle) % 1024 > 512) || (bSpawn.angle >= 0 && bSpawn.angle < 512)) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 512;
|
||||||
|
}
|
||||||
|
bossInt1 += 5 * bossInt3;
|
||||||
|
bossInt2 -= 10 * bossInt3;
|
||||||
|
bossInt3++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternSeven(){
|
||||||
|
if(bossClock % 120 < 100){
|
||||||
|
if(bossClock % 120 == 0) bossInt1 = 0;
|
||||||
|
if(bossClock % 15 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.angle = 0 + bossInt1,
|
||||||
|
.speed = FIX16(8),
|
||||||
|
.type = 2
|
||||||
|
};
|
||||||
|
for(s8 b = 0; b < 16; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 32 && bSpawn.angle % 1024 < 480) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1 += 24;
|
||||||
|
}
|
||||||
|
if(bossClock % 10 == 5){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 3
|
||||||
|
};
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 5, 128, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 5, 16, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternEight(){
|
||||||
|
if(bossClock % 30 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 60 == 0 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.angle = random() % 1024,
|
||||||
|
.speed = FIX16(8),
|
||||||
|
.type = 1
|
||||||
|
};
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 8; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 0 && bSpawn.angle % 1024 < 512){
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 48;
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
} else bSpawn.angle += 48;
|
||||||
|
bSpawn.angle += 80;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
} else if(bossClock % 30 == 15){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 60 == 15 ? 192 : 64),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.angle = random() % 1024,
|
||||||
|
.speed = FIX16(6),
|
||||||
|
.type = 4
|
||||||
|
};
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 16; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 0 && bSpawn.angle % 1024 < 512) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternNine(){
|
||||||
|
if(bossClock % 60 < 40 && bossClock % 6 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(64 + random() % 128),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 3
|
||||||
|
};
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 4; b++){
|
||||||
|
bSpawn.type = b % 2 == 0 ? 3 : 4;
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 5, 192, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 5, 8, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternTen(){
|
||||||
|
if(bossClock % 15 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(64 + random() % 128),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = bossClock % 30 == 0 ? 4 : 3,
|
||||||
|
.angle = random() % 1024,
|
||||||
|
.speed = FIX16(bossClock % 30 == 0 ? 7 : 5)
|
||||||
|
};
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 16; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 0 && bSpawn.angle % 1024 < 512) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
else if(bossClock % 60 > 15 && bossClock % 60 < 30 && bossClock % 2 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = bossClock % 4 == 0 ? 2 : 1
|
||||||
|
};
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, 6, 96, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, 6, 8, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternEleven(){
|
||||||
|
if(bossClock % 60 < 30 && bossClock % 4 == 0){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 120 < 60 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 3
|
||||||
|
};
|
||||||
|
if(bossClock % 60 == 0) bossInt1 = 4;
|
||||||
|
if(bossClock % 60 == 0 || bossClock % 60 == 12) spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
bSpawn.velocityX = honeEnemyBullet(bSpawn.x, bSpawn.y, bossInt1, 64, TRUE);
|
||||||
|
bSpawn.velocityY = honeEnemyBullet(bSpawn.x, bSpawn.y, bossInt1, 8, FALSE);
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1++;
|
||||||
|
}
|
||||||
|
if(bossClock % 15 == 5){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 2,
|
||||||
|
.angle = bossClock % 30 == 5 ? 32 : 0,
|
||||||
|
.speed = FIX16(6)
|
||||||
|
};
|
||||||
|
for(s8 b = 0; b < 16; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 0 && bSpawn.angle % 1024 < 512) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternTwelve(){
|
||||||
|
if(bossClock % 60 < 35 && bossClock % 6 == 0){
|
||||||
|
if(bossClock % 60 == 0){
|
||||||
|
bossInt1 = 320;
|
||||||
|
bossInt2 = 192;
|
||||||
|
}
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 12 == 0 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.speed = FIX16(7),
|
||||||
|
.angle = bossClock % 12 == 0 ? bossInt2 : bossInt1,
|
||||||
|
.type = 4
|
||||||
|
};
|
||||||
|
for(s8 b = 0; b < 4; b++){
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += bossClock % 12 == 0 ? 64 : -64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1 -= 8;
|
||||||
|
bossInt2 += 8;
|
||||||
|
}
|
||||||
|
if(bossClock % 3 == 1 && bossClock % 30 < 15){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 1
|
||||||
|
};
|
||||||
|
if(bossClock % 30 == 1){
|
||||||
|
bossFix1 = honeEnemyBullet(bSpawn.x, bSpawn.y, 7, 0, TRUE);
|
||||||
|
bossFix2 = honeEnemyBullet(bSpawn.x, bSpawn.y, 7, 0, FALSE);
|
||||||
|
}
|
||||||
|
bSpawn.velocityX = bossFix1;
|
||||||
|
bSpawn.velocityY = bossFix2;
|
||||||
|
spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bossPatternThirteen(){
|
||||||
|
if(bossClock % 5 == 0){
|
||||||
|
if(bossClock == 0){
|
||||||
|
bossInt1 = 0;
|
||||||
|
bossInt2 = 1024;
|
||||||
|
}
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = FIX16(bossClock % 10 == 0 ? 208 : 48),
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = 3,
|
||||||
|
.angle = bossClock % 10 == 0 ? bossInt2 : bossInt1,
|
||||||
|
.speed = FIX16(6)
|
||||||
|
};
|
||||||
|
spawnExplosion(fix16ToInt(bSpawn.x), fix16ToInt(bSpawn.y), FALSE);
|
||||||
|
for(s8 b = 0; b < 5; b++){
|
||||||
|
if(bSpawn.angle % 1024 > 0 && bSpawn.angle % 1024 < 512) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 205;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 0, SOUND_PCM_CH3);
|
||||||
|
bossInt1 += 19;
|
||||||
|
bossInt2 -= 15;
|
||||||
|
if(bossInt1 >= 1024) bossInt1 = 0;
|
||||||
|
if(bossInt2 <= 0) bossInt2 = 1024;
|
||||||
|
}
|
||||||
|
if(bossClock % 60 == 35 || bossClock % 60 == 36){
|
||||||
|
struct bulletSpawner bSpawn = {
|
||||||
|
.x = BOSS_B_X,
|
||||||
|
.y = BOSS_B_Y,
|
||||||
|
.type = bossClock % 60 == 35 ? 2 : 1,
|
||||||
|
.angle = bossClock % 60 == 35 ? 0 : 32,
|
||||||
|
.speed = FIX16(bossClock % 60 == 35 ? 5 : 8)
|
||||||
|
};
|
||||||
|
for(s8 b = 0; b < 8; b++){
|
||||||
|
if(b > 0 && (bossClock % 60 == 35 || (bossClock % 60 == 36 && b < 7))) spawnEnemyBullet(bSpawn, eUpdate);
|
||||||
|
bSpawn.angle += 64;
|
||||||
|
}
|
||||||
|
XGM_startPlayPCM(SFX_BULLET_1, 1, SOUND_PCM_CH3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hitBossPattern(u8 i){
|
||||||
|
if(!hitBossPatterns[i]){
|
||||||
|
hitBossPatterns[i] = TRUE;
|
||||||
|
bossClock = BOSS_SWITCH_TIME;
|
||||||
|
killBullets = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shootBoss(){
|
||||||
|
switch(bossType){
|
||||||
|
case 1:
|
||||||
|
if(bossHealth < 50){
|
||||||
|
hitBossPattern(0);
|
||||||
|
if(bossClock >= 0) bossPatternTwo();
|
||||||
|
} else if(bossClock >= 0) bossPatternOne();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(bossHealth < 50){
|
||||||
|
hitBossPattern(2);
|
||||||
|
if(bossClock >= 0) bossPatternFour();
|
||||||
|
} else if(bossHealth < 100){
|
||||||
|
hitBossPattern(1);
|
||||||
|
if(bossClock >= 0) bossPatternFive();
|
||||||
|
} else if(bossClock >= 0) bossPatternThree();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if(bossHealth < 50){
|
||||||
|
hitBossPattern(4);
|
||||||
|
if(bossClock >= 0) bossPatternEight();
|
||||||
|
} else if(bossHealth < 100){
|
||||||
|
hitBossPattern(3);
|
||||||
|
if(bossClock >= 0) bossPatternSeven();
|
||||||
|
} else if(bossClock >= 0) bossPatternSix();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if(bossHealth < 50){
|
||||||
|
hitBossPattern(8);
|
||||||
|
if(bossClock >= 0) bossPatternThirteen();
|
||||||
|
} else if(bossHealth < 100){
|
||||||
|
hitBossPattern(7);
|
||||||
|
if(bossClock >= 0) bossPatternTwelve();
|
||||||
|
} else if(bossHealth < 150){
|
||||||
|
hitBossPattern(6);
|
||||||
|
if(bossClock >= 0) bossPatternEleven();
|
||||||
|
} else if(bossHealth < 200){
|
||||||
|
hitBossPattern(5);
|
||||||
|
if(bossClock >= 0) bossPatternTen();
|
||||||
|
} else if(bossClock >= 0) bossPatternNine();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// collision
|
||||||
|
|
||||||
|
void hitBoss(){
|
||||||
|
bossHealth--;
|
||||||
|
// bossHealth -= 10;
|
||||||
|
if(bossHealth <= 0) finishBoss();
|
||||||
|
}
|
||||||
|
|
||||||
|
void collideBoss(){
|
||||||
|
if(bombing && bossClock % 10 == 0) bossHealth--;
|
||||||
|
for(s16 j = 0; j < PLAYER_BULLET_LIMIT; j++) if(playerBullets[j].active) {
|
||||||
|
bossCollisionDistance = getApproximatedDistance(
|
||||||
|
fix32Sub(fix16ToFix32(playerBullets[j].pos.x), BOSS_X),
|
||||||
|
fix32Sub(fix16ToFix32(playerBullets[j].pos.y), BOSS_Y));
|
||||||
|
if(bossCollisionDistance < BOSS_COLLIDE_OFFSET){
|
||||||
|
spawnExplosion(fix16ToInt(playerBullets[j].pos.x), fix16ToInt(playerBullets[j].pos.y), TRUE);
|
||||||
|
hitBoss();
|
||||||
|
removePlayerBullet(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishBoss(){
|
||||||
|
bossActive = FALSE;
|
||||||
|
bossLoaded = FALSE;
|
||||||
|
zoneOver = TRUE;
|
||||||
|
bossClock = BOSS_SWITCH_TIME;
|
||||||
|
for(s8 x = 0; x < 8; x++) for(s8 y = 0; y < 8; y++) VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, 11), x + 12, y + 4);
|
||||||
|
for(s8 x = 0; x < BOSS_TILE_COUNT; x++) VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, 11), x + 1, BOSS_TILE_Y);
|
||||||
|
|
||||||
|
|
||||||
|
// VDP_drawImageEx(BG_A, &chromeEnemy, TILE_ATTR_FULL(PAL1, 1, 0, 0, 190), 1, BOSS_TILE_Y, 0, DMA_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop
|
||||||
|
|
||||||
|
void loadBoss(){
|
||||||
|
bossType++;
|
||||||
|
// bossType = 4;
|
||||||
|
switch(bossType){
|
||||||
|
case 1:
|
||||||
|
bossHealth = 100;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
bossHealth = 150;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bossHealth = 150;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
bossHealth = 250;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bossLoaded = FALSE;
|
||||||
|
bossActive = TRUE;
|
||||||
|
bossMax = bossHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBoss(){
|
||||||
|
if(bossActive) {
|
||||||
|
if(bossLoaded){
|
||||||
|
collideBoss();
|
||||||
|
if(!gameOver) shootBoss();
|
||||||
|
} else if(bossClock == BOSS_LOAD_TIME){
|
||||||
|
VDP_drawImageEx(BG_A,
|
||||||
|
(bossType == 1 ? &roll : (bossType == 2 ? &waffle : (bossType == 3 ? &cake : &parfait))),
|
||||||
|
TILE_ATTR_FULL(PAL1, 0, 0, 0, 92), 12, 4, 0, DMA_QUEUE);
|
||||||
|
bossLoaded = TRUE;
|
||||||
|
bossClock = -1;
|
||||||
|
}
|
||||||
|
bossClock++;
|
||||||
|
if(bossClock >= 600) bossClock = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#define BOSS_LOAD_TIME 15
|
||||||
|
|
||||||
|
#define BOSS_X FIX32(16 * 8)
|
||||||
|
#define BOSS_Y FIX32(8 * 8)
|
||||||
|
#define BOSS_B_X fix32ToFix16(BOSS_X)
|
||||||
|
#define BOSS_B_Y fix32ToFix16(BOSS_Y)
|
||||||
|
#define BOSS_X_OFFSET FIX16(8 * 10)
|
||||||
|
#define BOSS_X_OFFSET_NEG fix16Sub(FIX16(0), BOSS_X_OFFSET)
|
||||||
|
|
||||||
|
#define BOSS_COLLIDE_OFFSET FIX32(40)
|
||||||
|
|
||||||
|
#define BOSS_SWITCH_TIME -90
|
||||||
|
|
||||||
|
s16 bossClock, bossInt1, bossInt2, bossInt3, bossType, bossHealth, bossMax;
|
||||||
|
f16 bossFix1, bossFix2;
|
||||||
|
s32 bossCollisionDistance;
|
||||||
|
|
||||||
|
bool hitBossPatterns[8];
|
||||||
|
bool bossActive, bossLoaded;
|
||||||
|
|
||||||
|
void loadBoss(),
|
||||||
|
|
||||||
|
bossPatternOne(),
|
||||||
|
bossPatternTwo(),
|
||||||
|
|
||||||
|
bossPatternThree(),
|
||||||
|
bossPatternFour(),
|
||||||
|
bossPatternFive(),
|
||||||
|
|
||||||
|
bossPatternSix(),
|
||||||
|
bossPatternSeven(),
|
||||||
|
bossPatternEight(),
|
||||||
|
|
||||||
|
bossPatternNine(),
|
||||||
|
bossPatternTen(),
|
||||||
|
bossPatternEleven(),
|
||||||
|
bossPatternTwelve(),
|
||||||
|
bossPatternThirteen(),
|
||||||
|
|
||||||
|
hitBossPattern(u8),
|
||||||
|
|
||||||
|
drawBoss(),
|
||||||
|
collideBoss(),
|
||||||
|
hitBoss(),
|
||||||
|
finishBoss(),
|
||||||
|
shootBoss(),
|
||||||
|
updateBoss();
|
|
@ -0,0 +1,195 @@
|
||||||
|
#include <genesis.h>
|
||||||
|
#include <resources.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "enemies.h"
|
||||||
|
#include "centipede.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "pod.h"
|
||||||
|
#include "explosion.h"
|
||||||
|
|
||||||
|
|
||||||
|
// spawn
|
||||||
|
|
||||||
|
void spawnCentipede(){}
|
||||||
|
|
||||||
|
|
||||||
|
// movement
|
||||||
|
|
||||||
|
void moveCentipede(s16 i){
|
||||||
|
if(centipedes[i].flipping){
|
||||||
|
centipedes[i].pos.y = fix16Add(centipedes[i].pos.y, (centipedes[i].flippedY ? fix16Sub(FIX16(0), centipedes[i].speed) : centipedes[i].speed));
|
||||||
|
centipedes[i].flipClock++;
|
||||||
|
if((centipedes[i].flippedY && centipedes[i].pos.y <= centipedes[i].nextY) || (!centipedes[i].flippedY && centipedes[i].pos.y >= centipedes[i].nextY)){
|
||||||
|
centipedes[i].flipping = FALSE;
|
||||||
|
centipedes[i].pos.y = centipedes[i].nextY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
centipedes[i].pos.x = fix16Add(centipedes[i].pos.x, (centipedes[i].flippedX ? fix16Sub(FIX16(0), centipedes[i].speed) : centipedes[i].speed));
|
||||||
|
if(centipedes[i].pos.x >= CENTIPEDE_LIMIT_RIGHT || centipedes[i].pos.x <= CENTIPEDE_LIMIT_LEFT){
|
||||||
|
centipedes[i].flippedX = centipedes[i].pos.x >= CENTIPEDE_LIMIT_RIGHT;
|
||||||
|
if(!centipedes[i].flippedY && centipedes[i].pos.y >= CENTIPEDE_LIMIT_BOTTOM){
|
||||||
|
centipedes[i].flippedY = TRUE;
|
||||||
|
if(i == lastCentipede && lastCentipede < centipedeCount){
|
||||||
|
struct podSpawner pSpawn = {
|
||||||
|
.x = FIX16(fix16ToInt(centipedes[i].pos.x) / 16 * 16),
|
||||||
|
.y = FIX16(fix16ToInt(centipedes[i].pos.y) / 16 * 16),
|
||||||
|
.random = FALSE
|
||||||
|
};
|
||||||
|
spawnPod(pSpawn);
|
||||||
|
}
|
||||||
|
// can add another head
|
||||||
|
}else if(centipedes[i].flippedY && centipedes[i].pos.y <= CENTIPEDE_LIMIT_TOP) centipedes[i].flippedY = FALSE;
|
||||||
|
centipedes[i].flipping = TRUE;
|
||||||
|
centipedes[i].nextY = centipedes[i].flippedY ? fix16Sub(centipedes[i].pos.y, FIX16(16)) : fix16Add(centipedes[i].pos.y, FIX16(16));
|
||||||
|
}
|
||||||
|
if(centipedes[i].flipClock > 0) centipedes[i].flipClock = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// change sprite
|
||||||
|
|
||||||
|
void animateCentipede(s16 i){
|
||||||
|
if(centipedes[i].definition > 0){
|
||||||
|
switch(centipedes[i].definition){
|
||||||
|
case 1:
|
||||||
|
SPR_setDefinition(centipedes[i].image, &imgGumdropRed);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
SPR_setDefinition(centipedes[i].image, &imgGumdropGreen);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
SPR_setDefinition(centipedes[i].image, &imgGumdropBlue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
centipedes[i].definition = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// collision against centipede
|
||||||
|
|
||||||
|
void hitCentipede(s16 i){
|
||||||
|
spawnExplosion(fix16ToInt(centipedes[i].pos.x), fix16ToInt(centipedes[i].pos.y), TRUE);
|
||||||
|
centipedes[i].health -= CENTIPEDE_HIT;
|
||||||
|
XGM_startPlayPCM(random() % 2 < 1 ? SFX_EXPLOSION_1 : SFX_EXPLOSION_2, 1, SOUND_PCM_CH4);
|
||||||
|
currentScore += 7;
|
||||||
|
if(centipedes[i].health < 0){
|
||||||
|
struct podSpawner pSpawn = {
|
||||||
|
.x = FIX16(fix16ToInt(centipedes[i].pos.x) / 16 * 16),
|
||||||
|
.y = FIX16(fix16ToInt(centipedes[i].pos.y) / 16 * 16),
|
||||||
|
.random = FALSE
|
||||||
|
};
|
||||||
|
spawnPod(pSpawn);
|
||||||
|
destroyCentipede(i);
|
||||||
|
currentScore += currentZone >= 10 ? 2500 : 1500;
|
||||||
|
XGM_startPlayPCM(SFX_EXPLOSION_3, 2, SOUND_PCM_CH4);
|
||||||
|
} else if(centipedes[i].health < 33) centipedes[i].definition = 1;
|
||||||
|
else if(centipedes[i].health < 67) centipedes[i].definition = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnCentipede(s16 i, s16 j){
|
||||||
|
centipedes[i].flippedX = centipedes[i].flippedX ? FALSE : TRUE;
|
||||||
|
centipedes[i].turning = TRUE;
|
||||||
|
centipedes[i].turnClock = 0;
|
||||||
|
if(centipedes[i].pos.x < pods[j].pos.x) centipedes[i].pos.x = fix16Sub(pods[j].pos.x, FIX16(8));
|
||||||
|
else if(centipedes[i].pos.x >= pods[j].pos.x) centipedes[i].pos.x = fix16Add(pods[j].pos.x, FIX16(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void collideCentipede(s16 i){
|
||||||
|
// against pods
|
||||||
|
for(s16 j = 0; j < POD_COUNT; j++) if(pods[j].active) {
|
||||||
|
centipedePodCheck = getApproximatedDistance(
|
||||||
|
fix16ToFix32(centipedes[i].pos.x) - fix16ToFix32(pods[j].pos.x),
|
||||||
|
fix16ToFix32(centipedes[i].pos.y) - fix16ToFix32(pods[j].pos.y));
|
||||||
|
if(centipedePodCheck < CENTIPEDE_POD_OFFSET) turnCentipede(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bombing && centipedes[i].clock % 20 == 0) hitCentipede(i);
|
||||||
|
// against player bullet
|
||||||
|
centipedeCollided = FALSE;
|
||||||
|
for(s16 j = 0; j < PLAYER_BULLET_LIMIT; j++) if(playerBullets[j].active) {
|
||||||
|
if(fix16Sub(playerBullets[j].pos.y, CENTIPEDE_BULLET_OFFSET) <= fix16Add(centipedes[i].pos.y, CENTIPEDE_COLLIDE_OFFSET) &&
|
||||||
|
fix16Add(playerBullets[j].pos.y, CENTIPEDE_BULLET_OFFSET) >= fix16Sub(centipedes[i].pos.y, CENTIPEDE_COLLIDE_OFFSET) &&
|
||||||
|
fix16Sub(playerBullets[j].pos.x, CENTIPEDE_BULLET_OFFSET) <= fix16Add(centipedes[i].pos.x, CENTIPEDE_COLLIDE_OFFSET) &&
|
||||||
|
fix16Add(playerBullets[j].pos.x, CENTIPEDE_BULLET_OFFSET) >= fix16Sub(centipedes[i].pos.x, CENTIPEDE_COLLIDE_OFFSET)){
|
||||||
|
centipedeCollided = TRUE;
|
||||||
|
hitCentipede(i);
|
||||||
|
removePlayerBullet(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// against player
|
||||||
|
if(centipedes[i].clock % 4 == 0 && (!centipedeCollided && centipedes[i].pos.y >= fix16Sub(playerPos.y, FIX16(32)))){
|
||||||
|
if(fix16Sub(playerPos.y, CENTIPEDE_PLAYER_OFFSET) <= fix16Add(centipedes[i].pos.y, CENTIPEDE_COLLIDE_OFFSET) &&
|
||||||
|
fix16Add(playerPos.y, CENTIPEDE_PLAYER_OFFSET) >= fix16Sub(centipedes[i].pos.y, CENTIPEDE_COLLIDE_OFFSET) &&
|
||||||
|
fix16Sub(playerPos.x, CENTIPEDE_PLAYER_OFFSET) <= fix16Add(centipedes[i].pos.x, CENTIPEDE_COLLIDE_OFFSET) &&
|
||||||
|
fix16Add(playerPos.x, CENTIPEDE_PLAYER_OFFSET) >= fix16Sub(centipedes[i].pos.x, CENTIPEDE_COLLIDE_OFFSET)){
|
||||||
|
// hitCentipede(i);
|
||||||
|
// turnCentipede(i);
|
||||||
|
// hit player here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyCentipede(s16 i){
|
||||||
|
centipedes[i].active = FALSE;
|
||||||
|
centipedes[i].flippedX = FALSE;
|
||||||
|
centipedes[i].flippedY = FALSE;
|
||||||
|
centipedes[i].flipping = FALSE;
|
||||||
|
centipedes[i].flag1 = FALSE;
|
||||||
|
centipedes[i].pos.x = CENTIPEDE_DUMP_X;
|
||||||
|
centipedes[i].pos.y = CENTIPEDE_DUMP_Y;
|
||||||
|
SPR_releaseSprite(centipedes[i].image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop
|
||||||
|
|
||||||
|
void loadCentipede(){
|
||||||
|
centipedeCount = 4;
|
||||||
|
if(currentZone >= 5) centipedeCount++;
|
||||||
|
if(currentZone >= 10) centipedeCount++;
|
||||||
|
if(currentZone >= 15) centipedeCount++;
|
||||||
|
for(s16 i = 0; i < centipedeCount; i++){
|
||||||
|
centipedes[i].active = TRUE;
|
||||||
|
centipedes[i].pos.x = FIX16(16 + 16 * i);
|
||||||
|
centipedes[i].pos.y = CENTIPEDE_LIMIT_TOP;
|
||||||
|
// centipedes[i].speed = FIX16(currentZone >= 10 ? 4 : 2);
|
||||||
|
centipedes[i].speed = FIX16(2);
|
||||||
|
centipedes[i].image = SPR_addSprite(&imgGumdropRed, fix16ToInt(centipedes[i].pos.x), fix16ToInt(centipedes[i].pos.y), TILE_ATTR(PAL1, 0, FALSE, FALSE));
|
||||||
|
centipedes[i].definition = 3;
|
||||||
|
centipedes[i].health = i % 2 == 0 ? 80 : 100;
|
||||||
|
centipedes[i].opposite = i % 2 == 1;
|
||||||
|
SPR_setDepth(centipedes[i].image, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetCentipede(){
|
||||||
|
for(s16 i = 0; i < centipedeCount; i++) destroyCentipede(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateCentipede(){
|
||||||
|
zoneOverCheck = TRUE;
|
||||||
|
tempLastCentipede = 0;
|
||||||
|
for(s16 i = 0; i < centipedeCount; i++) if(centipedes[i].active) {
|
||||||
|
tempLastCentipede++;
|
||||||
|
zoneOverCheck = FALSE;
|
||||||
|
moveCentipede(i);
|
||||||
|
collideCentipede(i);
|
||||||
|
animateCentipede(i);
|
||||||
|
if(centipedes[i].turning){
|
||||||
|
centipedes[i].turnClock++;
|
||||||
|
if(centipedes[i].turnClock >= 30) centipedes[i].turning = FALSE;
|
||||||
|
}
|
||||||
|
SPR_setPosition(centipedes[i].image, fix16ToInt(centipedes[i].pos.x) - CENTIPEDE_OFFSET, fix16ToInt(centipedes[i].pos.y) - CENTIPEDE_OFFSET);
|
||||||
|
if(centipedes[i].opposite){
|
||||||
|
if(centipedes[i].clock % 40 == 0) SPR_setFrame(centipedes[i].image, 1);
|
||||||
|
else if(centipedes[i].clock % 40 == 20) SPR_setFrame(centipedes[i].image, 0);
|
||||||
|
}
|
||||||
|
centipedes[i].clock++;
|
||||||
|
if(centipedes[i].clock >= 600) centipedes[i].clock = 120;
|
||||||
|
}
|
||||||
|
lastCentipede = tempLastCentipede;
|
||||||
|
if(zoneOverCheck) zoneOver = TRUE;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#define CENTIPEDE_MAX 8
|
||||||
|
#define CENTIPEDE_OFFSET 8
|
||||||
|
#define CENTIPEDE_LIMIT_LEFT FIX16(8)
|
||||||
|
#define CENTIPEDE_LIMIT_RIGHT FIX16(GAME_WIDTH - 8)
|
||||||
|
#define CENTIPEDE_LIMIT_TOP FIX16(32)
|
||||||
|
#define CENTIPEDE_LIMIT_BOTTOM FIX16(GAME_HEIGHT - 16)
|
||||||
|
|
||||||
|
#define CENTIPEDE_COLLIDE_OFFSET FIX16(8)
|
||||||
|
#define CENTIPEDE_BULLET_OFFSET FIX16(8)
|
||||||
|
#define CENTIPEDE_PLAYER_OFFSET FIX16(2)
|
||||||
|
#define CENTIPEDE_POD_OFFSET FIX32(4)
|
||||||
|
|
||||||
|
#define CENTIPEDE_DUMP_X FIX16(GAME_WIDTH + 64)
|
||||||
|
#define CENTIPEDE_DUMP_Y FIX16(0 - 64)
|
||||||
|
|
||||||
|
#define CENTIPEDE_HIT 6
|
||||||
|
// #define CENTIPEDE_HIT 100
|
||||||
|
|
||||||
|
struct centipede {
|
||||||
|
Sprite* image;
|
||||||
|
Vect2D_f16 pos;
|
||||||
|
bool flippedX, flippedY, flipping, active, flag1, turning, opposite;
|
||||||
|
s16 clock, flipClock, definition, health, turnClock;
|
||||||
|
f16 speed, nextY;
|
||||||
|
};
|
||||||
|
|
||||||
|
s16 centipedeCount, lastCentipede, tempLastCentipede;
|
||||||
|
s32 centipedePodCheck;
|
||||||
|
f16 centipedeSpeed;
|
||||||
|
|
||||||
|
struct centipede centipedes[CENTIPEDE_MAX];
|
||||||
|
|
||||||
|
bool centipedeCollided, zoneOverCheck;
|
||||||
|
|
||||||
|
void loadCentipede(),
|
||||||
|
moveCentipede(s16),
|
||||||
|
collideCentipede(s16),
|
||||||
|
animateCentipede(s16),
|
||||||
|
destroyCentipede(s16),
|
||||||
|
splitCentipede(s16),
|
||||||
|
turnCentipede(s16, s16),
|
||||||
|
resetCentipede(),
|
||||||
|
updateCentipede();
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include <genesis.h>
|
||||||
|
#include <resources.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "chrome.h"
|
||||||
|
#include "boss.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
|
||||||
|
// lives
|
||||||
|
|
||||||
|
void loadChromeLives(){
|
||||||
|
VDP_drawImageEx(BG_A, &chromePlayer, TILE_ATTR_FULL(PAL1, 1, 0, 0, 160), 1, 1, 0, DMA_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateChromePlayerLives(){
|
||||||
|
if(chromePlayerLives != playerLives){
|
||||||
|
for(s8 x = 0; x < 6; x++){
|
||||||
|
VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, 11), x + 6, 1);
|
||||||
|
if(x < playerLives) VDP_drawText("#", x + 6, 1);
|
||||||
|
}
|
||||||
|
chromePlayerLives = playerLives;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// bombs
|
||||||
|
|
||||||
|
void updateChromePlayerBombs(){
|
||||||
|
if(chromePlayerBombs != playerBombs){
|
||||||
|
for(s8 x = 0; x < 6; x++){
|
||||||
|
VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, 11), x + 1, PLAYER_BOMBS_Y);
|
||||||
|
if(x < playerBombs) VDP_drawText("*", x + 1, PLAYER_BOMBS_Y);
|
||||||
|
}
|
||||||
|
chromePlayerBombs = playerBombs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// score
|
||||||
|
|
||||||
|
void updateChromeScore(){
|
||||||
|
chromeCurrentScore = currentScore;
|
||||||
|
intToStr(chromeCurrentScore, chromeScoreStr, 8);
|
||||||
|
VDP_drawText(chromeScoreStr, 12, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// zone
|
||||||
|
|
||||||
|
void loadChromeZone(){
|
||||||
|
intToStr(currentZone, zoneHudStr, 2);
|
||||||
|
VDP_drawText(zoneHudStr, 29, 1);
|
||||||
|
VDP_drawImageEx(BG_A, &chromeStage, TILE_ATTR_FULL(PAL1, 1, 0, 0, 170), 24, 1, 0, DMA_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// states
|
||||||
|
|
||||||
|
void loadChromeZoneOver(){
|
||||||
|
chromePlayerLives = 0;
|
||||||
|
chromePlayerBombs = 0;
|
||||||
|
intToStr(currentZone, currentZoneStr, 2);
|
||||||
|
VDP_drawText("stage", 7, 8);
|
||||||
|
VDP_drawText(currentZoneStr, 13, 8);
|
||||||
|
VDP_drawText("complete!", 16, 8);
|
||||||
|
VDP_drawText("NO-MISS", 7, 12);
|
||||||
|
VDP_drawText(noMiss ? (currentZone >= 10 ? "35000" : "25000") : "00000", 20, 12);
|
||||||
|
VDP_drawText("STAGE", 7, 14);
|
||||||
|
VDP_drawText(currentZone >= 10 ? "15000" : "10000", 20, 14);
|
||||||
|
if(currentZone % 5 == 0){
|
||||||
|
VDP_drawText("BOSS", 7, 16);
|
||||||
|
VDP_drawText(currentZone >= 10 ? "30000" : "20000", 20, 16);
|
||||||
|
currentScore += currentZone >= 10 ? 30000 : 20000;
|
||||||
|
}
|
||||||
|
if(currentZone == 10) XGM_stopPlay();
|
||||||
|
currentZone++;
|
||||||
|
VDP_drawText("next stage", 7, 21);
|
||||||
|
loadedZoneOver = TRUE;
|
||||||
|
if(noMiss) currentScore += currentZone >= 10 ? 35000 : 25000;
|
||||||
|
currentScore += currentZone >= 10 ? 15000 : 10000;
|
||||||
|
updateChromeScore();
|
||||||
|
XGM_startPlayPCM(SFX_ZONE_OVER, 1, SOUND_PCM_CH2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateChromeZoneOver(){ // what the fuck am i on to do this
|
||||||
|
strcpy(zoneOverTime, zoneOverClock >= 180 ? "3" : (zoneOverClock >= 120 ? "2" : (zoneOverClock >= 60 ? "1" : "0")));
|
||||||
|
strcat(zoneOverTime, ";");
|
||||||
|
if(zoneOverClock % 60 < 10) strcat(zoneOverTime, "0");
|
||||||
|
else if(zoneOverClock % 60 < 20) strcat(zoneOverTime, "1");
|
||||||
|
else if(zoneOverClock % 60 < 30) strcat(zoneOverTime, "2");
|
||||||
|
else if(zoneOverClock % 60 < 40) strcat(zoneOverTime, "3");
|
||||||
|
else if(zoneOverClock % 60 < 50) strcat(zoneOverTime, "4");
|
||||||
|
else if(zoneOverClock % 60 < 60) strcat(zoneOverTime, "5");
|
||||||
|
switch(zoneOverClock % 6){
|
||||||
|
case 0: strcat(zoneOverTime, "0"); break;
|
||||||
|
case 1: strcat(zoneOverTime, "1"); break;
|
||||||
|
case 2: strcat(zoneOverTime, "2"); break;
|
||||||
|
case 3: strcat(zoneOverTime, "3"); break;
|
||||||
|
case 4: strcat(zoneOverTime, "4"); break;
|
||||||
|
case 5: strcat(zoneOverTime, "5"); break;
|
||||||
|
case 6: strcat(zoneOverTime, "6"); break;
|
||||||
|
case 7: strcat(zoneOverTime, "7"); break;
|
||||||
|
case 8: strcat(zoneOverTime, "8"); break;
|
||||||
|
case 9: strcat(zoneOverTime, "9"); break;
|
||||||
|
}
|
||||||
|
VDP_drawText(zoneOverTime, 21, 21);
|
||||||
|
zoneOverClock--;
|
||||||
|
if(zoneOverClock <= 0) nextZone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadChromeGameOver(bool beatIt){
|
||||||
|
XGM_stopPlay();
|
||||||
|
loadedChromeGameOver = TRUE;
|
||||||
|
VDP_drawText(beatIt ? "beat game!" : "game over!", 11, 10);
|
||||||
|
VDP_drawText(currentScore > highScore ? "NEW HI SCORE" : "FINAL SCORE;", 10, 13);
|
||||||
|
VDP_drawText(chromeScoreStr, 12, 15);
|
||||||
|
if(beatIt){
|
||||||
|
VDP_drawText("special thanks", 9, 19);
|
||||||
|
VDP_drawText("TOUHOU GAMEDEV DISCORD", 5, 21);
|
||||||
|
} else VDP_drawText("press any button", 8, 18);
|
||||||
|
if(currentScore > highScore) highScore = currentScore;
|
||||||
|
XGM_startPlayPCM(beatIt ? SFX_BEAT_GAME : SFX_GAME_OVER, 2, SOUND_PCM_CH2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadChromeBeatGame(){
|
||||||
|
gameOver = TRUE;
|
||||||
|
loadChromeGameOver(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// boss
|
||||||
|
|
||||||
|
void updateChromeBoss(){
|
||||||
|
if(bossActive){
|
||||||
|
if(lastBossHealth != bossHealth){
|
||||||
|
VDP_drawImageEx(BG_A, &chromeEnemy, TILE_ATTR_FULL(PAL1, 1, 0, 0, 190), 1, BOSS_TILE_Y, 0, DMA_QUEUE);
|
||||||
|
bossLimit = fix16Div(fix16Mul(fix16Div(FIX16(bossHealth), FIX16(bossMax)), BOSS_TILE_PX), 8);
|
||||||
|
for(s16 x = 0; x < BOSS_TILE_COUNT; x++){
|
||||||
|
if(bossHealth <= 1 || FIX16(x) >= bossLimit){
|
||||||
|
VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 0, 0, 0, 11), x + BOSS_TILE_X, BOSS_TILE_Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(s16 x = 0; x < BOSS_TILE_COUNT; x++){
|
||||||
|
if(bossHealth > 1 && FIX16(x) < bossLimit) VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 1, 0, 0, 8), x + BOSS_TILE_X, BOSS_TILE_Y);
|
||||||
|
}
|
||||||
|
lastBossHealth = bossHealth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop
|
||||||
|
|
||||||
|
void loadChrome(){
|
||||||
|
VDP_loadTileSet(bossBar.tileset, 8, DMA);
|
||||||
|
updateChromeScore();
|
||||||
|
loadChromeZone();
|
||||||
|
loadChromeLives();
|
||||||
|
zoneOverClock = ZONE_OVER_CHROME_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateChrome(){
|
||||||
|
if(zoneStarting) loadChrome();
|
||||||
|
else {
|
||||||
|
if(zoneOver){
|
||||||
|
if(!loadedZoneOver) currentZone == 20 ? loadChromeBeatGame() : loadChromeZoneOver();
|
||||||
|
updateChromeZoneOver();
|
||||||
|
} else if(gameOver){
|
||||||
|
if(!loadedChromeGameOver) loadChromeGameOver(FALSE);
|
||||||
|
} else {
|
||||||
|
updateChromePlayerLives();
|
||||||
|
updateChromePlayerBombs();
|
||||||
|
updateChromeBoss();
|
||||||
|
if(chromeCurrentScore < currentScore) updateChromeScore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// #define ZONE_OVER_CHROME_LIMIT 1
|
||||||
|
#define ZONE_OVER_CHROME_LIMIT 240
|
||||||
|
// #define ZONE_OVER_CHROME_LIMIT 60
|
||||||
|
|
||||||
|
#define BOSS_TILE_X 6
|
||||||
|
#define BOSS_TILE_Y 3
|
||||||
|
#define BOSS_TILE_COUNT 25
|
||||||
|
#define BOSS_TILE_PX BOSS_TILE_COUNT * 8
|
||||||
|
|
||||||
|
#define PLAYER_BOMBS_Y 26
|
||||||
|
|
||||||
|
s16 frameTileIndex, zoneOverClock, zoneOverStage, lastBossHealth, bossTileIndex;
|
||||||
|
s8 chromePlayerLives, chromePlayerBombs;
|
||||||
|
s32 chromeCurrentScore;
|
||||||
|
|
||||||
|
fix16 bossLimit, lastBossLimit;
|
||||||
|
|
||||||
|
bool loadedZoneOver, loadedChromeGameOver;
|
||||||
|
|
||||||
|
char currentZoneStr[2],
|
||||||
|
zoneHudStr[2],
|
||||||
|
currentZoneApp[1],
|
||||||
|
zoneOverTime[8],
|
||||||
|
chromeScoreStr[10];
|
||||||
|
|
||||||
|
void loadChrome(),
|
||||||
|
loadChromeZoneOver(),
|
||||||
|
loadChromeLives(),
|
||||||
|
loadChromeGameOver(bool),
|
||||||
|
updateChromeZoneOver(),
|
||||||
|
updateChromeScore(),
|
||||||
|
loadChromeBeatGame(),
|
||||||
|
updateChromePlayerLives(),
|
||||||
|
updateChromePlayerBombs(),
|
||||||
|
updateChromeBoss(),
|
||||||
|
updateChrome();
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <genesis.h>
|
||||||
|
#include "controls.h"
|
||||||
|
|
||||||
|
void updateControls(u16 joy, u16 changed, u16 state){
|
||||||
|
if(joy == JOY_1){
|
||||||
|
if(changed){}
|
||||||
|
controls.left = (state & BUTTON_LEFT);
|
||||||
|
controls.right = (state & BUTTON_RIGHT);
|
||||||
|
controls.up = (state & BUTTON_UP);
|
||||||
|
controls.down = (state & BUTTON_DOWN);
|
||||||
|
controls.a = (state & BUTTON_A);
|
||||||
|
controls.b = (state & BUTTON_B);
|
||||||
|
controls.c = (state & BUTTON_C);
|
||||||
|
controls.start = (state & BUTTON_START);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
struct controls {
|
||||||
|
bool left, right, up, down, a, b, c, x, y, z, start, mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct controls controls;
|
||||||
|
|
||||||
|
void updateControls(u16, u16, u16);
|