shithub: pokecrystal

ref: 3b7c495e38345dc135ef3224d5fc3c8d0e0ce087
dir: /engine/events/magikarp.asm/

View raw version
Special_CheckMagikarpLength: ; fbb32
	; 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, [CurPartySpecies]
	cp MAGIKARP
	jr nz, .not_magikarp

	; Now let's compute its length based on its DVs and ID.
	ld a, [CurPartyMon]
	ld hl, PartyMon1Species
	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
	farcall TrainerRankings_MagikarpLength
	ld hl, .MeasureItText
	call PrintText

	; Did we beat the record?
	ld hl, wMagikarpLength
	ld de, wBestMagikarpLengthFeet
	ld c, 2
	call StringCmp
	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, [CurPartyMon]
	ld hl, PartyMonOT
	call SkipNames
	call CopyBytes
	ld a, 3
	ld [ScriptVar], a
	ret

.not_long_enough
	ld a, 2
	ld [ScriptVar], a
	ret

.declined
	ld a, 1
	ld [ScriptVar], a
	ret

.not_magikarp
	xor a
	ld [ScriptVar], a
	ret
; fbba9

.MeasureItText: ; 0xfbba9
	; Let me measure that MAGIKARP. …Hm, it measures @ .
	text_jump UnknownText_0x1c1203
	db "@"
; 0xfbbae

Magikarp_LoadFeetInchesChars: ; fbbae
	ld hl, vTiles2 tile "′" ; $6e
	ld de, .feetinchchars
	lb bc, BANK(.feetinchchars), 2
	call Request2bpp
	ret
; fbbbb

.feetinchchars ; fbbb
INCBIN "gfx/font/feet_inches.2bpp"
; fbbdb

PrintMagikarpLength: ; fbbdb
	call Magikarp_LoadFeetInchesChars
	ld hl, StringBuffer1
	ld de, wMagikarpLength
	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
	call PrintNum
	ld [hl], "′"
	inc hl
	ld de, wMagikarpLength + 1
	lb bc, PRINTNUM_RIGHTALIGN | 1, 2
	call PrintNum
	ld [hl], "″"
	inc hl
	ld [hl], "@"
	ret
; fbbfc

CalcMagikarpLength: ; fbbfc
; Return Magikarp's length (in feet and inches) at wMagikarpLength (big endian).
;
; input:
;   de: EnemyMonDVs
;   bc: PlayerID

; 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, .Lengths
	ld a, 2
	ld [wd265], 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
	ld [hDividend + 0], a
	ld a, c
	ld [hDividend + 1], a
	ld a, [hl]
	ld [hDivisor], a
	ld b, 2
	call Divide
	ld a, [hQuotient + 2]
	ld c, a

	; de = c + 100 × (2 + i)
	xor a
	ld [hMultiplicand + 0], a
	ld [hMultiplicand + 1], a
	ld a, 100
	ld [hMultiplicand + 2], a
	ld a, [wd265]
	ld [hMultiplier], a
	call Multiply
	ld b, 0
	ld a, [hProduct + 3]
	add c
	ld e, a
	ld a, [hProduct + 2]
	adc b
	ld d, a
	jr .done

.next
	inc hl ; align to next triplet
	ld a, [wd265]
	inc a
	ld [wd265], 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
; fbc9a

.BCLessThanDE: ; fbc9a
; Intention: Return bc < de.
; Reality: Return b < d.
	ld a, b
	cp d
	ret c
	ret nc ; whoops
	ld a, c
	cp e
	ret
; fbca1

.BCMinusDE: ; fbca1
; bc -= de
	ld a, c
	sub e
	ld c, a
	ld a, b
	sbc d
	ld b, a
	ret
; fbca8

.Lengths: ; fbca8
; [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
; fbcd2



Special_MagikarpHouseSign: ; fbcd2
	ld a, [wBestMagikarpLengthFeet]
	ld [wMagikarpLength], a
	ld a, [wBestMagikarpLengthInches]
	ld [wMagikarpLength + 1], a
	call PrintMagikarpLength
	ld hl, .CurrentRecordtext
	call PrintText
	ret
; fbce8

.CurrentRecordtext: ; 0xfbce8
	; "CURRENT RECORD"
	text_jump UnknownText_0x1c123a
	db "@"
; 0xfbced