diff options
Diffstat (limited to 'engine')
-rw-r--r-- | engine/battle_transition.asm (renamed from engine/battle_start.asm) | 9 | ||||
-rw-r--r-- | engine/caught_data.asm | 247 | ||||
-rw-r--r-- | engine/check_nick_errors.asm | 74 | ||||
-rw-r--r-- | engine/check_time.asm | 19 | ||||
-rw-r--r-- | engine/collision_stdscripts.asm | 29 | ||||
-rw-r--r-- | engine/consume_held_item.asm | 80 | ||||
-rwxr-xr-x | engine/crystal_colors.asm | 10 | ||||
-rw-r--r-- | engine/european_mail.asm | 129 | ||||
-rw-r--r-- | engine/experience.asm | 162 | ||||
-rw-r--r-- | engine/init_map.asm | 103 | ||||
-rw-r--r-- | engine/map_objects.asm | 2 | ||||
-rw-r--r-- | engine/map_objects_2.asm | 70 | ||||
-rw-r--r-- | engine/map_palettes.asm | 86 | ||||
-rw-r--r-- | engine/menu_2.asm | 263 | ||||
-rw-r--r-- | engine/mon_stats.asm | 486 | ||||
-rw-r--r-- | engine/player_gfx.asm | 263 | ||||
-rw-r--r-- | engine/pokedex_3.asm | 162 | ||||
-rw-r--r-- | engine/pokerus.asm | 160 | ||||
-rw-r--r-- | engine/pokerus_tick.asm | 26 | ||||
-rw-r--r-- | engine/square_root.asm | 30 | ||||
-rw-r--r-- | engine/start_battle.asm | 197 | ||||
-rw-r--r-- | engine/timeofdaypals.asm | 4 | ||||
-rw-r--r-- | engine/trainer_scripts.asm | 31 | ||||
-rw-r--r-- | engine/unused_correct_party.asm | 229 |
24 files changed, 2869 insertions, 2 deletions
diff --git a/engine/battle_start.asm b/engine/battle_transition.asm index 9546980c2..f8756649b 100644 --- a/engine/battle_start.asm +++ b/engine/battle_transition.asm @@ -862,3 +862,12 @@ endm jr nz, .row ret ; 8c7c9 (23:47c9) + +Function8c7c9: +; XXX + ld a, $1 + ld [hBGMapMode], a + call WaitBGMap + xor a + ld [hBGMapMode], a + ret diff --git a/engine/caught_data.asm b/engine/caught_data.asm new file mode 100644 index 000000000..c079009ae --- /dev/null +++ b/engine/caught_data.asm @@ -0,0 +1,247 @@ +CheckPartyFullAfterContest: ; 4d9e5 + ld a, [wContestMon] + and a + jp z, .DidntCatchAnything + ld [CurPartySpecies], a + ld [CurSpecies], a + call GetBaseData + ld hl, PartyCount + ld a, [hl] + cp 6 + jp nc, .TryAddToBox + inc a + ld [hl], a + ld c, a + ld b, $0 + add hl, bc + ld a, [wContestMon] + ld [hli], a + ld [CurSpecies], a + ld a, $ff + ld [hl], a + ld hl, PartyMon1Species + ld a, [PartyCount] + dec a + ld bc, PARTYMON_STRUCT_LENGTH + call AddNTimes + ld d, h + ld e, l + ld hl, wContestMon + ld bc, PARTYMON_STRUCT_LENGTH + call CopyBytes + ld a, [PartyCount] + dec a + ld hl, PartyMonOT + call SkipNames + ld d, h + ld e, l + ld hl, PlayerName + call CopyBytes + ld a, [CurPartySpecies] + ld [wd265], a + call GetPokemonName + ld hl, StringBuffer1 + ld de, wMonOrItemNameBuffer + ld bc, PKMN_NAME_LENGTH + call CopyBytes + call GiveANickname_YesNo + jr c, .Party_SkipNickname + ld a, [PartyCount] + dec a + ld [CurPartyMon], a + xor a + ld [MonType], a + ld de, wMonOrItemNameBuffer + callab InitNickname + +.Party_SkipNickname: + ld a, [PartyCount] + dec a + ld hl, PartyMonNicknames + call SkipNames + ld d, h + ld e, l + ld hl, wMonOrItemNameBuffer + call CopyBytes + ld a, [PartyCount] + dec a + ld hl, PartyMon1Level + call GetPartyLocation + ld a, [hl] + ld [CurPartyLevel], a + call SetCaughtData + ld a, [PartyCount] + dec a + ld hl, PartyMon1CaughtLocation + call GetPartyLocation + ld a, [hl] + and $80 + ld b, $13 + or b + ld [hl], a + xor a + ld [wContestMon], a + and a + ld [ScriptVar], a + ret + +.TryAddToBox: ; 4daa3 + ld a, BANK(sBoxCount) + call GetSRAMBank + ld hl, sBoxCount + ld a, [hl] + cp MONS_PER_BOX + call CloseSRAM + jr nc, .BoxFull + xor a + ld [CurPartyMon], a + ld hl, wContestMon + ld de, wBufferMon + ld bc, BOXMON_STRUCT_LENGTH + call CopyBytes + ld hl, PlayerName + ld de, wBufferMonOT + ld bc, NAME_LENGTH + call CopyBytes + callab InsertPokemonIntoBox + ld a, [CurPartySpecies] + ld [wd265], a + call GetPokemonName + call GiveANickname_YesNo + ld hl, StringBuffer1 + jr c, .Box_SkipNickname + ld a, BOXMON + ld [MonType], a + ld de, wMonOrItemNameBuffer + callab InitNickname + ld hl, wMonOrItemNameBuffer + +.Box_SkipNickname: + ld a, BANK(sBoxMonNicknames) + call GetSRAMBank + ld de, sBoxMonNicknames + ld bc, PKMN_NAME_LENGTH + call CopyBytes + call CloseSRAM + +.BoxFull: + ld a, BANK(sBoxMon1Level) + call GetSRAMBank + ld a, [sBoxMon1Level] + ld [CurPartyLevel], a + call CloseSRAM + call SetBoxMonCaughtData + ld a, BANK(sBoxMon1CaughtLocation) + call GetSRAMBank + ld hl, sBoxMon1CaughtLocation + ld a, [hl] + and $80 + ld b, $13 + or b + ld [hl], a + call CloseSRAM + xor a + ld [wContestMon], a + ld a, $1 + ld [ScriptVar], a + ret + +.DidntCatchAnything: ; 4db35 + ld a, $2 + ld [ScriptVar], a + ret + +GiveANickname_YesNo: ; 4db3b + ld hl, TextJump_GiveANickname + call PrintText + jp YesNoBox + +TextJump_GiveANickname: ; 0x4db44 + ; Give a nickname to the @ you received? + text_jump UnknownText_0x1c12fc + db "@" + +SetCaughtData: ; 4db49 + ld a, [PartyCount] + dec a + ld hl, PartyMon1CaughtLevel + call GetPartyLocation +SetBoxmonOrEggmonCaughtData: ; 4db53 + ld a, [TimeOfDay] + inc a + rrca + rrca + ld b, a + ld a, [CurPartyLevel] + or b + ld [hli], a + ld a, [MapGroup] + ld b, a + ld a, [MapNumber] + ld c, a + cp MAP_POKECENTER_2F + jr nz, .NotPokecenter2F + ld a, b + cp GROUP_POKECENTER_2F + jr nz, .NotPokecenter2F + + ld a, [BackupMapGroup] + ld b, a + ld a, [BackupMapNumber] + ld c, a + +.NotPokecenter2F: + call GetWorldMapLocation + ld b, a + ld a, [PlayerGender] + rrca + or b + ld [hl], a + ret + +SetBoxMonCaughtData: ; 4db83 + ld a, BANK(sBoxMon1CaughtLevel) + call GetSRAMBank + ld hl, sBoxMon1CaughtLevel + call SetBoxmonOrEggmonCaughtData + call CloseSRAM + ret + +SetGiftBoxMonCaughtData: ; 4db92 + push bc + ld a, BANK(sBoxMon1CaughtLevel) + call GetSRAMBank + ld hl, sBoxMon1CaughtLevel + pop bc + call SetGiftMonCaughtData + call CloseSRAM + ret + +SetGiftPartyMonCaughtData: ; 4dba3 + ld a, [PartyCount] + dec a + ld hl, PartyMon1CaughtLevel + push bc + call GetPartyLocation + pop bc +SetGiftMonCaughtData: ; 4dbaf + xor a + ld [hli], a + ld a, $7e + rrc b + or b + ld [hl], a + ret + +SetEggMonCaughtData: ; 4dbb8 (13:5bb8) + ld a, [CurPartyMon] + ld hl, PartyMon1CaughtLevel + call GetPartyLocation + ld a, [CurPartyLevel] + push af + ld a, $1 + ld [CurPartyLevel], a + call SetBoxmonOrEggmonCaughtData + pop af + ld [CurPartyLevel], a + ret diff --git a/engine/check_nick_errors.asm b/engine/check_nick_errors.asm new file mode 100644 index 000000000..1cedca420 --- /dev/null +++ b/engine/check_nick_errors.asm @@ -0,0 +1,74 @@ +CheckNickErrors:: ; 669f +; error-check monster nick before use +; must be a peace offering to gamesharkers + +; input: de = nick location + + push bc + push de + ld b, PKMN_NAME_LENGTH + +.checkchar +; end of nick? + ld a, [de] + cp "@" ; terminator + jr z, .end + +; check if this char is a text command + ld hl, .textcommands + dec hl +.loop +; next entry + inc hl +; reached end of commands table? + ld a, [hl] + cp -1 + jr z, .done + +; is the current char between this value (inclusive)... + ld a, [de] + cp [hl] + inc hl + jr c, .loop +; ...and this one? + cp [hl] + jr nc, .loop + +; replace it with a "?" + ld a, "?" + ld [de], a + jr .loop + +.done +; next char + inc de +; reached end of nick without finding a terminator? + dec b + jr nz, .checkchar + +; change nick to "?@" + pop de + push de + ld a, "?" + ld [de], a + inc de + ld a, "@" + ld [de], a +.end +; if the nick has any errors at this point it's out of our hands + pop de + pop bc + ret + +.textcommands ; 66cf +; table defining which characters are actually text commands +; format: + ; ≥ < + db "<START>", TX_BOX + 1 + db "<PLAY_G>", $18 + 1 + db $1d, "%" + 1 + db $35, "<GREEN>" + 1 + db "<ENEMY>", "<ENEMY>" + 1 + db "<MOM>", "<TM>" + 1 + db "<ROCKET>", "┘" + 1 + db -1 ; end diff --git a/engine/check_time.asm b/engine/check_time.asm new file mode 100644 index 000000000..615b51d29 --- /dev/null +++ b/engine/check_time.asm @@ -0,0 +1,19 @@ +CheckTime:: ; c000 + ld a, [TimeOfDay] + ld hl, TimeOfDayTable + ld de, 2 + call IsInArray + inc hl + ld c, [hl] + ret c + + xor a + ld c, a + ret + +TimeOfDayTable: ; c012 + db MORN_F, MORN + db DAY_F, DAY + db NITE_F, NITE + db NITE_F, NITE + db -1 diff --git a/engine/collision_stdscripts.asm b/engine/collision_stdscripts.asm new file mode 100644 index 000000000..17b1e49b2 --- /dev/null +++ b/engine/collision_stdscripts.asm @@ -0,0 +1,29 @@ +CheckFacingTileForStd:: ; 1365b +; Checks to see if the tile you're facing has a std script associated with it. If so, executes the script and returns carry. + ld a, c + ld de, 3 + ld hl, TileCollisionStdScripts + call IsInArray + jr nc, .notintable + + ld a, jumpstd_command + ld [wJumpStdScriptBuffer], a + inc hl + ld a, [hli] + ld [wJumpStdScriptBuffer + 1], a + ld a, [hli] + ld [wJumpStdScriptBuffer + 2], a + ld a, BANK(Script_JumpStdFromRAM) + ld hl, Script_JumpStdFromRAM + call CallScript + scf + ret + +.notintable + xor a + ret + +INCLUDE "data/collision_stdscripts.asm" + +Script_JumpStdFromRAM: ; 0x1369a + jump wJumpStdScriptBuffer diff --git a/engine/consume_held_item.asm b/engine/consume_held_item.asm new file mode 100644 index 000000000..52d7894cd --- /dev/null +++ b/engine/consume_held_item.asm @@ -0,0 +1,80 @@ +ConsumeHeldItem: ; 27192 + push hl + push de + push bc + ld a, [hBattleTurn] + and a + ld hl, OTPartyMon1Item + ld de, EnemyMonItem + ld a, [CurOTMon] + jr z, .theirturn + ld hl, PartyMon1Item + ld de, BattleMonItem + ld a, [CurBattleMon] + +.theirturn + push hl + push af + ld a, [de] + ld b, a + callba GetItemHeldEffect + ld hl, .ConsumableEffects +.loop + ld a, [hli] + cp b + jr z, .ok + inc a + jr nz, .loop + pop af + pop hl + pop bc + pop de + pop hl + ret + +.ok + xor a + ld [de], a + pop af + pop hl + call GetPartyLocation + ld a, [hBattleTurn] + and a + jr nz, .ourturn + ld a, [wBattleMode] + dec a + jr z, .done + +.ourturn + ld [hl], $0 + +.done + pop bc + pop de + pop hl + ret + +.ConsumableEffects: ; 271de +; Consumable items? + db HELD_BERRY + db HELD_2 + db HELD_5 + db HELD_HEAL_POISON + db HELD_HEAL_FREEZE + db HELD_HEAL_BURN + db HELD_HEAL_SLEEP + db HELD_HEAL_PARALYZE + db HELD_HEAL_STATUS + db HELD_30 + db HELD_ATTACK_UP + db HELD_DEFENSE_UP + db HELD_SPEED_UP + db HELD_SP_ATTACK_UP + db HELD_SP_DEFENSE_UP + db HELD_ACCURACY_UP + db HELD_EVASION_UP + db HELD_38 + db HELD_71 + db HELD_ESCAPE + db HELD_CRITICAL_UP + db -1 diff --git a/engine/crystal_colors.asm b/engine/crystal_colors.asm index 125fee8bc..25b831f01 100755 --- a/engine/crystal_colors.asm +++ b/engine/crystal_colors.asm @@ -612,3 +612,13 @@ InitMG_Mobile_LinkTradePalMap: ; 49856 call _InitMG_Mobile_LinkTradePalMap ret ; 4985a + +Unknown_4985a: ; unreferenced + db $ab, $03, $57, $24, $ac, $0e, $13, $32 + db $be, $30, $5b, $4c, $47, $60, $ed, $f2 + db $ab, $03, $55, $26, $aa, $0a, $13, $3a + db $be, $28, $33, $24, $6e, $71, $df, $b0 + db $a8, $00, $e5, $e0, $9a, $fc, $f4, $2c + db $fe, $4c, $a3, $5e, $c6, $3a, $ab, $4d + db $a8, $00, $b5, $b0, $de, $e8, $fc, $1c + db $ba, $66, $f7, $0e, $ba, $5e, $43, $bd diff --git a/engine/european_mail.asm b/engine/european_mail.asm new file mode 100644 index 000000000..8f037cc43 --- /dev/null +++ b/engine/european_mail.asm @@ -0,0 +1,129 @@ +IsMailEuropean: ; 1de5c8 +; return 1 if French +; return 2 if German +; return 3 if Italian +; return 4 if Spanish +; return 0 if none of the above + ld c, $0 + ld hl, sPartyMon1MailAuthorNationality - sPartyMon1Mail + add hl, de + ld a, [hli] + cp "E" + ret nz + ld a, [hli] + inc c + cp "F" + ret z + inc c + cp "G" + ret z + inc c + cp "I" + ret z + inc c + cp "S" + ret z + ld c, $0 + ret + +; The regular font. +StandardEnglishFont: ; 1de5e6 +INCBIN "gfx/font/english.1bpp" + +; An extended font. +FrenchGermanFont: ; 1de9e6 +INCBIN "gfx/font/french_german.1bpp" + +; An even more extended font. +SpanishItalianFont: ; 1dede6 +INCBIN "gfx/font/spanish_italian.1bpp" + +HandleFrenchGermanMail: ; 1df1e6 +; called if mail is french or german +; fix 's 't 'v + ld b, sPartyMon1MailAuthor - sPartyMon1Mail + ld h, d + ld l, e +.loop + ld a, [hl] + cp $dc ; 's in french/german font + jr nz, .check_intermediate_chars + ld a, "'s" + jr .replace + +.check_intermediate_chars + sub "'s" + jr c, .dont_replace + cp "'v" - "'s" + 1 + jr nc, .dont_replace + add $cd + +.replace + ld [hl], a + +.dont_replace + inc hl + dec b + jr nz, .loop + ret + +LireLeCourrierAnglais: +DeutenEnglischenPost: ; 1df203 +; Cette fonction convertit certains des caractères anglais pour +; leur équivalent dans le jeu de caractères français. +; Diese Funktion wandelt bestimmte englische Zeichen, um ihre +; Entsprechung in der Deutschen-Zeichensatz. + ld b, sPartyMon1MailAuthor - sPartyMon1Mail + ld h, d + ld l, e +.loop + ld a, [hl] + cp "'s" + jr nz, .check_intermediate_chars + ld a, $dc + jr .replace + +.check_intermediate_chars + sub $cd + jr c, .dont_replace + cp "'v" - "'s" + 1 + jr nc, .dont_replace + add "'s" + +.replace + ld [hl], a + +.dont_replace + inc hl + dec b + jr nz, .loop + ret + +HandleSpanishItalianMail: ; 1df220 +LeerCorreosIngleses: +LeggiPostaInglese: +; This function converts certain characters between +; the English and Spanish/Italian character sets. +; Esta función convierte ciertos caracteres entre +; el juego de caracteres Inglés y Español. +; Questa funzione converte alcuni caratteri tra +; l'inglese e il set di caratteri italiani. + ld b, sPartyMon1MailAuthor - sPartyMon1Mail + ld h, d + ld l, e +.loop + ld a, [hl] + and $f0 + cp $d0 + jr nz, .dont_replace + ld a, [hl] + add $8 + and $f + or $d0 + ld [hl], a + +.dont_replace + inc hl + dec b + jr nz, .loop + ret diff --git a/engine/experience.asm b/engine/experience.asm new file mode 100644 index 000000000..c33aaf02a --- /dev/null +++ b/engine/experience.asm @@ -0,0 +1,162 @@ +CalcLevel: ; 50e1b + ld a, [TempMonSpecies] + ld [CurSpecies], a + call GetBaseData + ld d, 1 +.next_level + inc d + ld a, d + cp (MAX_LEVEL + 1) % $100 + jr z, .got_level + call CalcExpAtLevel + push hl + ld hl, TempMonExp + 2 + ld a, [hProduct + 3] + ld c, a + ld a, [hld] + sub c + ld a, [hProduct + 2] + ld c, a + ld a, [hld] + sbc c + ld a, [hProduct + 1] + ld c, a + ld a, [hl] + sbc c + pop hl + jr nc, .next_level + +.got_level + dec d + ret + +CalcExpAtLevel: ; 50e47 +; (a/b)*n**3 + c*n**2 + d*n - e + ld a, [BaseGrowthRate] + add a + add a + ld c, a + ld b, 0 + ld hl, GrowthRates + add hl, bc +; Cube the level + call .LevelSquared + ld a, d + ld [hMultiplier], a + call Multiply + +; Multiply by a + ld a, [hl] + and $f0 + swap a + ld [hMultiplier], a + call Multiply +; Divide by b + ld a, [hli] + and $f + ld [hDivisor], a + ld b, 4 + call Divide +; Push the cubic term to the stack + ld a, [hQuotient + 0] + push af + ld a, [hQuotient + 1] + push af + ld a, [hQuotient + 2] + push af +; Square the level and multiply by the lower 7 bits of c + call .LevelSquared + ld a, [hl] + and $7f + ld [hMultiplier], a + call Multiply +; Push the absolute value of the quadratic term to the stack + ld a, [hProduct + 1] + push af + ld a, [hProduct + 2] + push af + ld a, [hProduct + 3] + push af + ld a, [hli] + push af +; Multiply the level by d + xor a + ld [hMultiplicand + 0], a + ld [hMultiplicand + 1], a + ld a, d + ld [hMultiplicand + 2], a + ld a, [hli] + ld [hMultiplier], a + call Multiply +; Subtract e + ld b, [hl] + ld a, [hProduct + 3] + sub b + ld [hMultiplicand + 2], a + ld b, $0 + ld a, [hProduct + 2] + sbc b + ld [hMultiplicand + 1], a + ld a, [hProduct + 1] + sbc b + ld [hMultiplicand], a +; If bit 7 of c is set, c is negative; otherwise, it's positive + pop af + and $80 + jr nz, .subtract +; Add c*n**2 to (d*n - e) + pop bc + ld a, [hProduct + 3] + add b + ld [hMultiplicand + 2], a + pop bc + ld a, [hProduct + 2] + adc b + ld [hMultiplicand + 1], a + pop bc + ld a, [hProduct + 1] + adc b + ld [hMultiplicand], a + jr .done_quadratic + +.subtract +; Subtract c*n**2 from (d*n - e) + pop bc + ld a, [hProduct + 3] + sub b + ld [hMultiplicand + 2], a + pop bc + ld a, [hProduct + 2] + sbc b + ld [hMultiplicand + 1], a + pop bc + ld a, [hProduct + 1] + sbc b + ld [hMultiplicand], a + +.done_quadratic +; Add (a/b)*n**3 to (d*n - e +/- c*n**2) + pop bc + ld a, [hProduct + 3] + add b + ld [hMultiplicand + 2], a + pop bc + ld a, [hProduct + 2] + adc b + ld [hMultiplicand + 1], a + pop bc + ld a, [hProduct + 1] + adc b + ld [hMultiplicand], a + ret + +.LevelSquared: ; 50eed + xor a + ld [hMultiplicand + 0], a + ld [hMultiplicand + 1], a + ld a, d + ld [hMultiplicand + 2], a + ld [hMultiplier], a + jp Multiply + +INCLUDE "data/growth_rates.asm" diff --git a/engine/init_map.asm b/engine/init_map.asm new file mode 100644 index 000000000..5dd6c7b8a --- /dev/null +++ b/engine/init_map.asm @@ -0,0 +1,103 @@ +ReanchorBGMap_NoOAMUpdate:: ; 6454 + call DelayFrame + ld a, [hOAMUpdate] + push af + + ld a, $1 + ld [hOAMUpdate], a + ld a, [hBGMapMode] + push af + xor a + ld [hBGMapMode], a + + call .ReanchorBGMap + + pop af + ld [hBGMapMode], a + pop af + ld [hOAMUpdate], a + ld hl, VramState + set 6, [hl] + ret + +.ReanchorBGMap: + xor a + ld [hLCDCPointer], a + ld [hBGMapMode], a + ld a, $90 + ld [hWY], a + call OverworldTextModeSwitch + ld a, VBGMap1 / $100 + call .LoadBGMapAddrIntoHRAM + call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap + callba LoadOW_BGPal7 + callba ApplyPals + ld a, $1 + ld [hCGBPalUpdate], a + xor a + ld [hBGMapMode], a + ld [hWY], a + callba HDMATransfer_FillBGMap0WithBlack ; no need to farcall + ld a, VBGMap0 / $100 + call .LoadBGMapAddrIntoHRAM + xor a + ld [wBGMapAnchor], a + ld a, VBGMap0 / $100 + ld [wBGMapAnchor + 1], a + xor a + ld [hSCX], a + ld [hSCY], a + call ApplyBGMapAnchorToObjects + ret + +.LoadBGMapAddrIntoHRAM: ; 64b9 + ld [hBGMapAddress + 1], a + xor a + ld [hBGMapAddress], a + ret + +LoadFonts_NoOAMUpdate:: ; 64bf + ld a, [hOAMUpdate] + push af + ld a, $1 + ld [hOAMUpdate], a + + call .LoadGFX + + pop af + ld [hOAMUpdate], a + ret + +.LoadGFX: + call LoadFontsExtra + ld a, $90 + ld [hWY], a + call SafeUpdateSprites + call LoadStandardFont + ret + +HDMATransfer_FillBGMap0WithBlack: ; 64db + ld a, [rSVBK] + push af + ld a, $6 + ld [rSVBK], a + + ld a, "<BLACK>" ; $60 + ld hl, wDecompressScratch + ld bc, wScratchAttrMap - wDecompressScratch + call ByteFill + ld a, wDecompressScratch / $100 + ld [rHDMA1], a + ld a, wDecompressScratch % $100 + ld [rHDMA2], a + ld a, (VBGMap0 % $8000) / $100 + ld [rHDMA3], a + ld a, (VBGMap0 % $8000) % $100 + ld [rHDMA4], a + ld a, $3f + ld [hDMATransfer], a + call DelayFrame + + pop af + ld [rSVBK], a + ret diff --git a/engine/map_objects.asm b/engine/map_objects.asm index 162ea22df..4b8adb75f 100644 --- a/engine/map_objects.asm +++ b/engine/map_objects.asm @@ -1,7 +1,5 @@ - INCLUDE "data/facings.asm" - INCLUDE "data/map_objects.asm" diff --git a/engine/map_objects_2.asm b/engine/map_objects_2.asm new file mode 100644 index 000000000..3c9a9773c --- /dev/null +++ b/engine/map_objects_2.asm @@ -0,0 +1,70 @@ +LoadObjectMasks: ; 2454f + ld hl, wObjectMasks + xor a + ld bc, NUM_OBJECTS + call ByteFill + nop + ld bc, MapObjects + ld de, wObjectMasks + xor a +.loop + push af + push bc + push de + call GetObjectTimeMask + jr c, .next + call CheckObjectFlag +.next + pop de + ld [de], a + inc de + pop bc + ld hl, OBJECT_LENGTH + add hl, bc + ld b, h + ld c, l + pop af + inc a + cp NUM_OBJECTS + jr nz, .loop + ret + +CheckObjectFlag: ; 2457d (9:457d) + ld hl, MAPOBJECT_SPRITE + add hl, bc + ld a, [hl] + and a + jr z, .masked + ld hl, MAPOBJECT_EVENT_FLAG + add hl, bc + ld a, [hli] + ld e, a + ld a, [hl] + ld d, a + cp -1 + jr nz, .check + ld a, e + cp -1 + jr z, .unmasked + jr .masked +.check + ld b, CHECK_FLAG + call EventFlagAction + ld a, c + and a + jr nz, .masked +.unmasked + xor a + ret + +.masked + ld a, -1 + scf + ret + +GetObjectTimeMask: ; 245a7 (9:45a7) + call CheckObjectTime + ld a, -1 + ret c + xor a + ret diff --git a/engine/map_palettes.asm b/engine/map_palettes.asm new file mode 100644 index 000000000..ffeef7bf6 --- /dev/null +++ b/engine/map_palettes.asm @@ -0,0 +1,86 @@ +SwapTextboxPalettes:: ; 4c000 + hlcoord 0, 0 + decoord 0, 0, AttrMap + ld b, SCREEN_HEIGHT +.loop + push bc + ld c, SCREEN_WIDTH +.innerloop + ld a, [hl] + push hl + srl a + jr c, .UpperNybble + ld hl, TilesetPalettes + add [hl] + ld l, a + ld a, [TilesetPalettes + 1] + adc $0 + ld h, a + ld a, [hl] + and $f + jr .next + +.UpperNybble: + ld hl, TilesetPalettes + add [hl] + ld l, a + ld a, [TilesetPalettes + 1] + adc $0 + ld h, a + ld a, [hl] + swap a + and $f + +.next + pop hl + ld [de], a + res 7, [hl] + inc hl + inc de + dec c + jr nz, .innerloop + pop bc + dec b + jr nz, .loop + ret + +ScrollBGMapPalettes:: ; 4c03f + ld hl, BGMapBuffer + ld de, BGMapPalBuffer +.loop + ld a, [hl] + push hl + srl a + jr c, .UpperNybble + +; .LowerNybble + ld hl, TilesetPalettes + add [hl] + ld l, a + ld a, [TilesetPalettes + 1] + adc $0 + ld h, a + ld a, [hl] + and $f + jr .next + +.UpperNybble: + ld hl, TilesetPalettes + add [hl] + ld l, a + ld a, [TilesetPalettes + 1] + adc $0 + ld h, a + ld a, [hl] + swap a + and $f + +.next + pop hl + ld [de], a + res 7, [hl] + inc hl + inc de + dec c + jr nz, .loop + ret diff --git a/engine/menu_2.asm b/engine/menu_2.asm new file mode 100644 index 000000000..13568f3c5 --- /dev/null +++ b/engine/menu_2.asm @@ -0,0 +1,263 @@ +PlaceMenuItemName: ; 0x24ab4 + push de + ld a, [MenuSelection] + ld [wNamedObjectIndexBuffer], a + call GetItemName + pop hl + call PlaceString + ret + +PlaceMenuItemQuantity: ; 0x24ac3 + push de + ld a, [MenuSelection] + ld [CurItem], a + callba _CheckTossableItem + ld a, [wItemAttributeParamBuffer] + pop hl + and a + jr nz, .done + ld de, $15 + add hl, de + ld [hl], "×" + inc hl + ld de, MenuSelectionQuantity + lb bc, 1, 2 + call PrintNum + +.done + ret + +PlaceMoneyTopRight: ; 24ae8 + ld hl, MenuDataHeader_0x24b15 + call CopyMenuDataHeader + jr PlaceMoneyDataHeader + +PlaceMoneyBottomLeft: ; 24af0 + ld hl, MenuDataHeader_0x24b1d + call CopyMenuDataHeader + jr PlaceMoneyDataHeader + +PlaceMoneyAtTopLeftOfTextbox: ; 24af8 + ld hl, MenuDataHeader_0x24b15 + lb de, 0, 11 + call OffsetMenuDataHeader + +PlaceMoneyDataHeader: ; 24b01 + call MenuBox + call MenuBoxCoord2Tile + ld de, SCREEN_WIDTH + 1 + add hl, de + ld de, Money + lb bc, PRINTNUM_MONEY | 3, 6 + call PrintNum + ret + +MenuDataHeader_0x24b15: ; 0x24b15 + db $40 ; flags + db 00, 11 ; start coords + db 02, 19 ; end coords + dw NULL + db 1 ; default option + +MenuDataHeader_0x24b1d: ; 0x24b1d + db $40 ; flags + db 11, 00 ; start coords + db 13, 08 ; end coords + dw NULL + db 1 ; default option + +Special_DisplayCoinCaseBalance: ; 24b25 + ; Place a text box of size 1x7 at 11, 0. + hlcoord 11, 0 + ld b, 1 + ld c, 7 + call TextBox + hlcoord 12, 0 + ld de, CoinString + call PlaceString + hlcoord 17, 1 + ld de, ShowMoney_TerminatorString + call PlaceString + ld de, Coins + lb bc, 2, 4 + hlcoord 13, 1 + call PrintNum + ret + +Special_DisplayMoneyAndCoinBalance: ; 24b4e + hlcoord 5, 0 + ld b, 3 + ld c, 13 + call TextBox + hlcoord 6, 1 + ld de, MoneyString + call PlaceString + hlcoord 12, 1 + ld de, Money + lb bc, PRINTNUM_MONEY | 3, 6 + call PrintNum + hlcoord 6, 3 + ld de, CoinString + call PlaceString + hlcoord 15, 3 + ld de, Coins + lb bc, 2, 4 + call PrintNum + ret + +MoneyString: ; 24b83 + db "MONEY@" +CoinString: ; 24b89 + db "COIN@" +ShowMoney_TerminatorString: ; 24b8e + db "@" + +Function24b8f: ; 24b8f +; unreferenced, related to safari? + ld hl, Options + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + hlcoord 0, 0 + ld b, 3 + ld c, 7 + call TextBox + hlcoord 1, 1 + ld de, wSafariTimeRemaining + lb bc, 2, 3 + call PrintNum + hlcoord 4, 1 + ld de, .slash_500 + call PlaceString + hlcoord 1, 3 + ld de, .booru_ko + call PlaceString + hlcoord 5, 3 + ld de, wSafariBallsRemaining + lb bc, 1, 2 + call PrintNum + pop af + ld [Options], a + ret + +.slash_500 ; 24bcf + db "/500@" +.booru_ko ; 24bd4 + db "ボール こ@" + +StartMenu_DrawBugContestStatusBox: ; 24bdc + hlcoord 0, 0 + ld b, 5 + ld c, 17 + call TextBox + ret + +StartMenu_PrintBugContestStatus: ; 24be7 + ld hl, Options + ld a, [hl] + push af + set NO_TEXT_SCROLL, [hl] + call StartMenu_DrawBugContestStatusBox + hlcoord 1, 5 + ld de, .Balls_EN + call PlaceString + hlcoord 8, 5 + ld de, wParkBallsRemaining + lb bc, PRINTNUM_RIGHTALIGN | 1, 2 + call PrintNum + hlcoord 1, 1 + ld de, .CAUGHT + call PlaceString + ld a, [wContestMon] + and a + ld de, .None + jr z, .no_contest_mon + ld [wd265], a + call GetPokemonName + +.no_contest_mon + hlcoord 8, 1 + call PlaceString + ld a, [wContestMon] + and a + jr z, .skip_level + hlcoord 1, 3 + ld de, .LEVEL + call PlaceString + ld a, [wContestMonLevel] + ld h, b + ld l, c + inc hl + ld c, 3 + call Print8BitNumRightAlign + +.skip_level + pop af + ld [Options], a + ret + +.Balls_JP: ; 24c43 + db "ボール こ@" +.CAUGHT: ; 24c4b + db "CAUGHT@" +.Balls_EN: ; 24c52 + db "BALLS:@" +.None: ; 24c59 + db "None@" +.LEVEL: ; 24c5e + db "LEVEL@" + +FindApricornsInBag: ; 24c64 +; Checks the bag for Apricorns. + ld hl, Buffer1 + xor a + ld [hli], a + dec a + ld bc, 10 + call ByteFill + + ld hl, .ApricornBalls +.loop + ld a, [hl] + cp -1 + jr z, .done + push hl + ld [CurItem], a + ld hl, NumItems + call CheckItem + pop hl + jr nc, .nope + ld a, [hl] + call .addtobuffer +.nope + inc hl + inc hl + jr .loop + +.done + ld a, [Buffer1] + and a + ret nz + scf + ret + +.addtobuffer ; 24c94 + push hl + ld hl, Buffer1 + inc [hl] + ld e, [hl] + ld d, 0 + add hl, de + ld [hl], a + pop hl + ret + +.ApricornBalls: ; 24ca0 + db RED_APRICORN, LEVEL_BALL + db BLU_APRICORN, LURE_BALL + db YLW_APRICORN, MOON_BALL + db GRN_APRICORN, FRIEND_BALL + db WHT_APRICORN, FAST_BALL + db BLK_APRICORN, HEAVY_BALL + db PNK_APRICORN, LOVE_BALL + db -1 diff --git a/engine/mon_stats.asm b/engine/mon_stats.asm new file mode 100644 index 000000000..ec468be16 --- /dev/null +++ b/engine/mon_stats.asm @@ -0,0 +1,486 @@ +DrawPlayerHP: ; 50b0a + ld a, $1 + jr DrawHP + +DrawEnemyHP: ; 50b0e + ld a, $2 + +DrawHP: ; 50b10 + ld [wWhichHPBar], a + push hl + push bc + ; box mons have full HP + ld a, [MonType] + cp BOXMON + jr z, .at_least_1_hp + + ld a, [TempMonHP] + ld b, a + ld a, [TempMonHP + 1] + ld c, a + +; Any HP? + or b + jr nz, .at_least_1_hp + + xor a + ld c, a + ld e, a + ld a, 6 + ld d, a + jp .fainted + +.at_least_1_hp + ld a, [TempMonMaxHP] + ld d, a + ld a, [TempMonMaxHP + 1] + ld e, a + ld a, [MonType] + cp BOXMON + jr nz, .not_boxmon + + ld b, d + ld c, e + +.not_boxmon + predef ComputeHPBarPixels + ld a, 6 + ld d, a + ld c, a + +.fainted + ld a, c + pop bc + ld c, a + pop hl + push de + push hl + push hl + call DrawBattleHPBar + pop hl + +; Print HP + bccoord 1, 1, 0 + add hl, bc + ld de, TempMonHP + ld a, [MonType] + cp BOXMON + jr nz, .not_boxmon_2 + ld de, TempMonMaxHP +.not_boxmon_2 + lb bc, 2, 3 + call PrintNum + + ld a, "/" + ld [hli], a + +; Print max HP + ld de, TempMonMaxHP + lb bc, 2, 3 + call PrintNum + pop hl + pop de + ret + +PrintTempMonStats: ; 50b7b +; Print TempMon's stats at hl, with spacing bc. + push bc + push hl + ld de, .StatNames + call PlaceString + pop hl + pop bc + add hl, bc + ld bc, SCREEN_WIDTH + add hl, bc + ld de, TempMonAttack + lb bc, 2, 3 + call .PrintStat + ld de, TempMonDefense + call .PrintStat + ld de, TempMonSpclAtk + call .PrintStat + ld de, TempMonSpclDef + call .PrintStat + ld de, TempMonSpeed + jp PrintNum + +.PrintStat: ; 50bab + push hl + call PrintNum + pop hl + ld de, SCREEN_WIDTH * 2 + add hl, de + ret + +.StatNames: ; 50bb5 + db "ATTACK" + next "DEFENSE" + next "SPCL.ATK" + next "SPCL.DEF" + next "SPEED" + next "@" + +GetGender: ; 50bdd +; Return the gender of a given monster (CurPartyMon/CurOTMon/CurWildMon). +; When calling this function, a should be set to an appropriate MonType value. + +; return values: +; a = 1: f = nc|nz; male +; a = 0: f = nc|z; female +; f = c: genderless + +; This is determined by comparing the Attack and Speed DVs +; with the species' gender ratio. + +; Figure out what type of monster struct we're looking at. + +; 0: PartyMon + ld hl, PartyMon1DVs + ld bc, PARTYMON_STRUCT_LENGTH + ld a, [MonType] + and a + jr z, .PartyMon + +; 1: OTPartyMon + ld hl, OTPartyMon1DVs + dec a + jr z, .PartyMon + +; 2: sBoxMon + ld hl, sBoxMon1DVs + ld bc, BOXMON_STRUCT_LENGTH + dec a + jr z, .sBoxMon + +; 3: Unknown + ld hl, TempMonDVs + dec a + jr z, .DVs + +; else: WildMon + ld hl, EnemyMonDVs + jr .DVs + +; Get our place in the party/box. + +.PartyMon: +.sBoxMon + ld a, [CurPartyMon] + call AddNTimes + +.DVs: + +; sBoxMon data is read directly from SRAM. + ld a, [MonType] + cp BOXMON + ld a, 1 + call z, GetSRAMBank + +; Attack DV + ld a, [hli] + and $f0 + ld b, a +; Speed DV + ld a, [hl] + and $f0 + swap a + +; Put our DVs together. + or b + ld b, a + +; Close SRAM if we were dealing with a sBoxMon. + ld a, [MonType] + cp BOXMON + call z, CloseSRAM + +; We need the gender ratio to do anything with this. + push bc + ld a, [CurPartySpecies] + dec a + ld hl, BaseData + BASE_GENDER + ld bc, BASE_DATA_SIZE + call AddNTimes + pop bc + + ld a, BANK(BaseData) + call GetFarByte + +; The higher the ratio, the more likely the monster is to be female. + + cp GENDERLESS + jr z, .Genderless + + and a ; GENDER_F0? + jr z, .Male + + cp GENDER_F100 + jr z, .Female + +; Values below the ratio are male, and vice versa. + cp b + jr c, .Male + +.Female: + xor a + ret + +.Male: + ld a, 1 + and a + ret + +.Genderless: + scf + ret + +ListMovePP: ; 50c50 + ld a, [wNumMoves] + inc a + ld c, a + ld a, NUM_MOVES + sub c + ld b, a + push hl + ld a, [Buffer1] + ld e, a + ld d, $0 + ld a, $3e ; P + call .load_loop + ld a, b + and a + jr z, .skip + ld c, a + ld a, "-" + call .load_loop + +.skip + pop hl + inc hl + inc hl + inc hl + ld d, h + ld e, l + ld hl, TempMonMoves + ld b, 0 +.loop + ld a, [hli] + and a + jr z, .done + push bc + push hl + push de + ld hl, wMenuCursorY + ld a, [hl] + push af + ld [hl], b + push hl + callab GetMaxPPOfMove + pop hl + pop af + ld [hl], a + pop de + pop hl + push hl + ld bc, TempMonPP - (TempMonMoves + 1) + add hl, bc + ld a, [hl] + and $3f + ld [StringBuffer1 + 4], a + ld h, d + ld l, e + push hl + ld de, StringBuffer1 + 4 + lb bc, 1, 2 + call PrintNum + ld a, "/" + ld [hli], a + ld de, wd265 + lb bc, 1, 2 + call PrintNum + pop hl + ld a, [Buffer1] + ld e, a + ld d, 0 + add hl, de + ld d, h + ld e, l + pop hl + pop bc + inc b + ld a, b + cp NUM_MOVES + jr nz, .loop + +.done + ret + +.load_loop ; 50cc9 + ld [hli], a + ld [hld], a + add hl, de + dec c + jr nz, .load_loop + ret + +Function50cd0: ; 50cd0 +; XXX +.loop + ld [hl], $32 + inc hl + ld [hl], $3e + dec hl + add hl, de + dec c + jr nz, .loop + ret + +Predef22: ; unreferenced predef + push hl + push hl + ld hl, PartyMonNicknames + ld a, [CurPartyMon] + call GetNick + pop hl + call PlaceString + call CopyPkmnToTempMon + pop hl + ld a, [CurPartySpecies] + cp EGG + jr z, .egg + push hl + ld bc, -12 + add hl, bc + ld b, $0 + call DrawEnemyHP + pop hl + ld bc, 5 + add hl, bc + push de + call PrintLevel + pop de + +.egg + ret + +PlaceStatusString: ; 50d0a + push de + inc de + inc de + ld a, [de] + ld b, a + inc de + ld a, [de] + or b + pop de + jr nz, PlaceNonFaintStatus + push de + ld de, FntString + call CopyStatusString + pop de + ld a, $1 + and a + ret + +FntString: ; 50d22 + db "FNT@" + +CopyStatusString: ; 50d25 + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hli], a + ld a, [de] + ld [hl], a + ret + +PlaceNonFaintStatus: ; 50d2e + push de + ld a, [de] + ld de, PsnString + bit PSN, a + jr nz, .place + ld de, BrnString + bit BRN, a + jr nz, .place + ld de, FrzString + bit FRZ, a + jr nz, .place + ld de, ParString + bit PAR, a + jr nz, .place + ld de, SlpString + and SLP + jr z, .no_status + +.place + call CopyStatusString + ld a, $1 + and a + +.no_status + pop de + ret + +SlpString: db "SLP@" +PsnString: db "PSN@" +BrnString: db "BRN@" +FrzString: db "FRZ@" +ParString: db "PAR@" + +ListMoves: ; 50d6f +; List moves at hl, spaced every [Buffer1] tiles. + ld de, wListMoves_MoveIndicesBuffer + ld b, $0 +.moves_loop + ld a, [de] + inc de + and a + jr z, .no_more_moves + push de + push hl + push hl + ld [CurSpecies], a + ld a, MOVE_NAME + ld [wNamedObjectTypeBuffer], a + call GetName + ld de, StringBuffer1 + pop hl + push bc + call PlaceString + pop bc + ld a, b + ld [wNumMoves], a + inc b + pop hl + push bc + ld a, [Buffer1] + ld c, a + ld b, 0 + add hl, bc + pop bc + pop de + ld a, b + cp NUM_MOVES + jr z, .done + jr .moves_loop + +.no_more_moves + ld a, b +.nonmove_loop + push af + ld [hl], "-" + ld a, [Buffer1] + ld c, a + ld b, 0 + add hl, bc + pop af + inc a + cp NUM_MOVES + jr nz, .nonmove_loop + +.done + ret diff --git a/engine/player_gfx.asm b/engine/player_gfx.asm new file mode 100644 index 000000000..1af444d73 --- /dev/null +++ b/engine/player_gfx.asm @@ -0,0 +1,263 @@ +Function88248: ; 88248 +; XXX + ld c, CAL + ld a, [PlayerGender] + bit 0, a + jr z, .okay + ld c, KAREN + +.okay + ld a, c + ld [TrainerClass], a + ret + +MovePlayerPicRight: ; 88258 + hlcoord 6, 4 + ld de, 1 + jr MovePlayerPic + +MovePlayerPicLeft: ; 88260 + hlcoord 13, 4 + ld de, -1 + ; fallthrough + +MovePlayerPic: ; 88266 +; Move player pic at hl by de * 7 tiles. + ld c, $8 +.loop + push bc + push hl + push de + xor a + ld [hBGMapMode], a + lb bc, 7, 7 + predef PlaceGraphic + xor a + ld [hBGMapThird], a + call WaitBGMap + call DelayFrame + pop de + pop hl + add hl, de + pop bc + dec c + ret z + push hl + push bc + ld a, l + sub e + ld l, a + ld a, h + sbc d + ld h, a + lb bc, 7, 7 + call ClearBox + pop bc + pop hl + jr .loop + +ShowPlayerNamingChoices: ; 88297 + ld hl, ChrisNameMenuHeader + ld a, [PlayerGender] + bit 0, a + jr z, .GotGender + ld hl, KrisNameMenuHeader +.GotGender: + call LoadMenuDataHeader + call VerticalMenu + ld a, [wMenuCursorY] + dec a + call CopyNameFromMenu + call CloseWindow + ret + +ChrisNameMenuHeader: ; 882b5 + db $40 ; flags + db 00, 00 ; start coords + db 11, 10 ; end coords + dw .MaleNames + db 1 ; ???? + db 0 ; default option + +.MaleNames: ; 882be + db $91 ; flags + db 5 ; items + db "NEW NAME@" +MalePlayerNameArray: ; 882c9 + db "CHRIS@" + db "MAT@" + db "ALLAN@" + db "JON@" + db 2 ; displacement + db " NAME @" ; title + +KrisNameMenuHeader: ; 882e5 + db $40 ; flags + db 00, 00 ; start coords + db 11, 10 ; end coords + dw .FemaleNames + db 1 ; ???? + db 0 ; default option + +.FemaleNames: ; 882ee + db $91 ; flags + db 5 ; items + db "NEW NAME@" +FemalePlayerNameArray: ; 882f9 + db "KRIS@" + db "AMANDA@" + db "JUANA@" + db "JODI@" + db 2 ; displacement + db " NAME @" ; title + +GetPlayerNameArray: ; 88318 This Function is never called + ld hl, PlayerName + ld de, MalePlayerNameArray + ld a, [PlayerGender] + bit 0, a + jr z, .done + ld de, FemalePlayerNameArray + +.done + call InitName + ret + +GetPlayerIcon: ; 8832c +; Get the player icon corresponding to gender + +; Male + ld de, ChrisSpriteGFX + ld b, BANK(ChrisSpriteGFX) + + ld a, [PlayerGender] + bit 0, a + jr z, .done + +; Female + ld de, KrisSpriteGFX + ld b, BANK(KrisSpriteGFX) + +.done + ret + +GetCardPic: ; 8833e + ld hl, ChrisCardPic + ld a, [PlayerGender] + bit 0, a + jr z, .GotClass + ld hl, KrisCardPic +.GotClass: + ld de, VTiles2 tile $00 + ld bc, $23 tiles + ld a, BANK(ChrisCardPic) ; BANK(KrisCardPic) + call FarCopyBytes + ld hl, CardGFX + ld de, VTiles2 tile $23 + ld bc, 6 tiles + ld a, BANK(CardGFX) + call FarCopyBytes + ret + +ChrisCardPic: ; 88365 +INCBIN "gfx/trainer_card/chris_card.2bpp" + +KrisCardPic: ; 88595 +INCBIN "gfx/trainer_card/kris_card.2bpp" + +CardGFX: ; 887c5 +INCBIN "gfx/trainer_card/trainer_card.2bpp" + +GetPlayerBackpic: ; 88825 + ld a, [PlayerGender] + bit 0, a + jr z, GetChrisBackpic + call GetKrisBackpic + ret + +GetChrisBackpic: ; 88830 + ld hl, ChrisBackpic + ld b, BANK(ChrisBackpic) + ld de, VTiles2 tile $31 + ld c, 7 * 7 + predef DecompressPredef + ret + +HOF_LoadTrainerFrontpic: ; 88840 + call WaitBGMap + xor a + ld [hBGMapMode], a + ld e, 0 + ld a, [PlayerGender] + bit 0, a + jr z, .GotClass + ld e, 1 + +.GotClass: + ld a, e + ld [TrainerClass], a + ld de, ChrisPic + ld a, [PlayerGender] + bit 0, a + jr z, .GotPic + ld de, KrisPic + +.GotPic: + ld hl, VTiles2 + ld b, BANK(ChrisPic) ; BANK(KrisPic) + ld c, 7 * 7 + call Get2bpp + call WaitBGMap + ld a, $1 + ld [hBGMapMode], a + ret + +DrawIntroPlayerPic: ; 88874 +; Draw the player pic at (6,4). + +; Get class + ld e, CHRIS + ld a, [PlayerGender] + bit 0, a + jr z, .GotClass + ld e, KRIS +.GotClass: + ld a, e + ld [TrainerClass], a + +; Load pic + ld de, ChrisPic + ld a, [PlayerGender] + bit 0, a + jr z, .GotPic + ld de, KrisPic +.GotPic: + ld hl, VTiles2 + ld b, BANK(ChrisPic) ; BANK(KrisPic) + ld c, 7 * 7 ; dimensions + call Get2bpp + +; Draw + xor a + ld [hGraphicStartTile], a + hlcoord 6, 4 + lb bc, 7, 7 + predef PlaceGraphic + ret + +ChrisPic: ; 888a9 +INCBIN "gfx/player/chris.2bpp" + +KrisPic: ; 88bb9 +INCBIN "gfx/player/kris.2bpp" + +GetKrisBackpic: ; 88ec9 +; Kris's backpic is uncompressed. + ld de, KrisBackpic + ld hl, VTiles2 tile $31 + lb bc, BANK(KrisBackpic), 7 * 7 ; dimensions + call Get2bpp + ret + +KrisBackpic: ; 88ed6 +INCBIN "gfx/player/kris_back.2bpp" diff --git a/engine/pokedex_3.asm b/engine/pokedex_3.asm new file mode 100644 index 000000000..3414252c1 --- /dev/null +++ b/engine/pokedex_3.asm @@ -0,0 +1,162 @@ +LoadSGBPokedexGFX: ; 1ddf1c + ld hl, SGBPokedexGFX_LZ + ld de, VTiles2 tile $31 + call Decompress + ret + +LoadSGBPokedexGFX2: ; 1ddf26 (77:5f26) + ld hl, SGBPokedexGFX_LZ + ld de, VTiles2 tile $31 + lb bc, BANK(SGBPokedexGFX_LZ), $3a + call DecompressRequest2bpp + ret + +SGBPokedexGFX_LZ: ; 1ddf33 +INCBIN "gfx/pokedex/sgb.2bpp.lz" + +LoadQuestionMarkPic: ; 1de0d7 + ld hl, .QuestionMarkLZ + ld de, sScratch + call Decompress + ret + +.QuestionMarkLZ: ; 1de0e1 +INCBIN "gfx/pics/questionmark/front.2bpp.lz" + +DrawPokedexListWindow: ; 1de171 (77:6171) + ld a, $32 + hlcoord 0, 17 + ld bc, 12 + call ByteFill + hlcoord 0, 1 + lb bc, 15, 11 + call ClearBox + ld a, $34 + hlcoord 0, 0 + ld bc, 11 + call ByteFill + ld a, $39 + hlcoord 0, 16 + ld bc, 11 + call ByteFill + hlcoord 5, 0 + ld [hl], $3f + hlcoord 5, 16 + ld [hl], $40 + ld a, [wCurrentDexMode] + cp DEXMODE_OLD + jr z, .OldMode +; scroll bar + hlcoord 11, 0 + ld [hl], $50 + ld a, $51 + hlcoord 11, 1 + ld b, SCREEN_HEIGHT - 3 + call Bank77_FillColumn + ld [hl], $52 + jr .Done + +.OldMode: +; no scroll bar + hlcoord 11, 0 + ld [hl], $66 + ld a, $67 + hlcoord 11, 1 + ld b, SCREEN_HEIGHT - 3 + call Bank77_FillColumn + ld [hl], $68 +.Done: + ret + +DrawPokedexSearchResultsWindow: ; 1de1d1 (77:61d1) + ld a, $34 + hlcoord 0, 0 + ld bc, 11 + call ByteFill + ld a, $39 + hlcoord 0, 10 + ld bc, 11 + call ByteFill + hlcoord 5, 0 + ld [hl], $3f + hlcoord 5, 10 + ld [hl], $40 + hlcoord 11, 0 + ld [hl], $66 + ld a, $67 + hlcoord 11, 1 + ld b, SCREEN_HEIGHT / 2 + call Bank77_FillColumn + ld [hl], $68 + ld a, $34 + hlcoord 0, 11 + ld bc, 11 + call ByteFill + ld a, $39 + hlcoord 0, 17 + ld bc, 11 + call ByteFill + hlcoord 11, 11 + ld [hl], $66 + ld a, $67 + hlcoord 11, 12 + ld b, 5 + call Bank77_FillColumn + ld [hl], $68 + hlcoord 0, 12 + lb bc, 5, 11 + call ClearBox + ld de, .esults_D + hlcoord 0, 12 + call PlaceString + ret + +.esults_D ; 1de23c +; (SEARCH R) + db "ESULTS" + next "" +; (### FOUN) + next "D!@" + +DrawDexEntryScreenRightEdge: ; 1de247 + ld a, [hBGMapAddress] + ld l, a + ld a, [hBGMapAddress + 1] + ld h, a + push hl + inc hl + ld a, l + ld [hBGMapAddress], a + ld a, h + ld [hBGMapAddress + 1], a + hlcoord 19, 0 + ld [hl], $66 + hlcoord 19, 1 + ld a, $67 + ld b, 15 + call Bank77_FillColumn + ld [hl], $68 + hlcoord 19, 17 + ld [hl], $3c + xor a + ld b, SCREEN_HEIGHT + hlcoord 19, 0, AttrMap + call Bank77_FillColumn + call WaitBGMap2 + pop hl + ld a, l + ld [hBGMapAddress], a + ld a, h + ld [hBGMapAddress + 1], a + ret + +Bank77_FillColumn: ; 1de27f + push de + ld de, SCREEN_WIDTH +.loop + ld [hl], a + add hl, de + dec b + jr nz, .loop + pop de + ret diff --git a/engine/pokerus.asm b/engine/pokerus.asm new file mode 100644 index 000000000..3e5e094e4 --- /dev/null +++ b/engine/pokerus.asm @@ -0,0 +1,160 @@ +GivePokerusAndConvertBerries: ; 2ed44 + call ConvertBerriesToBerryJuice + ld hl, PartyMon1PokerusStatus + ld a, [PartyCount] + ld b, a + ld de, PARTYMON_STRUCT_LENGTH +; Check to see if any of your Pokemon already has Pokerus. +; If so, sample its spread through your party. +; This means that you cannot get Pokerus de novo while +; a party member has an active infection. +.loopMons + ld a, [hl] + and $f + jr nz, .TrySpreadPokerus + add hl, de + dec b + jr nz, .loopMons + +; If we haven't been to Goldenrod City at least once, +; prevent the contraction of Pokerus. + ld hl, StatusFlags2 + bit 6, [hl] + ret z + call Random + ld a, [hRandomAdd] + and a + ret nz + ld a, [hRandomSub] + cp $3 + ret nc ; 3/65536 chance (00 00, 00 01 or 00 02) + ld a, [PartyCount] + ld b, a +.randomMonSelectLoop + call Random + and $7 + cp b + jr nc, .randomMonSelectLoop + ld hl, PartyMon1PokerusStatus + call GetPartyLocation ; get pokerus byte of random mon + ld a, [hl] + and $f0 + ret nz ; if it already has pokerus, do nothing +.randomPokerusLoop ; Simultaneously sample the strain and duration + call Random + and a + jr z, .randomPokerusLoop + ld b, a + and $f0 + jr z, .load_pkrs + ld a, b + and $7 + inc a +.load_pkrs + ld b, a ; this should come before the label + swap b + and $3 + inc a + add b + ld [hl], a + ret + +.TrySpreadPokerus: + call Random + cp 1 + 33 percent + ret nc ; 1/3 chance + + ld a, [PartyCount] + cp 1 + ret z ; only one mon, nothing to do + + ld c, [hl] + ld a, b + cp 2 + jr c, .checkPreviousMonsLoop ; no more mons after this one, go backwards + + call Random + cp 1 + 50 percent + jr c, .checkPreviousMonsLoop ; 1/2 chance, go backwards +.checkFollowingMonsLoop + add hl, de + ld a, [hl] + and a + jr z, .infectMon + ld c, a + and $3 + ret z ; if mon has cured pokerus, stop searching + dec b ; go on to next mon + ld a, b + cp 1 + jr nz, .checkFollowingMonsLoop ; no more mons left + ret + +.checkPreviousMonsLoop + ld a, [PartyCount] + cp b + ret z ; no more mons + ld a, l + sub e + ld l, a + ld a, h + sbc d + ld h, a + ld a, [hl] + and a + jr z, .infectMon + ld c, a + and $3 + ret z ; if mon has cured pokerus, stop searching + inc b ; go on to next mon + jr .checkPreviousMonsLoop + +.infectMon + ld a, c + and $f0 + ld b, a + ld a, c + swap a + and $3 + inc a + add b + ld [hl], a + ret + +; any berry held by a Shuckle may be converted to berry juice +ConvertBerriesToBerryJuice: ; 2ede6 + ld hl, StatusFlags2 + bit 6, [hl] + ret z + call Random + cp $10 + ret nc ; 1/16 chance + ld hl, PartyMons + ld a, [PartyCount] +.partyMonLoop + push af + push hl + ld a, [hl] + cp SHUCKLE + jr nz, .loopMon + ld bc, MON_ITEM + add hl, bc + ld a, [hl] + cp BERRY + jr z, .convertToJuice + +.loopMon + pop hl + ld bc, PARTYMON_STRUCT_LENGTH + add hl, bc + pop af + dec a + jr nz, .partyMonLoop + ret + +.convertToJuice + ld a, BERRY_JUICE + ld [hl], a + pop hl + pop af + ret diff --git a/engine/pokerus_tick.asm b/engine/pokerus_tick.asm new file mode 100644 index 000000000..3c97fdc5e --- /dev/null +++ b/engine/pokerus_tick.asm @@ -0,0 +1,26 @@ +ApplyPokerusTick: ; 13988 +; decreases all pokemon's pokerus counter by b. if the lower nybble reaches zero, the pokerus is cured. + ld hl, PartyMon1PokerusStatus ; PartyMon1 + MON_PKRS + ld a, [PartyCount] + and a + ret z ; make sure it's not wasting time on an empty party + ld c, a +.loop + ld a, [hl] + and $f ; lower nybble is the number of days remaining + jr z, .next ; if already 0, skip + sub b ; subtract the number of days + jr nc, .ok ; max(result, 0) + xor a +.ok + ld d, a ; back up this value because we need to preserve the strain (upper nybble) + ld a, [hl] + and $f0 + add d + ld [hl], a ; this prevents a cured pokemon from recontracting pokerus +.next + ld de, PARTYMON_STRUCT_LENGTH + add hl, de + dec c + jr nz, .loop + ret diff --git a/engine/square_root.asm b/engine/square_root.asm new file mode 100644 index 000000000..496f66c83 --- /dev/null +++ b/engine/square_root.asm @@ -0,0 +1,30 @@ +GetSquareRoot: ; 13b87 +; Return the square root of de in b. + +; Rather than calculating the result, we take the index of the +; first value in a table of squares that isn't lower than de. + + ld hl, Squares + ld b, 0 +.loop +; Make sure we don't go past the end of the table. + inc b + ld a, b + cp $ff + ret z + +; Iterate over the table until b**2 >= de. + ld a, [hli] + sub e + ld a, [hli] + sbc d + + jr c, .loop + ret + +Squares: ; 13b98 +root set 1 + rept $ff + dw root*root +root set root+1 + endr diff --git a/engine/start_battle.asm b/engine/start_battle.asm new file mode 100644 index 000000000..51f46b3f2 --- /dev/null +++ b/engine/start_battle.asm @@ -0,0 +1,197 @@ +ShowLinkBattleParticipants: ; 2ee18 +; If we're not in a communications room, +; we don't need to be here. + ld a, [wLinkMode] + and a + ret z + + callba _ShowLinkBattleParticipants + ld c, 150 + call DelayFrames + call ClearTileMap + call ClearSprites + ret + +FindFirstAliveMonAndStartBattle: ; 2ee2f + xor a + ld [hMapAnims], a + call DelayFrame + ld b, 6 + ld hl, PartyMon1HP + ld de, PARTYMON_STRUCT_LENGTH - 1 + +.loop + ld a, [hli] + or [hl] + jr nz, .okay + add hl, de + dec b + jr nz, .loop + +.okay + ld de, MON_LEVEL - MON_HP + add hl, de + ld a, [hl] + ld [BattleMonLevel], a + predef Predef_StartBattle + callba _LoadBattleFontsHPBar + ld a, 1 + ld [hBGMapMode], a + call ClearSprites + call ClearTileMap + xor a + ld [hBGMapMode], a + ld [hWY], a + ld [rWY], a + ld [hMapAnims], a + ret + +PlayBattleMusic: ; 2ee6c + push hl + push de + push bc + + xor a + ld [MusicFade], a + ld de, MUSIC_NONE + call PlayMusic + call DelayFrame + call MaxVolume + + ld a, [BattleType] + cp BATTLETYPE_SUICUNE + ld de, MUSIC_SUICUNE_BATTLE + jp z, .done + cp BATTLETYPE_ROAMING + jp z, .done + + ; Are we fighting a trainer? + ld a, [OtherTrainerClass] + and a + jr nz, .trainermusic + + callba RegionCheck + ld a, e + and a + jr nz, .kantowild + + ld de, MUSIC_JOHTO_WILD_BATTLE + ld a, [TimeOfDay] + cp NITE_F + jr nz, .done + ld de, MUSIC_JOHTO_WILD_BATTLE_NIGHT + jr .done + +.kantowild + ld de, MUSIC_KANTO_WILD_BATTLE + jr .done + +.trainermusic + ld de, MUSIC_CHAMPION_BATTLE + cp CHAMPION + jr z, .done + cp RED + jr z, .done + + ; really, they should have included admins and scientists here too... + ld de, MUSIC_ROCKET_BATTLE + cp GRUNTM + jr z, .done + cp GRUNTF + jr z, .done + + ld de, MUSIC_KANTO_GYM_LEADER_BATTLE + callba IsKantoGymLeader + jr c, .done + + ld de, MUSIC_JOHTO_GYM_LEADER_BATTLE + callba IsJohtoGymLeader + jr c, .done + + ld de, MUSIC_RIVAL_BATTLE + ld a, [OtherTrainerClass] + cp RIVAL1 + jr z, .done + cp RIVAL2 + jr nz, .othertrainer + + ld a, [OtherTrainerID] + cp RIVAL2_2_CHIKORITA ; Rival in Indigo Plateau + jr c, .done + ld de, MUSIC_CHAMPION_BATTLE + jr .done + +.othertrainer + ld a, [wLinkMode] + and a + jr nz, .johtotrainer + + callba RegionCheck + ld a, e + and a + jr nz, .kantotrainer + +.johtotrainer + ld de, MUSIC_JOHTO_TRAINER_BATTLE + jr .done + +.kantotrainer + ld de, MUSIC_KANTO_TRAINER_BATTLE + +.done + call PlayMusic + + pop bc + pop de + pop hl + ret + +ClearBattleRAM: ; 2ef18 + xor a + ld [wPlayerAction], a + ld [wBattleResult], a + + ld hl, wPartyMenuCursor + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + + ld [wMenuScrollPosition], a + ld [CriticalHit], a + ld [BattleMonSpecies], a + ld [wBattleParticipantsNotFainted], a + ld [CurBattleMon], a + ld [wForcedSwitch], a + ld [TimeOfDayPal], a + ld [PlayerTurnsTaken], a + ld [EnemyTurnsTaken], a + ld [EvolvableFlags], a + + ld hl, PlayerHPPal + ld [hli], a + ld [hl], a + + ld hl, BattleMonDVs + ld [hli], a + ld [hl], a + + ld hl, EnemyMonDVs + ld [hli], a + ld [hl], a + +; Clear the entire BattleMons area + ld hl, wBattle + ld bc, wBattleEnd - wBattle + xor a + call ByteFill + + callab ResetEnemyStatLevels + + call ClearWindowData + + ld hl, hBGMapAddress + xor a + ld [hli], a + ld [hl], VBGMap0 / $100 + ret diff --git a/engine/timeofdaypals.asm b/engine/timeofdaypals.asm index 90ff9141c..a4a07bc4d 100644 --- a/engine/timeofdaypals.asm +++ b/engine/timeofdaypals.asm @@ -1,3 +1,7 @@ +Predef35: ; 8c000 +Predef36: + ret + UpdateTimeOfDayPal:: ; 8c001 call UpdateTime ld a, [TimeOfDay] diff --git a/engine/trainer_scripts.asm b/engine/trainer_scripts.asm new file mode 100644 index 000000000..33dab3b9e --- /dev/null +++ b/engine/trainer_scripts.asm @@ -0,0 +1,31 @@ +TalkToTrainerScript:: ; 0xbe66a + faceplayer + trainerflagaction CHECK_FLAG + iftrue AlreadyBeatenTrainerScript + loadmemtrainer + encountermusic + jump StartBattleWithMapTrainerScript + +SeenByTrainerScript:: ; 0xbe675 + loadmemtrainer + encountermusic + showemote EMOTE_SHOCK, LAST_TALKED, 30 + callasm TrainerWalkToPlayer + applymovement2 MovementBuffer + writepersonxy LAST_TALKED + faceperson PLAYER, LAST_TALKED + jump StartBattleWithMapTrainerScript + +StartBattleWithMapTrainerScript: ; 0xbe68a + opentext + trainertext $0 + waitbutton + closetext + loadmemtrainer + startbattle + reloadmapafterbattle + trainerflagaction SET_FLAG + loadvar wRunningTrainerBattleScript, -1 + +AlreadyBeatenTrainerScript: + scripttalkafter diff --git a/engine/unused_correct_party.asm b/engine/unused_correct_party.asm new file mode 100644 index 000000000..dd2e1111c --- /dev/null +++ b/engine/unused_correct_party.asm @@ -0,0 +1,229 @@ +CorrectErrorsInPlayerParty: ; unreferenced + ld hl, PartyCount + ld a, [hl] + and a + ret z + + cp PARTY_LENGTH + 1 + jr c, .party_length_okay + ld a, PARTY_LENGTH + ld [hl], a +.party_length_okay + inc hl + + ld b, a + ld c, 0 +.loop1 + ld a, [hl] + and a + jr z, .invalid_species + cp NUM_POKEMON + 1 + jr z, .invalid_species + cp EGG + 1 + jr c, .next_species + +.invalid_species + ld [hl], SMEARGLE + push hl + push bc + ld a, c + ld hl, PartyMon1Species + call GetPartyLocation + ld [hl], SMEARGLE + pop bc + pop hl + +.next_species + inc hl + inc c + dec b + jr nz, .loop1 + ld [hl], $ff + + ld hl, PartyMon1 + ld a, [PartyCount] + ld d, a + ld e, 0 +.loop2 + push de + push hl + ld b, h + ld c, l + ld a, [hl] + and a + jr z, .invalid_species_2 + cp NUM_POKEMON + 1 + jr c, .check_level + +.invalid_species_2 + ld [hl], SMEARGLE + push de + ld d, 0 + ld hl, PartySpecies + add hl, de + pop de + ld a, SMEARGLE + ld [hl], a + +.check_level + ld [CurSpecies], a + call GetBaseData + ld hl, MON_LEVEL + add hl, bc + ld a, [hl] + cp MIN_LEVEL + ld a, MIN_LEVEL + jr c, .invalid_level + ld a, [hl] + cp MAX_LEVEL + jr c, .load_level + ld a, MAX_LEVEL +.invalid_level + ld [hl], a +.load_level + ld [CurPartyLevel], a + + ld hl, MON_MAXHP + add hl, bc + ld d, h + ld e, l + ld hl, MON_STAT_EXP - 1 + add hl, bc + ld b, $1 + predef CalcPkmnStats + pop hl + ld bc, PARTYMON_STRUCT_LENGTH + add hl, bc + pop de + inc e + dec d + jr nz, .loop2 + + ld de, PartyMonNicknames + ld a, [PartyCount] + ld b, a + ld c, 0 +.loop3 + push bc + call .GetLengthOfStringWith6CharCap + push de + callba CheckStringForErrors + pop hl + pop bc + jr nc, .valid_nickname + + push bc + push hl + ld hl, PartySpecies + push bc + ld b, 0 + add hl, bc + pop bc + ld a, [hl] + cp EGG + ld hl, .TAMAGO + jr z, .got_nickname + ld [wd265], a + call GetPokemonName + ld hl, StringBuffer1 +.got_nickname + pop de + ld bc, PKMN_NAME_LENGTH + call CopyBytes + pop bc + +.valid_nickname + inc c + dec b + jr nz, .loop3 + + ld de, PartyMonOT + ld a, [PartyCount] + ld b, a + ld c, 0 +.loop4 + push bc + call .GetLengthOfStringWith6CharCap + push de + callba CheckStringForErrors + pop hl + jr nc, .valid_ot_name + ld d, h + ld e, l + ld hl, PlayerName + ld bc, NAME_LENGTH + call CopyBytes +.valid_ot_name + pop bc + inc c + dec b + jr nz, .loop4 + + ld hl, PartyMon1Moves + ld a, [PartyCount] + ld b, a +.loop5 + push hl + ld c, NUM_MOVES + ld a, [hl] + and a + jr z, .invalid_move + cp NUM_ATTACKS + 1 + jr c, .moves_loop +.invalid_move + ld [hl], POUND + +.moves_loop + ld a, [hl] + and a + jr z, .fill_invalid_moves + cp NUM_ATTACKS + 1 + jr c, .next_move + +.fill_invalid_moves + xor a + ld [hli], a + dec c + jr nz, .fill_invalid_moves + jr .next_pokemon + +.next_move + inc hl + dec c + jr nz, .moves_loop + +.next_pokemon + pop hl + push bc + ld bc, PARTYMON_STRUCT_LENGTH + add hl, bc + pop bc + dec b + jr nz, .loop5 + ret +; 13b6b + +.TAMAGO: ; 13b6b + db "タマゴ@@@" +; 13b71 + +.GetLengthOfStringWith6CharCap: ; 13b71 + push de + ld c, 1 + ld b, NAME_LENGTH_JAPANESE +.search_loop + ld a, [de] + cp "@" + jr z, .done + inc de + inc c + dec b + jr nz, .search_loop + dec c + dec de + ld a, "@" + ld [de], a +.done + pop de + ret +; 13b87 |