diff options
author | libjet <libj3t@gmail.com> | 2020-06-06 02:22:45 +0100 |
---|---|---|
committer | libjet <libj3t@gmail.com> | 2020-06-06 02:22:45 +0100 |
commit | 5ea5b0d9019b3de45129d347eaf2a1f565839a8d (patch) | |
tree | e9b237a0eb3ce252e33f1cf6d7437253f62eb7f0 | |
parent | dd65caf5110833e2edca0d9b6af797f8535c766f (diff) |
Add engine/events/magikarp.asm
-rwxr-xr-x | data/events/magikarp_lengths.asm | 20 | ||||
-rwxr-xr-x | engine/events/magikarp.asm | 314 | ||||
-rwxr-xr-x | gfx/font/feet_inches.2bpp | bin | 0 -> 32 bytes | |||
-rwxr-xr-x | gfx/font/feet_inches.png | bin | 0 -> 89 bytes | |||
-rw-r--r-- | main.asm | 8 |
5 files changed, 335 insertions, 7 deletions
diff --git a/data/events/magikarp_lengths.asm b/data/events/magikarp_lengths.asm new file mode 100755 index 00000000..1a1040d6 --- /dev/null +++ b/data/events/magikarp_lengths.asm @@ -0,0 +1,20 @@ +MagikarpLengths: +; [wMagikarpLength] = z * 100 + (bc - x) / y +; First argument is the bc threshold as well as x. +; Second argument is y. +; In reality, due to the bug at .BCLessThanDE, +; the threshold is determined by only register b. + dwb 110, 1 ; not used unless the bug is fixed + dwb 310, 2 + dwb 710, 4 + dwb 2710, 20 + dwb 7710, 50 + dwb 17710, 100 + dwb 32710, 150 + dwb 47710, 150 + dwb 57710, 100 + dwb 62710, 50 + dwb 64710, 20 + dwb 65210, 5 + dwb 65410, 2 + dwb 65510, 1 ; not used diff --git a/engine/events/magikarp.asm b/engine/events/magikarp.asm new file mode 100755 index 00000000..035148b5 --- /dev/null +++ b/engine/events/magikarp.asm @@ -0,0 +1,314 @@ +CheckMagikarpLength: + ; Returns 3 if you select a Magikarp that beats the previous record. + ; Returns 2 if you select a Magikarp, but the current record is longer. + ; Returns 1 if you press B in the Pokemon selection menu. + ; Returns 0 if the Pokemon you select is not a Magikarp. + + ; Let's start by selecting a Magikarp. + farcall SelectMonFromParty + jr c, .declined + ld a, [wCurPartySpecies] + cp MAGIKARP + jr nz, .not_magikarp + + ; Now let's compute its length based on its DVs and ID. + ld a, [wCurPartyMon] + ld hl, wPartyMon1Species + ld bc, PARTYMON_STRUCT_LENGTH + call AddNTimes + push hl + ld bc, MON_DVS + add hl, bc + ld d, h + ld e, l + pop hl + ld bc, MON_ID + add hl, bc + ld b, h + ld c, l + call CalcMagikarpLength + call PrintMagikarpLength + ld hl, .MagikarpGuruMeasureText + call PrintText + + ; Did we beat the record? + ld hl, wMagikarpLength + ld de, wBestMagikarpLengthFeet + ld c, 2 + call CompareBytes + jr nc, .not_long_enough + + ; NEW RECORD!!! Let's save that. + ld hl, wMagikarpLength + ld de, wBestMagikarpLengthFeet + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + inc de + ld a, [wCurPartyMon] + ld hl, wPartyMonOT + call SkipNames + call CopyBytes + ld a, MAGIKARPLENGTH_BEAT_RECORD + ld [wScriptVar], a + ret + +.not_long_enough + ld a, MAGIKARPLENGTH_TOO_SHORT + ld [wScriptVar], a + ret + +.declined + ld a, MAGIKARPLENGTH_REFUSED + ld [wScriptVar], a + ret + +.not_magikarp + xor a ; MAGIKARPLENGTH_NOT_MAGIKARP + ld [wScriptVar], a + ret + +.MagikarpGuruMeasureText: + text_far _MagikarpGuruMeasureText + text_end + +Magikarp_LoadFeetInchesChars: + ld hl, vTiles2 tile "′" ; $6e + ld de, .feetinchchars + lb bc, BANK(.feetinchchars), 2 + call Request2bpp + ret + +.feetinchchars +INCBIN "gfx/font/feet_inches.2bpp" + +PrintMagikarpLength: + call Magikarp_LoadFeetInchesChars + ld hl, wStringBuffer1 + ld de, wMagikarpLength + lb bc, PRINTNUM_LEFTALIGN | 1, 2 + call PrintNum + ld [hl], "′" + inc hl + ld de, wMagikarpLength + 1 + lb bc, PRINTNUM_LEFTALIGN | 1, 2 + call PrintNum + ld [hl], "″" + inc hl + ld [hl], "@" + ret + +CalcMagikarpLength: +; Return Magikarp's length (in feet and inches) at wMagikarpLength (big endian). +; +; input: +; de: wEnemyMonDVs +; bc: wPlayerID + +; This function is poorly commented. + +; In short, it generates a value between 190 and 1786 using +; a Magikarp's DVs and its trainer ID. This value is further +; filtered in LoadEnemyMon to make longer Magikarp even rarer. + +; The value is generated from a lookup table. +; The index is determined by the dv xored with the player's trainer id. + +; bc = rrc(dv[0]) ++ rrc(dv[1]) ^ rrc(id) + +; if bc < 10: [wMagikarpLength] = c + 190 +; if bc ≥ $ff00: [wMagikarpLength] = c + 1370 +; else: [wMagikarpLength] = z * 100 + (bc - x) / y + +; X, Y, and Z depend on the value of b as follows: + +; if b = 0: x = 310, y = 2, z = 3 +; if b = 1: x = 710, y = 4, z = 4 +; if b = 2-9: x = 2710, y = 20, z = 5 +; if b = 10-29: x = 7710, y = 50, z = 6 +; if b = 30-68: x = 17710, y = 100, z = 7 +; if b = 69-126: x = 32710, y = 150, z = 8 +; if b = 127-185: x = 47710, y = 150, z = 9 +; if b = 186-224: x = 57710, y = 100, z = 10 +; if b = 225-243: x = 62710, y = 50, z = 11 +; if b = 244-251: x = 64710, y = 20, z = 12 +; if b = 252-253: x = 65210, y = 5, z = 13 +; if b = 254: x = 65410, y = 2, z = 14 + + ; bc = rrc(dv[0]) ++ rrc(dv[1]) ^ rrc(id) + + ; id + ld h, b + ld l, c + ld a, [hli] + ld b, a + ld c, [hl] + rrc b + rrc c + + ; dv + ld a, [de] + inc de + rrca + rrca + xor b + ld b, a + + ld a, [de] + rrca + rrca + xor c + ld c, a + + ; if bc < 10: + ; de = bc + 190 + ; break + + ld a, b + and a + jr nz, .no + ld a, c + cp 10 + jr nc, .no + + ld hl, 190 + add hl, bc + ld d, h + ld e, l + jr .done + +.no + + ld hl, MagikarpLengths + ld a, 2 + ld [wTempByteValue], a + +.read + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + call .BCLessThanDE + jr nc, .next + + ; c = (bc - de) / [hl] + call .BCMinusDE + ld a, b + ldh [hDividend + 0], a + ld a, c + ldh [hDividend + 1], a + ld a, [hl] + ldh [hDivisor], a + ld b, 2 + call Divide + ldh a, [hQuotient + 3] + ld c, a + + ; de = c + 100 × (2 + i) + xor a + ldh [hMultiplicand + 0], a + ldh [hMultiplicand + 1], a + ld a, 100 + ldh [hMultiplicand + 2], a + ld a, [wTempByteValue] + ldh [hMultiplier], a + call Multiply + ld b, 0 + ldh a, [hProduct + 3] + add c + ld e, a + ldh a, [hProduct + 2] + adc b + ld d, a + jr .done + +.next + inc hl ; align to next triplet + ld a, [wTempByteValue] + inc a + ld [wTempByteValue], a + cp 16 + jr c, .read + + call .BCMinusDE + ld hl, 1600 + add hl, bc + ld d, h + ld e, l + +.done + ; convert from mm to feet and inches + ; in = mm / 25.4 + ; ft = in / 12 + + ; hl = de × 10 + ld h, d + ld l, e + add hl, hl + add hl, hl + add hl, de + add hl, hl + + ; hl = hl / 254 + ld de, -254 + ld a, -1 +.div_254 + inc a + add hl, de + jr c, .div_254 + + ; d, e = hl / 12, hl % 12 + ld d, 0 +.mod_12 + cp 12 + jr c, .ok + sub 12 + inc d + jr .mod_12 +.ok + ld e, a + + ld hl, wMagikarpLength + ld [hl], d ; ft + inc hl + ld [hl], e ; in + ret + +.BCLessThanDE: +; Intention: Return bc < de. +; Reality: Return b < d. + ld a, b + cp d + ret c + ret nc ; whoops + ld a, c + cp e + ret + +.BCMinusDE: +; bc -= de + ld a, c + sub e + ld c, a + ld a, b + sbc d + ld b, a + ret + +INCLUDE "data/events/magikarp_lengths.asm" + +MagikarpHouseSign: + ld a, [wBestMagikarpLengthFeet] + ld [wMagikarpLength], a + ld a, [wBestMagikarpLengthInches] + ld [wMagikarpLength + 1], a + call PrintMagikarpLength + ld hl, .KarpGuruRecordText + call PrintText + ret + +.KarpGuruRecordText: + text_far _KarpGuruRecordText + text_end diff --git a/gfx/font/feet_inches.2bpp b/gfx/font/feet_inches.2bpp Binary files differnew file mode 100755 index 00000000..fba5d65c --- /dev/null +++ b/gfx/font/feet_inches.2bpp diff --git a/gfx/font/feet_inches.png b/gfx/font/feet_inches.png Binary files differnew file mode 100755 index 00000000..60f319eb --- /dev/null +++ b/gfx/font/feet_inches.png @@ -380,13 +380,7 @@ INCLUDE "engine/events/play_slow_cry.asm" INCLUDE "engine/pokedex/new_pokedex_entry.asm" INCLUDE "engine/link/time_capsule_2.asm" INCLUDE "engine/pokedex/unown_dex.asm" - -CheckMagikarpLength:: - dr $fbc3c, $fbd00 -CalcMagikarpLength:: - dr $fbd00, $fbdd6 -MagikarpHouseSign:: - dr $fbdd6, $fbdf1 +INCLUDE "engine/events/magikarp.asm" HiddenPowerDamage:: dr $fbdf1, $fbe5a |