diff --git a/.gitignore b/.gitignore index 378eac2..89efb0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +*.swp diff --git a/Makefile b/Makefile index 652a748..b49a37a 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,9 @@ BUILD=./build ENTRY=${SRC}/main.asm ROM_OUTPUT=${BUILD}/${NAME}.gb OBJECT_OUTPUT=${BUILD}/${NAME}.o +SYMFILE_OUTPUT=${BUILD}/${NAME}.sym all : ${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} diff --git a/animation.sym b/animation.sym deleted file mode 100644 index a673909..0000000 --- a/animation.sym +++ /dev/null @@ -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 diff --git a/inc/structs.asm b/inc/structs.asm new file mode 100644 index 0000000..0e02c83 --- /dev/null +++ b/inc/structs.asm @@ -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 diff --git a/src/.actor.asm.swp b/src/.actor.asm.swp deleted file mode 100644 index e3410fe..0000000 Binary files a/src/.actor.asm.swp and /dev/null differ diff --git a/src/.entry.asm.swp b/src/.entry.asm.swp deleted file mode 100644 index 07c6146..0000000 Binary files a/src/.entry.asm.swp and /dev/null differ diff --git a/src/actor.asm b/src/actor.asm index 2360155..d25d022 100644 --- a/src/actor.asm +++ b/src/actor.asm @@ -2,23 +2,15 @@ ; Actor Animation ;----------------- -SECTION "Actor Variables Struct", WRAM, ALIGN[8] - -wWorldX: dw -wWorldY: dw -wActorState: db -wActorCounter: db -wActorData: dw -wActorTile: dw - SECTION "Actor", ROM0 -Actor:: +ActorROM:: .structs: dw ActorIdle .tiles: ActorIdle:: db 60 + db 15 dw .framePa db 15 dw .frameRe diff --git a/src/animation.asm b/src/animation.asm index 8835b4c..ff75495 100644 --- a/src/animation.asm +++ b/src/animation.asm @@ -2,20 +2,33 @@ ; 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 - hCameraY: dw +SECTION "Actor STructs", WRAM0 - hWorkingX: dw - hWorkingY: dw - hWorkingScreenX: db - hWorkingScreenY: db - hWorkingState: db - hWorkingCounter: db - hWorkingData: dw - hWorkingTile: dw -hWorkingEnd: + dstruct Actor, Player + +SECTION "Animation Variables", WRAM0 + +wCameraX: dw +wCameraY: dw + +wWorkingX: dw +wWorkingY: dw +wWorkingScreenX: db +wWorkingScreenY: db +wWorkingState: db +wWorkingCounter: db +wWorkingData: dw +wWorkingTile: db +wWorkingEnd: SECTION "Animations Subs", ROM0 @@ -32,28 +45,119 @@ SECTION "Animations Subs", ROM0 ; copied to shadowOAM (wShadowOAM) RenderActor:: - -; load world X and Y to temp RAM + ; @input: hl <- Player + ; @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 b, a + ld a, [hl] + ld l, b + ld h, a + 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 + jr z, .foundFrame + jr c, .foundFrame + inc hl + inc hl + jr .loopFrameFind +.foundFrame ld a, [hli] - ld [hWorkingX], a + ld b, a + ld a, [hl] + ld h, a + ld l, b ; hl <- pointer to frame data ld a, [hli] - ld [hWorkingX+1], a + ld b, a ; b <- sprite counter +.spriteLoop + ; load Y position, then offset by -16 ld a, [hli] - ld [hWorkingY], a + 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 [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 a, [hWorkingX] -; b = camera byte -; a = actor byte -; work out if actor minus camera is <= 1 - sub b -; --------- - -.skipRendering + 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 + +BUFFER EQU 160 +TRUE EQU $42 +FALSE EQU $69 diff --git a/src/dma.asm b/src/dma.asm index 90ce5c6..2ceb38d 100644 --- a/src/dma.asm +++ b/src/dma.asm @@ -57,3 +57,4 @@ hOAMDMA: SECTION "Shadow OAM", WRAM0,ALIGN[8] wShadowOAM:: ds 4*40 +wShadowOAMEnd:: diff --git a/src/entry.asm b/src/entry.asm index c35dc6d..73895c2 100644 --- a/src/entry.asm +++ b/src/entry.asm @@ -2,9 +2,7 @@ ; Program Start ;---------------- -BUFFER EQU 160 -TRUE EQU $42 -FALSE EQU $69 +INCLUDE "src/actor.asm" SECTION "Program Start", ROM0[$150] Start: @@ -17,6 +15,7 @@ Start: xor a ldh [rLCDC], a call Clear_Map + call Clear_OAM call Load_Tiles ; call Load_Map ld a, %11100100 @@ -32,129 +31,26 @@ Start: call CopyDMARoutine ld a, 72 - ld [rPlayerX], a - ld a, 88 - ld [rPlayerY], a - -;---- -; Testing -;---- - ld a, HIGH(ANS) - ld h, a - ld a, LOW(ANS) - ld l, 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 + ld [Player_YPos], a + ld a, 80 + ld [Player_XPos], a + xor a + ld [Player_GFXCounter], a + ld [Player_GFXState], a + ld [Player_TileData], a + ld a, HIGH(ActorROM) + ld [Player_GFXData], a + ld a, LOW(ActorROM) + ld [Player_GFXData + 1], a game_loop: call Wait_VBlank call Read_Pad - call PC_Update - call Player_To_OAM + call Clear_OAM + ld de, wShadowOAM + ld hl, Player + call RenderActor ld a, HIGH(wShadowOAM) call hOAMDMA 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 diff --git a/src/main.asm b/src/main.asm index 7a53691..ed34230 100644 --- a/src/main.asm +++ b/src/main.asm @@ -1,7 +1,9 @@ INCLUDE "inc/hardware.inc" +INCLUDE "inc/structs.asm" INCLUDE "ass/parecivo.ass" INCLUDE "ass/tiles.ass" INCLUDE "ass/map.ass" +INCLUDE "src/animation.asm" INCLUDE "src/entry.asm" INCLUDE "src/header.asm" INCLUDE "src/defines.asm" diff --git a/src/misc.asm b/src/misc.asm index 3912601..80aea55 100644 --- a/src/misc.asm +++ b/src/misc.asm @@ -134,16 +134,28 @@ PC_Update: ret -Clear_Map: +Clear_OAM: + ld hl, wShadowOAM + ld bc, wShadowOAMEnd - wShadowOAM +.loop: xor a + ld [hli], a + dec bc + ld a, b + or c + 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 z, .loop + jr nz, .loop ret Load_Tiles: