working animation, but ugly
This commit is contained in:
parent
f3fd560eae
commit
aa5b06312e
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
build
|
build
|
||||||
|
*.swp
|
||||||
|
3
Makefile
3
Makefile
@ -9,8 +9,9 @@ BUILD=./build
|
|||||||
ENTRY=${SRC}/main.asm
|
ENTRY=${SRC}/main.asm
|
||||||
ROM_OUTPUT=${BUILD}/${NAME}.gb
|
ROM_OUTPUT=${BUILD}/${NAME}.gb
|
||||||
OBJECT_OUTPUT=${BUILD}/${NAME}.o
|
OBJECT_OUTPUT=${BUILD}/${NAME}.o
|
||||||
|
SYMFILE_OUTPUT=${BUILD}/${NAME}.sym
|
||||||
|
|
||||||
all : ${ENTRY}
|
all : ${ENTRY}
|
||||||
${ASSEMBLER} -o ${OBJECT_OUTPUT} ${ENTRY} \
|
${ASSEMBLER} -o ${OBJECT_OUTPUT} ${ENTRY} \
|
||||||
&& ${LINKER} -o ${ROM_OUTPUT} -n ${NAME}.sym ${OBJECT_OUTPUT} \
|
&& ${LINKER} -o ${ROM_OUTPUT} -n ${SYMFILE_OUTPUT} ${OBJECT_OUTPUT} \
|
||||||
&& ${POSTPROC} -v -p 0 ${ROM_OUTPUT}
|
&& ${POSTPROC} -v -p 0 ${ROM_OUTPUT}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
; File generated by rgblink
|
|
||||||
|
|
||||||
00:0634 parecivo_tile_data
|
|
||||||
00:0234 Map
|
|
||||||
00:01F8 CheckBoundry
|
|
||||||
00:01E5 game_loop
|
|
||||||
00:0230 CheckBoundry.skipRender
|
|
||||||
00:021E CheckBoundry.swap
|
|
||||||
00:022C CheckBoundry.render
|
|
||||||
00:0150 Start
|
|
||||||
00:0017 dPlayerHeight
|
|
||||||
00:0016 dPlayerWidth
|
|
||||||
00:0018 dPlayerSpriteTiles
|
|
||||||
00:0008 CopyDMARoutine
|
|
||||||
00:0004 DMARoutine.wait
|
|
||||||
00:0000 DMARoutine
|
|
||||||
00:0008 DMARoutine.end
|
|
||||||
00:000F CopyDMARoutine.copy
|
|
||||||
00:0853 Read_Pad
|
|
||||||
00:084A MemCpy.copy
|
|
||||||
00:0883 Read_Pad.onenibble
|
|
||||||
00:086C Read_Pad.legalUpDown
|
|
||||||
00:0875 Read_Pad.legalLeftRight
|
|
||||||
00:084A MemCpy
|
|
||||||
00:0744 Wait_VBlank
|
|
||||||
00:0816 Clear_Map
|
|
||||||
00:0824 Load_Tiles
|
|
||||||
00:07D7 PC_Update
|
|
||||||
00:0750 Player_To_OAM
|
|
||||||
00:0747 Wait_VBlank.wait
|
|
||||||
00:07D1 Player_To_OAM.add4hl
|
|
||||||
00:0762 Player_To_OAM.finner
|
|
||||||
00:075E Player_To_OAM.fouter
|
|
||||||
00:0786 Player_To_OAM.sinner
|
|
||||||
00:077B Player_To_OAM.souter
|
|
||||||
00:07A5 Player_To_OAM.tloop1
|
|
||||||
00:07AA Player_To_OAM.tloop2
|
|
||||||
00:07C1 Player_To_OAM.lloop1
|
|
||||||
00:07C6 Player_To_OAM.lloop2
|
|
||||||
00:07E6 PC_Update.up
|
|
||||||
00:07F1 PC_Update.left
|
|
||||||
00:07FC PC_Update.right
|
|
||||||
00:0807 PC_Update.last
|
|
||||||
00:081D Clear_Map.loop
|
|
||||||
00:C005 rPlayerX
|
|
||||||
00:C006 rPlayerY
|
|
||||||
00:C004 ANS
|
|
||||||
00:C002 N
|
|
||||||
00:C000 X
|
|
||||||
00:C100 wShadowOAM
|
|
||||||
00:FF88 hVBlankFlag
|
|
||||||
00:FF89 hCurKeys
|
|
||||||
00:FF8A hNewKeys
|
|
||||||
00:FF80 hOAMDMA
|
|
367
inc/structs.asm
Normal file
367
inc/structs.asm
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
|
||||||
|
; MIT License
|
||||||
|
;
|
||||||
|
; Copyright (c) 2018-2019 Eldred Habert
|
||||||
|
; Originally hosted at https://github.com/ISSOtm/rgbds-structs
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
; !!! WARNING ABOUT READABILITY OF THIS CODE !!!
|
||||||
|
;
|
||||||
|
; RGBDS, being the venerable/old/decrepit (pick on depending on mood) assembler that it is, requires
|
||||||
|
; all label, variable etc. definitions to be on column 0. As in, no whitespace allowed (otherwise, syntax error)
|
||||||
|
; Meanwhile, these macros tend to use a lot of nesting (requiring indenting for readability),
|
||||||
|
; as well as variable definitions (requiring none to work).
|
||||||
|
; As you can probably tell, those two conflict and result in very poor readability
|
||||||
|
; Sadly, there is nothing I can do against that short of using a special preprocessor,
|
||||||
|
; which I refuse to do for usability's sake.
|
||||||
|
; You have all my apologies, how little they may matter, if you are trying to read this code
|
||||||
|
; I still did my best to use explicit comments and variable names, hope they will help!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; strreplace variable_name, original_char, new_char
|
||||||
|
strreplace: MACRO
|
||||||
|
DOT_POS = STRIN("{\1}", \2)
|
||||||
|
IF DOT_POS != 0
|
||||||
|
TMP equs STRCAT(STRSUB("{\1}", 1, DOT_POS + (-1)), STRCAT(\3, STRSUB("{\1}", DOT_POS + 1, STRLEN("{\1}") - DOT_POS)))
|
||||||
|
PURGE \1
|
||||||
|
\1 equs "{TMP}"
|
||||||
|
PURGE TMP
|
||||||
|
strreplace \1, \2, \3
|
||||||
|
ENDC
|
||||||
|
IF DEF(DOT_POS)
|
||||||
|
PURGE DOT_POS
|
||||||
|
ENDC
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
|
||||||
|
; rgbds_structs_version version_string
|
||||||
|
; Call with the expected version string to ensure you're using a compatible version
|
||||||
|
; Example: rgbds_structs_version 1.0.0
|
||||||
|
rgbds_structs_version: MACRO
|
||||||
|
CURRENT_VERSION equs "1,2,1"
|
||||||
|
EXPECTED_VERSION equs "\1"
|
||||||
|
strreplace EXPECTED_VERSION, ".", "\,"
|
||||||
|
check_ver: MACRO
|
||||||
|
IF \1 != \4 || \2 > \5 || \3 > \6
|
||||||
|
PURGE EXPECTED_VERSION
|
||||||
|
ENDC
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
CHECK_VER_CALL equs "check_ver {EXPECTED_VERSION},{CURRENT_VERSION}"
|
||||||
|
CHECK_VER_CALL
|
||||||
|
IF !DEF(EXPECTED_VERSION)
|
||||||
|
strreplace CURRENT_VERSION, "\,", "."
|
||||||
|
FAIL "RGBDS-structs version \1 is required, which is incompatible with current version {CURRENT_VERSION}"
|
||||||
|
ENDC
|
||||||
|
PURGE CHECK_VER_CALL
|
||||||
|
PURGE check_ver
|
||||||
|
PURGE CURRENT_VERSION
|
||||||
|
PURGE EXPECTED_VERSION
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
|
||||||
|
; struct struct_name
|
||||||
|
; Begins a struct declaration
|
||||||
|
struct: MACRO
|
||||||
|
IF DEF(NB_FIELDS)
|
||||||
|
FAIL "Please close struct definitions using `end_struct`"
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
STRUCT_NAME equs "\1"
|
||||||
|
|
||||||
|
NB_FIELDS = 0
|
||||||
|
RSRESET
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
; end_struct
|
||||||
|
; Ends a struct declaration
|
||||||
|
end_struct: MACRO
|
||||||
|
; Set nb of fields
|
||||||
|
STRUCT_NB_FIELDS equs "{STRUCT_NAME}_nb_fields"
|
||||||
|
STRUCT_NB_FIELDS = NB_FIELDS
|
||||||
|
PURGE STRUCT_NB_FIELDS
|
||||||
|
|
||||||
|
; Set size of struct
|
||||||
|
STRUCT_SIZEOF equs "sizeof_{STRUCT_NAME}"
|
||||||
|
STRUCT_SIZEOF RB 0
|
||||||
|
PURGE STRUCT_SIZEOF
|
||||||
|
|
||||||
|
PURGE NB_FIELDS
|
||||||
|
PURGE STRUCT_NAME
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
|
||||||
|
; get_nth_field_info field_id
|
||||||
|
; Defines EQUS strings pertaining to a struct's Nth field
|
||||||
|
; For internal use, please do not use externally
|
||||||
|
get_nth_field_info: MACRO
|
||||||
|
; Field's name
|
||||||
|
STRUCT_FIELD equs "{STRUCT_NAME}_field{d:\1}"
|
||||||
|
STRUCT_FIELD_NAME equs "{STRUCT_FIELD}_name"
|
||||||
|
STRUCT_FIELD_TYPE equs "{STRUCT_FIELD}_type"
|
||||||
|
STRUCT_FIELD_NBEL equs "{STRUCT_FIELD}_nb_el" ; Number of elements
|
||||||
|
STRUCT_FIELD_SIZE equs "{STRUCT_FIELD}_size" ; sizeof(type) * nb_el
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
|
||||||
|
; new_field nb_elems, rs_type, field_name
|
||||||
|
; For internal use, please do not use externally
|
||||||
|
new_field: MACRO
|
||||||
|
IF !DEF(STRUCT_NAME) || !DEF(NB_FIELDS)
|
||||||
|
FAIL "Please start defining a struct, using `define_struct`"
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
get_nth_field_info NB_FIELDS
|
||||||
|
; Set field name (keep in mind `STRUCT_FIELD_NAME` is *itself* an EQUS!)
|
||||||
|
STRUCT_FIELD_NAME equs "\"\3\""
|
||||||
|
PURGE STRUCT_FIELD_NAME
|
||||||
|
|
||||||
|
; Set field offset
|
||||||
|
STRUCT_FIELD \2 (\1)
|
||||||
|
; Alias this in a human-comprehensive manner
|
||||||
|
STRUCT_FIELD_NAME equs "{STRUCT_NAME}_\3"
|
||||||
|
STRUCT_FIELD_NAME = STRUCT_FIELD
|
||||||
|
|
||||||
|
; Compute field size
|
||||||
|
CURRENT_RS RB 0
|
||||||
|
STRUCT_FIELD_SIZE = CURRENT_RS - STRUCT_FIELD
|
||||||
|
|
||||||
|
; Set properties
|
||||||
|
STRUCT_FIELD_NBEL = \1
|
||||||
|
STRUCT_FIELD_TYPE equs STRSUB("\2", 2, 1)
|
||||||
|
|
||||||
|
PURGE STRUCT_FIELD
|
||||||
|
PURGE STRUCT_FIELD_NAME
|
||||||
|
PURGE STRUCT_FIELD_TYPE
|
||||||
|
PURGE STRUCT_FIELD_NBEL
|
||||||
|
PURGE STRUCT_FIELD_SIZE
|
||||||
|
PURGE CURRENT_RS
|
||||||
|
|
||||||
|
NB_FIELDS = NB_FIELDS + 1
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
; bytes nb_bytes, field_name
|
||||||
|
; Defines a field of N bytes
|
||||||
|
bytes: MACRO
|
||||||
|
new_field \1, RB, \2
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
; words nb_words, field_name
|
||||||
|
; Defines a field of N*2 bytes
|
||||||
|
words: MACRO
|
||||||
|
new_field \1, RW, \2
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
; longs nb_longs, field_name
|
||||||
|
; Defines a field of N*4 bytes
|
||||||
|
longs: MACRO
|
||||||
|
new_field \1, RL, \2
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
|
||||||
|
; dstruct struct_type, INSTANCE_NAME[, ...]
|
||||||
|
; Allocates space for a struct in memory
|
||||||
|
; If no further arguments are supplied, the space is simply allocated (using `ds`)
|
||||||
|
; Otherwise, the data is written to memory using the appropriate types
|
||||||
|
; For example, a struct defined with `bytes 1, Field1` and `words 3, Field2` would have four extra arguments, one byte then three words.
|
||||||
|
dstruct: MACRO
|
||||||
|
NB_FIELDS equs "\1_nb_fields"
|
||||||
|
IF !DEF(NB_FIELDS)
|
||||||
|
FAIL "Struct \1 isn't defined!"
|
||||||
|
ELIF _NARG != 2 && _NARG != NB_FIELDS + 2 ; We must have either a RAM declaration (no data args) or a ROM one (RAM args + data args)
|
||||||
|
EXPECTED_NARG = 2 + NB_FIELDS
|
||||||
|
FAIL "Invalid number of arguments, expected 2 or {d:EXPECTED_NARG} but got {d:_NARG}"
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
; Define the two fields required by `get_nth_field_info`
|
||||||
|
STRUCT_NAME equs "\1" ; Which struct `get_nth_field_info` should pull info about
|
||||||
|
INSTANCE_NAME equs "\2" ; The instance's base name
|
||||||
|
|
||||||
|
|
||||||
|
; RGBASM always expands `\X` macro args, so `IF _NARG > 2 && STRIN("\3", "=")` will error out when there are only 2 args
|
||||||
|
; Therefore, the condition is checked here (we can't nest the `IF`s over there because that doesn't translate well to `ELSE`)
|
||||||
|
IS_NAMED_INVOCATION = 0
|
||||||
|
IF _NARG > 2
|
||||||
|
IF STRIN("\3", "=")
|
||||||
|
IS_NAMED_INVOCATION = 1
|
||||||
|
ENDC
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
IF IS_NAMED_INVOCATION
|
||||||
|
; This is a named instantiation, translate that to an ordered one
|
||||||
|
; This is needed because data has to be laid out in order, so some translation is needed anyways
|
||||||
|
; And finally, it's better to re-use the existing code at the cost of a single nested macro, I believe
|
||||||
|
MACRO_CALL equs "dstruct \1, \2" ; This will be used later, but define it now because `SHIFT` will be run
|
||||||
|
; In practice `SHIFT` has no effect outside of one when invoked inside of a REPT block, but I hope this behavior is changed (causes a problem elsewhere)
|
||||||
|
|
||||||
|
ARG_NUM = 3
|
||||||
|
REPT NB_FIELDS
|
||||||
|
; Find out which argument the current one is
|
||||||
|
CUR_ARG equs "\3"
|
||||||
|
; Remove all whitespace to obtain something like ".name=value" (whitespace are unnecessary and complexify parsing)
|
||||||
|
strreplace CUR_ARG, " ", ""
|
||||||
|
strreplace CUR_ARG, "\t", ""
|
||||||
|
|
||||||
|
EQUAL_POS = STRIN("{CUR_ARG}", "=")
|
||||||
|
IF EQUAL_POS == 0
|
||||||
|
FAIL "Argument #{ARG_NUM} (\3) does not contain an equal sign in this named instantiation"
|
||||||
|
ELIF STRCMP(STRSUB("{CUR_ARG}", 1, 1), ".")
|
||||||
|
FAIL "Argument #{ARG_NUM} (\3) does not start with a period"
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
FIELD_ID = -1
|
||||||
|
CUR_FIELD_ID = 0
|
||||||
|
REPT NB_FIELDS
|
||||||
|
|
||||||
|
; Get the name of the Nth field and compare
|
||||||
|
TMP equs "{STRUCT_NAME}_field{d:CUR_FIELD_ID}_name"
|
||||||
|
CUR_FIELD_NAME equs TMP
|
||||||
|
PURGE TMP
|
||||||
|
|
||||||
|
IF !STRCMP(STRUPR("{CUR_FIELD_NAME}"), STRUPR(STRSUB("{CUR_ARG}", 2, EQUAL_POS - 2)))
|
||||||
|
; Match found!
|
||||||
|
IF FIELD_ID == -1
|
||||||
|
FIELD_ID = CUR_FIELD_ID
|
||||||
|
ELSE
|
||||||
|
TMP equs "{STRUCT_NAME}_field{d:CUR_FIELD_ID}_name"
|
||||||
|
CONFLICTING_FIELD_NAME equs TMP
|
||||||
|
PURGE TMP
|
||||||
|
FAIL "Fields {CUR_FIELD_NAME} and {CONFLICTING_FIELD_NAME} have conflicting names (case-insensitive), cannot perform named instantiation"
|
||||||
|
ENDC
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
PURGE CUR_FIELD_NAME
|
||||||
|
CUR_FIELD_ID = CUR_FIELD_ID + 1
|
||||||
|
ENDR
|
||||||
|
PURGE CUR_FIELD_ID
|
||||||
|
|
||||||
|
IF FIELD_ID == -1
|
||||||
|
FAIL "Argument #{d:ARG_NUM} (\3) does not match any field of the struct"
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
INITIALIZER_NAME equs "FIELD_{d:FIELD_ID}_INITIALIZER"
|
||||||
|
INITIALIZER_NAME equs STRSUB("{CUR_ARG}", EQUAL_POS + 1, STRLEN("{CUR_ARG}") - EQUAL_POS)
|
||||||
|
PURGE INITIALIZER_NAME
|
||||||
|
|
||||||
|
; Go to next arg
|
||||||
|
ARG_NUM = ARG_NUM + 1
|
||||||
|
SHIFT
|
||||||
|
PURGE CUR_ARG
|
||||||
|
|
||||||
|
ENDR
|
||||||
|
|
||||||
|
; Now that we matched each named initializer to their order, invoke the macro again but without names
|
||||||
|
FIELD_ID = 0
|
||||||
|
REPT NB_FIELDS
|
||||||
|
TMP equs "{MACRO_CALL}"
|
||||||
|
PURGE MACRO_CALL
|
||||||
|
INITIALIZER_VALUE equs "{FIELD_{d:FIELD_ID}_INITIALIZER}"
|
||||||
|
DELETE_INITIALIZER equs "PURGE FIELD_{d:FIELD_ID}_INITIALIZER"
|
||||||
|
DELETE_INITIALIZER
|
||||||
|
PURGE DELETE_INITIALIZER
|
||||||
|
MACRO_CALL equs "{TMP}, {INITIALIZER_VALUE}"
|
||||||
|
PURGE TMP
|
||||||
|
PURGE INITIALIZER_VALUE
|
||||||
|
FIELD_ID = FIELD_ID + 1
|
||||||
|
ENDR
|
||||||
|
|
||||||
|
PURGE FIELD_ID
|
||||||
|
; Clean up vars for nested invocation, otherwise some `equs` will be expanded
|
||||||
|
PURGE INSTANCE_NAME
|
||||||
|
PURGE STRUCT_NAME
|
||||||
|
PURGE IS_NAMED_INVOCATION
|
||||||
|
PURGE NB_FIELDS
|
||||||
|
|
||||||
|
MACRO_CALL ; Now do call the macro
|
||||||
|
PURGE MACRO_CALL
|
||||||
|
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
|
||||||
|
INSTANCE_NAME:: ; Declare the struct's root
|
||||||
|
; Define instance's properties from struct's
|
||||||
|
\2_nb_fields = NB_FIELDS
|
||||||
|
sizeof_\2 = sizeof_\1
|
||||||
|
|
||||||
|
; Start defining fields
|
||||||
|
FIELD_ID = 0
|
||||||
|
REPT NB_FIELDS
|
||||||
|
|
||||||
|
get_nth_field_info FIELD_ID
|
||||||
|
|
||||||
|
FIELD_NAME equs STRCAT("{INSTANCE_NAME}_", STRUCT_FIELD_NAME)
|
||||||
|
FIELD_NAME::
|
||||||
|
|
||||||
|
; We have defined a label, but now we also need the data backing it
|
||||||
|
; There are basically two options:
|
||||||
|
IF _NARG == 2 ; RAM definition, no data
|
||||||
|
ds STRUCT_FIELD_SIZE
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
DATA_TYPE equs STRCAT("D", {{STRUCT_FIELD_TYPE}})
|
||||||
|
|
||||||
|
REPT STRUCT_FIELD_NBEL
|
||||||
|
DATA_TYPE \3
|
||||||
|
SHIFT
|
||||||
|
ENDR
|
||||||
|
PURGE DATA_TYPE
|
||||||
|
ENDC
|
||||||
|
|
||||||
|
; Clean up vars for next iteration
|
||||||
|
PURGE STRUCT_FIELD
|
||||||
|
PURGE STRUCT_FIELD_NAME
|
||||||
|
PURGE STRUCT_FIELD_TYPE
|
||||||
|
PURGE STRUCT_FIELD_NBEL
|
||||||
|
PURGE STRUCT_FIELD_SIZE
|
||||||
|
PURGE FIELD_NAME
|
||||||
|
|
||||||
|
FIELD_ID = FIELD_ID + 1
|
||||||
|
ENDR
|
||||||
|
|
||||||
|
|
||||||
|
; Clean up
|
||||||
|
PURGE FIELD_ID
|
||||||
|
; Make sure to keep what's here in sync with cleanup at the end of a named invocation
|
||||||
|
PURGE INSTANCE_NAME
|
||||||
|
PURGE STRUCT_NAME
|
||||||
|
PURGE IS_NAMED_INVOCATION
|
||||||
|
PURGE NB_FIELDS
|
||||||
|
ENDC
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
|
||||||
|
; dstructs nb_structs, struct_type, INSTANCE_NAME
|
||||||
|
; Allocates space for an array of structs in memory
|
||||||
|
; Each struct will have the index appended to its name **as hex**
|
||||||
|
; (for example: `dstructs 32, NPC, wNPC` will define wNPC0, wNPC1, and so on until wNPC1F)
|
||||||
|
; This is a limitation because RGBASM does not provide an easy way to get the decimal representation of a number
|
||||||
|
; Does not support data declarations because I think each struct should be defined individually for that purpose
|
||||||
|
dstructs: MACRO
|
||||||
|
STRUCT_ID = 0
|
||||||
|
REPT \1
|
||||||
|
dstruct \2, \3{X:STRUCT_ID}
|
||||||
|
STRUCT_ID = STRUCT_ID + 1
|
||||||
|
ENDR
|
||||||
|
|
||||||
|
PURGE STRUCT_ID
|
||||||
|
ENDM
|
Binary file not shown.
Binary file not shown.
@ -2,23 +2,15 @@
|
|||||||
; Actor Animation
|
; Actor Animation
|
||||||
;-----------------
|
;-----------------
|
||||||
|
|
||||||
SECTION "Actor Variables Struct", WRAM, ALIGN[8]
|
|
||||||
|
|
||||||
wWorldX: dw
|
|
||||||
wWorldY: dw
|
|
||||||
wActorState: db
|
|
||||||
wActorCounter: db
|
|
||||||
wActorData: dw
|
|
||||||
wActorTile: dw
|
|
||||||
|
|
||||||
SECTION "Actor", ROM0
|
SECTION "Actor", ROM0
|
||||||
|
|
||||||
Actor::
|
ActorROM::
|
||||||
.structs:
|
.structs:
|
||||||
dw ActorIdle
|
dw ActorIdle
|
||||||
.tiles:
|
.tiles:
|
||||||
ActorIdle::
|
ActorIdle::
|
||||||
db 60
|
db 60
|
||||||
|
db 15
|
||||||
dw .framePa
|
dw .framePa
|
||||||
db 15
|
db 15
|
||||||
dw .frameRe
|
dw .frameRe
|
||||||
|
@ -2,20 +2,33 @@
|
|||||||
; Animation Subs
|
; Animation Subs
|
||||||
;----------------
|
;----------------
|
||||||
|
|
||||||
SECTION "Animation Variables", HRAM
|
struct Actor
|
||||||
|
bytes 1, YPos
|
||||||
|
bytes 1, XPos
|
||||||
|
bytes 1, GFXCounter
|
||||||
|
bytes 1, GFXState
|
||||||
|
words 1, GFXData
|
||||||
|
bytes 1, TileData
|
||||||
|
end_struct
|
||||||
|
|
||||||
hCameraX: dw
|
SECTION "Actor STructs", WRAM0
|
||||||
hCameraY: dw
|
|
||||||
|
|
||||||
hWorkingX: dw
|
dstruct Actor, Player
|
||||||
hWorkingY: dw
|
|
||||||
hWorkingScreenX: db
|
SECTION "Animation Variables", WRAM0
|
||||||
hWorkingScreenY: db
|
|
||||||
hWorkingState: db
|
wCameraX: dw
|
||||||
hWorkingCounter: db
|
wCameraY: dw
|
||||||
hWorkingData: dw
|
|
||||||
hWorkingTile: dw
|
wWorkingX: dw
|
||||||
hWorkingEnd:
|
wWorkingY: dw
|
||||||
|
wWorkingScreenX: db
|
||||||
|
wWorkingScreenY: db
|
||||||
|
wWorkingState: db
|
||||||
|
wWorkingCounter: db
|
||||||
|
wWorkingData: dw
|
||||||
|
wWorkingTile: db
|
||||||
|
wWorkingEnd:
|
||||||
|
|
||||||
SECTION "Animations Subs", ROM0
|
SECTION "Animations Subs", ROM0
|
||||||
|
|
||||||
@ -32,28 +45,119 @@ SECTION "Animations Subs", ROM0
|
|||||||
; copied to shadowOAM (wShadowOAM)
|
; copied to shadowOAM (wShadowOAM)
|
||||||
|
|
||||||
RenderActor::
|
RenderActor::
|
||||||
|
; @input: hl <- Player
|
||||||
; load world X and Y to temp RAM
|
; @input: de <- ShadowOAM place
|
||||||
|
ld a, [hli] ; a <- YPos
|
||||||
|
ld [wWorkingScreenY], a
|
||||||
|
ld a, [hli] ; a <- XPos
|
||||||
|
ld [wWorkingScreenX], a
|
||||||
|
push hl
|
||||||
|
ld a, [hli] ; a <- GFXCounter
|
||||||
|
ld [wWorkingCounter], a
|
||||||
|
ld a, [hli] ; a <- GFXState
|
||||||
|
ld [wWorkingState], a
|
||||||
|
ld a, [hli] ; a <- GFXData(Low)
|
||||||
|
ld [wWorkingData+1], a
|
||||||
|
ld a, [hli] ; a <- GFXData (High)
|
||||||
|
ld [wWorkingData], a
|
||||||
|
ld a, [hl] ; a <- TileData
|
||||||
|
ld [wWorkingTile], a
|
||||||
|
; fin loading data
|
||||||
|
ld a, [wWorkingData]
|
||||||
|
ld l, a
|
||||||
|
ld a, [wWorkingData+1]
|
||||||
|
ld h, a
|
||||||
|
; add actor struct offset saved in wWorkingState
|
||||||
|
ld a, [wWorkingState]
|
||||||
|
rlca ; double state offset because of word length
|
||||||
|
add a, l
|
||||||
|
ld l, a
|
||||||
|
adc a, h
|
||||||
|
sub l
|
||||||
|
ld h, a ; hl contains state struct pointer
|
||||||
ld a, [hli]
|
ld a, [hli]
|
||||||
ld [hWorkingX], a
|
|
||||||
ld a, [hli]
|
|
||||||
ld [hWorkingX+1], a
|
|
||||||
ld a, [hli]
|
|
||||||
ld [hWorkingY], a
|
|
||||||
ld a, [hli]
|
|
||||||
ld [hWorkingY+1], a
|
|
||||||
; done loading X and Y
|
|
||||||
; figure out if within 256 of camera
|
|
||||||
; ---------
|
|
||||||
; first compare upper byte of XXYY
|
|
||||||
; if this is more than 1 away, break
|
|
||||||
ld a, [hCameraX]
|
|
||||||
ld b, a
|
ld b, a
|
||||||
ld a, [hWorkingX]
|
ld a, [hl]
|
||||||
; b = camera byte
|
ld l, b
|
||||||
; a = actor byte
|
ld h, a
|
||||||
; work out if actor minus camera is <= 1
|
ld a, [hli] ; a <- state frame limit
|
||||||
|
ld b, a
|
||||||
|
ld a, [wWorkingCounter]
|
||||||
|
inc a
|
||||||
|
ld c, a
|
||||||
|
ld a, b
|
||||||
|
ld b, c
|
||||||
|
cp b
|
||||||
|
ld a, b
|
||||||
|
jr nc, .continueAnimation
|
||||||
|
xor a
|
||||||
|
.continueAnimation
|
||||||
|
; TODO: make counter 0 indexed so doesnt skip first frame
|
||||||
|
ld [wWorkingCounter], a
|
||||||
|
ld b, h
|
||||||
|
ld c, l
|
||||||
|
pop hl
|
||||||
|
ld [hl], a
|
||||||
|
ld h, b
|
||||||
|
ld l, c
|
||||||
|
.loopFrameFind
|
||||||
|
ld b, a ; b <- current frame count
|
||||||
|
ld a, [hli] ; a <- next frame block
|
||||||
|
ld c, a
|
||||||
|
ld a, b
|
||||||
|
ld b, c
|
||||||
sub b
|
sub b
|
||||||
; ---------
|
jr z, .foundFrame
|
||||||
|
jr c, .foundFrame
|
||||||
|
inc hl
|
||||||
|
inc hl
|
||||||
|
jr .loopFrameFind
|
||||||
|
.foundFrame
|
||||||
|
ld a, [hli]
|
||||||
|
ld b, a
|
||||||
|
ld a, [hl]
|
||||||
|
ld h, a
|
||||||
|
ld l, b ; hl <- pointer to frame data
|
||||||
|
ld a, [hli]
|
||||||
|
ld b, a ; b <- sprite counter
|
||||||
|
.spriteLoop
|
||||||
|
; load Y position, then offset by -16
|
||||||
|
ld a, [hli]
|
||||||
|
ld c, a
|
||||||
|
ld a, [wWorkingScreenY]
|
||||||
|
add c
|
||||||
|
ld c, 16
|
||||||
|
add c
|
||||||
|
ld [de], a ; store YPos in shadowOAM
|
||||||
|
inc de
|
||||||
|
; load X position, then offset by -8
|
||||||
|
ld a, [hli]
|
||||||
|
ld c, a
|
||||||
|
ld a, [wWorkingScreenX]
|
||||||
|
add c
|
||||||
|
ld c, 8
|
||||||
|
add c
|
||||||
|
ld [de], a ; store YPos in shadowOAM
|
||||||
|
inc de
|
||||||
|
; load tile offset, and add to base tile pointer
|
||||||
|
ld a, [hli]
|
||||||
|
ld c, a
|
||||||
|
ld a, [wWorkingTile]
|
||||||
|
add c
|
||||||
|
ld [de], a
|
||||||
|
inc de
|
||||||
|
; load attributes and xor them
|
||||||
|
ld a, [hli]
|
||||||
|
ld c, a
|
||||||
|
ld a, 0 ; TO DO: set base attributes
|
||||||
|
xor c
|
||||||
|
ld [de], a
|
||||||
|
inc de
|
||||||
|
; end of single sprite
|
||||||
|
dec b
|
||||||
|
jr nz, .spriteLoop
|
||||||
|
ret
|
||||||
|
|
||||||
.skipRendering
|
BUFFER EQU 160
|
||||||
|
TRUE EQU $42
|
||||||
|
FALSE EQU $69
|
||||||
|
@ -57,3 +57,4 @@ hOAMDMA:
|
|||||||
SECTION "Shadow OAM", WRAM0,ALIGN[8]
|
SECTION "Shadow OAM", WRAM0,ALIGN[8]
|
||||||
wShadowOAM::
|
wShadowOAM::
|
||||||
ds 4*40
|
ds 4*40
|
||||||
|
wShadowOAMEnd::
|
||||||
|
138
src/entry.asm
138
src/entry.asm
@ -2,9 +2,7 @@
|
|||||||
; Program Start
|
; Program Start
|
||||||
;----------------
|
;----------------
|
||||||
|
|
||||||
BUFFER EQU 160
|
INCLUDE "src/actor.asm"
|
||||||
TRUE EQU $42
|
|
||||||
FALSE EQU $69
|
|
||||||
|
|
||||||
SECTION "Program Start", ROM0[$150]
|
SECTION "Program Start", ROM0[$150]
|
||||||
Start:
|
Start:
|
||||||
@ -17,6 +15,7 @@ Start:
|
|||||||
xor a
|
xor a
|
||||||
ldh [rLCDC], a
|
ldh [rLCDC], a
|
||||||
call Clear_Map
|
call Clear_Map
|
||||||
|
call Clear_OAM
|
||||||
call Load_Tiles
|
call Load_Tiles
|
||||||
; call Load_Map
|
; call Load_Map
|
||||||
ld a, %11100100
|
ld a, %11100100
|
||||||
@ -32,129 +31,26 @@ Start:
|
|||||||
call CopyDMARoutine
|
call CopyDMARoutine
|
||||||
|
|
||||||
ld a, 72
|
ld a, 72
|
||||||
ld [rPlayerX], a
|
ld [Player_YPos], a
|
||||||
ld a, 88
|
ld a, 80
|
||||||
ld [rPlayerY], a
|
ld [Player_XPos], a
|
||||||
|
xor a
|
||||||
;----
|
ld [Player_GFXCounter], a
|
||||||
; Testing
|
ld [Player_GFXState], a
|
||||||
;----
|
ld [Player_TileData], a
|
||||||
ld a, HIGH(ANS)
|
ld a, HIGH(ActorROM)
|
||||||
ld h, a
|
ld [Player_GFXData], a
|
||||||
ld a, LOW(ANS)
|
ld a, LOW(ActorROM)
|
||||||
ld l, a
|
ld [Player_GFXData + 1], a
|
||||||
|
|
||||||
; Case One: Camera@E100 vs Actor@E195 (Pass)
|
|
||||||
ld a, $E1
|
|
||||||
ld [N], a
|
|
||||||
ld a, $E1
|
|
||||||
ld [X], a
|
|
||||||
ld a, $00
|
|
||||||
ld [N+1], a
|
|
||||||
ld a, $95
|
|
||||||
ld [X+1], a
|
|
||||||
call CheckBoundry
|
|
||||||
|
|
||||||
; Case One: Camera@E095 vs Actor@E120 (Pass)
|
|
||||||
ld a, $E0
|
|
||||||
ld [N], a
|
|
||||||
ld a, $E1
|
|
||||||
ld [X], a
|
|
||||||
ld a, $95
|
|
||||||
ld [N+1], a
|
|
||||||
ld a, $20
|
|
||||||
ld [X+1], a
|
|
||||||
call CheckBoundry
|
|
||||||
|
|
||||||
; Case One: Camera@E100 vs Actor@E1FF (Fail)
|
|
||||||
ld a, $E1
|
|
||||||
ld [N], a
|
|
||||||
ld a, $E1
|
|
||||||
ld [X], a
|
|
||||||
ld a, $00
|
|
||||||
ld [N+1], a
|
|
||||||
ld a, $FF
|
|
||||||
ld [X+1], a
|
|
||||||
call CheckBoundry
|
|
||||||
|
|
||||||
; Case One: Camera@E1F0 vs Actor@E2DE (Fail)
|
|
||||||
ld a, $E1
|
|
||||||
ld [N], a
|
|
||||||
ld a, $E2
|
|
||||||
ld [X], a
|
|
||||||
ld a, $F0
|
|
||||||
ld [N+1], a
|
|
||||||
ld a, $DE
|
|
||||||
ld [X+1], a
|
|
||||||
call CheckBoundry
|
|
||||||
|
|
||||||
game_loop:
|
game_loop:
|
||||||
call Wait_VBlank
|
call Wait_VBlank
|
||||||
call Read_Pad
|
call Read_Pad
|
||||||
call PC_Update
|
call Clear_OAM
|
||||||
call Player_To_OAM
|
ld de, wShadowOAM
|
||||||
|
ld hl, Player
|
||||||
|
call RenderActor
|
||||||
ld a, HIGH(wShadowOAM)
|
ld a, HIGH(wShadowOAM)
|
||||||
call hOAMDMA
|
call hOAMDMA
|
||||||
jr game_loop
|
jr game_loop
|
||||||
|
|
||||||
CheckBoundry::
|
|
||||||
;-----
|
|
||||||
; Check if word X is within BUFFER ahead of N
|
|
||||||
; BUFFER is always <= 255
|
|
||||||
; hl contains address to save result to
|
|
||||||
;-----
|
|
||||||
;= load high bytes
|
|
||||||
ld a, [N]
|
|
||||||
ld b, a
|
|
||||||
ld a, [X]
|
|
||||||
sub b
|
|
||||||
;= if carry is set, N is behind X, so skip
|
|
||||||
jr c, .skipRender
|
|
||||||
ld b, a
|
|
||||||
ld a, 2
|
|
||||||
cp b
|
|
||||||
;= if the difference is 2 or greater
|
|
||||||
;= we are not within BUFFER, so skip
|
|
||||||
jr c, .skipRender
|
|
||||||
jr z, .skipRender
|
|
||||||
dec a
|
|
||||||
cp b
|
|
||||||
;= if the high byte differ by 1, we
|
|
||||||
;= need to check over a a page
|
|
||||||
jr z, .swap
|
|
||||||
;= load the low bytes
|
|
||||||
ld a, [N+1]
|
|
||||||
ld b, a
|
|
||||||
ld a, [X+1]
|
|
||||||
sub b
|
|
||||||
ld b, a
|
|
||||||
ld a, BUFFER
|
|
||||||
cp b
|
|
||||||
;= if the difference is greater than
|
|
||||||
;= the buffer, skip
|
|
||||||
jr c, .skipRender
|
|
||||||
jr .render
|
|
||||||
.swap
|
|
||||||
;= load the low bytes in the opposite order
|
|
||||||
ld a, [X+1]
|
|
||||||
ld b, a
|
|
||||||
ld a, [N+1]
|
|
||||||
sub b
|
|
||||||
ld b, a
|
|
||||||
ld a, $FF - BUFFER
|
|
||||||
cp b
|
|
||||||
;= if they differ by the inverse of the buffer
|
|
||||||
;= they will not be within the gap between pages
|
|
||||||
jr nc, .skipRender
|
|
||||||
.render
|
|
||||||
;= success, do rendering stuff
|
|
||||||
; beep boop rendering stuff
|
|
||||||
ld a, TRUE
|
|
||||||
ld [hli], a
|
|
||||||
ret
|
|
||||||
.skipRender
|
|
||||||
;= failure, skip this one
|
|
||||||
; doing other stuff here
|
|
||||||
ld a, FALSE
|
|
||||||
ld [hli], a
|
|
||||||
ret
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
INCLUDE "inc/hardware.inc"
|
INCLUDE "inc/hardware.inc"
|
||||||
|
INCLUDE "inc/structs.asm"
|
||||||
INCLUDE "ass/parecivo.ass"
|
INCLUDE "ass/parecivo.ass"
|
||||||
INCLUDE "ass/tiles.ass"
|
INCLUDE "ass/tiles.ass"
|
||||||
INCLUDE "ass/map.ass"
|
INCLUDE "ass/map.ass"
|
||||||
|
INCLUDE "src/animation.asm"
|
||||||
INCLUDE "src/entry.asm"
|
INCLUDE "src/entry.asm"
|
||||||
INCLUDE "src/header.asm"
|
INCLUDE "src/header.asm"
|
||||||
INCLUDE "src/defines.asm"
|
INCLUDE "src/defines.asm"
|
||||||
|
22
src/misc.asm
22
src/misc.asm
@ -134,16 +134,28 @@ PC_Update:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
Clear_Map:
|
Clear_OAM:
|
||||||
xor a
|
ld hl, wShadowOAM
|
||||||
ld hl, _SCRN0
|
ld bc, wShadowOAMEnd - wShadowOAM
|
||||||
ld bc, _SCRN0_END - _SCRN0
|
|
||||||
.loop:
|
.loop:
|
||||||
|
xor a
|
||||||
ld [hli], a
|
ld [hli], a
|
||||||
dec bc
|
dec bc
|
||||||
ld a, b
|
ld a, b
|
||||||
or c
|
or c
|
||||||
jr z, .loop
|
jr nz, .loop
|
||||||
|
ret
|
||||||
|
|
||||||
|
Clear_Map:
|
||||||
|
ld hl, _SCRN0
|
||||||
|
ld bc, _SCRN0_END - _SCRN0
|
||||||
|
.loop:
|
||||||
|
xor a
|
||||||
|
ld [hli], a
|
||||||
|
dec bc
|
||||||
|
ld a, b
|
||||||
|
or c
|
||||||
|
jr nz, .loop
|
||||||
ret
|
ret
|
||||||
|
|
||||||
Load_Tiles:
|
Load_Tiles:
|
||||||
|
Loading…
Reference in New Issue
Block a user