diff --git a/audio/engine.asm b/audio/engine.asm index a45f6564c..e54bda967 100644 --- a/audio/engine.asm +++ b/audio/engine.asm @@ -16,27 +16,27 @@ SoundRestart: ; e8000 push bc push af call MusicOff - ld hl, $ff24 ; channel control registers + ld hl, rNR50 ; channel control registers xor a - ld [hli], a ; ff24 ; volume/vin - ld [hli], a ; ff25 ; sfx channels + ld [hli], a ; rNR50 ; volume/vin + ld [hli], a ; rNR51 ; sfx channels ld a, $80 ; all channels on ld [hli], a ; ff26 ; music channels - ld hl, $ff10 ; sound channel registers + ld hl, rNR10 ; sound channel registers ld e, $04 ; number of channels .clearsound ; sound channel 1 2 3 4 xor a - ld [hli], a ; $ff10, $ff15, $ff1a, $ff1f ; sweep = 0 + ld [hli], a ; rNR10, $ff15, rNR30, $ff1f ; sweep = 0 - ld [hli], a ; $ff11, $ff16, $ff1b, $ff20 ; length/wavepattern = 0 + ld [hli], a ; rNR11, rNR21, rNR31, rNR41 ; length/wavepattern = 0 ld a, $08 - ld [hli], a ; $ff12, $ff17, $ff1c, $ff21 ; envelope = 0 + ld [hli], a ; rNR12, rNR22, rNR32, rNR42 ; envelope = 0 xor a - ld [hli], a ; $ff13, $ff18, $ff1d, $ff22 ; frequency lo = 0 + ld [hli], a ; rNR13, rNR23, rNR33, rNR43 ; frequency lo = 0 ld a, $80 - ld [hli], a ; $ff14, $ff19, $ff1e, $ff23 ; restart sound (freq hi = 0) + ld [hli], a ; rNR14, rNR24, rNR34, rNR44 ; restart sound (freq hi = 0) dec e jr nz, .clearsound @@ -208,10 +208,10 @@ UpdateSound: ; e805c call FadeMusic ; write volume to hardware register ld a, [Volume] - ld [$ff24], a + ld [rNR50], a ; write SO on/off to hardware register ld a, [SoundOutput] - ld [$ff25], a + ld [rNR51], a ret ; e8125 @@ -251,7 +251,7 @@ UpdateChannels: ; e8125 jr z, .asm_e8159 ; ld a, [SoundInput] - ld [$ff10], a + ld [rNR10], a .asm_e8159 bit 5, [hl] ; rest jr nz, .ch1rest @@ -264,48 +264,48 @@ UpdateChannels: ; e8125 jr .asm_e8175 .asm_e816b ld a, [$c294] - ld [$ff13], a + ld [rNR13], a ld a, [$c295] - ld [$ff14], a + ld [rNR14], a .asm_e8175 bit 0, [hl] ret z ld a, [$c292] ld d, a - ld a, [$ff11] + ld a, [rNR11] and a, $3f ; sound length or d - ld [$ff11], a + ld [rNR11], a ret .asm_e8184 ld a, [$c292] ld d, a - ld a, [$ff11] + ld a, [rNR11] and a, $3f ; sound length or d - ld [$ff11], a + ld [rNR11], a ld a, [$c294] - ld [$ff13], a + ld [rNR13], a ret .ch1rest - ld a, [$ff26] + ld a, [rNR52] and a, %10001110 ; ch1 off - ld [$ff26], a - ld hl, $ff10 + ld [rNR52], a + ld hl, rNR10 call ClearChannel ret .asm_e81a2 ld hl, $c292 ld a, $3f ; sound length or [hl] - ld [$ff11], a + ld [rNR11], a ld a, [$c293] - ld [$ff12], a + ld [rNR12], a ld a, [$c294] - ld [$ff13], a + ld [rNR13], a ld a, [$c295] or a, $80 - ld [$ff14], a + ld [rNR14], a ret .Channel2 @@ -322,31 +322,31 @@ UpdateChannels: ; e8125 ret z ld a, [$c292] ld d, a - ld a, [$ff16] + ld a, [rNR21] and a, $3f ; sound length or d - ld [$ff16], a + ld [rNR21], a ret .asm_e81db ; unused ld a, [$c294] - ld [$ff18], a + ld [rNR23], a ld a, [$c295] - ld [$ff19], a + ld [rNR24], a ret .asm_e81e6 ld a, [$c292] ld d, a - ld a, [$ff16] + ld a, [rNR21] and a, $3f ; sound length or d - ld [$ff16], a + ld [rNR21], a ld a, [$c294] - ld [$ff18], a + ld [rNR23], a ret .ch2rest - ld a, [$ff26] + ld a, [rNR52] and a, %10001101 ; ch2 off - ld [$ff26], a + ld [rNR52], a ld hl, $ff15 call ClearChannel ret @@ -354,14 +354,14 @@ UpdateChannels: ; e8125 ld hl, $c292 ld a, $3f ; sound length or [hl] - ld [$ff16], a + ld [rNR21], a ld a, [$c293] - ld [$ff17], a + ld [rNR22], a ld a, [$c294] - ld [$ff18], a + ld [rNR23], a ld a, [$c295] or a, $80 ; initial (restart) - ld [$ff19], a + ld [rNR24], a ret .Channel3 @@ -377,34 +377,34 @@ UpdateChannels: ; e8125 ret .asm_e822f ; unused ld a, [$c294] - ld [$ff1d], a + ld [rNR33], a ld a, [$c295] - ld [$ff1e], a + ld [rNR34], a ret .asm_e823a ld a, [$c294] - ld [$ff1d], a + ld [rNR33], a ret .ch3rest - ld a, [$ff26] + ld a, [rNR52] and a, %10001011 ; ch3 off - ld [$ff26], a - ld hl, $ff1a + ld [rNR52], a + ld hl, rNR30 call ClearChannel ret .asm_e824d ld a, $3f - ld [$ff1b], a + ld [rNR31], a xor a - ld [$ff1a], a + ld [rNR30], a call .asm_e8268 ld a, $80 - ld [$ff1a], a + ld [rNR30], a ld a, [$c294] - ld [$ff1d], a + ld [rNR33], a ld a, [$c295] or a, $80 - ld [$ff1e], a + ld [rNR34], a ret .asm_e8268 push hl @@ -458,7 +458,7 @@ UpdateChannels: ; e8125 ld a, [$c293] and a, $f0 sla a - ld [$ff1c], a + ld [rNR32], a ret .Channel4 @@ -472,24 +472,24 @@ UpdateChannels: ; e8125 ret .asm_e82c1 ; unused ld a, [$c294] - ld [$ff22], a + ld [rNR43], a ret .ch4rest - ld a, [$ff26] + ld a, [rNR52] and a, %10000111 ; ch4 off - ld [$ff26], a + ld [rNR52], a ld hl, $ff1f call ClearChannel ret .asm_e82d4 ld a, $3f ; sound length - ld [$ff20], a + ld [rNR41], a ld a, [$c293] - ld [$ff21], a + ld [rNR42], a ld a, [$c294] - ld [$ff22], a + ld [rNR43], a ld a, $80 - ld [$ff23], a + ld [rNR44], a ret ; e82e7 @@ -535,15 +535,15 @@ Functione8307: ; e8307 ld hl, Tablee8350 .updatehw xor a - ld [$ff10], a ; sweep off + ld [rNR10], a ; sweep off ld a, [hli] - ld [$ff11], a ; sound length / duty cycle + ld [rNR11], a ; sound length / duty cycle ld a, [hli] - ld [$ff12], a ; ch1 volume envelope + ld [rNR12], a ; ch1 volume envelope ld a, [hli] - ld [$ff13], a ; ch1 frequency lo + ld [rNR13], a ; ch1 frequency lo ld a, [hli] - ld [$ff14], a ; ch1 frequency hi + ld [rNR14], a ; ch1 frequency hi .asm_e8335 ld a, d inc a @@ -1192,7 +1192,7 @@ ParseMusic: ; e85e1 jr nz, .ok ; ???? xor a - ld [$ff10], a ; sweep = 0 + ld [rNR10], a ; sweep = 0 .ok ; stop playing ; turn channel off @@ -2352,72 +2352,87 @@ LoadMusic: ; e8b30 ; e8b79 PlayCry: ; e8b79 -; input: de = cry id +; Play cry de using parameters: +; CryPitch +; CryEcho +; CryLength + call MusicOff - ; load cry id + +; Overload the music id with the cry id ld hl, MusicID ld [hl], e inc hl ld [hl], d - ; seek pointer table + +; 3-byte pointers (bank, address) ld hl, Cries add hl, de add hl, de add hl, de - ; get bank + ld a, [hli] ld [MusicBank], a - ; get address + ld e, [hl] inc hl ld d, [hl] -; read cry header - ; get byte at bank:address + +; Read the cry's sound header call FarLoadMusicByte - ; get top 2 bits (# chs) + ; Top 2 bits contain the number of channels rlca rlca - and a, $03 - inc a ; ch count -> loop count + and a, 3 + +; For each channel: + inc a .loop push af call LoadChannel + ld hl, Channel1Flags - Channel1 add hl, bc set 5, [hl] + ld hl, Channel1Flags2 - Channel1 add hl, bc set 4, [hl] - ld hl, $0027 + + ld hl, Channel1CryPitch - Channel1 add hl, bc - ld a, [$c2b0] + ld a, [CryPitch] ld [hli], a - ld a, [$c2b1] + ld a, [CryEcho] ld [hl], a - ; are we on the last channel? (music & sfx) + +; No tempo for channel 4 ld a, [CurChannel] - and a, $03 - cp a, $03 + and a, 3 + cp 3 jr nc, .start - ; update tempo + +; Tempo is effectively length ld hl, Channel1Tempo - Channel1 add hl, bc - ld a, [$c2b2] + ld a, [CryLength] ld [hli], a - ld a, [$c2b3] + ld a, [CryLength+1] ld [hl], a .start call StartChannel ld a, [$c2bc] and a jr z, .next -; play cry from the side of the monster it's coming from (stereo only) -; outside of battles cries play on both tracks - ; is stereo on? + +; Stereo only: Play cry from the monster's side. +; This only applies in-battle. + ld a, [Options] bit 5, a ; stereo jr z, .next - ; and [Tracks], [CryTracks] + +; [Tracks] &= [CryTracks] ld hl, Channel1Tracks - Channel1 add hl, bc ld a, [hl] @@ -2426,21 +2441,25 @@ PlayCry: ; e8b79 ld hl, Channel1Tracks - Channel1 add hl, bc ld [hl], a + .next pop af dec a jr nz, .loop - ; save current volume + + +; Cries play at max volume, so we save the current volume for later. ld a, [LastVolume] and a jr nz, .end + ld a, [Volume] ld [LastVolume], a - ; cries have max volume ld a, $77 ld [Volume], a + .end - ld a, $01 ; stop playing music + ld a, 1 ; stop playing music ld [SFXPriority], a call MusicOn ret @@ -2454,56 +2473,56 @@ LoadSFX: ; e8c04 jr z, .ch6 res 0, [hl] ; turn it off xor a - ld [$ff11], a ; length/wavepattern = 0 + ld [rNR11], a ; length/wavepattern = 0 ld a, $08 - ld [$ff12], a ; envelope = 0 + ld [rNR12], a ; envelope = 0 xor a - ld [$ff13], a ; frequency lo = 0 + ld [rNR13], a ; frequency lo = 0 ld a, $80 - ld [$ff14], a ; restart sound (freq hi = 0) + ld [rNR14], a ; restart sound (freq hi = 0) xor a ld [SoundInput], a ; global sound off - ld [$ff10], a ; sweep = 0 + ld [rNR10], a ; sweep = 0 .ch6 ld hl, $c1fe ; ch6 on? bit 0, [hl] jr z, .ch7 res 0, [hl] ; turn it off xor a - ld [$ff16], a ; length/wavepattern = 0 + ld [rNR21], a ; length/wavepattern = 0 ld a, $08 - ld [$ff17], a ; envelope = 0 + ld [rNR22], a ; envelope = 0 xor a - ld [$ff18], a ; frequency lo = 0 + ld [rNR23], a ; frequency lo = 0 ld a, $80 - ld [$ff19], a ; restart sound (freq hi = 0) + ld [rNR24], a ; restart sound (freq hi = 0) .ch7 ld hl, $c230 ; ch7 on? bit 0, [hl] jr z, .ch8 res 0, [hl] ; turn it off xor a - ld [$ff1a], a ; sound mode #3 off - ld [$ff1b], a ; length/wavepattern = 0 + ld [rNR30], a ; sound mode #3 off + ld [rNR31], a ; length/wavepattern = 0 ld a, $08 - ld [$ff1c], a ; envelope = 0 + ld [rNR32], a ; envelope = 0 xor a - ld [$ff1d], a ; frequency lo = 0 + ld [rNR33], a ; frequency lo = 0 ld a, $80 - ld [$ff1e], a ; restart sound (freq hi = 0) + ld [rNR34], a ; restart sound (freq hi = 0) .ch8 ld hl, $c262 ; ch8 on? bit 0, [hl] jr z, .chscleared res 0, [hl] ; turn it off xor a - ld [$ff20], a ; length/wavepattern = 0 + ld [rNR41], a ; length/wavepattern = 0 ld a, $08 - ld [$ff21], a ; envelope = 0 + ld [rNR42], a ; envelope = 0 xor a - ld [$ff22], a ; frequency lo = 0 + ld [rNR43], a ; frequency lo = 0 ld a, $80 - ld [$ff23], a ; restart sound (freq hi = 0) + ld [rNR44], a ; restart sound (freq hi = 0) xor a ld [NoiseSampleAddressLo], a ld [NoiseSampleAddressHi], a @@ -3126,13 +3145,13 @@ ChannelPointers: ; e8fd9 ClearChannels: ; e8fe9 ; runs ClearChannel for all 4 channels ; doesn't seem to be used, but functionally identical to SoundRestart - ld hl, $ff24 + ld hl, rNR50 xor a ld [hli], a ld [hli], a ld a, $80 ld [hli], a - ld hl, $ff10 + ld hl, rNR10 ld e, $04 .loop call ClearChannel @@ -3142,19 +3161,19 @@ ClearChannels: ; e8fe9 ; e8ffe ClearChannel: ; e8ffe -; input: hl = beginning hw sound register ($ff10, $ff15, $ff1a, $ff1f) +; input: hl = beginning hw sound register (rNR10, $ff15, rNR30, $ff1f) ; output: 00 00 80 00 80 ; sound channel 1 2 3 4 xor a - ld [hli], a ; $ff10, $ff15, $ff1a, $ff1f ; sweep = 0 + ld [hli], a ; rNR10, $ff15, rNR30, $ff1f ; sweep = 0 - ld [hli], a ; $ff11, $ff16, $ff1b, $ff20 ; length/wavepattern = 0 + ld [hli], a ; rNR11, rNR21, rNR31, rNR41 ; length/wavepattern = 0 ld a, $08 - ld [hli], a ; $ff12, $ff17, $ff1c, $ff21 ; envelope = 0 + ld [hli], a ; rNR12, rNR22, rNR32, rNR42 ; envelope = 0 xor a - ld [hli], a ; $ff13, $ff18, $ff1d, $ff22 ; frequency lo = 0 + ld [hli], a ; rNR13, rNR23, rNR33, rNR43 ; frequency lo = 0 ld a, $80 - ld [hli], a ; $ff14, $ff19, $ff1e, $ff23 ; restart sound (freq hi = 0) + ld [hli], a ; rNR14, rNR24, rNR34, rNR44 ; restart sound (freq hi = 0) ret ; e900a diff --git a/battle/magikarp_length.asm b/battle/magikarp_length.asm new file mode 100644 index 000000000..7b2d5e386 --- /dev/null +++ b/battle/magikarp_length.asm @@ -0,0 +1,220 @@ +CalcMagikarpLength: ; fbbfc +; Return Magikarp's length (in mm) in MagikarpLength (big endian) +; +; input: +; de: EnemyMonDVs +; bc: PlayerID + +; This function is needlessly convoluted, and poorly commented. +; Reading is discouraged. + +; In short, it generates a value between 190 and 1786 using +; a Magikarp's DVs and its trainer ID. This value is further +; scrutinized in GetEnemyMon to make longer Magikarp even rarer. + +; This is done by calculating the value using operands from +; a conversion lookup table. + +; Our index is calculated by xoring DVs with the trainer ID: + +; bc = rrc(rrc(dvs)) xor rrc(id) + +; if bc < $a: MagikarpLength = c + 190 +; if bc >= $ff00: MagikarpLength = c + 1370 +; else: MagikarpLength = 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 + +; These values represent arbitrary conversion points. + + +; b = rrcrrc(atkdefdv) xor rrc(id[0]) + +; id + ld h, b + ld l, c + ld a, [hli] + ld b, a + ld c, [hl] + rrc b + rrc c + +; dvs + ld a, [de] + inc de + rrca + rrca + xor b + ld b, a + +; c = rrcrrc(spdspcdv) xor rrc(id[1]) + + ld a, [de] + rrca + rrca + xor c + ld c, a + +; if bc < $000a: + ld a, b + and a + jr nz, .loadtable + ld a, c + cp a, $a + jr nc, .loadtable + +; de = hl = bc + $be + ld hl, $be + add hl, bc + ld d, h + ld e, l + jr .endtable + +.loadtable + ld hl, .MagikarpLengthTable + ld a, $02 + ld [$d265], a + +.readtable + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + call .BLessThanD + jr nc, .advancetable + +; c = bc / [hl] + call .BCMinusDE + ld a, b + ld [$ffb3], a + ld a, c + ld [$ffb4], a + ld a, [hl] + ld [$ffb7], a + ld b, $02 + call Divide + ld a, [$ffb6] + ld c, a + +; de = c + 100 * (2 + number of rows down the table) + xor a + ld [$ffb4], a + ld [$ffb5], a + ld a, $64 + ld [$ffb6], a + ld a, [$d265] + ld [$ffb7], a + call Multiply + ld b, $00 + ld a, [$ffb6] + add c + ld e, a + ld a, [$ffb5] + adc b + ld d, a + jr .endtable + +.advancetable + inc hl ; align to next triplet + ld a, [$d265] + inc a + ld [$d265], a + cp a, $10 + jr c, .readtable + + call .BCMinusDE + ld hl, $0640 + add hl, bc + ld d, h + ld e, l + +.endtable + ld h, d + ld l, e + add hl, hl + add hl, hl + add hl, de + add hl, hl ; hl = de * 10 + + ld de, $ff02 + ld a, $ff +.loop + inc a + add hl, de ; - 254 + jr c, .loop + + ld d, $00 + +; mod $0c +.modloop + cp a, $0c + jr c, .done + sub a, $0c + inc d + jr .modloop + +.done + ld e, a + ld hl, MagikarpLength + ld [hl], d + inc hl + ld [hl], e + ret +; fbc9a + +.BLessThanD ; fbc9a +; return carry if b < d + ld a, b + cp d + ret c + ret nc +; fbc9e + +.CLessThanE ; fbc9e +; unused + 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 + +.MagikarpLengthTable ; fbca8 +; ????, divisor + dwb $006e, $01 + dwb $0136, $02 + dwb $02c6, $04 + dwb $0a96, $14 + dwb $1e1e, $32 + dwb $452e, $64 + dwb $7fc6, $96 + dwb $ba5e, $96 + dwb $e16e, $64 + dwb $f4f6, $32 + dwb $fcc6, $14 + dwb $feba, $05 + dwb $ff82, $02 +; fbccf + diff --git a/constants.asm b/constants.asm index ec45875d6..8a3d4d080 100644 --- a/constants.asm +++ b/constants.asm @@ -3417,15 +3417,20 @@ BATTLETYPE_SUICUNE EQU $0c ; joypad -NO_INPUT EQU %00000000 -BUTTON_A EQU %00000001 -BUTTON_B EQU %00000010 -SELECT EQU %00000100 -START EQU %00001000 -D_RIGHT EQU %00010000 -D_LEFT EQU %00100000 -D_UP EQU %01000000 -D_DOWN EQU %10000000 +BUTTONS EQU %00010000 +D_PAD EQU %00100000 + +AUTO_INPUT EQU $ff + +NO_INPUT EQU %00000000 +BUTTON_A EQU %00000001 +BUTTON_B EQU %00000010 +SELECT EQU %00000100 +START EQU %00001000 +D_RIGHT EQU %00010000 +D_LEFT EQU %00100000 +D_UP EQU %01000000 +D_DOWN EQU %10000000 ; mbc NUM_SRAM_BANKS EQU 4 diff --git a/credits.asm b/credits.asm new file mode 100644 index 000000000..d5e4399b9 --- /dev/null +++ b/credits.asm @@ -0,0 +1,824 @@ +SATOSHI_TAJIRI EQU 00 +JUNICHI_MASUDA EQU 01 +TETSUYA_WATANABE EQU 02 +SHIGEKI_MORIMOTO EQU 03 +SOUSUKE_TAMADA EQU 04 +TAKENORI_OOTA EQU 05 +KEN_SUGIMORI EQU 06 +MOTOFUMI_FUJIWARA EQU 07 +ATSUKO_NISHIDA EQU 08 +MUNEO_SAITO EQU 09 +SATOSHI_OOTA EQU 10 +RENA_YOSHIKAWA EQU 11 +JUN_OKUTANI EQU 12 +HIRONOBU_YOSHIDA EQU 13 +ASUKA_IWASHITA EQU 14 +GO_ICHINOSE EQU 15 +MORIKAZU_AOKI EQU 16 +KOHJI_NISHINO EQU 17 +KENJI_MATSUSHIMA EQU 18 +TOSHINOBU_MATSUMIYA EQU 19 +SATORU_IWATA EQU 20 +NOBUHIRO_SEYA EQU 21 +KAZUHITO_SEKINE EQU 22 +TETSUJI_OOTA EQU 23 +NCL_SUPER_MARIO_CLUB EQU 24 +SARUGAKUCHO EQU 25 +AKITO_MORI EQU 26 +TAKAHIRO_HARADA EQU 27 +TOHRU_HASHIMOTO EQU 28 +NOBORU_MATSUMOTO EQU 29 +TAKEHIRO_IZUSHI EQU 30 +TAKASHI_KAWAGUCHI EQU 31 +TSUNEKAZU_ISHIHARA EQU 32 +HIROSHI_YAMAUCHI EQU 33 +KENJI_SAIKI EQU 34 +ATSUSHI_TADA EQU 35 +NAOKO_KAWAKAMI EQU 36 +HIROYUKI_ZINNAI EQU 37 +KUNIMI_KAWAMURA EQU 38 +HISASHI_SOGABE EQU 39 +KEITA_KAGAYA EQU 40 +YOSHINORI_MATSUDA EQU 41 +HITOMI_SATO EQU 42 +TORU_OSAWA EQU 43 +TAKAO_OHARA EQU 44 +YUICHIRO_ITO EQU 45 +TAKAO_SHIMIZU EQU 46 +PLANNING EQU 47 +KEITA_NAKAMURA EQU 48 +HIROTAKA_UEMURA EQU 49 +HIROAKI_TAMURA EQU 50 +NORIAKI_SAKAGUCHI EQU 51 +MIYUKI_SATO EQU 52 +GAKUZI_NOMOTO EQU 53 +AI_MASHIMA EQU 54 +MIKIHIRO_ISHIKAWA EQU 55 +HIDEYUKI_HASHIMOTO EQU 56 +SATOSHI_YAMATO EQU 57 +SHIGERU_MIYAMOTO EQU 58 +GAIL_TILDEN EQU 59 +NOB_OGASAWARA EQU 60 +SETH_MCMAHILL EQU 61 +HIROTO_ALEXANDER EQU 62 +TERESA_LILLYGREN EQU 63 +THOMAS_HERTZOG EQU 64 +ERIK_JOHNSON EQU 65 +HIRO_NAKAMURA EQU 66 +TERUKI_MURAKAWA EQU 67 +KAZUYOSHI_OSAWA EQU 68 +KIMIKO_NAKAMICHI EQU 69 +END EQU 70 +CREDITS_UNKNOWN EQU 71 +STAFF EQU 72 +DIRECTOR EQU 73 +CODIRECTOR EQU 74 +PROGRAMMERS EQU 75 +GRAPHICS_DIRECTOR EQU 76 +MONSTER_DESIGN EQU 77 +GRAPHICS_DESIGN EQU 78 +MUSIC EQU 79 +SOUND_EFFECTS EQU 80 +GAME_DESIGN EQU 81 +GAME_SCENARIO EQU 82 +TOOL_PROGRAMMING EQU 83 +PARAMETRIC_DESIGN EQU 84 +SCRIPT_DESIGN EQU 85 +MAP_DATA_DESIGN EQU 86 +MAP_DESIGN EQU 87 +PRODUCT_TESTING EQU 88 +SPECIAL_THANKS EQU 89 +PRODUCERS EQU 90 +EXECUTIVE_PRODUCER EQU 91 +POKEMON_ANIMATION EQU 92 +POKEDEX_TEXT EQU 93 +MOBILE_PRJ_LEADER EQU 94 +MOBILE_SYSTEM_AD EQU 95 +MOBILE_STADIUM_DIR EQU 96 +COORDINATION EQU 97 +COPYRIGHT EQU 98 +US_VERSION_STAFF EQU 99 +US_COORDINATION EQU 100 +TEXT_TRANSLATION EQU 101 +PAAD_TESTING EQU 102 + +CREDITS_THEEND EQU $f9 +CREDITS_WAIT2 EQU $fa +CREDITS_MUSIC EQU $fb +CREDITS_CLEAR EQU $fc +CREDITS_SCENE EQU $fd +CREDITS_WAIT EQU $fe + + +ParseCredits: ; 1099aa + ld hl, $cf63 + bit 7, [hl] + jp nz, .done + +; Wait until the timer has run out to parse the next command. + ld hl, CreditsTimer + ld a, [hl] + and a + jr z, .parse + +; One tick has passed. + dec [hl] + jp .done + +.parse +; First, let's clear the current text display, +; starting from line 5. + xor a + ld [$ffd4], a + hlcoord 0, 5 + ld bc, 20 * 12 + ld a, " " + call ByteFill + +; Then read the script. + +.loop + call .get + +; Commands: + cp $ff + jp z, .end + cp CREDITS_WAIT + jr z, .wait + cp CREDITS_SCENE + jr z, .scene + cp CREDITS_CLEAR + jr z, .clear + cp CREDITS_MUSIC + jr z, .music + cp CREDITS_WAIT2 + jr z, .wait2 + cp CREDITS_THEEND + jr z, .theend + +; If it's not a command, it's a string identifier. + + push af + ld e, a + ld d, 0 + ld hl, CreditsStrings + add hl, de + add hl, de + ld a, [hli] + ld d, [hl] + ld e, a + pop af + +; Strings spanning multiple lines have special cases. + + cp COPYRIGHT + jr z, .copyright + + cp STAFF + jr c, .staff + +; The rest start from line 6. + + hlcoord 0, 6 + jr .print + +.copyright + hlcoord 2, 6 + jr .print + +.staff + hlcoord 0, 6 + +.print +; Print strings spaced every two lines. + call .get + ld bc, 20 * 2 + call AddNTimes + call PlaceString + jr .loop + +.theend +; Display "The End" graphic. + call $5c11 + jr .loop + +.scene +; Update the scene number and corresponding palette. + call .get + ld [$cf65], a ; scene + xor a + ld [$cf64], a ; frame + call GetCreditsPalette + call $32f9 ; update hw pal registers + jr .loop + +.clear +; Clear the banner. + ld a, $ff + ld [$cf64], a ; frame + jr .loop + +.music +; Play the credits music. + ld de, MUSIC_CREDITS + push de + ld de, MUSIC_NONE + call StartMusic + call DelayFrame + pop de + call StartMusic + jp .loop + +.wait2 +; Wait for some amount of ticks. + call .get + ld [CreditsTimer], a + jr .done + +.wait +; Wait for some amount of ticks, and do something else. + call .get + ld [CreditsTimer], a + + xor a + ld [$ffd5], a + ld a, 1 + ld [$ffd4], a + +.done + jp $5951 + +.end +; Stop execution. + ld hl, $cf63 + set 7, [hl] + ld a, $20 + ld [$c2a7], a + ld a, $5c + ld [$c2a9], a + ld a, $00 + ld [$c2aa], a + ret + +.get +; Get byte CreditsPos from CreditsScript + push hl + push de + ld a, [CreditsPos] + ld e, a + ld a, [CreditsPos+1] + ld d, a + ld hl, CreditsScript + add hl, de + + inc de + ld a, e + ld [CreditsPos], a + ld a, d + ld [CreditsPos+1], a + ld a, [hl] + pop de + pop hl + ret +; 109a95 + + +INCBIN "baserom.gbc", $109a95, $109b2c - $109a95 + + +GetCreditsPalette: ; 109b2c + call .GetPalAddress + + push hl + ld a, 0 + call .UpdatePals + pop hl + ret + +.GetPalAddress +; Each set of palette data is 24 bytes long. + ld a, [$cf65] ; scene + and 3 + add a + add a ; * 8 + add a + ld e, a + ld d, 0 + ld hl, .CreditsPalettes + add hl, de + add hl, de ; * 3 + add hl, de + ret + +.UpdatePals +; Update the first three colors in both palette buffers. + + push af + push hl + add $00 ; lo($d000) + ld e, a + ld a, 0 + adc $d0 ; hi($d000) + ld d, a + ld bc, 24 + call CopyBytes + + pop hl + pop af + add $80 ; lo($d080) + ld e, a + ld a, 0 + adc $d0 ; hi($d080) + ld d, a + ld bc, 24 + call CopyBytes + ret + + +.CreditsPalettes +INCBIN "baserom.gbc",$109b6a,$18 ; pichu.pal +INCBIN "baserom.gbc",$109b82,$18 ; smoochum.pal +INCBIN "baserom.gbc",$109b9a,$18 ; ditto.pal +INCBIN "baserom.gbc",$109bb2,$18 ; igglybuff.pal +; 109bca + +INCBIN "baserom.gbc", $109bca, $109c24 - $109bca + +CreditsGFX: +INCBIN "gfx/credits/border.2bpp" +INCBIN "gfx/credits/pichu.2bpp" +INCBIN "gfx/credits/smoochum.2bpp" +INCBIN "gfx/credits/ditto.2bpp" +INCBIN "gfx/credits/igglybuff.2bpp" + + +CreditsScript: ; 10acb4 + +; Clear the banner. + db CREDITS_CLEAR + +; Pokemon Crystal Version Staff + db STAFF, 01 + db CREDITS_WAIT, 08 + +; Play the credits music. + db CREDITS_MUSIC + + db CREDITS_WAIT2, 10 + + db CREDITS_WAIT, 01 + +; Update the banner. + db CREDITS_SCENE, 00 ; Pichu + + db DIRECTOR, 01 + db SATOSHI_TAJIRI, 02 + db CREDITS_WAIT, 12 + + db CODIRECTOR, 01 + db JUNICHI_MASUDA, 02 + db CREDITS_WAIT, 12 + + db PROGRAMMERS, 00 + db SOUSUKE_TAMADA, 01 + db HISASHI_SOGABE, 02 + db KEITA_KAGAYA, 03 + db YOSHINORI_MATSUDA, 04 + db CREDITS_WAIT, 12 + + db PROGRAMMERS, 00 + db SHIGEKI_MORIMOTO, 01 + db TETSUYA_WATANABE, 02 + db TAKENORI_OOTA, 03 + db CREDITS_WAIT, 12 + + db GRAPHICS_DIRECTOR, 01 + db KEN_SUGIMORI, 02 + db CREDITS_WAIT, 12 + + db MONSTER_DESIGN, 00 + db KEN_SUGIMORI, 01 + db MOTOFUMI_FUJIWARA, 02 + db SHIGEKI_MORIMOTO, 03 + db HIRONOBU_YOSHIDA, 04 + db SATOSHI_OOTA, 05 + db CREDITS_WAIT, 12 + + db MONSTER_DESIGN, 00 + db ATSUKO_NISHIDA, 01 + db MUNEO_SAITO, 02 + db RENA_YOSHIKAWA, 03 + db CREDITS_WAIT, 12 + + db POKEMON_ANIMATION, 01 + db HIRONOBU_YOSHIDA, 02 + db JUN_OKUTANI, 03 + db CREDITS_WAIT, 12 + +; Clear the banner. + db CREDITS_CLEAR + + db CREDITS_WAIT, 01 + +; Update the banner. + db CREDITS_SCENE, 01 ; Smoochum + + db GRAPHICS_DESIGN, 00 + db HIRONOBU_YOSHIDA, 01 + db JUN_OKUTANI, 02 + db ASUKA_IWASHITA, 03 + db TETSUYA_WATANABE, 04 + db CREDITS_WAIT, 12 + + db MUSIC, 00 + db JUNICHI_MASUDA, 01 + db MORIKAZU_AOKI, 02 + db GO_ICHINOSE, 03 + db CREDITS_WAIT, 12 + + db SOUND_EFFECTS, 00 + db MORIKAZU_AOKI, 01 + db JUNICHI_MASUDA, 02 + db TETSUYA_WATANABE, 03 + db CREDITS_WAIT, 12 + + db GAME_DESIGN, 00 + db JUNICHI_MASUDA, 01 + db SHIGEKI_MORIMOTO, 02 + db KOHJI_NISHINO, 03 + db CREDITS_WAIT, 12 + + db GAME_DESIGN, 00 + db TETSUJI_OOTA, 01 + db HITOMI_SATO, 02 + db KENJI_MATSUSHIMA, 03 + db CREDITS_WAIT, 12 + + db GAME_SCENARIO, 00 + db JUNICHI_MASUDA, 01 + db KOHJI_NISHINO, 02 + db TOSHINOBU_MATSUMIYA, 03 + db KENJI_MATSUSHIMA, 04 + db CREDITS_WAIT, 12 + + db POKEDEX_TEXT, 01 + db TOSHINOBU_MATSUMIYA, 02 + db CREDITS_WAIT, 12 + + db TOOL_PROGRAMMING, 01 + db SOUSUKE_TAMADA, 02 + db TAKENORI_OOTA, 03 + db CREDITS_WAIT, 12 + + db PARAMETRIC_DESIGN, 01 + db KOHJI_NISHINO, 02 + db CREDITS_WAIT, 12 + +; Clear the banner. + db CREDITS_CLEAR + + db CREDITS_WAIT, 01 + +; Update the banner. + db CREDITS_SCENE, 02 ; Ditto + + db SCRIPT_DESIGN, 01 + db TETSUJI_OOTA, 02 + db NOBUHIRO_SEYA, 03 + db CREDITS_WAIT, 12 + + db MAP_DATA_DESIGN, 01 + db TETSUJI_OOTA, 02 + db KAZUHITO_SEKINE, 03 + db CREDITS_WAIT, 12 + + db MAP_DESIGN, 00 + db TETSUJI_OOTA, 01 + db KOHJI_NISHINO, 02 + db NOBUHIRO_SEYA, 03 + db CREDITS_WAIT, 12 + + db COORDINATION, 01 + db HIROYUKI_ZINNAI, 02 + db CREDITS_WAIT, 12 + + db PRODUCERS, 00 + db SATORU_IWATA, 01 + db SATOSHI_YAMATO, 02 + db SHIGERU_MIYAMOTO, 03 + db CREDITS_WAIT, 12 + + db PRODUCERS, 01 + db TSUNEKAZU_ISHIHARA, 02 + db CREDITS_WAIT, 12 + +; Clear the banner. + db CREDITS_CLEAR + + db CREDITS_WAIT, 01 + +; Update the banner. + db CREDITS_SCENE, 03 ; Igglybuff + + db US_VERSION_STAFF, 02 + db CREDITS_WAIT, 09 + + db US_COORDINATION, 01 + db GAIL_TILDEN, 02 + db HIRO_NAKAMURA, 03 + db CREDITS_WAIT, 12 + + db US_COORDINATION, 01 + db JUNICHI_MASUDA, 02 + db SETH_MCMAHILL, 03 + db CREDITS_WAIT, 12 + + db US_COORDINATION, 01 + db HIROTO_ALEXANDER, 02 + db TERESA_LILLYGREN, 03 + db CREDITS_WAIT, 12 + + db TEXT_TRANSLATION, 01 + db NOB_OGASAWARA, 02 + db CREDITS_WAIT, 12 + + db PROGRAMMERS, 01 + db TERUKI_MURAKAWA, 02 + db KAZUYOSHI_OSAWA, 03 + db CREDITS_WAIT, 12 + + db PAAD_TESTING, 01 + db THOMAS_HERTZOG, 02 + db ERIK_JOHNSON, 03 + db CREDITS_WAIT, 12 + + db PRODUCT_TESTING, 00 + db PLANNING, 01 + db CREDITS_WAIT, 12 + + db PRODUCT_TESTING, 00 + db KEITA_NAKAMURA, 01 + db HIROTAKA_UEMURA, 02 + db HIROAKI_TAMURA, 03 + db NORIAKI_SAKAGUCHI, 04 + db CREDITS_WAIT, 12 + + db PRODUCT_TESTING, 00 + db NCL_SUPER_MARIO_CLUB, 01 + db KENJI_SAIKI, 02 + db ATSUSHI_TADA, 03 + db MIYUKI_SATO, 04 + db CREDITS_WAIT, 12 + + db SPECIAL_THANKS, 00 + db KIMIKO_NAKAMICHI, 01 + db AKITO_MORI, 02 + db CREDITS_WAIT, 12 + + db SPECIAL_THANKS, 00 + db GAKUZI_NOMOTO, 01 + db AI_MASHIMA, 02 + db KUNIMI_KAWAMURA, 03 + db CREDITS_WAIT, 12 + + db SPECIAL_THANKS, 00 + db MIKIHIRO_ISHIKAWA, 01 + db HIDEYUKI_HASHIMOTO, 02 + db CREDITS_WAIT, 12 + + db EXECUTIVE_PRODUCER, 01 + db HIROSHI_YAMAUCHI, 02 + db CREDITS_WAIT, 12 + + db COPYRIGHT, 01 + db CREDITS_WAIT, 09 + +; Display "The End" graphic. + db CREDITS_THEEND + + db CREDITS_WAIT, 20 + + db $ff ; end +; 10ae13 + + +CreditsStrings: + dw .SatoshiTajiri + dw .JunichiMasuda + dw .TetsuyaWatanabe + dw .ShigekiMorimoto + dw .SousukeTamada + dw .TakenoriOota + dw .KenSugimori + dw .MotofumiFujiwara + dw .AtsukoNishida + dw .MuneoSaito + dw .SatoshiOota + dw .RenaYoshikawa + dw .JunOkutani + dw .HironobuYoshida + dw .AsukaIwashita + dw .GoIchinose + dw .MorikazuAoki + dw .KohjiNishino + dw .KenjiMatsushima + dw .ToshinobuMatsumiya + dw .SatoruIwata + dw .NobuhiroSeya + dw .KazuhitoSekine + dw .TetsujiOota + dw .NclSuperMarioClub + dw .Sarugakucho + dw .AkitoMori + dw .TakahiroHarada + dw .TohruHashimoto + dw .NoboruMatsumoto + dw .TakehiroIzushi + dw .TakashiKawaguchi + dw .TsunekazuIshihara + dw .HiroshiYamauchi + dw .KenjiSaiki + dw .AtsushiTada + dw .NaokoKawakami + dw .HiroyukiZinnai + dw .KunimiKawamura + dw .HisashiSogabe + dw .KeitaKagaya + dw .YoshinoriMatsuda + dw .HitomiSato + dw .ToruOsawa + dw .TakaoOhara + dw .YuichiroIto + dw .TakaoShimizu + dw .Planning + dw .KeitaNakamura + dw .HirotakaUemura + dw .HiroakiTamura + dw .NoriakiSakaguchi + dw .MiyukiSato + dw .GakuziNomoto + dw .AiMashima + dw .MikihiroIshikawa + dw .HideyukiHashimoto + dw .SatoshiYamato + dw .ShigeruMiyamoto + dw .GailTilden + dw .NobOgasawara + dw .SethMcMahill + dw .HirotoAlexander + dw .TeresaLillygren + dw .ThomasHertzog + dw .ErikJohnson + dw .HiroNakamura + dw .TerukiMurakawa + dw .KazuyoshiOsawa + dw .KimikoNakamichi + dw .End + dw .Unknown + dw .Staff + dw .Director + dw .CoDirector + dw .Programmers + dw .GraphicsDirector + dw .MonsterDesign + dw .GraphicsDesign + dw .Music + dw .SoundEffects + dw .GameDesign + dw .GameScenario + dw .ToolProgramming + dw .ParametricDesign + dw .ScriptDesign + dw .MapDataDesign + dw .MapDesign + dw .ProductTesting + dw .SpecialThanks + dw .Producers + dw .ExecutiveProducer + dw .PokemonAnimation + dw .PokedexText + dw .MobilePrjLeader + dw .MobileSystemAd + dw .MobileStadiumDir + dw .Coordination + dw .Copyright + dw .UsVersionStaff + dw .UsCoordination + dw .TextTranslation + dw .PaadTesting + +.SatoshiTajiri: db " SATOSHI TAJIRI@" ; "たじり さとし@" +.JunichiMasuda: db " JUNICHI MASUDA@" ; "ますだ じゅんいち@" +.TetsuyaWatanabe: db " TETSUYA WATANABE@" ; "わたなべ てつや@" +.ShigekiMorimoto: db " SHIGEKI MORIMOTO@" ; "もりもと しげき@" +.SousukeTamada: db " SOUSUKE TAMADA@" ; "たまだ そうすけ@" +.TakenoriOota: db " TAKENORI OOTA@" ; "おおた たけのり@" +.KenSugimori: db " KEN SUGIMORI@" ; "すぎもり けん@" +.MotofumiFujiwara: db " MOTOFUMI FUJIWARA@" ; "ふじわら もとふみ@" +.AtsukoNishida: db " ATSUKO NISHIDA@" ; "にしだ あつこ@" +.MuneoSaito: db " MUNEO SAITO@" ; "さいとう むねお@" +.SatoshiOota: db " SATOSHI OOTA@" ; "おおた さとし@" +.RenaYoshikawa: db " RENA YOSHIKAWA@" ; "よしかわ れな@" +.JunOkutani: db " JUN OKUTANI@" ; "おくたに じゅん@" +.HironobuYoshida: db " HIRONOBU YOSHIDA@" ; "よしだ ひろのぶ@" +.AsukaIwashita: db " ASUKA IWASHITA@" ; "いわした あすか@" +.GoIchinose: db " GO ICHINOSE@" ; "いちのせ ごう@" +.MorikazuAoki: db " MORIKAZU AOKI@" ; "あおき もりかず@" +.KohjiNishino: db " KOHJI NISHINO@" ; "にしの こうじ@" +.KenjiMatsushima: db " KENJI MATSUSHIMA@" ; "まつしま けんじ@" +.ToshinobuMatsumiya: db "TOSHINOBU MATSUMIYA@" ; "まつみや としのぶ@" +.SatoruIwata: db " SATORU IWATA@" ; "いわた さとる@" +.NobuhiroSeya: db " NOBUHIRO SEYA@" ; "せや のぶひろ@" +.KazuhitoSekine: db " KAZUHITO SEKINE@" ; "せきね かずひと@" +.TetsujiOota: db " TETSUJI OOTA@" ; "おおた てつじ@" +.NclSuperMarioClub: db "NCL SUPER MARIO CLUB@" ; "スーパーマりォクラブ@" +.Sarugakucho: db " SARUGAKUCHO@" ; "さるがくちょう@" +.AkitoMori: db " AKITO MORI@" ; "もり あきと@" +.TakahiroHarada: db " TAKAHIRO HARADA@" ; "はらだ たかひろ@" +.TohruHashimoto: db " TOHRU HASHIMOTO@" ; "はしもと とおる@" +.NoboruMatsumoto: db " NOBORU MATSUMOTO@" ; "まつもと のぼる@" +.TakehiroIzushi: db " TAKEHIRO IZUSHI@" ; "いずし たけひろ@" +.TakashiKawaguchi: db " TAKASHI KAWAGUCHI@" ; "かわぐち たかし@" +.TsunekazuIshihara: db " TSUNEKAZU ISHIHARA@" ; "いしはら つねかず@" +.HiroshiYamauchi: db " HIROSHI YAMAUCHI@" ; "やまうち ひろし@" +.KenjiSaiki: db " KENJI SAIKI@" ; "さいき けんじ@" +.AtsushiTada: db " ATSUSHI TADA@" ; "ただ あつし@" +.NaokoKawakami: db " NAOKO KAWAKAMI@" ; "かわかみ なおこ@" +.HiroyukiZinnai: db " HIROYUKI ZINNAI@" ; "じんない ひろゆき@" +.KunimiKawamura: db " KUNIMI KAWAMURA@" ; "かわむら くにみ@" +.HisashiSogabe: db " HISASHI SOGABE@" ; "そがべ ひさし@" +.KeitaKagaya: db " KEITA KAGAYA@" ; "かがや けいた@" +.YoshinoriMatsuda: db " YOSHINORI MATSUDA@" ; "まつだ よしのり@" +.HitomiSato: db " HITOMI SATO@" ; "さとう ひとみ@" +.ToruOsawa: db " TORU OSAWA@" ; "おおさわ とおる@" +.TakaoOhara: db " TAKAO OHARA@" ; "おおはら たかお@" +.YuichiroIto: db " YUICHIRO ITO@" ; "いとう ゆういちろう@" +.TakaoShimizu: db " TAKAO SHIMIZU@" ; "しみず たかお@" +.Planning: db " SPECIAL PRODUCTION", $4e + db " PLANNING", $4e ; "きかくかいはつぶ@" + db " & DEVELOPMENT DEPT.@" +.KeitaNakamura: db " KEITA NAKAMURA@" ; "なかむら けいた@" +.HirotakaUemura: db " HIROTAKA UEMURA@" ; "うえむら ひろたか@" +.HiroakiTamura: db " HIROAKI TAMURA@" ; "たむら ひろあき@" +.NoriakiSakaguchi: db " NORIAKI SAKAGUCHI@" ; "さかぐち のりあき@" +.MiyukiSato: db " MIYUKI SATO@" ; "さとう みゆき@" +.GakuziNomoto: db " GAKUZI NOMOTO@" ; "のもと がくじ@" +.AiMashima: db " AI MASHIMA@" ; "ましま あい@" +.MikihiroIshikawa: db " MIKIHIRO ISHIKAWA@" ; "いしかわ みきひろ@" +.HideyukiHashimoto: db " HIDEYUKI HASHIMOTO@" ; "はしもと ひでゆき@" +.SatoshiYamato: db " SATOSHI YAMATO@" ; "やまと さとし@" +.ShigeruMiyamoto: db " SHIGERU MIYAMOTO@" ; "みやもと しげる@" +.End: db " END@" ; "おしまい@" +.Unknown: db " ????????@" ; "????????@" +.GailTilden: db " GAIL TILDEN@" +.NobOgasawara: db " NOB OGASAWARA@" +.SethMcMahill: db " SETH McMAHILL@" +.HirotoAlexander: db " HIROTO ALEXANDER@" +.TeresaLillygren: db " TERESA LILLYGREN@" +.ThomasHertzog: db " THOMAS HERTZOG@" +.ErikJohnson: db " ERIK JOHNSON@" +.HiroNakamura: db " HIRO NAKAMURA@" +.TerukiMurakawa: db " TERUKI MURAKAWA@" +.KazuyoshiOsawa: db " KAZUYOSHI OSAWA@" +.KimikoNakamichi: db " KIMIKO NAKAMICHI@" +.Staff: db " #MON", $4e ; "ポケットモンスター", $4e + db " CRYSTAL VERSION", $4e ; " クりスタル バージョン", $4e + db " STAFF@" ; " スタッフ@" +.Director: db " DIRECTOR@" ; "エグゼクティブ ディレクター@" +.CoDirector: db " CO-DIRECTOR@" ; "ディレクター@" +.Programmers: db " PROGRAMMERS@" ; "プログラム@" +.GraphicsDirector: db " GRAPHICS DIRECTOR@" ; "グラフィック ディレクター@" +.MonsterDesign: db " MONSTER DESIGN@" ; "# デザイン@" +.GraphicsDesign: db " GRAPHICS DESIGN@" ; "グラフィック デザイン@" +.Music: db " MUSIC@" ; "おんがく@" +.SoundEffects: db " SOUND EFFECTS@" ; "サウンド エフ→クト@" +.GameDesign: db " GAME DESIGN@" ; "ゲームデザイン@" +.GameScenario: db " GAME SCENARIO@" ; "シナりォ@" +.ToolProgramming: db " TOOL PROGRAMMING@" ; "ツール プログラム@" +.ParametricDesign: db " PARAMETRIC DESIGN@" ; "パラメーター せってい@" +.ScriptDesign: db " SCRIPT DESIGN@" ; "スクりプト せってい@" +.MapDataDesign: db " MAP DATA DESIGN@" ; "マップデータ せってい@" +.MapDesign: db " MAP DESIGN@" ; "マップ デザイン@" +.ProductTesting: db " PRODUCT TESTING@" ; "デバッグプレイ@" +.SpecialThanks: db " SPECIAL THANKS@" ; "スぺシャルサンクス@" +.Producers: db " PRODUCERS@" ; "プロデューサー@" +.ExecutiveProducer: db " EXECUTIVE PRODUCER@" ; "エグゼクティブ プロデューサー@" +.PokemonAnimation: db " #MON ANIMATION@" ; "# アニメーション@" +.PokedexText: db " #DEX TEXT@" ; "ずかん テキスト@" +.MobilePrjLeader: db " MOBILE PRJ. LEADER@" ; "モバイルプロジ→クト りーダー@" +.MobileSystemAd: db " MOBILE SYSTEM AD.@" ; "モバイル システムアドバイザー@" +.MobileStadiumDir: db "MOBILE STADIUM DIR.@" ; "モバイルスタジアム ディレクター@" +.Coordination: db " COORDINATION@" ; "コーディネーター@" +.UsVersionStaff: db " US VERSION STAFF@" +.UsCoordination: db " US COORDINATION@" +.TextTranslation: db " TEXT TRANSLATION@" +.PaadTesting: db " PAAD TESTING@" + +.Copyright: +; (C) 1 9 9 5 - 2 0 0 1 N i n t e n d o +db $60,$61,$62,$63,$64,$65,$66, $67, $68, $69, $6a, $6b, $6c, $4e +; (C) 1 9 9 5 - 2 0 0 1 C r e a t u r e s i n c . +db $60,$61,$62,$63,$64,$65,$66, $6d, $6e, $6f, $70, $71, $72, $7a, $7b, $7c, $4e +; (C) 1 9 9 5 - 2 0 0 1 G A M E F R E A K i n c . +db $60,$61,$62,$63,$64,$65,$66, $73, $74, $75, $76, $77, $78, $79, $7a, $7b, $7c, "@" + diff --git a/extras/crystal.py b/extras/crystal.py index 06d54ae22..b3f29a12f 100644 --- a/extras/crystal.py +++ b/extras/crystal.py @@ -2816,16 +2816,18 @@ pksv_crystal_more = { 0x9C: ["specialphonecall", ["call_id", MultiByteParam]], 0x9D: ["checkphonecall"], 0x9E: ["verbosegiveitem", ["item", ItemLabelByte], ["quantity", DecimalParam]], - 0x9F: ["verbosegiveitem2", ["item", ItemLabelByte]], + 0x9F: ["verbosegiveitem2", ["item", ItemLabelByte], ["var", SingleByteParam]], 0xA0: ["loadwilddata", ["map_group", MapGroupParam], ["map_id", MapIdParam]], 0xA1: ["halloffame"], 0xA2: ["credits"], 0xA3: ["warpfacing", ["facing", SingleByteParam], ["map_group", MapGroupParam], ["map_id", MapIdParam], ["x", SingleByteParam], ["y", SingleByteParam]], 0xA4: ["storetext", ["pointer", PointerLabelBeforeBank], ["memory", SingleByteParam]], 0xA5: ["displaylocation", ["id", SingleByteParam]], + 0xA6: ["unknown0xa6"], + 0xA7: ["unknown0xa7"], 0xA8: ["unknown0xa8", ["unknown", SingleByteParam]], - 0xB2: ["unknown0xb2", ["unknown", SingleByteParam]], - 0xCC: ["unknown0xcc"], + 0xA9: ["unknown0xa9"], + 0xAA: ["unknown0xaa"], } def create_command_classes(debug=False): """creates some classes for each command byte""" @@ -6322,489 +6324,9 @@ class PokedexEntry: {4}""".format(self.species, self.weight, self.height, self.page1.to_asm(), self.page2.to_asm()) return output -# map names with no labels will be generated at the end of the structure -map_names = { - 1: { - 0x1: {"name": "Olivine Pokémon Center 1F", - "label": "OlivinePokeCenter1F"}, - 0x2: {"name": "Olivine Gym"}, - 0x3: {"name": "Olivine Voltorb House"}, - 0x4: {"name": "Olivine House Beta"}, - 0x5: {"name": "Olivine Punishment Speech House"}, - 0x6: {"name": "Olivine Good Rod House"}, - 0x7: {"name": "Olivine Cafe"}, - 0x8: {"name": "Olivine Mart"}, - 0x9: {"name": "Route 38 Ecruteak Gate"}, - 0xA: {"name": "Route 39 Barn"}, - 0xB: {"name": "Route 39 Farmhouse"}, - 0xC: {"name": "Route 38"}, - 0xD: {"name": "Route 39"}, - 0xE: {"name": "Olivine City"}, - }, - 2: { - 0x1: {"name": "Mahogany Red Gyarados Speech House"}, - 0x2: {"name": "Mahogany Gym"}, - 0x3: {"name": "Mahogany Pokémon Center 1F", - "label": "MahoganyPokeCenter1F"}, - 0x4: {"name": "Route 42 Ecruteak Gate"}, - 0x5: {"name": "Route 42"}, - 0x6: {"name": "Route 44"}, - 0x7: {"name": "Mahogany Town"}, - }, - 3: { - 0x1: {"name": "Sprout Tower 1F"}, - 0x2: {"name": "Sprout Tower 2F"}, - 0x3: {"name": "Sprout Tower 3F"}, - 0x4: {"name": "Tin Tower 1F"}, - 0x5: {"name": "Tin Tower 2F"}, - 0x6: {"name": "Tin Tower 3F"}, - 0x7: {"name": "Tin Tower 4F"}, - 0x8: {"name": "Tin Tower 5F"}, - 0x9: {"name": "Tin Tower 6F"}, - 0xA: {"name": "Tin Tower 7F"}, - 0xB: {"name": "Tin Tower 8F"}, - 0xC: {"name": "Tin Tower 9F"}, - 0xD: {"name": "Burned Tower 1F"}, - 0xE: {"name": "Burned Tower B1F"}, - 0xF: {"name": "National Park"}, - 0x10: {"name": "National Park Bug Contest"}, - 0x11: {"name": "Radio Tower 1F"}, - 0x12: {"name": "Radio Tower 2F"}, - 0x13: {"name": "Radio Tower 3F"}, - 0x14: {"name": "Radio Tower 4F"}, - 0x15: {"name": "Radio Tower 5F"}, - 0x16: {"name": "Ruins of Alph Outside"}, - 0x17: {"name": "Ruins of Alph Ho-oh Chamber"}, - 0x18: {"name": "Ruins of Alph Kabuto Chamber"}, - 0x19: {"name": "Ruins of Alph Omanyte Chamber"}, - 0x1A: {"name": "Ruins of Alph Aerodactyl Chamber"}, - 0x1B: {"name": "Ruins of Alph Inner Chamber"}, - 0x1C: {"name": "Ruins of Alph Research Center"}, - 0x1D: {"name": "Ruins of Alph Ho-oh Item Room"}, - 0x1E: {"name": "Ruins of Alph Kabuto Item Room"}, - 0x1F: {"name": "Ruins of Alph Omanyte Item Room"}, - 0x20: {"name": "Ruins of Alph Aerodactyl Item Room"}, - 0x21: {"name": "Ruins of Alph Ho-Oh Word Room"}, - 0x22: {"name": "Ruins of Alph Kabuto Word Room"}, - 0x23: {"name": "Ruins of Alph Omanyte Word Room"}, - 0x24: {"name": "Ruins of Alph Aerodactyl Word Room"}, - 0x25: {"name": "Union Cave 1F"}, - 0x26: {"name": "Union Cave B1F"}, - 0x27: {"name": "Union Cave B2F"}, - 0x28: {"name": "Slowpoke Well B1F"}, - 0x29: {"name": "Slowpoke Well B2F"}, - 0x2A: {"name": "Olivine Lighthouse 1F"}, - 0x2B: {"name": "Olivine Lighthouse 2F"}, - 0x2C: {"name": "Olivine Lighthouse 3F"}, - 0x2D: {"name": "Olivine Lighthouse 4F"}, - 0x2E: {"name": "Olivine Lighthouse 5F"}, - 0x2F: {"name": "Olivine Lighthouse 6F"}, - 0x30: {"name": "Mahogany Mart 1F"}, - 0x31: {"name": "Team Rocket Base B1F"}, - 0x32: {"name": "Team Rocket Base B2F"}, - 0x33: {"name": "Team Rocket Base B3F"}, - 0x34: {"name": "Ilex Forest"}, - 0x35: {"name": "Warehouse Entrance"}, - 0x36: {"name": "Underground Path Switch Room Entrances"}, - 0x37: {"name": "Goldenrod Dept Store B1F"}, - 0x38: {"name": "Underground Warehouse"}, - 0x39: {"name": "Mount Mortar 1F Outside"}, - 0x3A: {"name": "Mount Mortar 1F Inside"}, - 0x3B: {"name": "Mount Mortar 2F Inside"}, - 0x3C: {"name": "Mount Mortar B1F"}, - 0x3D: {"name": "Ice Path 1F"}, - 0x3E: {"name": "Ice Path B1F"}, - 0x3F: {"name": "Ice Path B2F Mahogany Side"}, - 0x40: {"name": "Ice Path B2F Blackthorn Side"}, - 0x41: {"name": "Ice Path B3F"}, - 0x42: {"name": "Whirl Island NW"}, - 0x43: {"name": "Whirl Island NE"}, - 0x44: {"name": "Whirl Island SW"}, - 0x45: {"name": "Whirl Island Cave"}, - 0x46: {"name": "Whirl Island SE"}, - 0x47: {"name": "Whirl Island B1F"}, - 0x48: {"name": "Whirl Island B2F"}, - 0x49: {"name": "Whirl Island Lugia Chamber"}, - 0x4A: {"name": "Silver Cave Room 1"}, - 0x4B: {"name": "Silver Cave Room 2"}, - 0x4C: {"name": "Silver Cave Room 3"}, - 0x4D: {"name": "Silver Cave Item Rooms"}, - 0x4E: {"name": "Dark Cave Violet Entrance"}, - 0x4F: {"name": "Dark Cave Blackthorn Entrance"}, - 0x50: {"name": "Dragon's Den 1F"}, - 0x51: {"name": "Dragon's Den B1F"}, - 0x52: {"name": "Dragon Shrine"}, - 0x53: {"name": "Tohjo Falls"}, - 0x54: {"name": "Diglett's Cave"}, - 0x55: {"name": "Mount Moon"}, - 0x56: {"name": "Underground"}, - 0x57: {"name": "Rock Tunnel 1F"}, - 0x58: {"name": "Rock Tunnel B1F"}, - 0x59: {"name": "Safari Zone Fuchsia Gate Beta"}, - 0x5A: {"name": "Safari Zone Beta"}, - 0x5B: {"name": "Victory Road"}, - }, - 4: { - 0x1: {"name": "Ecruteak House"}, # passage to Tin Tower - 0x2: {"name": "Wise Trio's Room"}, - 0x3: {"name": "Ecruteak Pokémon Center 1F", - "label": "EcruteakPokeCenter1F"}, - 0x4: {"name": "Ecruteak Lugia Speech House"}, - 0x5: {"name": "Dance Theatre"}, - 0x6: {"name": "Ecruteak Mart"}, - 0x7: {"name": "Ecruteak Gym"}, - 0x8: {"name": "Ecruteak Itemfinder House"}, - 0x9: {"name": "Ecruteak City"}, - }, - 5: { - 0x1: {"name": "Blackthorn Gym 1F"}, - 0x2: {"name": "Blackthorn Gym 2F"}, - 0x3: {"name": "Blackthorn Dragon Speech House"}, - 0x4: {"name": "Blackthorn Dodrio Trade House"}, - 0x5: {"name": "Blackthorn Mart"}, - 0x6: {"name": "Blackthorn Pokémon Center 1F", - "label": "BlackthornPokeCenter1F"}, - 0x7: {"name": "Move Deleter's House"}, - 0x8: {"name": "Route 45"}, - 0x9: {"name": "Route 46"}, - 0xA: {"name": "Blackthorn City"}, - }, - 6: { - 0x1: {"name": "Cinnabar Pokémon Center 1F", - "label": "CinnabarPokeCenter1F"}, - 0x2: {"name": "Cinnabar Pokémon Center 2F Beta", - "label": "CinnabarPokeCenter2FBeta"}, - 0x3: {"name": "Route 19 - Fuchsia Gate"}, - 0x4: {"name": "Seafoam Gym"}, - 0x5: {"name": "Route 19"}, - 0x6: {"name": "Route 20"}, - 0x7: {"name": "Route 21"}, - 0x8: {"name": "Cinnabar Island"}, - }, - 7: { - 0x1: {"name": "Cerulean Gym Badge Speech House"}, - 0x2: {"name": "Cerulean Police Station"}, - 0x3: {"name": "Cerulean Trade Speech House"}, - 0x4: {"name": "Cerulean Pokémon Center 1F", - "label": "CeruleanPokeCenter1F"}, - 0x5: {"name": "Cerulean Pokémon Center 2F Beta", - "label": "CeruleanPokeCenter2FBeta"}, - 0x6: {"name": "Cerulean Gym"}, - 0x7: {"name": "Cerulean Mart"}, - 0x8: {"name": "Route 10 Pokémon Center 1F", - "label": "Route10PokeCenter1F"}, - 0x9: {"name": "Route 10 Pokémon Center 2F Beta", - "label": "Route10PokeCenter2FBeta"}, - 0xA: {"name": "Power Plant"}, - 0xB: {"name": "Bill's House"}, - 0xC: {"name": "Route 4"}, - 0xD: {"name": "Route 9"}, - 0xE: {"name": "Route 10 North"}, - 0xF: {"name": "Route 24"}, - 0x10: {"name": "Route 25"}, - 0x11: {"name": "Cerulean City"}, - }, - 8: { - 0x1: {"name": "Azalea Pokémon Center 1F", - "label": "AzaleaPokeCenter1F"}, - 0x2: {"name": "Charcoal Kiln"}, - 0x3: {"name": "Azalea Mart"}, - 0x4: {"name": "Kurt's House"}, - 0x5: {"name": "Azalea Gym"}, - 0x6: {"name": "Route 33"}, - 0x7: {"name": "Azalea Town"}, - }, - 9: { - 0x1: {"name": "Lake of Rage Hidden Power House"}, - 0x2: {"name": "Lake of Rage Magikarp House"}, - 0x3: {"name": "Route 43 Mahogany Gate"}, - 0x4: {"name": "Route 43 Gate"}, - 0x5: {"name": "Route 43"}, - 0x6: {"name": "Lake of Rage"}, - }, - 10: { - 0x1: {"name": "Route 32"}, - 0x2: {"name": "Route 35"}, - 0x3: {"name": "Route 36"}, - 0x4: {"name": "Route 37"}, - 0x5: {"name": "Violet City"}, - 0x6: {"name": "Violet Mart"}, - 0x7: {"name": "Violet Gym"}, - 0x8: {"name": "Earl's Pokémon Academy", - "label": "EarlsPokemonAcademy"}, - 0x9: {"name": "Violet Nickname Speech House"}, - 0xA: {"name": "Violet Pokémon Center 1F", - "label": "VioletPokeCenter1F"}, - 0xB: {"name": "Violet Onix Trade House"}, - 0xC: {"name": "Route 32 Ruins of Alph Gate"}, - 0xD: {"name": "Route 32 Pokémon Center 1F", - "label": "Route32PokeCenter1F"}, - 0xE: {"name": "Route 35 Goldenrod gate"}, - 0xF: {"name": "Route 35 National Park gate"}, - 0x10: {"name": "Route 36 Ruins of Alph gate"}, - 0x11: {"name": "Route 36 National Park gate"}, - }, - 11: { - 0x1: {"name": "Route 34"}, - 0x2: {"name": "Goldenrod City"}, - 0x3: {"name": "Goldenrod Gym"}, - 0x4: {"name": "Goldenrod Bike Shop"}, - 0x5: {"name": "Goldenrod Happiness Rater"}, - 0x6: {"name": "Goldenrod Bill's House"}, - 0x7: {"name": "Goldenrod Magnet Train Station"}, - 0x8: {"name": "Goldenrod Flower Shop"}, - 0x9: {"name": "Goldenrod PP Speech House"}, - 0xA: {"name": "Goldenrod Name Rater's House"}, - 0xB: {"name": "Goldenrod Dept Store 1F"}, - 0xC: {"name": "Goldenrod Dept Store 2F"}, - 0xD: {"name": "Goldenrod Dept Store 3F"}, - 0xE: {"name": "Goldenrod Dept Store 4F"}, - 0xF: {"name": "Goldenrod Dept Store 5F"}, - 0x10: {"name": "Goldenrod Dept Store 6F"}, - 0x11: {"name": "Goldenrod Dept Store Elevator"}, - 0x12: {"name": "Goldenrod Dept Store Roof"}, - 0x13: {"name": "Goldenrod Game Corner"}, - 0x14: {"name": "Goldenrod Pokémon Center 1F", - "label": "GoldenrodPokeCenter1F"}, - 0x15: {"name": "Goldenrod PokéCom Center 2F Mobile", - "label": "GoldenrodPokeComCenter2FMobile"}, - 0x16: {"name": "Ilex Forest Azalea Gate"}, - 0x17: {"name": "Route 34 Ilex Forest Gate"}, - 0x18: {"name": "Day Care"}, - }, - 12: { - 0x1: {"name": "Route 6"}, - 0x2: {"name": "Route 11"}, - 0x3: {"name": "Vermilion City"}, - 0x4: {"name": "Vermilion House Fishing Speech House"}, - 0x5: {"name": "Vermilion Pokémon Center 1F", - "label": "VermilionPokeCenter1F"}, - 0x6: {"name": "Vermilion Pokémon Center 2F Beta", - "label": "VermilionPokeCenter2FBeta"}, - 0x7: {"name": "Pokémon Fan Club"}, - 0x8: {"name": "Vermilion Magnet Train Speech House"}, - 0x9: {"name": "Vermilion Mart"}, - 0xA: {"name": "Vermilion House Diglett's Cave Speech House"}, - 0xB: {"name": "Vermilion Gym"}, - 0xC: {"name": "Route 6 Saffron Gate"}, - 0xD: {"name": "Route 6 Underground Entrance"}, - }, - 13: { - 0x1: {"name": "Route 1"}, - 0x2: {"name": "Pallet Town"}, - 0x3: {"name": "Red's House 1F"}, - 0x4: {"name": "Red's House 2F"}, - 0x5: {"name": "Blue's House"}, - 0x6: {"name": "Oak's Lab"}, - }, - 14: { - 0x1: {"name": "Route 3"}, - 0x2: {"name": "Pewter City"}, - 0x3: {"name": "Pewter Nidoran Speech House"}, - 0x4: {"name": "Pewter Gym"}, - 0x5: {"name": "Pewter Mart"}, - 0x6: {"name": "Pewter Pokémon Center 1F", - "label": "PewterPokeCenter1F"}, - 0x7: {"name": "Pewter Pokémon Center 2F Beta", - "label": "PewterPokeCEnter2FBeta"}, - 0x8: {"name": "Pewter Snooze Speech House"}, - }, - 15: { - 0x1: {"name": "Olivine Port"}, - 0x2: {"name": "Vermilion Port"}, - 0x3: {"name": "Fast Ship 1F"}, - 0x4: {"name": "Fast Ship Cabins NNW, NNE, NE", - "label": "FastShipCabins_NNW_NNE_NE"}, - 0x5: {"name": "Fast Ship Cabins SW, SSW, NW", - "label": "FastShipCabins_SW_SSW_NW"}, - 0x6: {"name": "Fast Ship Cabins SE, SSE, Captain's Cabin", - "label": "FastShipCabins_SE_SSE_CaptainsCabin"}, - 0x7: {"name": "Fast Ship B1F"}, - 0x8: {"name": "Olivine Port Passage"}, - 0x9: {"name": "Vermilion Port Passage"}, - 0xA: {"name": "Mount Moon Square"}, - 0xB: {"name": "Mount Moon Gift Shop"}, - 0xC: {"name": "Tin Tower Roof"}, - }, - 16: { - 0x1: {"name": "Route 23"}, - 0x2: {"name": "Indigo Plateau Pokémon Center 1F", - "label": "IndigoPlateauPokeCenter1F"}, - 0x3: {"name": "Will's Room"}, - 0x4: {"name": "Koga's Room"}, - 0x5: {"name": "Bruno's Room"}, - 0x6: {"name": "Karen's Room"}, - 0x7: {"name": "Lance's Room"}, - 0x8: {"name": "Hall of Fame", - "label": "HallOfFame"}, - }, - 17: { - 0x1: {"name": "Route 13"}, - 0x2: {"name": "Route 14"}, - 0x3: {"name": "Route 15"}, - 0x4: {"name": "Route 18"}, - 0x5: {"name": "Fuchsia City"}, - 0x6: {"name": "Fuchsia Mart"}, - 0x7: {"name": "Safari Zone Main Office"}, - 0x8: {"name": "Fuchsia Gym"}, - 0x9: {"name": "Fuchsia Bill Speech House"}, - 0xA: {"name": "Fuchsia Pokémon Center 1F", - "label": "FuchsiaPokeCenter1F"}, - 0xB: {"name": "Fuchsia Pokémon Center 2F Beta", - "label": "FuchsiaPokeCenter2FBeta"}, - 0xC: {"name": "Safari Zone Warden's Home"}, - 0xD: {"name": "Route 15 Fuchsia Gate"}, - }, - 18: { - 0x1: {"name": "Route 8"}, - 0x2: {"name": "Route 12"}, - 0x3: {"name": "Route 10 South"}, - 0x4: {"name": "Lavender Town"}, - 0x5: {"name": "Lavender Pokémon Center 1F", - "label": "LavenderPokeCenter1F"}, - 0x6: {"name": "Lavender Pokémon Center 2F Beta", - "label": "LavenderPokeCenter2FBeta"}, - 0x7: {"name": "Mr. Fuji's House"}, - 0x8: {"name": "Lavender Town Speech House"}, - 0x9: {"name": "Lavender Name Rater"}, - 0xA: {"name": "Lavender Mart"}, - 0xB: {"name": "Soul House"}, - 0xC: {"name": "Lav Radio Tower 1F"}, - 0xD: {"name": "Route 8 Saffron Gate"}, - 0xE: {"name": "Route 12 Super Rod House"}, - }, - 19: { - 0x1: {"name": "Route 28"}, - 0x2: {"name": "Silver Cave Outside"}, - 0x3: {"name": "Silver Cave Pokémon Center 1F", - "label": "SilverCavePokeCenter1F"}, - 0x4: {"name": "Route 28 Famous Speech House"}, - }, - 20: { - 0x1: {"name": "Pokémon Center 2F", - "label": "PokeCenter2F"}, - 0x2: {"name": "Trade Center"}, - 0x3: {"name": "Colosseum"}, - 0x4: {"name": "Time Capsule"}, - 0x5: {"name": "Mobile Trade Room Mobile"}, - 0x6: {"name": "Mobile Battle Room"}, - }, - 21: { - 0x1: {"name": "Route 7"}, - 0x2: {"name": "Route 16"}, - 0x3: {"name": "Route 17"}, - 0x4: {"name": "Celadon City"}, - 0x5: {"name": "Celadon Dept Store 1F"}, - 0x6: {"name": "Celadon Dept Store 2F"}, - 0x7: {"name": "Celadon Dept Store 3F"}, - 0x8: {"name": "Celadon Dept Store 4F"}, - 0x9: {"name": "Celadon Dept Store 5F"}, - 0xA: {"name": "Celadon Dept Store 6F"}, - 0xB: {"name": "Celadon Dept Store Elevator"}, - 0xC: {"name": "Celadon Mansion 1F"}, - 0xD: {"name": "Celadon Mansion 2F"}, - 0xE: {"name": "Celadon Mansion 3F"}, - 0xF: {"name": "Celadon Mansion Roof"}, - 0x10: {"name": "Celadon Mansion Roof House"}, - 0x11: {"name": "Celadon Pokémon Center 1F", - "label": "CeladonPokeCenter1F"}, - 0x12: {"name": "Celadon Pokémon Center 2F Beta", - "label": "CeladonPokeCenter2FBeta"}, - 0x13: {"name": "Celadon Game Corner"}, - 0x14: {"name": "Celadon Game Corner Prize Room"}, - 0x15: {"name": "Celadon Gym"}, - 0x16: {"name": "Celadon Cafe"}, - 0x17: {"name": "Route 16 Fuchsia Speech House"}, - 0x18: {"name": "Route 16 Gate"}, - 0x19: {"name": "Route 7 Saffron Gate"}, - 0x1A: {"name": "Route 17 18 Gate"}, - }, - 22: { - 0x1: {"name": "Route 40"}, - 0x2: {"name": "Route 41"}, - 0x3: {"name": "Cianwood City"}, - 0x4: {"name": "Mania's House"}, - 0x5: {"name": "Cianwood Gym"}, - 0x6: {"name": "Cianwood Pokémon Center 1F", - "label": "CianwoodPokeCenter1F"}, - 0x7: {"name": "Cianwood Pharmacy"}, - 0x8: {"name": "Cianwood City Photo Studio"}, - 0x9: {"name": "Cianwood Lugia Speech House"}, - 0xA: {"name": "Poke Seer's House"}, - 0xB: {"name": "Battle Tower 1F"}, - 0xC: {"name": "Battle Tower Battle Room"}, - 0xD: {"name": "Battle Tower Elevator"}, - 0xE: {"name": "Battle Tower Hallway"}, - 0xF: {"name": "Route 40 Battle Tower Gate"}, - 0x10: {"name": "Battle Tower Outside"}, - }, - 23: { - 0x1: {"name": "Route 2"}, - 0x2: {"name": "Route 22"}, - 0x3: {"name": "Viridian City"}, - 0x4: {"name": "Viridian Gym"}, - 0x5: {"name": "Viridian Nickname Speech House"}, - 0x6: {"name": "Trainer House 1F"}, - 0x7: {"name": "Trainer House B1F"}, - 0x8: {"name": "Viridian Mart"}, - 0x9: {"name": "Viridian Pokémon Center 1F", - "label": "ViridianPokeCenter1F"}, - 0xA: {"name": "Viridian Pokémon Center 2F Beta", - "label": "ViridianPokeCenter2FBeta"}, - 0xB: {"name": "Route 2 Nugget Speech House"}, - 0xC: {"name": "Route 2 Gate"}, - 0xD: {"name": "Victory Road Gate"}, - }, - 24: { - 0x1: {"name": "Route 26"}, - 0x2: {"name": "Route 27"}, - 0x3: {"name": "Route 29"}, - 0x4: {"name": "New Bark Town"}, - 0x5: {"name": "Elm's Lab"}, - 0x6: {"name": "Kris's House 1F"}, - 0x7: {"name": "Kris's House 2F"}, - 0x8: {"name": "Kris's Neighbor's House"}, - 0x9: {"name": "Elm's House"}, - 0xA: {"name": "Route 26 Heal Speech House"}, - 0xB: {"name": "Route 26 Day of Week Siblings House"}, - 0xC: {"name": "Route 27 Sandstorm House"}, - 0xD: {"name": "Route 29 46 Gate"}, - }, - 25: { - 0x1: {"name": "Route 5"}, - 0x2: {"name": "Saffron City"}, - 0x3: {"name": "Fighting Dojo"}, - 0x4: {"name": "Saffron Gym"}, - 0x5: {"name": "Saffron Mart"}, - 0x6: {"name": "Saffron Pokémon Center 1F", - "label": "SaffronPokeCenter1F"}, - 0x7: {"name": "Saffron Pokémon Center 2F Beta", - "label": "SaffronPokeCenter2FBeta"}, - 0x8: {"name": "Mr. Psychic's House"}, - 0x9: {"name": "Saffron Train Station"}, - 0xA: {"name": "Silph Co. 1F"}, - 0xB: {"name": "Copycat's House 1F"}, - 0xC: {"name": "Copycat's House 2F"}, - 0xD: {"name": "Route 5 Underground Entrance"}, - 0xE: {"name": "Route 5 Saffron City Gate"}, - 0xF: {"name": "Route 5 Cleanse Tag Speech House"}, - }, - 26: { - 0x1: {"name": "Route 30"}, - 0x2: {"name": "Route 31"}, - 0x3: {"name": "Cherrygrove City"}, - 0x4: {"name": "Cherrygrove Mart"}, - 0x5: {"name": "Cherrygrove Pokémon Center 1F", - "label": "CherrygrovePokeCenter1F"}, - 0x6: {"name": "Cherrygrove Gym Speech House"}, - 0x7: {"name": "Guide Gent's House"}, - 0x8: {"name": "Cherrygrove Evolution Speech House"}, - 0x9: {"name": "Route 30 Berry Speech House"}, - 0xA: {"name": "Mr. Pokémon's House"}, - 0xB: {"name": "Route 31 Violet Gate"}, - }, -} +from map_names import map_names +# map names with no labels will be generated # generate labels for each map name for map_group_id in map_names.keys(): map_group = map_names[map_group_id] @@ -6834,7 +6356,7 @@ incbin_lines = [] # storage for processed incbin lines processed_incbins = {} -def to_asm(some_object): +def to_asm(some_object, use_asm_rules=False): """shows an object's asm with a label and an ending comment showing the next byte address""" if isinstance(some_object, int): @@ -6850,6 +6372,9 @@ def to_asm(some_object): asmr = asmr.replace("\n"+spacing+"\n", "\n\n"+spacing) asmr = asmr.replace("\n\n"+spacing+spacing, "\n\n"+spacing) asm += spacing + asmr + if use_asm_rules: + asm = asm.replace("\n" + spacing + "; ", "\n; ") + asm = asm.replace("\n" + spacing + ".asm_", "\n.asm_") # show the address of the next byte below this asm += "\n; " + hex(last_address) return asm @@ -7223,7 +6748,7 @@ class Asm: asm_list = AsmList(asm) bank = 0 for line in asm_list: - if line[0:6] == "INCBIN" or line[1:6] == "INCBIN": + if (line[0:6] == "INCBIN" or line[1:6] == "INCBIN") and not any([contaminant+"\"" in line for contaminant in [".2bpp", ".1bpp", ".asm", ".lz"]]): thing = Incbin(line, bank=bank) elif line[0:7] == "SECTION": thing = AsmSection(line) @@ -7288,11 +6813,13 @@ class Asm: # check if the object is already inserted if new_object in self.parts: - print "object was previously inserted ("+str(new_object)+")" + print "object was previously inserted ("+str(new_object)+"; " + hex(new_object.address) + ")" return # check by label - if self.is_label_name_in_file(new_object.label.name): - print "object was previously inserted ("+str(new_object)+") by label: "+new_object.label.name + other_obj = self.is_label_name_in_file(new_object.label.name) + if other_obj: + other_obj = other_obj.object + print "object was previously inserted ("+new_object.label.name+" at "+hex(new_object.address)+") by "+other_obj.label.name+" at "+hex(other_obj.address) return # check by address #if self.does_address_have_label(new_object.address): diff --git a/extras/disassemble_map_scripts.py b/extras/disassemble_map_scripts.py new file mode 100644 index 000000000..21df56924 --- /dev/null +++ b/extras/disassemble_map_scripts.py @@ -0,0 +1,151 @@ +# -*- encoding: utf-8 -*- +""" +Dump out asm for scripting things in bank $25. This script will modify main.asm +and insert all scripting commands. +""" + +import crystal +from gbz80disasm import output_bank_opcodes + +rom = crystal.load_rom() +roml = [ord(x) for x in rom] + +script_command_table_address = 0x96cb1 +script_command_count = 170 + +# a list of addresses for each script command +command_pointers = [crystal.calculate_pointer_from_bytes_at(script_command_table_address + (id * 2), bank=0x25) for id in range(0, 170)] + +# a list of hex addresses for each script command in bank $25 +command_pointers_hex = ["$%.2x" % (x % 0x4000 + 0x4000) for x in command_pointers] + +commands = {} + +# force data into a more usable form +for command in crystal.command_classes: + name = "Script_" + command.macro_name + id = command.id + params = {} + + for (id2, param_type) in command.param_types.items(): + param = { + "name": param_type["name"], + "type": param_type["class"].__name__, + } + params[id2] = param + + if id <= 0xa9: + commands[id] = { + "name": name, + "params": params, + "address": command_pointers[id], + } + +avoid = [ + 0x974b0, + 0x974be, + 0x9754b, + 0x97556, + 0x97562, + 0x9756e, + 0x97540, + + 0x96f8e, # verbosegiveitem2 +] + +class DisassembledScriptCommand(): + """ + Just a temporary object to store information about a script command's asm. + This is used by some of the infrastructure in crystal.py to automatically + insert asm into main.asm, rather than having someone do it manually. + """ + dependencies = None + + def __init__(self, label=None, id=None, address=None, params=None): + self.id = id + self.label = crystal.Label(name=label, address=address, object=self) + self.address = address + self.params = params + + max_byte_count = 0x4000 + + # Some of these scripts need to be truncated before insertion, because + # output_bank_opcodes doesn't know anything about stopping if some of + # the local labels are not resolved yet. + + # Script_if_equal + if address == 0x97540: + max_byte_count = 86 + + # disassemble and laso get the last address + (asm, last_address, last_hl_address, last_a_address, used_3d97) = output_bank_opcodes(address, max_byte_count=max_byte_count, stop_at=command_pointers, include_last_address=False) + + # remove indentation + asm = asm.replace("\n\t", "\n") + if asm[0] == "\t": + asm = asm[1:] + + # remove the last two newlines + while asm[-1] == "\n": + asm = asm[:-1] + + self.asm = asm + self.last_address = last_address + + # make sure this gets dumped into main.asm + #if crystal.script_parse_table[self.address] == None and crystal.script_parse_table[self.last_address] == None: + crystal.script_parse_table[self.address : self.last_address] = self + #else: + # print ".. hm, something is already at " + hex(self.address) + " for " + self.label.name + + def to_asm(self): + #output += self.label + ": ; " + hex(self.address) + "\n" + output = "; script command " + hex(self.id) + "\n" + if len(self.params) > 0: + output += "; parameters:\n" + for (id2, param) in self.params.items(): + output += "; " + param["name"] + " (" + param["type"] + ")\n" + output += "\n" + output += self.asm + return output + + def get_dependencies(*args, **kwargs): + return [] + +# make instances of DisassembledScriptCommand +for (id, command) in commands.items(): + name = command["name"] + params = command["params"] + address = command["address"] + + script_asm = DisassembledScriptCommand(label=name, id=id, address=address, params=params) + #print script_asm.to_asm() + #print crystal.to_asm(script_asm, use_asm_rules=True) + +class ScriptCommandTable(): + address = script_command_table_address + last_address = script_command_table_address + (2 * 170) + dependencies = None + + def __init__(self): + self.label = crystal.Label(name="ScriptCommandTable", address=self.address, object=self) + + # make sure this gets dumped into main.asm + crystal.script_parse_table[self.address : self.last_address] = self + + def get_dependencies(*args, **kwargs): + return [] + + def to_asm(self): + output = "" + for (id, command) in commands.items(): + output += "dw " + command["name"] + "; " + hex(command["address"]) + "\n" + if output[-1] == "\n": + output = output[:-1] + return output +script_command_table = ScriptCommandTable() +#print crystal.to_asm(script_command_table, use_asm_rules=True) + +# automatic asm insertion +asm = crystal.Asm() +asm.insert_and_dump(limit=500) diff --git a/extras/gbz80disasm.py b/extras/gbz80disasm.py index d22f152f1..efb4689ab 100644 --- a/extras/gbz80disasm.py +++ b/extras/gbz80disasm.py @@ -592,7 +592,7 @@ def asm_label(address): # why using a random value when you can use the address? return ".ASM_" + hex(address)[2:] -def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False): +def output_bank_opcodes(original_offset, max_byte_count=0x4000, include_last_address=True, stop_at=[], debug = False): #fs = current_address #b = bank_byte #in = input_data -- rom @@ -601,6 +601,10 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False): #ad = end_address #a, oa = current_byte_number + # stop_at can be used to supply a list of addresses to not disassemble + # over. This is useful if you know in advance that there are a lot of + # fall-throughs. + load_labels() load_rom() @@ -622,6 +626,7 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False): byte_labels = {} + first_loop = True output = "" keep_reading = True while offset <= end_address and keep_reading: @@ -629,6 +634,11 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False): is_data = False maybe_byte = current_byte + # stop at any address + if not first_loop and offset in stop_at: + keep_reading = False + break + #first check if this byte already has a label #if it does, use the label #if not, generate a new label @@ -816,6 +826,8 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False): #offset += 1 #current_byte_number += 1 + first_loop = False + #clean up unused labels for label_line in byte_labels.keys(): address = label_line @@ -824,7 +836,8 @@ def output_bank_opcodes(original_offset, max_byte_count=0x4000, debug = False): output = output.replace((label_line["name"] + "\n").lower(), "") #add the offset of the final location - output += "; " + hex(offset) + if include_last_address: + output += "; " + hex(offset) return (output, offset, last_hl_address, last_a_address, used_3d97) diff --git a/extras/map_names.py b/extras/map_names.py new file mode 100644 index 000000000..599b377db --- /dev/null +++ b/extras/map_names.py @@ -0,0 +1,486 @@ +# -*- coding: utf-8 -*- +""" +""" + +# this is modified in crystal.py during run-time +map_names = { + 1: { + 0x1: {"name": "Olivine Pokémon Center 1F", + "label": "OlivinePokeCenter1F"}, + 0x2: {"name": "Olivine Gym"}, + 0x3: {"name": "Olivine Voltorb House"}, + 0x4: {"name": "Olivine House Beta"}, + 0x5: {"name": "Olivine Punishment Speech House"}, + 0x6: {"name": "Olivine Good Rod House"}, + 0x7: {"name": "Olivine Cafe"}, + 0x8: {"name": "Olivine Mart"}, + 0x9: {"name": "Route 38 Ecruteak Gate"}, + 0xA: {"name": "Route 39 Barn"}, + 0xB: {"name": "Route 39 Farmhouse"}, + 0xC: {"name": "Route 38"}, + 0xD: {"name": "Route 39"}, + 0xE: {"name": "Olivine City"}, + }, + 2: { + 0x1: {"name": "Mahogany Red Gyarados Speech House"}, + 0x2: {"name": "Mahogany Gym"}, + 0x3: {"name": "Mahogany Pokémon Center 1F", + "label": "MahoganyPokeCenter1F"}, + 0x4: {"name": "Route 42 Ecruteak Gate"}, + 0x5: {"name": "Route 42"}, + 0x6: {"name": "Route 44"}, + 0x7: {"name": "Mahogany Town"}, + }, + 3: { + 0x1: {"name": "Sprout Tower 1F"}, + 0x2: {"name": "Sprout Tower 2F"}, + 0x3: {"name": "Sprout Tower 3F"}, + 0x4: {"name": "Tin Tower 1F"}, + 0x5: {"name": "Tin Tower 2F"}, + 0x6: {"name": "Tin Tower 3F"}, + 0x7: {"name": "Tin Tower 4F"}, + 0x8: {"name": "Tin Tower 5F"}, + 0x9: {"name": "Tin Tower 6F"}, + 0xA: {"name": "Tin Tower 7F"}, + 0xB: {"name": "Tin Tower 8F"}, + 0xC: {"name": "Tin Tower 9F"}, + 0xD: {"name": "Burned Tower 1F"}, + 0xE: {"name": "Burned Tower B1F"}, + 0xF: {"name": "National Park"}, + 0x10: {"name": "National Park Bug Contest"}, + 0x11: {"name": "Radio Tower 1F"}, + 0x12: {"name": "Radio Tower 2F"}, + 0x13: {"name": "Radio Tower 3F"}, + 0x14: {"name": "Radio Tower 4F"}, + 0x15: {"name": "Radio Tower 5F"}, + 0x16: {"name": "Ruins of Alph Outside"}, + 0x17: {"name": "Ruins of Alph Ho-oh Chamber"}, + 0x18: {"name": "Ruins of Alph Kabuto Chamber"}, + 0x19: {"name": "Ruins of Alph Omanyte Chamber"}, + 0x1A: {"name": "Ruins of Alph Aerodactyl Chamber"}, + 0x1B: {"name": "Ruins of Alph Inner Chamber"}, + 0x1C: {"name": "Ruins of Alph Research Center"}, + 0x1D: {"name": "Ruins of Alph Ho-oh Item Room"}, + 0x1E: {"name": "Ruins of Alph Kabuto Item Room"}, + 0x1F: {"name": "Ruins of Alph Omanyte Item Room"}, + 0x20: {"name": "Ruins of Alph Aerodactyl Item Room"}, + 0x21: {"name": "Ruins of Alph Ho-Oh Word Room"}, + 0x22: {"name": "Ruins of Alph Kabuto Word Room"}, + 0x23: {"name": "Ruins of Alph Omanyte Word Room"}, + 0x24: {"name": "Ruins of Alph Aerodactyl Word Room"}, + 0x25: {"name": "Union Cave 1F"}, + 0x26: {"name": "Union Cave B1F"}, + 0x27: {"name": "Union Cave B2F"}, + 0x28: {"name": "Slowpoke Well B1F"}, + 0x29: {"name": "Slowpoke Well B2F"}, + 0x2A: {"name": "Olivine Lighthouse 1F"}, + 0x2B: {"name": "Olivine Lighthouse 2F"}, + 0x2C: {"name": "Olivine Lighthouse 3F"}, + 0x2D: {"name": "Olivine Lighthouse 4F"}, + 0x2E: {"name": "Olivine Lighthouse 5F"}, + 0x2F: {"name": "Olivine Lighthouse 6F"}, + 0x30: {"name": "Mahogany Mart 1F"}, + 0x31: {"name": "Team Rocket Base B1F"}, + 0x32: {"name": "Team Rocket Base B2F"}, + 0x33: {"name": "Team Rocket Base B3F"}, + 0x34: {"name": "Ilex Forest"}, + 0x35: {"name": "Warehouse Entrance"}, + 0x36: {"name": "Underground Path Switch Room Entrances"}, + 0x37: {"name": "Goldenrod Dept Store B1F"}, + 0x38: {"name": "Underground Warehouse"}, + 0x39: {"name": "Mount Mortar 1F Outside"}, + 0x3A: {"name": "Mount Mortar 1F Inside"}, + 0x3B: {"name": "Mount Mortar 2F Inside"}, + 0x3C: {"name": "Mount Mortar B1F"}, + 0x3D: {"name": "Ice Path 1F"}, + 0x3E: {"name": "Ice Path B1F"}, + 0x3F: {"name": "Ice Path B2F Mahogany Side"}, + 0x40: {"name": "Ice Path B2F Blackthorn Side"}, + 0x41: {"name": "Ice Path B3F"}, + 0x42: {"name": "Whirl Island NW"}, + 0x43: {"name": "Whirl Island NE"}, + 0x44: {"name": "Whirl Island SW"}, + 0x45: {"name": "Whirl Island Cave"}, + 0x46: {"name": "Whirl Island SE"}, + 0x47: {"name": "Whirl Island B1F"}, + 0x48: {"name": "Whirl Island B2F"}, + 0x49: {"name": "Whirl Island Lugia Chamber"}, + 0x4A: {"name": "Silver Cave Room 1"}, + 0x4B: {"name": "Silver Cave Room 2"}, + 0x4C: {"name": "Silver Cave Room 3"}, + 0x4D: {"name": "Silver Cave Item Rooms"}, + 0x4E: {"name": "Dark Cave Violet Entrance"}, + 0x4F: {"name": "Dark Cave Blackthorn Entrance"}, + 0x50: {"name": "Dragon's Den 1F"}, + 0x51: {"name": "Dragon's Den B1F"}, + 0x52: {"name": "Dragon Shrine"}, + 0x53: {"name": "Tohjo Falls"}, + 0x54: {"name": "Diglett's Cave"}, + 0x55: {"name": "Mount Moon"}, + 0x56: {"name": "Underground"}, + 0x57: {"name": "Rock Tunnel 1F"}, + 0x58: {"name": "Rock Tunnel B1F"}, + 0x59: {"name": "Safari Zone Fuchsia Gate Beta"}, + 0x5A: {"name": "Safari Zone Beta"}, + 0x5B: {"name": "Victory Road"}, + }, + 4: { + 0x1: {"name": "Ecruteak House"}, # passage to Tin Tower + 0x2: {"name": "Wise Trio's Room"}, + 0x3: {"name": "Ecruteak Pokémon Center 1F", + "label": "EcruteakPokeCenter1F"}, + 0x4: {"name": "Ecruteak Lugia Speech House"}, + 0x5: {"name": "Dance Theatre"}, + 0x6: {"name": "Ecruteak Mart"}, + 0x7: {"name": "Ecruteak Gym"}, + 0x8: {"name": "Ecruteak Itemfinder House"}, + 0x9: {"name": "Ecruteak City"}, + }, + 5: { + 0x1: {"name": "Blackthorn Gym 1F"}, + 0x2: {"name": "Blackthorn Gym 2F"}, + 0x3: {"name": "Blackthorn Dragon Speech House"}, + 0x4: {"name": "Blackthorn Dodrio Trade House"}, + 0x5: {"name": "Blackthorn Mart"}, + 0x6: {"name": "Blackthorn Pokémon Center 1F", + "label": "BlackthornPokeCenter1F"}, + 0x7: {"name": "Move Deleter's House"}, + 0x8: {"name": "Route 45"}, + 0x9: {"name": "Route 46"}, + 0xA: {"name": "Blackthorn City"}, + }, + 6: { + 0x1: {"name": "Cinnabar Pokémon Center 1F", + "label": "CinnabarPokeCenter1F"}, + 0x2: {"name": "Cinnabar Pokémon Center 2F Beta", + "label": "CinnabarPokeCenter2FBeta"}, + 0x3: {"name": "Route 19 - Fuchsia Gate"}, + 0x4: {"name": "Seafoam Gym"}, + 0x5: {"name": "Route 19"}, + 0x6: {"name": "Route 20"}, + 0x7: {"name": "Route 21"}, + 0x8: {"name": "Cinnabar Island"}, + }, + 7: { + 0x1: {"name": "Cerulean Gym Badge Speech House"}, + 0x2: {"name": "Cerulean Police Station"}, + 0x3: {"name": "Cerulean Trade Speech House"}, + 0x4: {"name": "Cerulean Pokémon Center 1F", + "label": "CeruleanPokeCenter1F"}, + 0x5: {"name": "Cerulean Pokémon Center 2F Beta", + "label": "CeruleanPokeCenter2FBeta"}, + 0x6: {"name": "Cerulean Gym"}, + 0x7: {"name": "Cerulean Mart"}, + 0x8: {"name": "Route 10 Pokémon Center 1F", + "label": "Route10PokeCenter1F"}, + 0x9: {"name": "Route 10 Pokémon Center 2F Beta", + "label": "Route10PokeCenter2FBeta"}, + 0xA: {"name": "Power Plant"}, + 0xB: {"name": "Bill's House"}, + 0xC: {"name": "Route 4"}, + 0xD: {"name": "Route 9"}, + 0xE: {"name": "Route 10 North"}, + 0xF: {"name": "Route 24"}, + 0x10: {"name": "Route 25"}, + 0x11: {"name": "Cerulean City"}, + }, + 8: { + 0x1: {"name": "Azalea Pokémon Center 1F", + "label": "AzaleaPokeCenter1F"}, + 0x2: {"name": "Charcoal Kiln"}, + 0x3: {"name": "Azalea Mart"}, + 0x4: {"name": "Kurt's House"}, + 0x5: {"name": "Azalea Gym"}, + 0x6: {"name": "Route 33"}, + 0x7: {"name": "Azalea Town"}, + }, + 9: { + 0x1: {"name": "Lake of Rage Hidden Power House"}, + 0x2: {"name": "Lake of Rage Magikarp House"}, + 0x3: {"name": "Route 43 Mahogany Gate"}, + 0x4: {"name": "Route 43 Gate"}, + 0x5: {"name": "Route 43"}, + 0x6: {"name": "Lake of Rage"}, + }, + 10: { + 0x1: {"name": "Route 32"}, + 0x2: {"name": "Route 35"}, + 0x3: {"name": "Route 36"}, + 0x4: {"name": "Route 37"}, + 0x5: {"name": "Violet City"}, + 0x6: {"name": "Violet Mart"}, + 0x7: {"name": "Violet Gym"}, + 0x8: {"name": "Earl's Pokémon Academy", + "label": "EarlsPokemonAcademy"}, + 0x9: {"name": "Violet Nickname Speech House"}, + 0xA: {"name": "Violet Pokémon Center 1F", + "label": "VioletPokeCenter1F"}, + 0xB: {"name": "Violet Onix Trade House"}, + 0xC: {"name": "Route 32 Ruins of Alph Gate"}, + 0xD: {"name": "Route 32 Pokémon Center 1F", + "label": "Route32PokeCenter1F"}, + 0xE: {"name": "Route 35 Goldenrod gate"}, + 0xF: {"name": "Route 35 National Park gate"}, + 0x10: {"name": "Route 36 Ruins of Alph gate"}, + 0x11: {"name": "Route 36 National Park gate"}, + }, + 11: { + 0x1: {"name": "Route 34"}, + 0x2: {"name": "Goldenrod City"}, + 0x3: {"name": "Goldenrod Gym"}, + 0x4: {"name": "Goldenrod Bike Shop"}, + 0x5: {"name": "Goldenrod Happiness Rater"}, + 0x6: {"name": "Goldenrod Bill's House"}, + 0x7: {"name": "Goldenrod Magnet Train Station"}, + 0x8: {"name": "Goldenrod Flower Shop"}, + 0x9: {"name": "Goldenrod PP Speech House"}, + 0xA: {"name": "Goldenrod Name Rater's House"}, + 0xB: {"name": "Goldenrod Dept Store 1F"}, + 0xC: {"name": "Goldenrod Dept Store 2F"}, + 0xD: {"name": "Goldenrod Dept Store 3F"}, + 0xE: {"name": "Goldenrod Dept Store 4F"}, + 0xF: {"name": "Goldenrod Dept Store 5F"}, + 0x10: {"name": "Goldenrod Dept Store 6F"}, + 0x11: {"name": "Goldenrod Dept Store Elevator"}, + 0x12: {"name": "Goldenrod Dept Store Roof"}, + 0x13: {"name": "Goldenrod Game Corner"}, + 0x14: {"name": "Goldenrod Pokémon Center 1F", + "label": "GoldenrodPokeCenter1F"}, + 0x15: {"name": "Goldenrod PokéCom Center 2F Mobile", + "label": "GoldenrodPokeComCenter2FMobile"}, + 0x16: {"name": "Ilex Forest Azalea Gate"}, + 0x17: {"name": "Route 34 Ilex Forest Gate"}, + 0x18: {"name": "Day Care"}, + }, + 12: { + 0x1: {"name": "Route 6"}, + 0x2: {"name": "Route 11"}, + 0x3: {"name": "Vermilion City"}, + 0x4: {"name": "Vermilion House Fishing Speech House"}, + 0x5: {"name": "Vermilion Pokémon Center 1F", + "label": "VermilionPokeCenter1F"}, + 0x6: {"name": "Vermilion Pokémon Center 2F Beta", + "label": "VermilionPokeCenter2FBeta"}, + 0x7: {"name": "Pokémon Fan Club"}, + 0x8: {"name": "Vermilion Magnet Train Speech House"}, + 0x9: {"name": "Vermilion Mart"}, + 0xA: {"name": "Vermilion House Diglett's Cave Speech House"}, + 0xB: {"name": "Vermilion Gym"}, + 0xC: {"name": "Route 6 Saffron Gate"}, + 0xD: {"name": "Route 6 Underground Entrance"}, + }, + 13: { + 0x1: {"name": "Route 1"}, + 0x2: {"name": "Pallet Town"}, + 0x3: {"name": "Red's House 1F"}, + 0x4: {"name": "Red's House 2F"}, + 0x5: {"name": "Blue's House"}, + 0x6: {"name": "Oak's Lab"}, + }, + 14: { + 0x1: {"name": "Route 3"}, + 0x2: {"name": "Pewter City"}, + 0x3: {"name": "Pewter Nidoran Speech House"}, + 0x4: {"name": "Pewter Gym"}, + 0x5: {"name": "Pewter Mart"}, + 0x6: {"name": "Pewter Pokémon Center 1F", + "label": "PewterPokeCenter1F"}, + 0x7: {"name": "Pewter Pokémon Center 2F Beta", + "label": "PewterPokeCEnter2FBeta"}, + 0x8: {"name": "Pewter Snooze Speech House"}, + }, + 15: { + 0x1: {"name": "Olivine Port"}, + 0x2: {"name": "Vermilion Port"}, + 0x3: {"name": "Fast Ship 1F"}, + 0x4: {"name": "Fast Ship Cabins NNW, NNE, NE", + "label": "FastShipCabins_NNW_NNE_NE"}, + 0x5: {"name": "Fast Ship Cabins SW, SSW, NW", + "label": "FastShipCabins_SW_SSW_NW"}, + 0x6: {"name": "Fast Ship Cabins SE, SSE, Captain's Cabin", + "label": "FastShipCabins_SE_SSE_CaptainsCabin"}, + 0x7: {"name": "Fast Ship B1F"}, + 0x8: {"name": "Olivine Port Passage"}, + 0x9: {"name": "Vermilion Port Passage"}, + 0xA: {"name": "Mount Moon Square"}, + 0xB: {"name": "Mount Moon Gift Shop"}, + 0xC: {"name": "Tin Tower Roof"}, + }, + 16: { + 0x1: {"name": "Route 23"}, + 0x2: {"name": "Indigo Plateau Pokémon Center 1F", + "label": "IndigoPlateauPokeCenter1F"}, + 0x3: {"name": "Will's Room"}, + 0x4: {"name": "Koga's Room"}, + 0x5: {"name": "Bruno's Room"}, + 0x6: {"name": "Karen's Room"}, + 0x7: {"name": "Lance's Room"}, + 0x8: {"name": "Hall of Fame", + "label": "HallOfFame"}, + }, + 17: { + 0x1: {"name": "Route 13"}, + 0x2: {"name": "Route 14"}, + 0x3: {"name": "Route 15"}, + 0x4: {"name": "Route 18"}, + 0x5: {"name": "Fuchsia City"}, + 0x6: {"name": "Fuchsia Mart"}, + 0x7: {"name": "Safari Zone Main Office"}, + 0x8: {"name": "Fuchsia Gym"}, + 0x9: {"name": "Fuchsia Bill Speech House"}, + 0xA: {"name": "Fuchsia Pokémon Center 1F", + "label": "FuchsiaPokeCenter1F"}, + 0xB: {"name": "Fuchsia Pokémon Center 2F Beta", + "label": "FuchsiaPokeCenter2FBeta"}, + 0xC: {"name": "Safari Zone Warden's Home"}, + 0xD: {"name": "Route 15 Fuchsia Gate"}, + }, + 18: { + 0x1: {"name": "Route 8"}, + 0x2: {"name": "Route 12"}, + 0x3: {"name": "Route 10 South"}, + 0x4: {"name": "Lavender Town"}, + 0x5: {"name": "Lavender Pokémon Center 1F", + "label": "LavenderPokeCenter1F"}, + 0x6: {"name": "Lavender Pokémon Center 2F Beta", + "label": "LavenderPokeCenter2FBeta"}, + 0x7: {"name": "Mr. Fuji's House"}, + 0x8: {"name": "Lavender Town Speech House"}, + 0x9: {"name": "Lavender Name Rater"}, + 0xA: {"name": "Lavender Mart"}, + 0xB: {"name": "Soul House"}, + 0xC: {"name": "Lav Radio Tower 1F"}, + 0xD: {"name": "Route 8 Saffron Gate"}, + 0xE: {"name": "Route 12 Super Rod House"}, + }, + 19: { + 0x1: {"name": "Route 28"}, + 0x2: {"name": "Silver Cave Outside"}, + 0x3: {"name": "Silver Cave Pokémon Center 1F", + "label": "SilverCavePokeCenter1F"}, + 0x4: {"name": "Route 28 Famous Speech House"}, + }, + 20: { + 0x1: {"name": "Pokémon Center 2F", + "label": "PokeCenter2F"}, + 0x2: {"name": "Trade Center"}, + 0x3: {"name": "Colosseum"}, + 0x4: {"name": "Time Capsule"}, + 0x5: {"name": "Mobile Trade Room Mobile"}, + 0x6: {"name": "Mobile Battle Room"}, + }, + 21: { + 0x1: {"name": "Route 7"}, + 0x2: {"name": "Route 16"}, + 0x3: {"name": "Route 17"}, + 0x4: {"name": "Celadon City"}, + 0x5: {"name": "Celadon Dept Store 1F"}, + 0x6: {"name": "Celadon Dept Store 2F"}, + 0x7: {"name": "Celadon Dept Store 3F"}, + 0x8: {"name": "Celadon Dept Store 4F"}, + 0x9: {"name": "Celadon Dept Store 5F"}, + 0xA: {"name": "Celadon Dept Store 6F"}, + 0xB: {"name": "Celadon Dept Store Elevator"}, + 0xC: {"name": "Celadon Mansion 1F"}, + 0xD: {"name": "Celadon Mansion 2F"}, + 0xE: {"name": "Celadon Mansion 3F"}, + 0xF: {"name": "Celadon Mansion Roof"}, + 0x10: {"name": "Celadon Mansion Roof House"}, + 0x11: {"name": "Celadon Pokémon Center 1F", + "label": "CeladonPokeCenter1F"}, + 0x12: {"name": "Celadon Pokémon Center 2F Beta", + "label": "CeladonPokeCenter2FBeta"}, + 0x13: {"name": "Celadon Game Corner"}, + 0x14: {"name": "Celadon Game Corner Prize Room"}, + 0x15: {"name": "Celadon Gym"}, + 0x16: {"name": "Celadon Cafe"}, + 0x17: {"name": "Route 16 Fuchsia Speech House"}, + 0x18: {"name": "Route 16 Gate"}, + 0x19: {"name": "Route 7 Saffron Gate"}, + 0x1A: {"name": "Route 17 18 Gate"}, + }, + 22: { + 0x1: {"name": "Route 40"}, + 0x2: {"name": "Route 41"}, + 0x3: {"name": "Cianwood City"}, + 0x4: {"name": "Mania's House"}, + 0x5: {"name": "Cianwood Gym"}, + 0x6: {"name": "Cianwood Pokémon Center 1F", + "label": "CianwoodPokeCenter1F"}, + 0x7: {"name": "Cianwood Pharmacy"}, + 0x8: {"name": "Cianwood City Photo Studio"}, + 0x9: {"name": "Cianwood Lugia Speech House"}, + 0xA: {"name": "Poke Seer's House"}, + 0xB: {"name": "Battle Tower 1F"}, + 0xC: {"name": "Battle Tower Battle Room"}, + 0xD: {"name": "Battle Tower Elevator"}, + 0xE: {"name": "Battle Tower Hallway"}, + 0xF: {"name": "Route 40 Battle Tower Gate"}, + 0x10: {"name": "Battle Tower Outside"}, + }, + 23: { + 0x1: {"name": "Route 2"}, + 0x2: {"name": "Route 22"}, + 0x3: {"name": "Viridian City"}, + 0x4: {"name": "Viridian Gym"}, + 0x5: {"name": "Viridian Nickname Speech House"}, + 0x6: {"name": "Trainer House 1F"}, + 0x7: {"name": "Trainer House B1F"}, + 0x8: {"name": "Viridian Mart"}, + 0x9: {"name": "Viridian Pokémon Center 1F", + "label": "ViridianPokeCenter1F"}, + 0xA: {"name": "Viridian Pokémon Center 2F Beta", + "label": "ViridianPokeCenter2FBeta"}, + 0xB: {"name": "Route 2 Nugget Speech House"}, + 0xC: {"name": "Route 2 Gate"}, + 0xD: {"name": "Victory Road Gate"}, + }, + 24: { + 0x1: {"name": "Route 26"}, + 0x2: {"name": "Route 27"}, + 0x3: {"name": "Route 29"}, + 0x4: {"name": "New Bark Town"}, + 0x5: {"name": "Elm's Lab"}, + 0x6: {"name": "Kris's House 1F"}, + 0x7: {"name": "Kris's House 2F"}, + 0x8: {"name": "Kris's Neighbor's House"}, + 0x9: {"name": "Elm's House"}, + 0xA: {"name": "Route 26 Heal Speech House"}, + 0xB: {"name": "Route 26 Day of Week Siblings House"}, + 0xC: {"name": "Route 27 Sandstorm House"}, + 0xD: {"name": "Route 29 46 Gate"}, + }, + 25: { + 0x1: {"name": "Route 5"}, + 0x2: {"name": "Saffron City"}, + 0x3: {"name": "Fighting Dojo"}, + 0x4: {"name": "Saffron Gym"}, + 0x5: {"name": "Saffron Mart"}, + 0x6: {"name": "Saffron Pokémon Center 1F", + "label": "SaffronPokeCenter1F"}, + 0x7: {"name": "Saffron Pokémon Center 2F Beta", + "label": "SaffronPokeCenter2FBeta"}, + 0x8: {"name": "Mr. Psychic's House"}, + 0x9: {"name": "Saffron Train Station"}, + 0xA: {"name": "Silph Co. 1F"}, + 0xB: {"name": "Copycat's House 1F"}, + 0xC: {"name": "Copycat's House 2F"}, + 0xD: {"name": "Route 5 Underground Entrance"}, + 0xE: {"name": "Route 5 Saffron City Gate"}, + 0xF: {"name": "Route 5 Cleanse Tag Speech House"}, + }, + 26: { + 0x1: {"name": "Route 30"}, + 0x2: {"name": "Route 31"}, + 0x3: {"name": "Cherrygrove City"}, + 0x4: {"name": "Cherrygrove Mart"}, + 0x5: {"name": "Cherrygrove Pokémon Center 1F", + "label": "CherrygrovePokeCenter1F"}, + 0x6: {"name": "Cherrygrove Gym Speech House"}, + 0x7: {"name": "Guide Gent's House"}, + 0x8: {"name": "Cherrygrove Evolution Speech House"}, + 0x9: {"name": "Route 30 Berry Speech House"}, + 0xA: {"name": "Mr. Pokémon's House"}, + 0xB: {"name": "Route 31 Violet Gate"}, + }, +} diff --git a/extras/pksv.py b/extras/pksv.py index 03ad2d077..f30ab9294 100644 --- a/extras/pksv.py +++ b/extras/pksv.py @@ -298,6 +298,7 @@ pksv_crystal_more_enders = [0x03, 0x04, 0x05, 0x0C, 0x51, 0x52, 0x9B, 0xB2, #maybe? 0xCC, #maybe? + 0x9A, # describedecoration ] # these have no pksv names as of pksv 2.1.1 diff --git a/extras/vba.py b/extras/vba.py new file mode 100644 index 000000000..8ed0d7b5a --- /dev/null +++ b/extras/vba.py @@ -0,0 +1,841 @@ +#!/usr/bin/jython +# -*- encoding: utf-8 -*- +""" +vba-clojure (but really it's jython/python/jvm) + +This is jython, not python. Use jython to run this file. Before running this +file, some of the dependencies need to be constructed. These can be obtained +from the vba-clojure project. + sudo apt-get install g++ libtool openjdk-6-jre openjdk-6-jdk libsdl1.2-dev ant jython + + export JAVA_INCLUDE_PATH=/usr/lib/jvm/java-6-openjdk-amd64/include/ + export JAVA_INCLUDE_PATH2=/usr/lib/jvm/java-6-openjdk-amd64/include/ + + hg clone http://hg.bortreb.com/vba-clojure + cd vba-clojure/java/ + ant all + cd .. + autoreconf -i + ./configure + make + sudo make install + +Make sure vba-clojure bindings are in $CLASSPATH: + export CLASSPATH=$CLASSPATH:java/dist/gb-bindings.jar + +Make sure vba-clojure is available within "java.library.path": + sudo ln -s \ + $HOME/local/vba-clojure/vba-clojure/src/clojure/.libs/libvba.so.0.0.0 \ + /usr/lib/jni/libvba.so + +Also make sure VisualBoyAdvance.cfg is somewhere in the $PATH for VBA to find. +A default configuration is provided in vba-clojure under src/. + +Usage (in jython, not python): + import vba + + # activate the laser beam + vba.load_rom("/path/to/baserom.gbc") + + # make the emulator eat some instructions + vba.nstep(300) + + # save the state because we're paranoid + copyrights = vba.get_state() + # or ... + vba.save_state("copyrights") + # >>> vba.load_state("copyrights") == copyrights + # True + + # play for a while, then press F12 + vba.run() + + # let's save the game again + vba.save_state("unknown-delete-me") + + # and let's go back to the other state + vba.set_state(copyrights) + + # or why not the other way around? + vba.set_state(vba.load_state("unknown-delete-me")) + + vba.get_memory_at(0xDCDA) + vba.set_memory_at(0xDCDB, 0xFF) + vba.get_memory_range(0xDCDA, 10) + +TOOD: + [ ] set a specific register + [ ] get a specific register + [ ] breakpoints + [ ] vgm stuff + [ ] gbz80disasm integration + [ ] pokecrystal.extras integration + +""" + +import os +import sys +import re +from array import array +import string +from copy import copy +import unittest + +# for converting bytes to readable text +from chars import chars + +from map_names import map_names + +# for _check_java_library_path +from java.lang import System + +# for passing states to the emulator +from java.nio import ByteBuffer + +# For getRegisters and other times we have to pass a java int array to a +# function. +import jarray + +# load in the vba-clojure bindings +import com.aurellem.gb.Gb as Gb + +# load the vba-clojure library +Gb.loadVBA() + +from vba_config import * + +if not os.path.exists(rom_path): + raise Exception("rom_path is not configured properly; edit vba_config.py?") + +def _check_java_library_path(): + """ + Returns the value of java.library.path. The vba-clojure library must be + compiled and linked from this location. + """ + return System.getProperty("java.library.path") + +class RomList(list): + """ + Simple wrapper to prevent a giant rom from being shown on screen. + """ + def __init__(self, *args, **kwargs): + list.__init__(self, *args, **kwargs) + + def __repr__(self): + """ + Simplifies this object so that the output doesn't overflow stdout. + """ + return "RomList(too long)" + +button_masks = { + "a": 0x0001, + "b": 0x0002, + "r": 0x0010, + "l": 0x0020, + "u": 0x0040, + "d": 0x0080, + "select": 0x0004, + "start": 0x0008, + "restart": 0x0800, + "listen": -1, # what? +} + +# useful for directly stating what to press +a, b, r, l, u, d, select, start, restart = "a", "b", "r", "l", "u", "d", "select", "start", "restart" + +def button_combiner(buttons): + """ + Combines multiple button presses into an integer. This is used when sending + a keypress to the emulator. + """ + result = 0 + + # String inputs need to be cleaned up so that "start" doesn't get + # recognized as "s" and "t" etc.. + if isinstance(buttons, str): + if "restart" in buttons: + buttons.replace("restart", "") + result |= button_masks["restart"] + if "start" in buttons: + buttons.replace("start", "") + result |= button_masks["start"] + if "select" in buttons: + buttons.replace("select", "") + result |= button_masks["select"] + + for each in buttons: + result |= button_masks[each] + + print "button: " + str(result) + return result + +def load_rom(path=None): + """ + Starts the emulator with a certain ROM. Defaults to rom_path if no + parameters are given. + """ + if path == None: + path = rom_path + try: + root = load_state("root") + except: + # "root.sav" is required because if you create it in the future, you + # will have to shutdown the emulator and possibly lose your state. Some + # functions require there to be at least one root state available to do + # computations between two states. + sys.stderr.write("ERROR: unable to read \"root.sav\", please run" + " generate_root() or get_root() to make an initial save.\n") + Gb.startEmulator(path) + +def shutdown(): + """ + Stops the emulator. Closes the window. The "opposite" of this is the + load_rom function. + """ + Gb.shutdown() + +def step(): + """ + Advances the emulator forward by one step. + """ + Gb.step() + +def nstep(steplimit): + """ + Step the game forward by a certain number of instructions. + """ + for counter in range(0, steplimit): + Gb.step() + +def step_until_capture(): + """ + Loop step() until SDLK_F12 is detected. + """ + Gb.stepUntilCapture() + +# just some aliases for step_until_capture +run = go = step_until_capture + +def translate_chars(charz): + result = "" + for each in charz: + result += chars[each] + return result + +def _create_byte_buffer(data): + """ + Converts data into a ByteBuffer. This is useful for interfacing with the Gb + class. + """ + buf = ByteBuffer.allocateDirect(len(data)) + if isinstance(data[0], int): + for byte in data: + buf.put(byte) + else: + for byte in data: + buf.put(ord(byte)) + return buf + +def set_state(state, do_step=False): + """ + Injects the given state into the emulator. Use do_step if you want to call + step(), which also allows SDL to render the latest frame. Note that the + default is to not step, and that the screen (if it is enabled) will appear + as if it still has the last state loaded. This is normal. + """ + Gb.loadState(_create_byte_buffer(state)) + if do_step: + step() + +def get_state(): + """ + Retrieves the current state of the emulator. + """ + buf = Gb.saveState() + state = [buf.get(x) for x in range(0, buf.capacity())] + arr = array("b") + arr.extend(state) + return arr.tostring() # instead of state + +def save_state(name, state=None, override=False): + """ + Saves the given state to save_state_path. The file format must be ".sav" + (and this will be appended to your string if necessary). + """ + if state == None: + state = get_state() + if len(name) < 4 or name[-4:] != ".sav": + name += ".sav" + save_path = os.path.join(save_state_path, name) + if not override and os.path.exists(save_path): + raise Exception("oops, save state path already exists: " + str(save_path)) + else: + # convert the state into a reasonable output + data = array('b') + data.extend(state) + output = data.tostring() + + file_handler = open(save_path, "wb") + file_handler.write(output) + file_handler.close() + +def load_state(name): + """ + Reads a state from file based on name. Looks in save_state_path for a file + with this name (".sav" is optional). + """ + save_path = os.path.join(save_state_path, name) + if not os.path.exists(save_path): + if len(name) < 4 or name[-4:] != ".sav": + name += ".sav" + save_path = os.path.join(save_state_path, name) + file_handler = open(save_path, "rb") + state = file_handler.read() + file_handler.close() + return state + +def generate_root(): + """ + Restarts the emulator and saves the initial state to "root.sav". + """ + shutdown() + load_rom() + root = get_state() + save_state("root", state=root, override=True) + return root + +def get_root(): + """ + Loads the root state, or restarts the emulator and creates a new root + state. + """ + try: + root = load_state("root") + except: + root = generate_root() + +def get_registers(): + """ + Returns a list of current register values. + """ + register_array = jarray.zeros(Gb.NUM_REGISTERS, "i") + Gb.getRegisters(register_array) + return list(register_array) + +def set_registers(registers): + """ + Applies the set of registers to the CPU. + """ + Gb.writeRegisters(registers) +write_registers = set_registers + +def get_rom(): + """ + Returns the ROM in bytes. + """ + rom_array = jarray.zeros(Gb.ROM_SIZE, "i") + Gb.getROM(rom_array) + return RomList(rom_array) + +def get_ram(): + """ + Returns the RAM in bytes. + """ + ram_array = jarray.zeros(Gb.RAM_SIZE, "i") + Gb.getRAM(ram_array) + return RomList(ram_array) + +def say_hello(): + """ + Test that the VBA/GB bindings are working. + """ + Gb.sayHello() + +def get_memory(): + """ + Returns memory in bytes. + """ + memory_size = 0x10000 + memory = jarray.zeros(memory_size, "i") + Gb.getMemory(memory) + return RomList(memory) + +def set_memory(memory): + """ + Sets memory in the emulator. Use get_memory() to retrieve the current + state. + """ + Gb.writeMemory(memory) + +def get_pixels(): + """ + Returns a list of pixels on the screen display. Broken, probably. Use + screenshot() instead. + """ + sys.stderr.write("ERROR: seems to be broken on VBA's end? Good luck. Use" + " screenshot() instead.\n") + size = Gb.DISPLAY_WIDTH * Gb.DISPLAY_HEIGHT + pixels = jarray.zeros(size, "i") + Gb.getPixels(pixels) + return RomList(pixels) + +def screenshot(filename, literal=False): + """ + Saves a PNG screenshot to the file at filename. Use literal if you want to + store it in the current directory. Default is to save it to screenshots/ + under the project. + """ + screenshots_path = os.path.join(project_path, "screenshots/") + filename = os.path.join(screenshots_path, filename) + if len(filename) < 4 or filename[-4:] != ".png": + filename += ".png" + Gb.nwritePNG(filename) + print "Screenshot saved to: " + str(filename) +save_png = screenshot + +def read_memory(address): + """ + Read an integer at an address. + """ + return Gb.readMemory(address) +get_memory_at = read_memory + +def get_memory_range(start_address, byte_count): + """ + Returns a list of bytes. + + start_address - address to start reading at + byte_count - how many bytes (0 returns just 1 byte) + """ + bytez = [] + for counter in range(0, byte_count): + byte = get_memory_at(start_address + counter) + bytez.append(byte) + return bytez + +def set_memory_at(address, value): + """ + Sets a byte at a certain address in memory. This directly sets the memory + instead of copying the memory from the emulator. + """ + Gb.setMemoryAt(address, value) + +def press(buttons, steplimit=1): + """ + Press a button. Use steplimit to say for how many steps you want to press + the button (try leaving it at the default, 1). + """ + if hasattr(buttons, "__len__"): + number = button_combiner(buttons) + elif isinstance(buttons, int): + number = buttons + else: + number = buttons + for step_counter in range(0, steplimit): + Gb.step(number) + +class Registers: + order = [ + "pc", + "sp", + "af", + "bc", + "de", + "hl", + "iff", + "div", + "tima", + "tma", + "tac", + "if", + "lcdc", + "stat", + "scy", + "scx", + "ly", + "lyc", + "dma", + "wy", + "wx", + "vbk", + "hdma1", + "hdma2", + "hdma3", + "hdma4", + "hdma5", + "svbk", + "ie", + ] + + def __setitem__(self, key, value): + current_registers = get_registers() + current_registers[Registers.order.index(key)] = value + set_registers(current_registers) + + def __getitem__(self, key): + current_registers = get_registers() + return current_registers[Registers.order.index(key)] + + def __list__(self): + return get_registers() + + def _get_register(id): + def constructed_func(self, id=copy(id)): + return get_registers()[id] + return constructed_func + + def _set_register(id): + def constructed_func(self, value, id=copy(id)): + current_registers = get_registers() + current_registers[id] = value + set_registers(current_registers) + return constructed_func + + pc = property(fget=_get_register(0), fset=_set_register(0)) + sp = property(fget=_get_register(1), fset=_set_register(1)) + af = property(fget=_get_register(2), fset=_set_register(2)) + bc = property(fget=_get_register(3), fset=_set_register(3)) + de = property(fget=_get_register(4), fset=_set_register(4)) + hl = property(fget=_get_register(5), fset=_set_register(5)) + iff = property(fget=_get_register(6), fset=_set_register(6)) + div = property(fget=_get_register(7), fset=_set_register(7)) + tima = property(fget=_get_register(8), fset=_set_register(8)) + tma = property(fget=_get_register(9), fset=_set_register(9)) + tac = property(fget=_get_register(10), fset=_set_register(10)) + _if = property(fget=_get_register(11), fset=_set_register(11)) + lcdc = property(fget=_get_register(12), fset=_set_register(12)) + stat = property(fget=_get_register(13), fset=_set_register(13)) + scy = property(fget=_get_register(14), fset=_set_register(14)) + scx = property(fget=_get_register(15), fset=_set_register(15)) + ly = property(fget=_get_register(16), fset=_set_register(16)) + lyc = property(fget=_get_register(17), fset=_set_register(17)) + dma = property(fget=_get_register(18), fset=_set_register(18)) + wy = property(fget=_get_register(19), fset=_set_register(19)) + wx = property(fget=_get_register(20), fset=_set_register(20)) + vbk = property(fget=_get_register(21), fset=_set_register(21)) + hdma1 = property(fget=_get_register(22), fset=_set_register(22)) + hdma2 = property(fget=_get_register(23), fset=_set_register(23)) + hdma3 = property(fget=_get_register(24), fset=_set_register(24)) + hdma4 = property(fget=_get_register(25), fset=_set_register(25)) + hdma5 = property(fget=_get_register(26), fset=_set_register(26)) + svbk = property(fget=_get_register(27), fset=_set_register(27)) + ie = property(fget=_get_register(28), fset=_set_register(28)) + + def __repr__(self): + spacing = "\t" + output = "Registers:\n" + for (id, each) in enumerate(self.order): + output += spacing + each + " = " + hex(get_registers()[id]) + #hex(self[each]) + output += "\n" + return output + +registers = Registers() + +def call(bank, address): + """ + Jumps into a function at a certain address. + + Go into the start menu, pause the game and try call(1, 0x1078) to see a + string printed to the screen. + """ + push = [ + registers.pc, + registers.hl, + registers.de, + registers.bc, + registers.af, + 0x3bb7, + ] + + for value in push: + registers.sp -= 2 + set_memory_at(registers.sp + 1, value >> 8) + set_memory_at(registers.sp, value & 0xFF) + if get_memory_range(registers.sp, 2) != [value & 0xFF, value >> 8]: + print "desired memory values: " + str([value & 0xFF, value >> 8] ) + print "actual memory values: " + str(get_memory_range(registers.sp , 2)) + print "wrong value at " + hex(registers.sp) + " expected " + hex(value) + " but got " + hex(get_memory_at(registers.sp)) + + if bank != 0: + registers["af"] = (bank << 8) | (registers["af"] & 0xFF) + registers["hl"] = address + registers["pc"] = 0x2d63 # FarJump + else: + registers["pc"] = address + +class crystal: + """ + Just a simple namespace to store a bunch of functions for Pokémon Crystal. + """ + + @staticmethod + def walk_through_walls_slow(): + memory = get_memory() + memory[0xC2FA] = 0 + memory[0xC2FB] = 0 + memory[0xC2FC] = 0 + memory[0xC2FD] = 0 + set_memory(memory) + + @staticmethod + def walk_through_walls(): + """ + Lets the player walk all over the map. These values are probably reset + by some of the map/collision functions when you move on to a new + location, so this needs to be executed each step/tick if continuous + walk-through-walls is desired. + """ + set_memory_at(0xC2FA, 0) + set_memory_at(0xC2FB, 0) + set_memory_at(0xC2FC, 0) + set_memory_at(0xC2FD, 0) + + #@staticmethod + #def set_enemy_level(level): + # set_memory_at(0xd213, level) + + @staticmethod + def nstep(steplimit=500): + """ + Steps the CPU forward and calls some functions in between each step, + like to manipulate memory. This is pretty slow. + """ + for step_counter in range(0, steplimit): + crystal.walk_through_walls() + #call(0x1, 0x1078) + step() + + @staticmethod + def disable_triggers(): + set_memory_at(0x23c4, 0xAF) + set_memory_at(0x23d0, 0xAF); + + @staticmethod + def disable_callbacks(): + set_memory_at(0x23f2, 0xAF) + set_memory_at(0x23fe, 0xAF) + + @staticmethod + def get_map_group_id(): + """ + Returns the current map group. + """ + return get_memory_at(0xdcb5) + + @staticmethod + def get_map_id(): + """ + Returns the map number of the current map. + """ + return get_memory_at(0xdcb6) + + @staticmethod + def get_map_name(): + """ + Figures out the current map name. + """ + map_group_id = crystal.get_map_group_id() + map_id = crystal.get_map_id() + return map_names[map_group_id][map_id]["name"] + + @staticmethod + def get_xy(): + """ + (x, y) coordinates of player on map. + Relative to top-left corner of map. + """ + x = get_memory_at(0xdcb8) + y = get_memory_at(0xdcb7) + return (x, y) + + @staticmethod + def menu_select(id=1): + """ + Sets the cursor to the given pokemon in the player's party. This is + under Start -> PKMN. This is useful for selecting a certain pokemon + with fly or another skill. + + This probably works on other menus. + """ + set_memory_at(0xcfa9, id) + + @staticmethod + def is_in_battle(): + """ + Checks whether or not we're in a battle. + """ + return (get_memory_at(0xd22d) != 0) or crystal.is_in_link_battle() + + @staticmethod + def is_in_link_battle(): + return get_memory_at(0xc2dc) != 0 + + @staticmethod + def unlock_flypoints(): + """ + Unlocks different destinations for flying. + + Note: this might start at 0xDCA4 (minus one on all addresses), but not + sure. + """ + set_memory_at(0xDCA5, 0xFF) + set_memory_at(0xDCA6, 0xFF) + set_memory_at(0xDCA7, 0xFF) + set_memory_at(0xDCA8, 0xFF) + + @staticmethod + def get_gender(): + """ + Returns 'male' or 'female'. + """ + gender = get_memory_at(0xD472) + if gender == 0: + return "male" + elif gender == 1: + return "female" + else: + return gender + + @staticmethod + def get_player_name(): + """ + Returns the 7 characters making up the player's name. + """ + bytez = get_memory_range(0xD47D, 7) + name = translate_chars(bytez) + return name + + @staticmethod + def warp(map_group_id, map_id, x, y): + set_memory_at(0xdcb5, map_group_id) + set_memory_at(0xdcb6, map_id) + set_memory_at(0xdcb7, y) + set_memory_at(0xdcb8, x) + set_memory_at(0xd001, 0xFF) + set_memory_at(0xff9f, 0xF1) + set_memory_at(0xd432, 1) + set_memory_at(0xd434, 0 & 251) + + @staticmethod + def warp_pokecenter(): + crystal.warp(1, 1, 3, 3) + crystal.nstep(200) + + @staticmethod + def masterballs(): + # masterball + set_memory_at(0xd8d8, 1) + set_memory_at(0xd8d9, 99) + + # ultraball + set_memory_at(0xd8da, 2) + set_memory_at(0xd8db, 99) + + # pokeballs + set_memory_at(0xd8dc, 5) + set_memory_at(0xd8dd, 99) + + @staticmethod + def get_text(): + """ + Returns alphanumeric text on the screen. Other characters will not be + shown. + """ + output = "" + tiles = get_memory_range(0xc4a0, 1000) + for each in tiles: + if each in chars.keys(): + thing = chars[each] + acceptable = False + + if len(thing) == 2: + portion = thing[1:] + else: + portion = thing + + if portion in string.printable: + acceptable = True + + if acceptable: + output += thing + + # remove extra whitespace + output = re.sub(" +", " ", output) + output = output.strip() + + return output + + @staticmethod + def set_partymon2(): + """ + This causes corruption, so it's not working yet. + """ + memory = get_memory() + memory[0xdcd7] = 2 + memory[0xdcd9] = 0x7 + + memory[0xdd0f] = 0x7 + memory[0xdd10] = 0x1 + + # moves + memory[0xdd11] = 0x1 + memory[0xdd12] = 0x2 + memory[0xdd13] = 0x3 + memory[0xdd14] = 0x4 + + # id + memory[0xdd15] = 0x1 + memory[0xdd16] = 0x2 + + # experience + memory[0xdd17] = 0x2 + memory[0xdd18] = 0x3 + memory[0xdd19] = 0x4 + + # hp + memory[0xdd1a] = 0x5 + memory[0xdd1b] = 0x6 + + # current hp + memory[0xdd31] = 0x10 + memory[0xdd32] = 0x25 + + # max hp + memory[0xdd33] = 0x10 + memory[0xdd34] = 0x40 + + set_memory(memory) + +class TestEmulator(unittest.TestCase): + try: + state = load_state("cheating-12") + except: + if "__name__" == "__main__": + raise Exception("failed to setup unit tests because no save state found") + + def setUp(self): + load_rom() + set_state(self.state) + + def tearDown(self): + shutdown() + + def test_PlaceString(self): + call(0, 0x1078) + + # where to draw the text + registers["hl"] = 0xc4a0 + + # what text to read from + registers["de"] = 0x1276 + + nstep(10) + + text = crystal.get_text() + + self.assertTrue("TRAINER" in text) + +if __name__ == "__main__": + unittest.main() + diff --git a/extras/vba_config.py b/extras/vba_config.py new file mode 100644 index 000000000..8377c8818 --- /dev/null +++ b/extras/vba_config.py @@ -0,0 +1,15 @@ +#!/usr/bin/jython +# -*- encoding: utf-8 -*- +import os + +# by default we assume the user has things in their $HOME +home = os.path.expanduser("~") # or System.getProperty("user.home") + +# and that the pokecrystal project folder is in there somewhere +project_path = os.path.join(home, os.path.join("code", "pokecrystal")) + +# save states are in ~/code/pokecrystal/save-states/ +save_state_path = os.path.join(project_path, "save-states") + +# where is your rom? +rom_path = os.path.join(project_path, "baserom.gbc") diff --git a/gbhw.asm b/gbhw.asm new file mode 100644 index 000000000..de87d304a --- /dev/null +++ b/gbhw.asm @@ -0,0 +1,65 @@ +; Graciously aped from http://nocash.emubase.de/pandocs.htm . + +rJOYP EQU $ff00 ; Joypad (R/W) +rSB EQU $ff01 ; Serial transfer data (R/W) +rSC EQU $ff02 ; Serial Transfer Control (R/W) +rDIV EQU $ff04 ; Divider Register (R/W) +rTIMA EQU $ff05 ; Timer counter (R/W) +rTMA EQU $ff06 ; Timer Modulo (R/W) +rTAC EQU $ff07 ; Timer Control (R/W) +rIF EQU $ff0f ; Interrupt Flag (R/W) +rNR10 EQU $ff10 ; Channel 1 Sweep register (R/W) +rNR11 EQU $ff11 ; Channel 1 Sound length/Wave pattern duty (R/W) +rNR12 EQU $ff12 ; Channel 1 Volume Envelope (R/W) +rNR13 EQU $ff13 ; Channel 1 Frequency lo (Write Only) +rNR14 EQU $ff14 ; Channel 1 Frequency hi (R/W) +rNR21 EQU $ff16 ; Channel 2 Sound Length/Wave Pattern Duty (R/W) +rNR22 EQU $ff17 ; Channel 2 Volume Envelope (R/W) +rNR23 EQU $ff18 ; Channel 2 Frequency lo data (W) +rNR24 EQU $ff19 ; Channel 2 Frequency hi data (R/W) +rNR30 EQU $ff1a ; Channel 3 Sound on/off (R/W) +rNR31 EQU $ff1b ; Channel 3 Sound Length +rNR32 EQU $ff1c ; Channel 3 Select output level (R/W) +rNR33 EQU $ff1d ; Channel 3 Frequency's lower data (W) +rNR34 EQU $ff1e ; Channel 3 Frequency's higher data (R/W) +rNR41 EQU $ff20 ; Channel 4 Sound Length (R/W) +rNR42 EQU $ff21 ; Channel 4 Volume Envelope (R/W) +rNR43 EQU $ff22 ; Channel 4 Polynomial Counter (R/W) +rNR44 EQU $ff23 ; Channel 4 Counter/consecutive; Inital (R/W) +rNR50 EQU $ff24 ; Channel control / ON-OFF / Volume (R/W) +rNR51 EQU $ff25 ; Selection of Sound output terminal (R/W) +rNR52 EQU $ff26 ; Sound on/off +rLCDC EQU $ff40 ; LCD Control (R/W) +rSTAT EQU $ff41 ; LCDC Status (R/W) +rSCY EQU $ff42 ; Scroll Y (R/W) +rSCX EQU $ff43 ; Scroll X (R/W) +rLY EQU $ff44 ; LCDC Y-Coordinate (R) +rLYC EQU $ff45 ; LY Compare (R/W) +rDMA EQU $ff46 ; DMA Transfer and Start Address (W) +rBGP EQU $ff47 ; BG Palette Data (R/W) - Non CGB Mode Only +rOBP0 EQU $ff48 ; Object Palette 0 Data (R/W) - Non CGB Mode Only +rOBP1 EQU $ff49 ; Object Palette 1 Data (R/W) - Non CGB Mode Only +rWY EQU $ff4a ; Window Y Position (R/W) +rWX EQU $ff4b ; Window X Position minus 7 (R/W) +rKEY1 EQU $ff4d ; CGB Mode Only - Prepare Speed Switch +rVBK EQU $ff4f ; CGB Mode Only - VRAM Bank +rHDMA1 EQU $ff51 ; CGB Mode Only - New DMA Source, High +rHDMA2 EQU $ff52 ; CGB Mode Only - New DMA Source, Low +rHDMA3 EQU $ff53 ; CGB Mode Only - New DMA Destination, High +rHDMA4 EQU $ff54 ; CGB Mode Only - New DMA Destination, Low +rHDMA5 EQU $ff55 ; CGB Mode Only - New DMA Length/Mode/Start +rRP EQU $ff56 ; CGB Mode Only - Infrared Communications Port +rBGPI EQU $ff68 ; CGB Mode Only - Background Palette Index +rBGPD EQU $ff69 ; CGB Mode Only - Background Palette Data +rOBPI EQU $ff6a ; CGB Mode Only - Sprite Palette Index +rOBPD EQU $ff6b ; CGB Mode Only - Sprite Palette Data +rUNKNOWN1 EQU $ff6c ; (FEh) Bit 0 (Read/Write) - CGB Mode Only +rSVBK EQU $ff70 ; CGB Mode Only - WRAM Bank +rUNKNOWN2 EQU $ff72 ; (00h) - Bit 0-7 (Read/Write) +rUNKNOWN3 EQU $ff73 ; (00h) - Bit 0-7 (Read/Write) +rUNKNOWN4 EQU $ff74 ; (00h) - Bit 0-7 (Read/Write) - CGB Mode Only +rUNKNOWN5 EQU $ff75 ; (8Fh) - Bit 4-6 (Read/Write) +rUNKNOWN6 EQU $ff76 ; (00h) - Always 00h (Read Only) +rUNKNOWN7 EQU $ff77 ; (00h) - Always 00h (Read Only) +rIE EQU $ffff ; Interrupt Enable (R/W) + diff --git a/gfx/debug/color_test.2bpp b/gfx/debug/color_test.2bpp new file mode 100644 index 000000000..113aa1256 Binary files /dev/null and b/gfx/debug/color_test.2bpp differ diff --git a/gfx/evo/bubble.2bpp b/gfx/evo/bubble.2bpp new file mode 100644 index 000000000..741ee9026 Binary files /dev/null and b/gfx/evo/bubble.2bpp differ diff --git a/gfx/evo/bubble_large.2bpp b/gfx/evo/bubble_large.2bpp new file mode 100644 index 000000000..a69044414 Binary files /dev/null and b/gfx/evo/bubble_large.2bpp differ diff --git a/gfx/font.1bpp b/gfx/misc/font.1bpp similarity index 100% rename from gfx/font.1bpp rename to gfx/misc/font.1bpp diff --git a/gfx/font_battle_extra.2bpp b/gfx/misc/font_battle_extra.2bpp similarity index 100% rename from gfx/font_battle_extra.2bpp rename to gfx/misc/font_battle_extra.2bpp diff --git a/gfx/font_extra.2bpp b/gfx/misc/font_extra.2bpp similarity index 100% rename from gfx/font_extra.2bpp rename to gfx/misc/font_extra.2bpp diff --git a/gfx/font_inversed.1bpp b/gfx/misc/font_inversed.1bpp similarity index 100% rename from gfx/font_inversed.1bpp rename to gfx/misc/font_inversed.1bpp diff --git a/gfx/misc/pack_f.2bpp b/gfx/misc/pack_f.2bpp new file mode 100644 index 000000000..60d6b7f91 Binary files /dev/null and b/gfx/misc/pack_f.2bpp differ diff --git a/gfx/misc/unown_font.2bpp b/gfx/misc/unown_font.2bpp new file mode 100644 index 000000000..4ec0bbea6 Binary files /dev/null and b/gfx/misc/unown_font.2bpp differ diff --git a/gfx/ow/misc.2bpp b/gfx/ow/misc.2bpp new file mode 100644 index 000000000..8f9b3b96f Binary files /dev/null and b/gfx/ow/misc.2bpp differ diff --git a/gfx/special/celebi/1.2bpp b/gfx/special/celebi/1.2bpp new file mode 100644 index 000000000..6379fc92f --- /dev/null +++ b/gfx/special/celebi/1.2bpp @@ -0,0 +1 @@ +00.>  d$6&_g?83<}__{jn @ ظ00 \ No newline at end of file diff --git a/gfx/special/celebi/2.2bpp b/gfx/special/celebi/2.2bpp new file mode 100644 index 000000000..f7c3294d3 Binary files /dev/null and b/gfx/special/celebi/2.2bpp differ diff --git a/gfx/special/celebi/3.2bpp b/gfx/special/celebi/3.2bpp new file mode 100644 index 000000000..00cac65a7 Binary files /dev/null and b/gfx/special/celebi/3.2bpp differ diff --git a/gfx/special/celebi/4.2bpp b/gfx/special/celebi/4.2bpp new file mode 100644 index 000000000..00cac65a7 Binary files /dev/null and b/gfx/special/celebi/4.2bpp differ diff --git a/gfx/special/celebi/leaf.2bpp b/gfx/special/celebi/leaf.2bpp new file mode 100644 index 000000000..1c8a3f9a8 Binary files /dev/null and b/gfx/special/celebi/leaf.2bpp differ diff --git a/joypad.asm b/joypad.asm new file mode 100644 index 000000000..099bfbef6 --- /dev/null +++ b/joypad.asm @@ -0,0 +1,275 @@ +JoypadInt: ; 92e +; Replaced by Joypad, called from VBlank instead of the useless +; joypad interrupt. + +; This is a placeholder in case the interrupt is somehow enabled. + reti +; 92f + +ClearJoypadPublic: ; 92f + xor a +; Pressed this frame (delta) + ld [$ffa7], a +; Currently pressed + ld [$ffa8], a + ret +; 935 + +Joypad: ; 935 +; Read the joypad register and translate it to something more +; workable for use in-game. There are 8 buttons, so we can use +; one byte to contain all player input. + +; Updates: + +; $ffa2: released this frame (delta) +; $ffa3: pressed this frame (delta) +; $ffa4: currently pressed +; $ffa5: pressed so far + +; Any of these three bits can be used to disable input. + ld a, [$cfbe] + and %11010000 + ret nz + +; If we're saving, input is disabled. + ld a, [$c2cd] + and a + ret nz + +; We can only get four inputs at a time. +; We take d-pad first for no particular reason. + ld a, D_PAD + ld [rJOYP], a +; Read twice to give the request time to take. + ld a, [rJOYP] + ld a, [rJOYP] + +; The Joypad register output is in the lo nybble (inversed). +; We make the hi nybble of our new container d-pad input. + cpl + and $f + swap a + +; We'll keep this in b for now. + ld b, a + +; Buttons make 8 total inputs (A, B, Select, Start). +; We can fit this into one byte. + ld a, BUTTONS + ld [rJOYP], a +; Wait for input to stabilize. + ld a, [rJOYP] + ld a, [rJOYP] + ld a, [rJOYP] + ld a, [rJOYP] + ld a, [rJOYP] + ld a, [rJOYP] +; Buttons take the lo nybble. + cpl + and $f + or b + ld b, a + +; Reset the joypad register since we're done with it. + ld a, $30 + ld [rJOYP], a + +; To get the delta we xor the last frame's input with the new one. + ld a, [$ffa4] ; last frame + ld e, a + xor b + ld d, a +; Released this frame: + and e + ld [$ffa2], a +; Pressed this frame: + ld a, d + and b + ld [$ffa3], a + +; Add any new presses to the list of collective presses: + ld c, a + ld a, [$ffa5] + or c + ld [$ffa5], a + +; Currently pressed: + ld a, b + ld [$ffa4], a + +; Now that we have the input, we can do stuff with it. + +; For example, soft reset: + and BUTTON_A | BUTTON_B | SELECT | START + cp BUTTON_A | BUTTON_B | SELECT | START + jp z, $0150 ; reset + + ret +; 984 + + +GetJoypadPublic: ; 984 +; Update mirror joypad input from $ffa4 (real input) + +; $ffa6: released this frame (delta) +; $ffa7: pressed this frame (delta) +; $ffa8: currently pressed + +; bit 0 A +; 1 B +; 2 SELECT +; 3 START +; 4 RIGHT +; 5 LEFT +; 6 UP +; 7 DOWN + + push af + push hl + push de + push bc + +; The player input can be automated using an input stream. +; See more below. + ld a, [InputType] + cp a, AUTO_INPUT + jr z, .auto + +; To get deltas, take this and last frame's input. + ld a, [$ffa4] ; real input + ld b, a + ld a, [$ffa8] ; last frame mirror + ld e, a + +; Released this frame: + xor b + ld d, a + and e + ld [$ffa6], a + +; Pressed this frame: + ld a, d + and b + ld [$ffa7], a + +; It looks like the collective presses got commented out here. + ld c, a + +; Currently pressed: + ld a, b + ld [$ffa8], a ; frame input + +.quit + pop bc + pop de + pop hl + pop af + ret + +.auto +; Use a predetermined input stream (used in the catching tutorial). + +; Stream format: [input][duration] +; A value of $ff will immediately end the stream. + +; Read from the input stream. + ld a, [$ff9d] + push af + ld a, [AutoInputBank] + rst Bankswitch + + ld hl, AutoInputAddress + ld a, [hli] + ld h, [hl] + ld l, a + +; We only update when the input duration has expired. + ld a, [AutoInputLength] + and a + jr z, .updateauto + +; Until then, don't change anything. + dec a + ld [AutoInputLength], a + pop af + rst Bankswitch + jr .quit + + +.updateauto +; An input of $ff will end the stream. + ld a, [hli] + cp a, $ff + jr z, .stopauto + ld b, a + +; A duration of $ff will end the stream indefinitely. + ld a, [hli] + ld [AutoInputLength], a + cp a, $ff + jr nz, .next + +; The current input is overwritten. + dec hl + dec hl + ld b, NO_INPUT + jr .finishauto + +.next +; On to the next input... + ld a, l + ld [AutoInputAddress], a + ld a, h + ld [AutoInputAddress+1], a + jr .finishauto + +.stopauto + call StopAutoInput + ld b, NO_INPUT + +.finishauto + pop af + rst Bankswitch + ld a, b + ld [$ffa7], a ; pressed + ld [$ffa8], a ; input + jr .quit +; 9ee + + +StartAutoInput: ; 9ee +; Start reading automated input stream at a:hl. + + ld [AutoInputBank], a + ld a, l + ld [AutoInputAddress], a + ld a, h + ld [AutoInputAddress+1], a +; Start reading the stream immediately. + xor a + ld [AutoInputLength], a +; Reset input mirrors. + xor a + ld [$ffa7], a ; pressed this frame + ld [$ffa6], a ; released this frame + ld [$ffa8], a ; currently pressed + + ld a, AUTO_INPUT + ld [InputType], a + ret +; a0a + + +StopAutoInput: ; a0a +; Clear variables related to automated input. + xor a + ld [AutoInputBank], a + ld [AutoInputAddress], a + ld [AutoInputAddress+1], a + ld [AutoInputLength], a +; Back to normal input. + ld [InputType], a + ret +; a1b + diff --git a/main.asm b/main.asm index 6674f4c76..0b99b9c22 100644 --- a/main.asm +++ b/main.asm @@ -4,7 +4,7 @@ SECTION "rst0",HOME[$0] jp Start SECTION "rst8",HOME[$8] ; FarCall - jp $2d63 + jp FarJpHl SECTION "rst10",HOME[$10] ; Bankswitch ld [$ff9d], a @@ -47,7 +47,7 @@ SECTION "serial",HOME[$58] ; serial interrupt jp $06ef SECTION "joypad",HOME[$60] ; joypad interrupt - jp $092e + jp JoypadInt SECTION "romheader",HOME[$100] Start: @@ -85,7 +85,6 @@ DelayFrames: ; 0x468 ret ; 0x46f - RTC: ; 46f ; update time and time-sensitive palettes @@ -150,47 +149,47 @@ DisableLCD: ; 568 ; Most of this is just going through the motions ; don't need to do anything if lcd is already off - ld a, [$ff40] ; LCDC + ld a, [rLCDC] bit 7, a ; lcd enable ret z ; reset ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; save enabled ints - ld a, [$ffff] ; IE + ld a, [rIE] ld b, a ; disable vblank res 0, a ; vblank - ld [$ffff], a ; IE + ld [rIE], a .wait ; wait until vblank - ld a, [$ff44] ; LY + ld a, [rLY] cp 145 ; >144 (ensure beginning of vblank) jr nz, .wait ; turn lcd off - ld a, [$ff40] ; LCDC + ld a, [rLCDC] and %01111111 ; lcd enable off - ld [$ff40], a ; LCDC + ld [rLCDC], a ; reset ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; restore enabled ints ld a, b - ld [$ffff], a ; IE + ld [rIE], a ret ; 58a EnableLCD: ; 58a - ld a, [$ff40] ; LCDC + ld a, [rLCDC] set 7, a ; lcd enable - ld [$ff40], a ; LCDC + ld [rLCDC], a ret ; 591 @@ -425,252 +424,11 @@ SetClock: ; 691 ret ; 6c4 -INCBIN "baserom.gbc",$6c4,$935 - $6c4 - -Joypad: ; 935 -; update joypad state -; $ffa2: released -; $ffa3: pressed -; $ffa4: input -; $ffa5: total pressed - -; - ld a, [$cfbe] - and $d0 - ret nz - -; pause game update? - ld a, [$c2cd] - and a - ret nz - -; d-pad - ld a, $20 - ld [$ff00], a - ld a, [$ff00] - ld a, [$ff00] -; hi nybble - cpl - and $f - swap a - ld b, a - -; buttons - ld a, $10 - ld [$ff00], a -; wait to stabilize - ld a, [$ff00] - ld a, [$ff00] - ld a, [$ff00] - ld a, [$ff00] - ld a, [$ff00] - ld a, [$ff00] -; lo nybble - cpl - and $f - or b - ld b, a - -; reset joypad - ld a, $30 - ld [$ff00], a - -; get change in input - ld a, [$ffa4] ; last frame's input - ld e, a - xor b ; current frame input - ld d, a -; released - and e - ld [$ffa2], a -; pressed - ld a, d - and b - ld [$ffa3], a - -; total pressed - ld c, a - ld a, [$ffa5] - or c - ld [$ffa5], a - -; original input - ld a, b - ld [$ffa4], a - -; A+B+SELECT+START - and $f - cp $f - jp z, $0150 ; reset - - ret -; 984 +INCBIN "baserom.gbc",$6c4,$92e - $6c4 -GetJoypadPublic: ; 984 -; update mirror joypad input from $ffa4 (real input) +INCLUDE "joypad.asm" -; $ffa6: released -; $ffa7: pressed -; $ffa8: input - -; bit 0 A -; 1 B -; 2 SELECT -; 3 START -; 4 RIGHT -; 5 LEFT -; 6 UP -; 7 DOWN - - push af - push hl - push de - push bc - -; automated input? - ld a, [InputType] - cp a, $ff ; INPUT_AUTO - jr z, .auto - -; get input - ld a, [$ffa4] ; real input - ld b, a - ld a, [$ffa8] ; last frame mirror - ld e, a - -; released - xor b - ld d, a - and e - ld [$ffa6], a - -; pressed - ld a, d - and b - ld [$ffa7], a - -; leftover from pasted code - ld c, a - -; - ld a, b - ld [$ffa8], a ; frame input -.quit - pop bc - pop de - pop hl - pop af - ret - -.auto -; use predetermined input feed (used in catch tutorial) -; struct: [input][duration] - -; save bank - ld a, [$ff9d] - push af -; - ld a, [AutoInputBank] - rst Bankswitch -; - ld hl, AutoInputAddress ; AutoInputAddress-9 - ld a, [hli] - ld h, [hl] - ld l, a - -; update when frame count hits 0 - ld a, [AutoInputLength] - and a - jr z, .updateauto - -; until then, do nothing - dec a - ld [AutoInputLength], a -; restore bank - pop af - rst Bankswitch -; we're done - jr .quit - -.updateauto -; get input - ld a, [hli] -; stop? - cp a, $ff - jr z, .stopinput - ld b, a - -; duration - ld a, [hli] - ld [AutoInputLength], a -; duration $ff = end at input - cp a, $ff - jr nz, .next - -; no input - dec hl - dec hl - ld b, $00 ; no input - jr .finishauto - -.next -; output recorded - ld a, l - ld [AutoInputAddress], a - ld a, h - ld [AutoInputAddress+1], a - jr .finishauto - -.stopinput - call StopAutoInput - ld b, $00 ; no input - -.finishauto -; restore bank - pop af - rst Bankswitch -; update mirrors - ld a, b - ld [$ffa7], a ; pressed - ld [$ffa8], a ; input - jr .quit -; 9ee - -StartAutoInput: ; 9ee -; start auto input stream at a:hl -; bank - ld [AutoInputBank], a -; address - ld a, l - ld [AutoInputAddress], a - ld a, h - ld [AutoInputAddress+1], a -; don't wait to update - xor a - ld [AutoInputLength], a -; clear input mirrors - xor a - ld [$ffa7], a ; pressed - ld [$ffa6], a ; released - ld [$ffa8], a ; input -; start reading input stream instead of player input - ld a, $ff ; INPUT_AUTO - ld [InputType], a - ret -; a0a - -StopAutoInput: ; a0a -; clear autoinput ram - xor a - ld [AutoInputBank], a - ld [AutoInputAddress], a - ld [AutoInputAddress+1], a - ld [AutoInputLength], a -; normal input - ld [InputType], a - ret -; a1b INCBIN "baserom.gbc",$a1b,$b40 - $a1b @@ -1063,18 +821,18 @@ UpdateCGBPals: ; c33 ForceUpdateCGBPals: ; c37 ; save wram bank - ld a, [$ff70] ; wram bank + ld a, [rSVBK] push af ; bankswitch ld a, 5 ; BANK(BGPals) - ld [$ff70], a ; wram bank + ld [rSVBK], a ; get bg pal buffer ld hl, BGPals ; 5:d080 ; update bg pals ld a, %10000000 ; auto increment, index 0 - ld [$ff68], a ; BGPI - ld c, $69 ; $ff69 + ld [rBGPI], a + ld c, rBGPD - rJOYP ld b, 4 ; NUM_PALS / 2 .bgp @@ -1119,8 +877,8 @@ ForceUpdateCGBPals: ; c37 ; update obj pals ld a, %10000000 ; auto increment, index 0 - ld [$ff6a], a - ld c, $6b ; $ff6b - $ff00 + ld [rOBPI], a + ld c, rOBPD - rJOYP ld b, 4 ; NUM_PALS / 2 .obp @@ -1163,7 +921,7 @@ ForceUpdateCGBPals: ; c37 ; restore wram bank pop af - ld [$ff70], a ; wram bank + ld [rSVBK], a ; clear pal update queue xor a ld [$ffe5], a @@ -1177,7 +935,7 @@ DmgToCgbBGPals: ; c9f ; exists to forego reinserting cgb-converted image data ; input: a -> bgp - ld [$ff47], a ; bgp + ld [rBGP], a push af ; check cgb @@ -1199,7 +957,7 @@ DmgToCgbBGPals: ; c9f ld hl, BGPals ; to ld de, Unkn1Pals ; from ; order - ld a, [$ff47] ; bgp + ld a, [rBGP] ld b, a ; # pals ld c, 8 ; all pals @@ -1225,9 +983,9 @@ DmgToCgbObjPals: ; ccb ; input: d -> obp1 ; e -> obp2 ld a, e - ld [$ff48], a ; obp0 + ld [rOBP0], a ld a, d - ld [$ff49], a ; obp1 + ld [rOBP1], a ; check cgb ld a, [$ffe6] @@ -1250,7 +1008,7 @@ DmgToCgbObjPals: ; ccb ; from ld de, Unkn2Pals ; order - ld a, [$ff48] ; obp0 + ld a, [rOBP0] ld b, a ; # pals ld c, 8 ; all pals @@ -1378,7 +1136,7 @@ ClearTileMap: ; fc8 call ByteFill ; We aren't done if the LCD is on - ld a, [$ff40] ; LCDC + ld a, [rLCDC] bit 7, a ret z jp WaitBGMap @@ -1668,7 +1426,7 @@ DMATransfer: ; 15d8 and a ret z ; start transfer - ld [$ff55], a ; hdma5 + ld [rHDMA5], a ; indicate that transfer has occurred xor a ld [$ffe8], a @@ -1689,7 +1447,7 @@ UpdateBGMapBuffer: ; 15e3 and a ret z ; save wram bank - ld a, [$ff4f] ; vram bank + ld a, [rVBK] push af ; save sp ld [$ffd9], sp @@ -1712,7 +1470,7 @@ UpdateBGMapBuffer: ; 15e3 pop bc ; update palettes ld a, $1 - ld [$ff4f], a ; vram bank + ld [rVBK], a ; tile 1 ld a, [hli] ld [bc], a @@ -1723,7 +1481,7 @@ UpdateBGMapBuffer: ; 15e3 dec c ; update tiles ld a, $0 - ld [$ff4f], a ; vram bank + ld [rVBK], a ; tile 1 ld a, [de] inc de @@ -1740,7 +1498,7 @@ UpdateBGMapBuffer: ; 15e3 pop bc ; update palettes ld a, $1 - ld [$ff4f], a ; vram bank + ld [rVBK], a ; tile 1 ld a, [hli] ld [bc], a @@ -1751,7 +1509,7 @@ UpdateBGMapBuffer: ; 15e3 dec c ; update tiles ld a, $0 - ld [$ff4f], a ; vram bank + ld [rVBK], a ; tile 1 ld a, [de] inc de @@ -1781,7 +1539,7 @@ UpdateBGMapBuffer: ; 15e3 ; restore vram bank pop af - ld [$ff4f], a ; vram bank + ld [rVBK], a ; we don't need to update bg map until new tiles are loaded xor a @@ -1859,13 +1617,13 @@ UpdateBGMap: ; 164c .attr ; switch vram banks ld a, 1 - ld [$ff4f], a ; vram bank + ld [rVBK], a ; bg map 1 ld hl, AttrMap call .getthird ; restore vram bank ld a, 0 - ld [$ff4f], a ; vram bank + ld [rVBK], a ret .tiles @@ -2012,7 +1770,7 @@ SafeLoadTiles2: ; 170a and a ret z ; abort if too far into vblank - ld a, [$ff44] ; LY + ld a, [rLY] ; ly = 144-145? cp 144 ret c @@ -2114,7 +1872,7 @@ SafeLoadTiles: ; 1769 and a ret z ; abort if too far into vblank - ld a, [$ff44] ; LY + ld a, [rLY] ; ly = 144-145? cp 144 ret c @@ -2230,7 +1988,7 @@ SafeTileAnimation: ; 17d3 ret z ; abort if too far into vblank - ld a, [$ff44] ; LY + ld a, [rLY] ; ret unless ly = 144-150 cp 144 ret c @@ -2244,24 +2002,24 @@ SafeTileAnimation: ; 17d3 ld a, BANK(DoTileAnimation) rst Bankswitch ; bankswitch - ld a, [$ff70] ; wram bank + ld a, [rSVBK] push af ; save wram bank ld a, $1 ; wram bank 1 - ld [$ff70], a ; wram bank + ld [rSVBK], a - ld a, [$ff4f] ; vram bank + ld a, [rVBK] push af ; save vram bank ld a, $0 ; vram bank 0 - ld [$ff4f], a ; vram bank + ld [rVBK], a ; take care of tile animation queue call DoTileAnimation ; restore affected banks pop af - ld [$ff4f], a ; vram bank + ld [rVBK], a pop af - ld [$ff70], a ; wram bank + ld [rSVBK], a pop af rst Bankswitch ; bankswitch ret @@ -2319,15 +2077,15 @@ AskSerial: ; 2063 ; handshake ld a, $88 - ld [$ff01], a + ld [rSB], a ; switch to internal clock ld a, %00000001 - ld [$ff02], a + ld [rSC], a ; start transfer ld a, %10000001 - ld [$ff02], a + ld [rSC], a ret ; 208a @@ -2339,17 +2097,17 @@ GameTimer: ; 209e nop ; save wram bank - ld a, [$ff70] ; wram bank + ld a, [rSVBK] push af ld a, $1 - ld [$ff70], a ; wram bank + ld [rSVBK], a call UpdateGameTimer ; restore wram bank pop af - ld [$ff70], a ; wram bank + ld [rSVBK], a ret ; 20ad @@ -2486,16 +2244,50 @@ PushScriptPointer: ; 261f ret ; 2631 -INCBIN "baserom.gbc",$2631,$26ef - $2631 +INCBIN "baserom.gbc",$2631,$26d4 - $2631 + +GetScriptByte: ; 0x26d4 +; Return byte at ScriptBank:ScriptPos in a. + + push hl + push bc + + ld a, [$ff9d] + push af + + ld a, [ScriptBank] + rst Bankswitch + + ld hl, ScriptPos + ld c, [hl] + inc hl + ld b, [hl] + + ld a, [bc] + + inc bc + ld [hl], b + dec hl + ld [hl], c + + ld b, a + pop af + rst Bankswitch + ld a, b + + pop bc + pop hl + ret +; 0x26ef ObjectEvent: ; 0x26ef jumptextfaceplayer ObjectEventText ; 0x26f2 - ObjectEventText: TX_FAR _ObjectEventText db "@" +; 0x26f7 INCBIN "baserom.gbc",$26f7,$2bed-$26f7 @@ -2530,6 +2322,7 @@ GetMapHeaderPointer: ; 0x2bed ld a, OlivineGym_MapHeader - OlivinePokeCenter1F_MapHeader call AddNTimes ret +; 0x2c04 GetMapHeaderMember: ; 0x2c04 ; Extract data from the current map's header. @@ -2596,7 +2389,43 @@ GetWorldMapLocation: ; 0x2caf ret ; 0x2cbd -INCBIN "baserom.gbc",$2cbd,$2d83-$2cbd +INCBIN "baserom.gbc",$2cbd,$2d63-$2cbd + +FarJpHl: ; 2d63 +; Jump to a:hl. +; Preserves all registers besides a. + +; Switch to the new bank. + ld [$ff8b], a + ld a, [$ff9d] + push af + ld a, [$ff8b] + rst Bankswitch + + call .hl + +; We want to retain the contents of f. +; To do this, we can pop to bc instead of af. + + ld a, b + ld [$cfb9], a + ld a, c + ld [$cfba], a + +; Restore the working bank. + pop bc + ld a, b + rst Bankswitch + + ld a, [$cfb9] + ld b, a + ld a, [$cfba] + ld c, a + ret +.hl + jp [hl] +; 2d83 + Predef: ; 2d83 ; call a function from given id a @@ -2764,13 +2593,13 @@ RNG: ; 2f8c push bc ; Added value - ld a, [$ff04] ; divider + ld a, [rDIV] ld b, a ld a, [$ffe1] adc b ld [$ffe1], a ; Subtracted value - ld a, [$ff04] ; divider + ld a, [rDIV] ld b, a ld a, [$ffe2] sbc b @@ -3216,9 +3045,9 @@ ClearPalettes: ; 3317 ; In DMG mode, we can just change palettes to 0 (white) xor a - ld [$ff47], a ; BGP - ld [$ff48], a ; OBP0 - ld [$ff49], a ; OBP1 + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a ret .cgb @@ -3633,7 +3462,71 @@ StartMusic: ; 3b97 ret ; 3bbc -INCBIN "baserom.gbc",$3bbc,$3c23 - $3bbc +INCBIN "baserom.gbc",$3bbc,$3be3 - $3bbc + +PlayCryHeader: ; 3be3 +; Play a cry given parameters in header de + + push hl + push de + push bc + push af + +; Save current bank + ld a, [$ff9d] + push af + +; Cry headers are stuck in one bank. + ld a, BANK(CryHeaders) + ld [$ff9d], a + ld [$2000], a + +; Each header is 6 bytes long: + ld hl, CryHeaders + add hl, de + add hl, de + add hl, de + add hl, de + add hl, de + add hl, de + +; Header struct: + +; id + ld e, [hl] + inc hl + ld d, [hl] + inc hl +; pitch + ld a, [hli] + ld [CryPitch], a +; echo + ld a, [hli] + ld [CryEcho], a +; length + ld a, [hli] + ld [CryLength], a + ld a, [hl] + ld [CryLength+1], a + +; That's it for the header + ld a, BANK(PlayCry) + ld [$ff9d], a + ld [$2000], a + call PlayCry + +; Restore bank + pop af + ld [$ff9d], a + ld [$2000], a + + pop af + pop bc + pop de + pop hl + ret +; 3c23 + StartSFX: ; 3c23 ; sfx id order is by priority (highest to lowest) @@ -3782,7 +3675,66 @@ IntroFadePalettes: ; 0x617c db %11100100 ; 6182 -INCBIN "baserom.gbc",$6182,$669f - $6182 +INCBIN "baserom.gbc",$6182,$6274 - $6182 + +FarStartTitleScreen: ; 6274 + callba StartTitleScreen + ret +; 627b + +INCBIN "baserom.gbc",$627b,$62bc - $627b + +TitleScreenEntrance: ; 62bc + +; Animate the logo: +; Move each line by 4 pixels until our count hits 0. + ld a, [$ffcf] + and a + jr z, .done + sub 4 + ld [$ffcf], a + +; Lay out a base (all lines scrolling together). + ld e, a + ld hl, $d100 + ld bc, 8 * 10 ; logo height + call ByteFill + +; Alternate signage for each line's position vector. +; This is responsible for the interlaced effect. + ld a, e + xor $ff + inc a + + ld b, 8 * 10 / 2 ; logo height / 2 + ld hl, $d101 +.loop + ld [hli], a + inc hl + dec b + jr nz, .loop + + callba AnimateTitleCrystal + ret + + +.done +; Next scene + ld hl, $cf63 + inc [hl] + xor a + ld [$ffc6], a + +; Play the title screen music. + ld de, MUSIC_TITLE + call StartMusic + + ld a, $88 + ld [$ffd2], a + ret +; 62f6 + +INCBIN "baserom.gbc",$62f6,$669f - $62f6 CheckNickErrors: ; 669f ; error-check monster nick before use @@ -3890,7 +3842,7 @@ DrawGraphic: ; 6eef ret ; 6f07 -INCBIN "baserom.gbc",$6f07,$8000 - $6f07 +INCBIN "baserom.gbc",$6f07,$747b - $6f07 SECTION "bank2",DATA,BANK[$2] @@ -4102,7 +4054,7 @@ INCBIN "baserom.gbc",$b0ae,$b0d2 - $b0ae TrainerPalettes: INCLUDE "gfx/trainers/palette_pointers.asm" -INCBIN "baserom.gbc",$b1de,$bc3a - $b1de +INCBIN "baserom.gbc",$b1de,$b825 - $b1de SECTION "bank3",DATA,BANK[$3] @@ -4666,7 +4618,7 @@ AskSurfText: ; ca36 db "@" ; Want to SURF? ; ca3b -INCBIN "baserom.gbc",$ca3b,$10000 - $ca3b +INCBIN "baserom.gbc",$ca3b,$fa0b - $ca3b SECTION "bank4",DATA,BANK[$4] @@ -4887,7 +4839,39 @@ OpenPartyStats: ; 12e00 ret ; 0x12e1b -INCBIN "baserom.gbc",$12e1b,$14000 - $12e1b +INCBIN "baserom.gbc",$12e1b,$13b87 - $12e1b + +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 +; 13d96 SECTION "bank5",DATA,BANK[$5] @@ -4989,7 +4973,7 @@ Tileset20GFX: ; 1b43e INCBIN "gfx/tilesets/20.lz" ; 1b8f1 -INCBIN "baserom.gbc", $1b8f1, $1c000 - $1b8f1 +INCBIN "baserom.gbc", $1b8f1, $1bdfe - $1b8f1 SECTION "bank7",DATA,BANK[$7] @@ -5032,8 +5016,6 @@ Music_Credits: INCLUDE "audio/music/credits.asm" Music_Clair: INCLUDE "audio/music/clair.asm" Music_MobileAdapter: INCLUDE "audio/music/mobileadapter.asm" -INCBIN "baserom.gbc",$1ff6c, $20000 - $1ff6c - SECTION "bank8",DATA,BANK[$8] @@ -5172,7 +5154,7 @@ TrainerClassDVs ; 270d6 db $98, $88 ; mysticalman ; 2715c -INCBIN "baserom.gbc",$2715c,$28000 - $2715c +INCBIN "baserom.gbc",$2715c,$27a2d - $2715c SECTION "bankA",DATA,BANK[$A] @@ -5415,7 +5397,7 @@ INCBIN "baserom.gbc",$2C41a,$2ee8f - $2C41a pop hl ret -INCBIN "baserom.gbc",$2ef18,$30000 - $2ef18 +INCBIN "baserom.gbc",$2ef18,$2ef9f - $2ef18 SECTION "bankC",DATA,BANK[$C] @@ -5448,7 +5430,7 @@ Tileset30GFX: ; 326b0 INCBIN "gfx/tilesets/30.lz" ; 329ed -INCBIN "baserom.gbc",$329ed,$34000 - $329ed +INCBIN "baserom.gbc",$329ed,$333f0 - $329ed SECTION "bankD",DATA,BANK[$D] @@ -5459,7 +5441,7 @@ TypeMatchup: ; 34bb1 INCLUDE "battle/type_matchup.asm" ; 34cfd -INCBIN "baserom.gbc",$34cfd,$38000 - $34cfd +INCBIN "baserom.gbc",$34cfd,$37ee2 - $34cfd SECTION "bankE",DATA,BANK[$E] @@ -5761,7 +5743,7 @@ LoadEnemyMon: ; 3e8eb callab CalcMagikarpLength ; We're clear if the length is < 1536 - ld a, [MagikarpLengthHi] + ld a, [MagikarpLength] cp a, $06 ; $600 = 1536 jr nz, .CheckMagikarpArea @@ -5770,7 +5752,7 @@ LoadEnemyMon: ; 3e8eb cp a, $0c ; / $100 jr c, .CheckMagikarpArea ; Try again if > 1614 - ld a, [MagikarpLengthLo] + ld a, [MagikarpLength + 1] cp a, $50 jr nc, .GenerateDVs @@ -5779,7 +5761,7 @@ LoadEnemyMon: ; 3e8eb cp a, $32 ; / $100 jr c, .CheckMagikarpArea ; Try again if > 1598 - ld a, [MagikarpLengthLo] + ld a, [MagikarpLength + 1] cp a, $40 jr nc, .GenerateDVs @@ -5804,7 +5786,7 @@ LoadEnemyMon: ; 3e8eb cp a, $64 ; / $100 jr c, .Happiness ; Floor at length 1024 - ld a, [MagikarpLengthHi] + ld a, [MagikarpLength] cp a, $04 ; $400 = 1024 jr c, .GenerateDVs ; try again @@ -6081,42 +6063,47 @@ CheckSleepingTreeMon: ; 3eb38 CheckUnownLetter: ; 3eb75 ; Return carry if the Unown letter hasn't been unlocked yet - ld a, [$def3] ; UnownLetter + + ld a, [UnlockedUnowns] ld c, a - ld de, $0000 + ld de, 0 + .loop -; Has this set been unlocked? + +; Don't check this set unless it's been unlocked srl c jr nc, .next -; Check out the set + +; Is our letter in the set? ld hl, .LetterSets add hl, de ld a, [hli] ld h, [hl] ld l, a -; Is our letter in the set? + push de - ld a, [$d234] - ld de, $0001 + ld a, [UnownLetter] + ld de, 1 push bc call IsInArray pop bc pop de - jr c, .Match + + jr c, .match + .next -; Next set +; Make sure we haven't gone past the end of the table inc e inc e ld a, e -; Gone past the end of the table? - cp a, 4*2 ; 4 sets with 2-byte pointers + cp a, .Set1 - .LetterSets jr c, .loop -; Didn't find the letter (not unlocked) +; Hasn't been unlocked, or the letter is invalid scf ret -.Match +.match ; Valid letter and a ret @@ -6128,26 +6115,21 @@ CheckUnownLetter: ; 3eb75 dw .Set4 .Set1 - ; A B C D E F G H I J K - db $01, $02, $03, $04, $05, $06, $07, $08, $09, $0a, $0b - db $ff ; end - + ; A B C D E F G H I J K + db 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, $ff .Set2 - ; L M N O P Q R - db $0c, $0d, $0e, $0f, $10, $11, $12 - db $ff ; end - + ; L M N O P Q R + db 12, 13, 14, 15, 16, 17, 18, $ff .Set3 - ; S T U V W - db $13, $14, $15, $16, $17 - db $ff ; end - + ; S T U V W + db 19, 20, 21, 22, 23, $ff .Set4 - ; X Y Z - db $18, $19, $1a - db $ff ; end + ; X Y Z + db 24, 25, 26, $ff + ; 3ebc7 + INCBIN "baserom.gbc", $3ebc7, $3edd8 - $3ebc7 BattleRNG: ; 3edd8 @@ -6341,7 +6323,7 @@ BattleStartMessage: ret ; 0x3fd26 -INCBIN "baserom.gbc",$3fd26,$40000 - $3fd26 +INCBIN "baserom.gbc",$3fd26,$3fe86 - $3fd26 SECTION "bank10",DATA,BANK[$10] @@ -6374,12 +6356,26 @@ INCBIN "baserom.gbc",$44000,$44378 - $44000 PokedexDataPointerTable: ; 0x44378 INCLUDE "stats/pokedex/entry_pointers.asm" -INCBIN "baserom.gbc",$4456e,$3a92 +INCBIN "baserom.gbc",$4456e,$44997 - $4456e SECTION "bank12",DATA,BANK[$12] -INCBIN "baserom.gbc",$48000,$49d24 - $48000 +INCBIN "baserom.gbc",$48000,$48e9b - $48000 + +PackFGFX: +INCBIN "gfx/misc/pack_f.2bpp" + +INCBIN "baserom.gbc",$4925b,$49962 - $4925b + +SpecialCelebiGFX: +INCBIN "gfx/special/celebi/leaf.2bpp" +INCBIN "gfx/special/celebi/1.2bpp" +INCBIN "gfx/special/celebi/2.2bpp" +INCBIN "gfx/special/celebi/3.2bpp" +INCBIN "gfx/special/celebi/4.2bpp" + +INCBIN "baserom.gbc",$49aa2,$49d24 - $49aa2 ContinueText: ; 0x49d24 db "CONTINUE@" @@ -6736,7 +6732,7 @@ UpdateOTPointer: ; 0x4a83a ret ; 0x4a843 -INCBIN "baserom.gbc",$4a843,$4C000 - $4a843 +INCBIN "baserom.gbc",$4a843,$4ae78 - $4a843 SECTION "bank13",DATA,BANK[$13] @@ -6985,7 +6981,13 @@ EggALotMoreTimeString: ; 0x4e46e ; 0x4e497 -INCBIN "baserom.gbc",$4e497,$50000 - $4e497 +INCBIN "baserom.gbc",$4e497,$4e831 - $4e497 + +EvolutionGFX: +INCBIN "gfx/evo/bubble_large.2bpp" +INCBIN "gfx/evo/bubble.2bpp" + +INCBIN "baserom.gbc",$4e881,$4f31c - $4e881 SECTION "bank14",DATA,BANK[$14] @@ -7167,16 +7169,136 @@ Dragon: Dark: db "DARK@" -INCBIN "baserom.gbc",$50A28, $51424 - $50A28 +INCBIN "baserom.gbc", $50a28, $50bdd - $50a28 +GetGender: ; 50bdd +; Return the gender of a given monster in a. + +; 1: male +; 0: female +; 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, PartyMon2 - PartyMon1 + ld a, [MonType] + and a + jr z, .PartyMon + +; 1: OTPartyMon + ld hl, OTPartyMon1DVs + dec a + jr z, .PartyMon + +; 2: BoxMon + ld hl, $ad26 + $15 ; BoxMon1DVs + ld bc, $20 ; BoxMon2 - BoxMon1 + dec a + jr z, .BoxMon + +; 3: Unknown + ld hl, $d123 ; DVBuffer + dec a + jr z, .DVs + +; else: WildMon + ld hl, EnemyMonDVs + jr .DVs + + +; Get our place in the party/box. + +.PartyMon +.BoxMon + ld a, [CurPartyMon] + call AddNTimes + + +.DVs + +; BoxMon data is read directly from SRAM. + ld a, [MonType] + cp 2 + 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 BoxMon. + ld a, [MonType] ; MonType + cp 2 ; BOXMON + call z, CloseSRAM + + +; We need the gender ratio to do anything with this. + push bc + ld a, [CurPartySpecies] + dec a + ld hl, BaseStats + 13 ; BASE_GENDER + ld bc, BaseStats1 - BaseStats + call AddNTimes + pop bc + + ld a, BANK(BaseStats) + call GetFarByte + + +; The higher the ratio, the more likely the monster is to be female. + + cp $ff + jr z, .Genderless + + and a + jr z, .Male + + cp $fe + 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 +; 50c50 + +INCBIN "baserom.gbc", $50c50, $51424 - $50c50 + BaseStats: INCLUDE "stats/base_stats.asm" PokemonNames: INCLUDE "stats/pokemon_names.asm" -INCBIN "baserom.gbc",$53D84,$54000 - $53D84 +INCBIN "baserom.gbc",$53D84,$53e2e - $53D84 SECTION "bank15",DATA,BANK[$15] @@ -8596,7 +8718,12 @@ BattleText_0x8188e: ; 0x8188e db "left today!", $57 ; 0x818ac -INCBIN "baserom.gbc",$818ac,$84000-$818ac +INCBIN "baserom.gbc",$818ac,$81fe3-$818ac + +DebugColorTestGFX: +INCBIN "gfx/debug/color_test.2bpp" + +INCBIN "baserom.gbc",$82153,$823c8-$82153 SECTION "bank21",DATA,BANK[$21] @@ -8836,8 +8963,50 @@ FX39GFX: ; 8638e INCBIN "gfx/fx/039.lz" ; 8640b -INCBIN "baserom.gbc", $8640b, $88000 - $8640b +INCBIN "baserom.gbc", $8640b, $8640e - $8640b +HallOfFame3: ; 0x8640e + call $648e + ld a, [$d84c] + push af + ld a, $1 + ld [$c2cd], a + call $2ed3 + ld a, $1 + ld [$d4b5], a + + ; Enable the Pokégear map to cycle through all of Kanto + ld hl, $d84c + set 6, [hl] + + ld a, $5 + ld hl, $4da0 + rst $8 + ld hl, $d95e + ld a, [hl] + cp $c8 + jr nc, .asm_86436 ; 0x86433 $1 + inc [hl] +.asm_86436 + ld a, $5 + ld hl, $4b85 + rst $8 + call $653f + ld a, $5 + ld hl, $4b5f + rst $8 + xor a + ld [$c2cd], a + call $64c3 + pop af + ld b, a + ld a, $42 + ld hl, $5847 + rst $8 + ret +; 0x86455 + +INCBIN "baserom.gbc", $86455, $88000 - $86455 SECTION "bank22",DATA,BANK[$22] @@ -9027,7 +9196,7 @@ GetNthPartyMon: ; 0x8b1ce scf ret -INCBIN "baserom.gbc",$8b1e1,$8c000-$8b1e1 +INCBIN "baserom.gbc",$8b1e1,$8ba24-$8b1e1 SECTION "bank23",DATA,BANK[$23] @@ -9068,11 +9237,11 @@ TimeOfDayPals: ; 8c011 ld hl, $d038 ; Unkn1Pals + 7 pals ; save wram bank - ld a, [$ff70] ; wram bank + ld a, [rSVBK] ld b, a ; wram bank 5 ld a, 5 - ld [$ff70], a ; wram bank + ld [rSVBK], a ; push palette ld c, 4 ; NUM_PAL_COLORS @@ -9087,7 +9256,7 @@ TimeOfDayPals: ; 8c011 ; restore wram bank ld a, b - ld [$ff70], a ; wram bank + ld [rSVBK], a ; update sgb pals @@ -9099,11 +9268,11 @@ TimeOfDayPals: ; 8c011 ld hl, $d03f ; last byte in Unkn1Pals ; save wram bank - ld a, [$ff70] ; wram bank + ld a, [rSVBK] ld d, a ; wram bank 5 ld a, 5 - ld [$ff70], a ; wram bank + ld [rSVBK], a ; pop palette ld e, 4 ; NUM_PAL_COLORS @@ -9118,7 +9287,7 @@ TimeOfDayPals: ; 8c011 ; restore wram bank ld a, d - ld [$ff70], a ; wram bank + ld [rSVBK], a ; update palettes call UpdateTimePals @@ -10364,8 +10533,11 @@ INCLUDE "maps/map_headers.asm" INCLUDE "maps/second_map_headers.asm" -INCBIN "baserom.gbc",$966b0,$1950 +INCBIN "baserom.gbc",$966b0,$96cb1 - $966b0 +INCLUDE "scripting.asm" + +INCBIN "baserom.gbc",$97c20,$35e SECTION "bank26",DATA,BANK[$26] @@ -10423,12 +10595,12 @@ INCLUDE "maps/BattleTowerOutside.asm" SECTION "bank28",DATA,BANK[$28] -INCBIN "baserom.gbc",$A0000,$4000 +INCBIN "baserom.gbc",$a0000,$a1eca - $a0000 SECTION "bank29",DATA,BANK[$29] -INCBIN "baserom.gbc",$A4000,$4000 +INCBIN "baserom.gbc",$a4000,$a64ad - $a4000 SECTION "bank2A",DATA,BANK[$2A] @@ -10693,8 +10865,6 @@ Route22_BlockData: ; 0xabef7 INCBIN "maps/Route22.blk" ; 0xabfab -INCBIN "baserom.gbc",$abfab,$55 - SECTION "bank2B",DATA,BANK[$2B] @@ -11563,7 +11733,7 @@ Tileset16GFX: ; b74e8 INCBIN "gfx/tilesets/16.lz" ; b799a -INCBIN "baserom.gbc", $b799a, $b8000 - $b799a +INCBIN "baserom.gbc", $b799a, $b7ea8 - $b799a SECTION "bank2E",DATA,BANK[$2E] @@ -11808,7 +11978,7 @@ WildRockMonTable: ; b83de db $ff ; end ; b83e5 -INCBIN "baserom.gbc",$B83E5,$bc000 - $b83e5 +INCBIN "baserom.gbc",$b83e5,$b9e8b - $b83e5 SECTION "bank2F",DATA,BANK[$2F] @@ -12242,17 +12412,17 @@ INCBIN "baserom.gbc",$bd0d0,$be699-$bd0d0 SECTION "bank30",DATA,BANK[$30] -INCBIN "baserom.gbc",$C0000,$4000 +INCBIN "baserom.gbc",$c0000,$c3fc0 - $c0000 SECTION "bank31",DATA,BANK[$31] -INCBIN "baserom.gbc",$C4000,$4000 +INCBIN "baserom.gbc",$c4000,$c7f80 - $c4000 SECTION "bank32",DATA,BANK[$32] -INCBIN "baserom.gbc",$C8000,$4000 +INCBIN "baserom.gbc",$c8000,$cbe2b - $c8000 SECTION "bank33",DATA,BANK[$33] @@ -12263,7 +12433,6 @@ INCBIN "baserom.gbc",$cc000, $cfd9e - $cc000 Music_PostCredits: INCLUDE "audio/music/postcredits.asm" -INCBIN "baserom.gbc",$cff04, $d0000 - $cff04 ; Pic animations I @@ -12324,7 +12493,7 @@ INCLUDE "gfx/pics/kanto_frames.asm" SECTION "bank36",DATA,BANK[$36] -FontInversed: INCBIN "gfx/font_inversed.1bpp" +FontInversed: INCBIN "gfx/misc/font_inversed.1bpp" ; Johto frame definitions INCLUDE "gfx/pics/johto_frames.asm" @@ -12364,12 +12533,12 @@ Tileset11GFX: ; de570 INCBIN "gfx/tilesets/11.lz" ; de98a -INCBIN "baserom.gbc", $de98a, $e0000 - $de98a +INCBIN "baserom.gbc", $de98a, $dfd14 - $de98a SECTION "bank38",DATA,BANK[$38] -INCBIN "baserom.gbc",$E0000,$4000 +INCBIN "baserom.gbc",$e0000,$e37f9 - $e0000 SECTION "bank39",DATA,BANK[$39] @@ -12677,13 +12846,13 @@ Music_BugCatchingContest: INCLUDE "audio/music/bugcatchingcontest.asm" SECTION "bank3E",DATA,BANK[$3E] FontExtra: -INCBIN "gfx/font_extra.2bpp",$0,$200 +INCBIN "gfx/misc/font_extra.2bpp",$0,$200 Font: -INCBIN "gfx/font.1bpp",$0,$400 +INCBIN "gfx/misc/font.1bpp",$0,$400 FontBattleExtra: -INCBIN "gfx/font_battle_extra.2bpp",$0,$200 +INCBIN "gfx/misc/font_battle_extra.2bpp",$0,$200 INCBIN "baserom.gbc", $f8800, $f8ba0 - $f8800 @@ -12693,192 +12862,9 @@ INCBIN "gfx/misc/town_map.lz" INCBIN "baserom.gbc", $f8ea3, $fbbfc - $f8ea3 -CalcMagikarpLength: ; fbbfc -; Stores Magikarp's length at $d1ea-$d1eb in big endian -; -; input: -; de: EnemyMonDVs -; bc: PlayerID -; output: -; $d1ea-$d1eb: length -; -; does a whole bunch of arbitrary nonsense -; cycles through a table of arbitrary values -; http://web.archive.org/web/20110628181718/http://upokecenter.com/games/gs/guides/magikarp.php +INCLUDE "battle/magikarp_length.asm" -; b = rrcrrc(atkdefdv) xor rrc(pidhi) - ld h, b - ld l, c - ld a, [hli] - ld b, a - ld c, [hl] ; ld bc, [PlayerID] - rrc b - rrc c - ld a, [de] - inc de - rrca - rrca - xor b - ld b, a - -; c = rrcrrc(spdspcdv) xor rrc(pidlo) - ld a, [de] - rrca - rrca - xor c - ld c, a - -; if bc < $000a: - ld a, b - and a - jr nz, .loadtable - ld a, c - cp a, $0a - jr nc, .loadtable - -; de = hl = bc + $be - ld hl, $00be - add hl, bc - ld d, h - ld e, l - jr .endtable - -.loadtable - ld hl, .MagikarpLengthTable - ld a, $02 - ld [$d265], a - -.readtable - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - call .BLessThanD - jr nc, .advancetable - -; c = bc / [hl] - call .BCMinusDE - ld a, b - ld [$ffb3], a - ld a, c - ld [$ffb4], a - ld a, [hl] - ld [$ffb7], a - ld b, $02 - call Divide - ld a, [$ffb6] - ld c, a - -; de = c + $64 * (2 + number of rows down the table) - xor a - ld [$ffb4], a - ld [$ffb5], a - ld a, $64 - ld [$ffb6], a - ld a, [$d265] - ld [$ffb7], a - call Multiply - ld b, $00 - ld a, [$ffb6] - add c - ld e, a - ld a, [$ffb5] - adc b - ld d, a - jr .endtable - -.advancetable - inc hl ; align to next triplet - ld a, [$d265] - inc a - ld [$d265], a - cp a, $10 - jr c, .readtable - - call .BCMinusDE - ld hl, $0640 - add hl, bc - ld d, h - ld e, l - -.endtable - ld h, d - ld l, e - add hl, hl - add hl, hl - add hl, de - add hl, hl ; hl = de * 10 - - ld de, $ff02 - ld a, $ff -.loop - inc a - add hl, de ; - 254 - jr c, .loop - - ld d, $00 - -; mod $0c -.modloop - cp a, $0c - jr c, .done - sub a, $0c - inc d - jr .modloop - -.done - ld e, a - ld hl, $d1ea - ld [hl], d - inc hl - ld [hl], e - ret -; fbc9a - -.BLessThanD ; fbc9a -; return carry if b < d - ld a, b - cp d - ret c - ret nc -; fbc9e - -.CLessThanE ; fbc9e -; unused - 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 - -.MagikarpLengthTable ; fbca8 -; ????, divisor - dwb $006e, $01 - dwb $0136, $02 - dwb $02c6, $04 - dwb $0a96, $14 - dwb $1e1e, $32 - dwb $452e, $64 - dwb $7fc6, $96 - dwb $ba5e, $96 - dwb $e16e, $64 - dwb $f4f6, $32 - dwb $fcc6, $14 - dwb $feba, $05 - dwb $ff82, $02 -; fbccf - -INCBIN "baserom.gbc",$FBCCF,$fc000-$fbccf +INCBIN "baserom.gbc",$fbccf,$fbe91 - $fbccf SECTION "bank3F",DATA,BANK[$3F] @@ -12930,12 +12916,16 @@ INCBIN "baserom.gbc",$fcf38,$fd1d2-$fcf38 SECTION "bank40",DATA,BANK[$40] -INCBIN "baserom.gbc",$100000,$4000 +INCBIN "baserom.gbc",$100000,$10389d - $100000 SECTION "bank41",DATA,BANK[$41] -INCBIN "baserom.gbc",$104000,$105258 - $104000 +INCBIN "baserom.gbc",$104000,$104350 - $104000 + +INCBIN "gfx/ow/misc.2bpp" + +INCBIN "baserom.gbc",$1045b0,$105258 - $1045b0 MysteryGiftGFX: INCBIN "gfx/misc/mystery_gift.2bpp" @@ -12945,14 +12935,24 @@ INCBIN "baserom.gbc",$105688,$105930 - $105688 ; japanese mystery gift gfx INCBIN "gfx/misc/mystery_gift_jp.2bpp" -INCBIN "baserom.gbc",$105db0,$1060bb - $105db0 +INCBIN "baserom.gbc",$105db0,$105ef6 - $105db0 + +HallOfFame2: ; 0x105ef6 + ret + +INCBIN "baserom.gbc",$105ef7,$106078 - $105ef7 + +HallOfFame1: ; 0x106078 + ret + +INCBIN "baserom.gbc",$106079,$1060bb - $106079 Function1060bb: ; 1060bb ; commented out ret ; 1060bc -INCBIN "baserom.gbc",$1060bc,$108000 - $1060bc +INCBIN "baserom.gbc",$1060bc,$106dbc - $1060bc SECTION "bank42",DATA,BANK[$42] @@ -12963,128 +12963,17 @@ IntroLogoGFX: ; 109407 INCBIN "gfx/intro/logo.lz" ; 10983f -INCBIN "baserom.gbc", $10983f, $10aee1 - $10983f +INCBIN "baserom.gbc", $10983f, $1099aa - $10983f -Credits: - db " SATOSHI TAJIRI@" ; "たじり さとし@" - db " JUNICHI MASUDA@" ; "ますだ じゅんいち@" - db " TETSUYA WATANABE@" ; "わたなべ てつや@" - db " SHIGEKI MORIMOTO@" ; "もりもと しげき@" - db " SOUSUKE TAMADA@" ; "たまだ そうすけ@" - db " TAKENORI OOTA@" ; "おおた たけのり@" - db " KEN SUGIMORI@" ; "すぎもり けん@" - db " MOTOFUMI FUJIWARA@" ; "ふじわら もとふみ@" - db " ATSUKO NISHIDA@" ; "にしだ あつこ@" - db " MUNEO SAITO@" ; "さいとう むねお@" - db " SATOSHI OOTA@" ; "おおた さとし@" - db " RENA YOSHIKAWA@" ; "よしかわ れな@" - db " JUN OKUTANI@" ; "おくたに じゅん@" - db " HIRONOBU YOSHIDA@" ; "よしだ ひろのぶ@" - db " ASUKA IWASHITA@" ; "いわした あすか@" - db " GO ICHINOSE@" ; "いちのせ ごう@" - db " MORIKAZU AOKI@" ; "あおき もりかず@" - db " KOHJI NISHINO@" ; "にしの こうじ@" - db " KENJI MATSUSHIMA@" ; "まつしま けんじ@" - db "TOSHINOBU MATSUMIYA@" ; "まつみや としのぶ@" - db " SATORU IWATA@" ; "いわた さとる@" - db " NOBUHIRO SEYA@" ; "せや のぶひろ@" - db " KAZUHITO SEKINE@" ; "せきね かずひと@" - db " TETSUJI OOTA@" ; "おおた てつじ@" - db "NCL SUPER MARIO CLUB@" ; "スーパーマりォクラブ@" - db " SARUGAKUCHO@" ; "さるがくちょう@" - db " AKITO MORI@" ; "もり あきと@" - db " TAKAHIRO HARADA@" ; "はらだ たかひろ@" - db " TOHRU HASHIMOTO@" ; "はしもと とおる@" - db " NOBORU MATSUMOTO@" ; "まつもと のぼる@" - db " TAKEHIRO IZUSHI@" ; "いずし たけひろ@" - db " TAKASHI KAWAGUCHI@" ; "かわぐち たかし@" - db " TSUNEKAZU ISHIHARA@" ; "いしはら つねかず@" - db " HIROSHI YAMAUCHI@" ; "やまうち ひろし@" - db " KENJI SAIKI@" ; "さいき けんじ@" - db " ATSUSHI TADA@" ; "ただ あつし@" - db " NAOKO KAWAKAMI@" ; "かわかみ なおこ@" - db " HIROYUKI ZINNAI@" ; "じんない ひろゆき@" - db " KUNIMI KAWAMURA@" ; "かわむら くにみ@" - db " HISASHI SOGABE@" ; "そがべ ひさし@" - db " KEITA KAGAYA@" ; "かがや けいた@" - db " YOSHINORI MATSUDA@" ; "まつだ よしのり@" - db " HITOMI SATO@" ; "さとう ひとみ@" - db " TORU OSAWA@" ; "おおさわ とおる@" - db " TAKAO OHARA@" ; "おおはら たかお@" - db " YUICHIRO ITO@" ; "いとう ゆういちろう@" - db " TAKAO SHIMIZU@" ; "しみず たかお@" - db " SPECIAL PRODUCTION", $4e - db " PLANNING", $4e ; "きかくかいはつぶ@" - db " & DEVELOPMENT DEPT.@" - db " KEITA NAKAMURA@" ; "なかむら けいた@" - db " HIROTAKA UEMURA@" ; "うえむら ひろたか@" - db " HIROAKI TAMURA@" ; "たむら ひろあき@" - db " NORIAKI SAKAGUCHI@" ; "さかぐち のりあき@" - db " MIYUKI SATO@" ; "さとう みゆき@" - db " GAKUZI NOMOTO@" ; "のもと がくじ@" - db " AI MASHIMA@" ; "ましま あい@" - db " MIKIHIRO ISHIKAWA@" ; "いしかわ みきひろ@" - db " HIDEYUKI HASHIMOTO@" ; "はしもと ひでゆき@" - db " SATOSHI YAMATO@" ; "やまと さとし@" - db " SHIGERU MIYAMOTO@" ; "みやもと しげる@" - db " END@" ; "おしまい@" - db " ????????@" ; "????????@" - db " GAIL TILDEN@" - db " NOB OGASAWARA@" - db " SETH McMAHILL@" - db " HIROTO ALEXANDER@" - db " TERESA LILLYGREN@" - db " THOMAS HERTZOG@" - db " ERIK JOHNSON@" - db " HIRO NAKAMURA@" - db " TERUKI MURAKAWA@" - db " KAZUYOSHI OSAWA@" - db " KIMIKO NAKAMICHI@" - db " #MON", $4e ; "ポケットモンスター", $4e - db " CRYSTAL VERSION", $4e ; " クりスタル バージョン", $4e - db " STAFF@" ; " スタッフ@" - db " DIRECTOR@" ; "エグゼクティブ ディレクター@" - db " CO-DIRECTOR@" ; "ディレクター@" - db " PROGRAMMERS@" ; "プログラム@" - db " GRAPHICS DIRECTOR@" ; "グラフィック ディレクター@" - db " MONSTER DESIGN@" ; "# デザイン@" - db " GRAPHICS DESIGN@" ; "グラフィック デザイン@" - db " MUSIC@" ; "おんがく@" - db " SOUND EFFECTS@" ; "サウンド エフ→クト@" - db " GAME DESIGN@" ; "ゲームデザイン@" - db " GAME SCENARIO@" ; "シナりォ@" - db " TOOL PROGRAMMING@" ; "ツール プログラム@" - db " PARAMETRIC DESIGN@" ; "パラメーター せってい@" - db " SCRIPT DESIGN@" ; "スクりプト せってい@" - db " MAP DATA DESIGN@" ; "マップデータ せってい@" - db " MAP DESIGN@" ; "マップ デザイン@" - db " PRODUCT TESTING@" ; "デバッグプレイ@" - db " SPECIAL THANKS@" ; "スぺシャルサンクス@" - db " PRODUCERS@" ; "プロデューサー@" - db " EXECUTIVE PRODUCER@" ; "エグゼクティブ プロデューサー@" - db " #MON ANIMATION@" ; "# アニメーション@" - db " #DEX TEXT@" ; "ずかん テキスト@" - db " MOBILE PRJ. LEADER@" ; "モバイルプロジ→クト りーダー@" - db " MOBILE SYSTEM AD.@" ; "モバイル システムアドバイザー@" - db "MOBILE STADIUM DIR.@" ; "モバイルスタジアム ディレクター@" - db " COORDINATION@" ; "コーディネーター@" - db " US VERSION STAFF@" - db " US COORDINATION@" - db " TEXT TRANSLATION@" - db " PAAD TESTING@" - ; (C) 1 9 9 5 - 2 0 0 1 N i n t e n d o - db $60,$61,$62,$63,$64,$65,$66, $67, $68, $69, $6a, $6b, $6c, $4e - ; (C) 1 9 9 5 - 2 0 0 1 C r e a t u r e s i n c . - db $60,$61,$62,$63,$64,$65,$66, $6d, $6e, $6f, $70, $71, $72, $7a, $7b, $7c, $4e - ; (C) 1 9 9 5 - 2 0 0 1 G A M E F R E A K i n c . - db $60,$61,$62,$63,$64,$65,$66, $73, $74, $75, $76, $77, $78, $79, $7a, $7b, $7c, "@" +; Credits +INCLUDE "credits.asm" SECTION "bank43",DATA,BANK[$43] INCBIN "baserom.gbc", $10c000, $10ed67 - $10c000 -TitleScreen: ; 10ed67 +StartTitleScreen: ; 10ed67 call WhiteBGMap call ClearSprites @@ -13107,7 +12996,7 @@ TitleScreen: ; 10ed67 ; VRAM bank 1 ld a, 1 - ld [$ff4f], a + ld [rVBK], a ; Decompress running Suicune gfx @@ -13180,7 +13069,7 @@ TitleScreen: ; 10ed67 ; Back to VRAM bank 0 ld a, $0 - ld [$ff4f], a + ld [rVBK], a ; Decompress logo @@ -13276,7 +13165,7 @@ TitleScreen: ; 10ed67 call ByteFill ; Let LCD Stat know we're messing around with SCX - ld a, $43 ; ff43 ; SCX + ld a, rSCX - rJOYP ld [$ffc6], a ; Restore WRAM bank @@ -13289,9 +13178,9 @@ TitleScreen: ; 10ed67 call $058a ; Set sprite size to 8x16 - ld a, [$ff40] ; LCDC + ld a, [rLCDC] set 2, a - ld [$ff40], a ; LCDC + ld [rLCDC], a ; ld a, $70 @@ -13320,7 +13209,32 @@ TitleScreen: ; 10ed67 ret ; 10eea7 -INCBIN "baserom.gbc", $10eea7, $10ef46 - $10eea7 +INCBIN "baserom.gbc", $10eea7, $10ef32 - $10eea7 + +AnimateTitleCrystal: ; 10ef32 +; Move the title screen crystal downward until it's fully visible + +; Stop at y=6 +; y is really from the bottom of the sprite, which is two tiles high + ld hl, Sprites + ld a, [hl] + cp 6 + 16 + ret z + +; Move all 30 parts of the crystal down by 2 + ld c, 30 +.loop + ld a, [hl] + add 2 + ld [hli], a + inc hl + inc hl + inc hl + dec c + jr nz, .loop + + ret +; 10ef46 TitleSuicuneGFX: ; 10ef46 INCBIN "gfx/title/suicune.lz" @@ -13423,14 +13337,22 @@ TitleScreenPalettes: RGB 00, 00, 00 RGB 00, 00, 00 - -INCBIN "baserom.gbc", $10ff5e, $110000 - $10ff5e - - SECTION "bank44",DATA,BANK[$44] -INCBIN "baserom.gbc",$110000,$4000 +INCBIN "baserom.gbc",$110000,$110fad - $110000 +URIPrefix: ; 0x110fad + ascii "http://" +HTTPDownloadURL: ; 0x110fb4 + ascii "gameboy.datacenter.ne.jp/cgb/download" +HTTPUploadURL: ; 0x110fd9 + ascii "gameboy.datacenter.ne.jp/cgb/upload" +HTTPUtilityURL: ; 0x110ffc + ascii "gameboy.datacenter.ne.jp/cgb/utility" +HTTPRankingURL: ; 0x111020 + ascii "gameboy.datacenter.ne.jp/cgb/ranking" + +INCBIN "baserom.gbc",$111044,$113f84 - $111044 SECTION "bank45",DATA,BANK[$45] @@ -13785,12 +13707,38 @@ Function117cdd: ; 0x117cdd SECTION "bank46",DATA,BANK[$46] -INCBIN "baserom.gbc",$118000,$4000 +INCBIN "baserom.gbc",$118000,$118ba5 - $118000 +ExchangeDownloadURL: ; 0x118ba5 + ascii "http://gameboy.datacenter.ne.jp/cgb/download?name=/01/CGB-BXTJ/exchange/index.txt" + +db $0 + +BattleDownloadURL: ; 0x118bf7 + ascii "http://gameboy.datacenter.ne.jp/cgb/download?name=/01/CGB-BXTJ/battle/index.txt" + +db $0 + +NewsDownloadURL: ; 0x118c47 + ascii "http://gameboy.datacenter.ne.jp/cgb/download?name=/01/CGB-BXTJ/news/index.txt" + +db $0 + +MenuDownloadURL: ; 0x118c95 + ascii "http://gameboy.datacenter.ne.jp/cgb/download?name=/01/CGB-BXTJ/POKESTA/menu.cgb" + +db $0 + +IndexDownloadURL: ; 0x118ce4 + ascii "http://gameboy.datacenter.ne.jp/cgb/download?name=/01/CGB-BXTJ/tamago/index.txt" + +db $0 + +INCBIN "baserom.gbc",$118d35,$11bc9e - $118d35 SECTION "bank47",DATA,BANK[$47] -INCBIN "baserom.gbc",$11C000,$4000 +INCBIN "baserom.gbc",$11c000,$11f686 - $11c000 SECTION "bank48",DATA,BANK[$48] @@ -14617,17 +14565,17 @@ INCBIN "gfx/pics/201r/back.lz" SECTION "bank5B",DATA,BANK[$5B] -INCBIN "baserom.gbc",$16C000,$4000 +INCBIN "baserom.gbc",$16c000,$16d7fe - $16c000 SECTION "bank5C",DATA,BANK[$5C] -INCBIN "baserom.gbc",$170000,$4000 +INCBIN "baserom.gbc",$170000,$17367f - $170000 SECTION "bank5D",DATA,BANK[$5D] -INCBIN "baserom.gbc",$174000,$4000 +INCBIN "baserom.gbc",$174000,$177561 - $174000 SECTION "bank5E",DATA,BANK[$5E] @@ -14655,7 +14603,7 @@ INCBIN "baserom.gbc",$17a68f, $17b629 - $17a68f SECTION "bank5F",DATA,BANK[$5F] -INCBIN "baserom.gbc",$17C000,$4000 +INCBIN "baserom.gbc",$17c000,$17ff6c - $17c000 SECTION "bank60",DATA,BANK[$60] @@ -14953,7 +14901,7 @@ INCLUDE "stats/pokedex/entries_2.asm" SECTION "bank6F",DATA,BANK[$6F] -INCBIN "baserom.gbc",$1BC000,$4000 +INCBIN "baserom.gbc",$1bc000,$1be08d - $1bc000 SECTION "bank70",DATA,BANK[$70] @@ -15093,12 +15041,12 @@ PokegearGFX: ; 1de2e4 INCBIN "gfx/misc/pokegear.lz" ; 1de5c7 -INCBIN "baserom.gbc",$1de5c7,$1e0000 - $1de5c7 +INCBIN "baserom.gbc",$1de5c7,$1df238 - $1de5c7 SECTION "bank78",DATA,BANK[$78] -INCBIN "baserom.gbc",$1E0000,$4000 +INCBIN "baserom.gbc",$1e0000,$1e1000 - $1e0000 SECTION "bank79",DATA,BANK[$79] @@ -15109,24 +15057,26 @@ SECTION "bank7A",DATA,BANK[$7A] SECTION "bank7B",DATA,BANK[$7B] -INCBIN "baserom.gbc",$1EC000,$4000 +INCBIN "baserom.gbc",$1ec000,$1ecf02 - $1ec000 SECTION "bank7C",DATA,BANK[$7C] -INCBIN "baserom.gbc",$1F0000,$4000 +INCBIN "baserom.gbc",$1f0000,$1f09d8 - $1f0000 SECTION "bank7D",DATA,BANK[$7D] -INCBIN "baserom.gbc",$1F4000,$4000 +INCBIN "baserom.gbc",$1f4000,$1f636a - $1f4000 SECTION "bank7E",DATA,BANK[$7E] -INCBIN "baserom.gbc",$1F8000,$4000 +INCBIN "baserom.gbc",$1f8000,$1fb8a8 - $1f8000 SECTION "bank7F",DATA,BANK[$7F] -INCBIN "baserom.gbc",$1FC000,$4000 +SECTION "stadium2",DATA[$8000-$220],BANK[$7F] +INCBIN "baserom.gbc",$1ffde0,$220 + diff --git a/maps/KrissHouse2F.asm b/maps/KrissHouse2F.asm index 76b4caccb..f4f8aadfa 100644 --- a/maps/KrissHouse2F.asm +++ b/maps/KrissHouse2F.asm @@ -38,15 +38,64 @@ INCBIN "baserom.gbc",$7abc9,$7abcc - $7abc9 UnknownScript_0x7abcc: ; 0x7abcc describedecoration $1 +; 0x7abce + +UnknownScript_0x7abce: ; 0x7abce describedecoration $2 +; 0x7abd0 + +UnknownScript_0x7abd0: ; 0x7abd0 describedecoration $3 +; 0x7abd2 + +UnknownScript_0x7abd2: ; 0x7abd2 describedecoration $4 - unknown0xcc -; 0x7abd5 +; 0x7abd4 -INCBIN "baserom.gbc",$7abd5,$3d +MapKrissHouse2FSignpost4: ; 0x7abd4 + dw $02cc ; bit1 + dw MapKrissHouse2FSignpost4Script +; 0x7abd8 -MapKrissHouse2FSignpost2Script: ; 0x7ac12 +MapKrissHouse2FSignpost4Script: ; 0x7abd8 + describedecoration $0 +; 0x7abda + +MapKrissHouse2FSignpost2Script: ; 0x7abda + checkbit1 $001a + iftrue UnknownScript_0x7ac07 + checkbit1 $0325 + iftrue UnknownScript_0x7ac0a + playmusic $001d + loadfont + 2writetext UnknownText_0x7ac24 + pause 45 + 2writetext UnknownText_0x7ac55 + pause 45 + 2writetext UnknownText_0x7ac64 + pause 45 + musicfadeout $003c, $10 + 2writetext UnknownText_0x7ac84 + pause 45 + loadmovesprites + setbit1 $0325 + end +; 0x7ac07 + +UnknownScript_0x7ac07: ; 0x7ac07 + jumpstd $000b +; 0x7ac0a + +UnknownScript_0x7ac0a: ; 0x7ac0a + loadfont + 2writetext UnknownText_0x7ac84 + pause 45 + loadmovesprites + end +; 0x7ac12 + + +MapKrissHouse2FSignpost3Script: ; 0x7ac12 jumpstd $0002 ; 0x7ac15 @@ -97,15 +146,15 @@ KrissHouse2F_MapEventHeader: ; 0x7ac99 ; signposts db 4 signpost 1, 2, $1, MapKrissHouse2FSignpost0Script - signpost 1, 3, $0, $6bda - signpost 1, 5, $0, MapKrissHouse2FSignpost2Script - signpost 0, 6, $5, $6bd4 + signpost 1, 3, $0, MapKrissHouse2FSignpost2Script + signpost 1, 5, $0, MapKrissHouse2FSignpost3Script + signpost 0, 6, $5, MapKrissHouse2FSignpost4 ; 6bd4 ; people-events db 4 - person_event $f0, 6, 8, $1, $0, 255, 255, $0, 0, $6bd2, $0741 + person_event $f0, 6, 8, $1, $0, 255, 255, $0, 0, UnknownScript_0x7abd2, $0741 person_event $f1, 8, 8, $1, $0, 255, 255, $0, 0, UnknownScript_0x7abcc, $0742 - person_event $f2, 8, 9, $1, $0, 255, 255, $0, 0, $6bce, $0743 - person_event $f3, 5, 4, $21, $0, 255, 255, $0, 0, $6bd0, $0744 + person_event $f2, 8, 9, $1, $0, 255, 255, $0, 0, UnknownScript_0x7abce, $0743 + person_event $f3, 5, 4, $21, $0, 255, 255, $0, 0, UnknownScript_0x7abd0, $0744 ; 0x7acec diff --git a/maps/KurtsHouse.asm b/maps/KurtsHouse.asm index f3325b0d0..0536d9630 100644 --- a/maps/KurtsHouse.asm +++ b/maps/KurtsHouse.asm @@ -208,9 +208,8 @@ UnknownScript_0x18e2b4: ; 0x18e2b4 iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 LEVEL_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 LEVEL_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e2c4: ; 0x18e2c4 clearbit1 $0258 2jump UnknownScript_0x18e2ab @@ -221,9 +220,8 @@ UnknownScript_0x18e2ca: ; 0x18e2ca iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 LURE_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 LURE_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e2da: ; 0x18e2da clearbit1 $0259 2jump UnknownScript_0x18e2ab @@ -234,9 +232,8 @@ UnknownScript_0x18e2e0: ; 0x18e2e0 iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 MOON_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 MOON_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e2f0: ; 0x18e2f0 clearbit1 $025a 2jump UnknownScript_0x18e2ab @@ -247,9 +244,8 @@ UnknownScript_0x18e2f6: ; 0x18e2f6 iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 FRIEND_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 FRIEND_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e306: ; 0x18e306 clearbit1 $025b 2jump UnknownScript_0x18e2ab @@ -260,9 +256,8 @@ UnknownScript_0x18e30c: ; 0x18e30c iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 FAST_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 FAST_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e31c: ; 0x18e31c clearbit1 $025c 2jump UnknownScript_0x18e2ab @@ -273,9 +268,8 @@ UnknownScript_0x18e322: ; 0x18e322 iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 HEAVY_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 HEAVY_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e332: ; 0x18e332 clearbit1 $025d 2jump UnknownScript_0x18e2ab @@ -286,9 +280,8 @@ UnknownScript_0x18e338: ; 0x18e338 iftrue UnknownScript_0x18e3c5 2writetext UnknownText_0x18e7fb keeptextopen - verbosegiveitem2 LOVE_BALL - addvar $8 - unknown0xb2 $62 + verbosegiveitem2 LOVE_BALL, $16 + iffalse UnknownScript_0x18e2b2 UnknownScript_0x18e348: ; 0x18e348 clearbit1 $025e 2jump UnknownScript_0x18e2ab diff --git a/pokecrystal.asm b/pokecrystal.asm index 163ce91c4..fe71bfa29 100644 --- a/pokecrystal.asm +++ b/pokecrystal.asm @@ -1,3 +1,4 @@ INCLUDE "wram.asm" INCLUDE "constants.asm" +INCLUDE "gbhw.asm" INCLUDE "main.tx" diff --git a/preprocessor.py b/preprocessor.py index 3ef9e1e88..cb09fb898 100644 --- a/preprocessor.py +++ b/preprocessor.py @@ -599,6 +599,11 @@ def read_line(l): if "INCLUDE \"" in l: include_file(asm) + # ascii string macro preserves the bytes as ascii (skip the translator) + elif len(asm) > 6 and "\tascii " in [asm[:7], "\t" + asm[:6]]: + asm = asm.replace("ascii", "db", 1) + sys.stdout.write(asm) + # convert text to bytes when a quote appears (not in a comment) elif "\"" in asm: quote_translator(asm) diff --git a/requirement.txt b/requirements.txt similarity index 100% rename from requirement.txt rename to requirements.txt diff --git a/scripting.asm b/scripting.asm new file mode 100644 index 000000000..b029b7865 --- /dev/null +++ b/scripting.asm @@ -0,0 +1,3127 @@ +ScriptCommandTable: ; 0x96cb1 + dw Script_2call + dw Script_3call + dw Script_2ptcall + dw Script_2jump + dw Script_3jump + dw Script_2ptjump + dw Script_if_equal + dw Script_if_not_equal + dw Script_iffalse + dw Script_iftrue + dw Script_if_less_than + dw Script_if_greater_than + dw Script_jumpstd + dw Script_callstd + dw Script_3callasm + dw Script_special + dw Script_2ptcallasm + dw Script_checkmaptriggers + dw Script_domaptrigger + dw Script_checktriggers + dw Script_dotrigger + dw Script_writebyte + dw Script_addvar + dw Script_random + dw Script_checkver + dw Script_copybytetovar + dw Script_copyvartobyte + dw Script_loadvar + dw Script_checkcode + dw Script_writevarcode + dw Script_writecode + dw Script_giveitem + dw Script_takeitem + dw Script_checkitem + dw Script_givemoney + dw Script_takemoney + dw Script_checkmoney + dw Script_givecoins + dw Script_takecoins + dw Script_checkcoins + dw Script_addcellnum + dw Script_delcellnum + dw Script_checkcellnum + dw Script_checktime + dw Script_checkpoke + dw Script_givepoke + dw Script_giveegg + dw Script_givepokeitem + dw Script_checkpokeitem + dw Script_checkbit1 + dw Script_clearbit1 + dw Script_setbit1 + dw Script_checkbit2 + dw Script_clearbit2 + dw Script_setbit2 + dw Script_wildoff + dw Script_wildon + dw Script_xycompare + dw Script_warpmod + dw Script_blackoutmod + dw Script_warp + dw Script_readmoney + dw Script_readcoins + dw Script_RAM2MEM + dw Script_pokenamemem + dw Script_itemtotext + dw Script_mapnametotext + dw Script_trainertotext + dw Script_stringtotext + dw Script_itemnotify + dw Script_pocketisfull + dw Script_loadfont + dw Script_refreshscreen + dw Script_loadmovesprites + dw Script_loadbytec1ce + dw Script_3writetext + dw Script_2writetext + dw Script_repeattext + dw Script_yesorno + dw Script_loadmenudata + dw Script_writebackup + dw Script_jumptextfaceplayer + dw Script_3jumptext + dw Script_jumptext + dw Script_closetext + dw Script_keeptextopen + dw Script_pokepic + dw Script_pokepicyesorno + dw Script_interpretmenu + dw Script_interpretmenu2 + dw Script_loadpikachudata + dw Script_battlecheck + dw Script_loadtrainerdata + dw Script_loadpokedata + dw Script_loadtrainer + dw Script_startbattle + dw Script_returnafterbattle + dw Script_catchtutorial + dw Script_trainertext + dw Script_trainerstatus + dw Script_winlosstext + dw Script_scripttalkafter + dw Script_talkaftercancel + dw Script_talkaftercheck + dw Script_setlasttalked + dw Script_applymovement + dw Script_applymovement2 + dw Script_faceplayer + dw Script_faceperson + dw Script_variablesprite + dw Script_disappear + dw Script_appear + dw Script_follow + dw Script_stopfollow + dw Script_moveperson + dw Script_writepersonxy + dw Script_loademote + dw Script_showemote + dw Script_spriteface + dw Script_follownotexact + dw Script_earthquake + dw Script_changemap + dw Script_changeblock + dw Script_reloadmap + dw Script_reloadmappart + dw Script_writecmdqueue + dw Script_delcmdqueue + dw Script_playmusic + dw Script_playrammusic + dw Script_musicfadeout + dw Script_playmapmusic + dw Script_reloadmapmusic + dw Script_cry + dw Script_playsound + dw Script_waitbutton + dw Script_warpsound + dw Script_specialsound + dw Script_passtoengine + dw Script_newloadmap + dw Script_pause + dw Script_deactivatefacing + dw Script_priorityjump + dw Script_warpcheck + dw Script_ptpriorityjump + dw Script_return + dw Script_end + dw Script_reloadandreturn + dw Script_resetfuncs + dw Script_pokemart + dw Script_elevator + dw Script_trade + dw Script_askforphonenumber + dw Script_phonecall + dw Script_hangup + dw Script_describedecoration + dw Script_fruittree + dw Script_specialphonecall + dw Script_checkphonecall + dw Script_verbosegiveitem + dw Script_verbosegiveitem2 + dw Script_loadwilddata + dw Script_halloffame + dw Script_credits + dw Script_warpfacing + dw Script_storetext + dw Script_displaylocation + dw Script_unknown0xa6 + dw Script_unknown0xa7 + dw Script_unknown0xa8 + dw Script_unknown0xa9 +; 0x96e05 + +Unknown_0x96e05: ; 0x96e05 + ld hl, $d434 + set 2, [hl] + ret +; 0x96e0b + +Unknown_0x96e0b: ; 0x96e0b + ld hl, $d434 + bit 2, [hl] + ret +; 0x96e11 + +Unknown_0x96e11: ; 0x96e11 + ld hl, $d434 + res 2, [hl] + ret +; 0x96e17 + +Script_3callasm: ; 0x96e17 +; script command 0xe +; parameters: +; asm (AsmPointerParam) + + call GetScriptByte + ld b, a + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, b + rst $8 + ret +; 0x96e26 + +Script_special: ; 0x96e26 +; script command 0xf +; parameters: +; predefined_script (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, $3 + ld hl, $401b + rst $8 + ret +; 0x96e35 + +Script_2ptcallasm: ; 0x96e35 +; script command 0x10 +; parameters: +; asm (PointerToAsmPointerParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld b, [hl] + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + ld a, b + rst $8 + ret +; 0x96e45 + +Script_jumptextfaceplayer: ; 0x96e45 +; script command 0x51 +; parameters: +; text_pointer (RawTextPointerLabelParam) + + ld a, [ScriptBank] + ld [$d44e], a + call GetScriptByte + ld [$d44f], a + call GetScriptByte + ld [$d450], a + ld b, $25 + ld hl, $6e79 + jp $759d +; 0x96e5f + +Script_jumptext: ; 0x96e5f +; script command 0x53 +; parameters: +; text_pointer (RawTextPointerLabelParam) + + ld a, [ScriptBank] + ld [$d44e], a + call GetScriptByte + ld [$d44f], a + call GetScriptByte + ld [$d450], a + ld b, $25 + ld hl, $6e7a + jp $759d +; 0x96e79 + +INCBIN "baserom.gbc",$96e79,$96e81 - $96e79 + +Script_3jumptext: ; 0x96e81 +; script command 0x52 +; parameters: +; text_pointer (PointerLabelBeforeBank) + + call GetScriptByte + ld [$d44e], a + call GetScriptByte + ld [$d44f], a + call GetScriptByte + ld [$d450], a + ld b, $25 + ld hl, $6e7a + jp $759d +; 0x96e9b + +Script_2writetext: ; 0x96e9b +; script command 0x4c +; parameters: +; text_pointer (RawTextPointerLabelParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [ScriptBank] + ld b, a + call $269a + ret +; 0x96eab + +Script_3writetext: ; 0x96eab +; script command 0x4b +; parameters: +; text_pointer (PointerLabelBeforeBank) + + call GetScriptByte + ld b, a + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + call $269a + ret +; 0x96ebb + +Script_repeattext: ; 0x96ebb +; script command 0x4d +; parameters: +; byte (SingleByteParam) +; byte (SingleByteParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + cp $ff + jr nz, .asm_96ed8 ; 0x96ec5 $11 + ld a, l + cp $ff + jr nz, .asm_96ed8 ; 0x96eca $c + ld hl, $d44e + ld a, [hli] + ld b, a + ld a, [hli] + ld h, [hl] + ld l, a + call $269a + ret +.asm_96ed8 + ret +; 0x96ed9 + +Script_closetext: ; 0x96ed9 +; script command 0x54 + + jp $0a46 +; 0x96edc + +Script_keeptextopen: ; 0x96edc +; script command 0x55 + + ld a, [$ffd8] + push af + ld a, $1 + ld [$ffd8], a + call $31f6 + call $0aaf + pop af + ld [$ffd8], a + ret +; 0x96eed + +Script_yesorno: ; 0x96eed +; script command 0x4e + + call $1dcf + ld a, $0 + jr c, .asm_96ef6 ; 0x96ef2 $2 + ld a, $1 +.asm_96ef6 + ld [$c2dd], a + ret +; 0x96efa + +Script_loadmenudata: ; 0x96efa +; script command 0x4f +; parameters: +; data (MenuDataPointerParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld de, $1d35 + ld a, [ScriptBank] + call $26b7 + call $1ad2 + ret +; 0x96f0f + +Script_writebackup: ; 0x96f0f +; script command 0x50 + + call $1c17 + call $1ad2 + ret +; 0x96f16 + +Script_pokepic: ; 0x96f16 +; script command 0x56 +; parameters: +; pokemon (PokemonParam) + + call GetScriptByte + and a + jr nz, .asm_96f1f ; 0x96f1a $3 + ld a, [$c2dd] +.asm_96f1f + ld [$d108], a + ld a, $9 + ld hl, $44e3 + rst $8 + ret +; 0x96f29 + +Script_pokepicyesorno: ; 0x96f29 +; script command 0x57 + + ld a, $9 + ld hl, $4528 + rst $8 + ret +; 0x96f30 + +Script_interpretmenu2: ; 0x96f30 +; script command 0x59 + + ld a, [ScriptBank] + ld hl, $1d81 + rst $8 + ld a, [$cfa9] + jr nc, .asm_96f3d ; 0x96f3a $1 + xor a +.asm_96f3d + ld [$c2dd], a + ret +; 0x96f41 + +Script_interpretmenu: ; 0x96f41 +; script command 0x58 + + ld a, [ScriptBank] + ld hl, $202a + rst $8 + ld a, [$cf88] + jr nc, .asm_96f4e ; 0x96f4b $1 + xor a +.asm_96f4e + ld [$c2dd], a + ret +; 0x96f52 + +Script_storetext: ; 0x96f52 +; script command 0xa4 +; parameters: +; pointer (PointerLabelBeforeBank) +; memory (SingleByteParam) + + call $106c + call GetScriptByte + ld c, a + ld a, $47 + ld hl, $4000 + rst $8 + ret +; 0x96f60 + +Script_verbosegiveitem: ; 0x96f60 +; script command 0x9e +; parameters: +; item (ItemLabelByte) +; quantity (DecimalParam) + + call $77ca + call $7051 + ld de, $d073 + ld a, $1 + call $76c8 + ld b, $25 + ld de, $6f77 + jp $74cb +; 0x96f76 + +INCBIN "baserom.gbc",$96f76,$96f8e - $96f76 + +Script_verbosegiveitem2: ; 0x96f8e +; script command 0x9f +; parameters: +; item (ItemLabelByte) +; var (SingleByteParam) + + call GetScriptByte + cp $ff + jr nz, .asm_96f98 ; 0x96f93 $3 + ld a, [$c2dd] +.asm_96f98 + ld [$d106], a + call GetScriptByte + call $769e + ld a, [de] + ld [$d10c], a + ld hl, $d892 + call $2f66 + ld a, $1 + jr c, .asm_96fb0 ; 0x96fad $1 + xor a +.asm_96fb0 + ld [$c2dd], a + call $7051 + ld de, $d073 + ld a, $1 + call $76c8 + ld b, $25 + ld de, $6f77 + jp $74cb +; 0x96fc6 + +Script_itemnotify: ; 0x96fc6 +; script command 0x45 + + call $6ffe + call $7051 + ld b, $25 + ld hl, $705b + call $269a + ret +; 0x96fd5 + +Script_pocketisfull: ; 0x96fd5 +; script command 0x46 + + call $6ffe + call $7051 + ld b, $25 + ld hl, $7060 + call $269a + ret +; 0x96fe4 + +Script_specialsound: ; 0x96fe4 +; script command 0x88 + + ld a, $3 + ld hl, $543d + rst $8 + ld a, [$d142] + cp $4 + ld de, $009b + jr z, .asm_96ff7 ; 0x96ff2 $3 + ld de, $0001 +.asm_96ff7 + call StartSFX + call $3c55 + ret +; 0x96ffe + +INCBIN "baserom.gbc",$96ffe,$97065 - $96ffe + +Script_pokemart: ; 0x97065 +; script command 0x94 +; parameters: +; dialog_id (SingleByteParam) +; mart_id (MultiByteParam) + + call GetScriptByte + ld c, a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [ScriptBank] + ld b, a + ld a, $5 + ld hl, $5a45 + rst $8 + ret +; 0x9707c + +Script_elevator: ; 0x9707c +; script command 0x95 +; parameters: +; floor_list_pointer (PointerLabelParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [ScriptBank] + ld b, a + ld a, $4 + ld hl, $742d + rst $8 + ret c + ld a, $1 + ld [$c2dd], a + ret +; 0x97099 + +Script_trade: ; 0x97099 +; script command 0x96 +; parameters: +; trade_id (SingleByteParam) + + call GetScriptByte + ld e, a + ld a, $3f + ld hl, $4ba8 + rst $8 + ret +; 0x970a4 + +Script_phonecall: ; 0x970a4 +; script command 0x98 +; parameters: +; caller_name (RawTextPointerLabelParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [ScriptBank] + ld b, a + ld a, $24 + ld hl, $429a + rst $8 + ret +; 0x970b7 + +Script_hangup: ; 0x970b7 +; script command 0x99 + + ld a, $24 + ld hl, $42eb + rst $8 + ret +; 0x970be + +Script_askforphonenumber: ; 0x970be +; script command 0x97 +; parameters: +; number (SingleByteParam) + + call $1dcf + jr c, .asm_970d6 ; 0x970c1 $13 + call GetScriptByte + ld c, a + ld a, $24 + ld hl, $4000 + rst $8 + jr c, .asm_970d2 ; 0x970cd $3 + xor a + jr .asm_970db ; 0x970d0 $9 +.asm_970d2 + ld a, $1 + jr .asm_970db ; 0x970d4 $5 +.asm_970d6 + call GetScriptByte + ld a, $2 +.asm_970db + ld [$c2dd], a + ret +; 0x970df + +Script_describedecoration: ; 0x970df +; script command 0x9a +; parameters: +; byte (SingleByteParam) + + call GetScriptByte + ld b, a + ld a, $9 + ld hl, $6f59 + rst $8 + ld h, d + ld l, e + jp $759d +; 0x970ee + +Script_fruittree: ; 0x970ee +; script command 0x9b +; parameters: +; tree_id (SingleByteParam) + + call GetScriptByte + ld [$d03e], a + ld b, $11 + ld hl, $4000 + jp $759d +; 0x970fc + +Script_loadwilddata: ; 0x970fc +; script command 0xa0 +; parameters: +; map_group (MapGroupParam) +; map_id (MapIdParam) + + call GetScriptByte + ld c, a + call GetScriptByte + ld d, a + call GetScriptByte + ld e, a + ld a, $3 + ld hl, $4403 + rst $8 + ret +; 0x9710f + +Script_trainertext: ; 0x9710f +; script command 0x62 +; parameters: +; which_text (SingleByteParam) + + call GetScriptByte + ld c, a + ld b, $0 + ld hl, $d045 + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [$d03e] + ld b, a + call $269a + ret +; 0x97125 + +Script_scripttalkafter: ; 0x97125 +; script command 0x65 + + ld hl, $d04b + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [$d03e] + ld b, a + jp $759d +; 0x97132 + +Script_trainerstatus: ; 0x97132 +; script command 0x63 +; parameters: +; action (SingleByteParam) + + xor a + ld [$c2dd], a + ld hl, $d041 + ld e, [hl] + inc hl + ld d, [hl] + call GetScriptByte + ld b, a + call BitTable1Func + ld a, c + and a + ret z + ld a, $1 + ld [$c2dd], a + ret +; 0x9714c + +Script_winlosstext: ; 0x9714c +; script command 0x64 +; parameters: +; win_text_pointer (TextPointerLabelParam) +; loss_text_pointer (TextPointerLabelParam) + + ld hl, $d047 + call GetScriptByte + ld [hli], a + call GetScriptByte + ld [hli], a + ld hl, $d049 + call GetScriptByte + ld [hli], a + call GetScriptByte + ld [hli], a + ret +; 0x97163 + +Script_talkaftercancel: ; 0x97163 +; script command 0x66 + + ld a, [$d04d] + and a + ret z + jp $7b74 +; 0x9716b + +Script_talkaftercheck: ; 0x9716b +; script command 0x67 + + ld a, $1 + ld [$c2dd], a + ld a, [$d04d] + and a + ret nz + xor a + ld [$c2dd], a + ret +; 0x9717a + +Script_playrammusic: ; 0x9717a +; script command 0x80 + + ld a, [$d22f] + ld e, a + ld a, $3a + ld hl, $500a + rst $8 + ret +; 0x97185 + +Script_playmapmusic: ; 0x97185 +; script command 0x82 + + call $3cdf + ret +; 0x97189 + +Script_playmusic: ; 0x97189 +; script command 0x7f +; parameters: +; music_pointer (MultiByteParam) + + ld de, $0000 + call StartMusic + xor a + ld [$c2a7], a + call MaxVolume + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + call StartMusic + ret +; 0x971a2 + +Script_musicfadeout: ; 0x971a2 +; script command 0x81 +; parameters: +; music (MultiByteParam) +; fadetime (SingleByteParam) + + call GetScriptByte + ld [$c2a9], a + call GetScriptByte + ld [$c2aa], a + call GetScriptByte + and $7f + ld [$c2a7], a + ret +; 0x971b7 + +Script_playsound: ; 0x971b7 +; script command 0x85 +; parameters: +; sound_pointer (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + call StartSFX + ret +; 0x971c3 + +Script_waitbutton: ; 0x971c3 +; script command 0x86 + + call $3c55 + ret +; 0x971c7 + +Script_warpsound: ; 0x971c7 +; script command 0x87 + + ld a, $5 + ld hl, $4a07 + rst $8 + call StartSFX + ret +; 0x971d1 + +Script_cry: ; 0x971d1 +; script command 0x84 +; parameters: +; cry_id (MultiByteParam) + + call GetScriptByte + push af + call GetScriptByte + pop af + and a + jr nz, .asm_971df ; 0x971da $3 + ld a, [$c2dd] +.asm_971df + call $37ce + ret +; 0x971e3 + +Unknown_0x971e3: ; 0x971e3 + and a + ret z + cp $fe + ret z + dec a + ret +; 0x971ea + +Script_setlasttalked: ; 0x971ea +; script command 0x68 +; parameters: +; person (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + ld [$ffe0], a + ret +; 0x971f3 + +Script_applymovement: ; 0x971f3 +; script command 0x69 +; parameters: +; person (SingleByteParam) +; data (MovementPointerLabelParam) + + call GetScriptByte + call Unknown_0x971e3 + ld c, a + push bc + ld a, c + ld a, $1 + ld hl, $585c + rst $8 + pop bc + push bc + call $7221 + pop bc + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [ScriptBank] + ld b, a + call $26c7 + ret c + ld a, $2 + ld [$d437], a + call Unknown_0x96e11 + ret +; 0x97221 + +Unknown_0x97221: ; 0x97221 + ld a, $1 + ld hl, $5897 + rst $8 + ret +; 0x97228 + +Script_applymovement2: ; 0x97228 +; script command 0x6a +; parameters: +; data (MovementPointerLabelParam) + + ld a, [$ffe0] + ld c, a + jp $71fa +; 0x9722e + +Script_faceplayer: ; 0x9722e +; script command 0x6b + + ld a, [$ffe0] + and a + ret z + ld d, $0 + ld a, [$ffe0] + ld e, a + ld a, $2 + ld hl, $4417 + rst $8 + ld a, d + add a + add a + ld e, a + ld a, [$ffe0] + ld d, a + call $728b + ret +; 0x97248 + +Script_faceperson: ; 0x97248 +; script command 0x6c +; parameters: +; person1 (SingleByteParam) +; person2 (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + cp $fe + jr c, .asm_97254 ; 0x97250 $2 + ld a, [$ffe0] +.asm_97254 + ld e, a + call GetScriptByte + call Unknown_0x971e3 + cp $fe + jr nz, .asm_97261 ; 0x9725d $2 + ld a, [$ffe0] +.asm_97261 + ld d, a + push de + ld a, $2 + ld hl, $4417 + rst $8 + pop bc + ret c + ld a, d + add a + add a + ld e, a + ld d, c + call $728b + ret +; 0x97274 + +Script_spriteface: ; 0x97274 +; script command 0x76 +; parameters: +; person (SingleByteParam) +; facing (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + cp $fe + jr nz, .asm_97280 ; 0x9727c $2 + ld a, [$ffe0] +.asm_97280 + ld d, a + call GetScriptByte + add a + add a + ld e, a + call $728b + ret +; 0x9728b + +Unknown_0x9728b: ; 0x9728b + ld a, d + push de + call $18de + jr c, .asm_972b9 ; 0x97290 $27 + ld hl, $0000 + add hl, bc + ld a, [hl] + push bc + call $1836 + pop bc + jr c, .asm_972b9 ; 0x9729c $1b + ld hl, $0004 + add hl, bc + bit 2, [hl] + jr nz, .asm_972b9 ; 0x972a4 $13 + pop de + ld a, e + call $1af8 + ld hl, $d0ed + bit 6, [hl] + jr nz, .asm_972b5 ; 0x972b0 $3 + call $72bc +.asm_972b5 + call $1ad2 + ret +.asm_972b9 + pop de + scf + ret +; 0x972bc + +Unknown_0x972bc: ; 0x972bc + call $217a + ld hl, $c4a0 + ld bc, $0168 +.asm_972c5 + res 7, [hl] + inc hl + dec bc + ld a, b + or c + jr nz, .asm_972c5 ; 0x972cb $f8 + ret +; 0x972ce + +Script_variablesprite: ; 0x972ce +; script command 0x6d +; parameters: +; byte (SingleByteParam) +; sprite (SingleByteParam) + + call GetScriptByte + ld e, a + ld d, $0 + ld hl, $d82e + add hl, de + call GetScriptByte + ld [hl], a + ret +; 0x972dd + +Script_appear: ; 0x972dd +; script command 0x6f +; parameters: +; person (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + call $1956 + ld a, [$ffaf] + ld b, $0 + call $730b + ret +; 0x972ee + +Script_disappear: ; 0x972ee +; script command 0x6e +; parameters: +; person (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + cp $fe + jr nz, .asm_972fa ; 0x972f6 $2 + ld a, [$ffe0] +.asm_972fa + call $199f + ld a, [$ffaf] + ld b, $1 + call $730b + ld a, $1 + ld hl, $5920 + rst $8 + ret +; 0x9730b + +Unknown_0x9730b: ; 0x9730b + push bc + call $18d2 + ld hl, $000c + add hl, bc + pop bc + ld e, [hl] + inc hl + ld d, [hl] + ld a, $ff + cp e + jr nz, .asm_97321 ; 0x9731a $5 + cp d + jr nz, .asm_97321 ; 0x9731d $2 + xor a + ret +.asm_97321 + call BitTable1Func + ret +; 0x97325 + +Script_follow: ; 0x97325 +; script command 0x70 +; parameters: +; person2 (SingleByteParam) +; person1 (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + ld b, a + call GetScriptByte + call Unknown_0x971e3 + ld c, a + ld a, $1 + ld hl, $5803 + rst $8 + ret +; 0x9733a + +Script_stopfollow: ; 0x9733a +; script command 0x71 + + ld a, $1 + ld hl, $581f + rst $8 + ret +; 0x97341 + +Script_moveperson: ; 0x97341 +; script command 0x72 +; parameters: +; person (SingleByteParam) +; x (SingleByteParam) +; y (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + ld b, a + call GetScriptByte + add $4 + ld d, a + call GetScriptByte + add $4 + ld e, a + ld a, $2 + ld hl, $407e + rst $8 + ret +; 0x9735b + +Script_writepersonxy: ; 0x9735b +; script command 0x73 +; parameters: +; person (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + cp $fe + jr nz, .asm_97367 ; 0x97363 $2 + ld a, [$ffe0] +.asm_97367 + ld b, a + ld a, $2 + ld hl, $40a1 + rst $8 + ret +; 0x9736f + +Script_follownotexact: ; 0x9736f +; script command 0x77 +; parameters: +; person2 (SingleByteParam) +; person1 (SingleByteParam) + + call GetScriptByte + call Unknown_0x971e3 + ld b, a + call GetScriptByte + call Unknown_0x971e3 + ld c, a + ld a, $2 + ld hl, $439e + rst $8 + ret +; 0x97384 + +Script_loademote: ; 0x97384 +; script command 0x74 +; parameters: +; bubble (SingleByteParam) + + call GetScriptByte + cp $ff + jr nz, .asm_9738e ; 0x97389 $3 + ld a, [$c2dd] +.asm_9738e + ld c, a + ld a, $5 + ld hl, $442f + rst $8 + ret +; 0x97396 + +Script_showemote: ; 0x97396 +; script command 0x75 +; parameters: +; bubble (SingleByteParam) +; person (SingleByteParam) +; time (DecimalParam) + + call GetScriptByte + ld [$c2dd], a + call GetScriptByte + call Unknown_0x971e3 + cp $fe + jr z, .asm_973a8 ; 0x973a4 $2 + ld [$ffe0], a +.asm_973a8 + call GetScriptByte + ld [$d44d], a + ld b, $25 + ld de, $73b6 + jp $74cb +; 0x973b6 + +INCBIN "baserom.gbc",$973b6,$973c7 - $973b6 + +Script_earthquake: ; 0x973c7 +; script command 0x78 +; parameters: +; param (DecimalParam) + + ld hl, $73eb + ld de, $d002 + ld bc, $0005 + call CopyBytes + call GetScriptByte + ld [$d003], a + and $3f + ld [$d005], a + ld b, $25 + ld de, $73e6 + jp $74cb +; 0x973e6 + +INCBIN "baserom.gbc",$973e6,$973f0 - $973e6 + +Script_loadpikachudata: ; 0x973f0 +; script command 0x5a + + ld a, $19 + ld [$d22e], a + ld a, $5 + ld [$d143], a + ret +; 0x973fb + +Script_battlecheck: ; 0x973fb +; script command 0x5b + + xor a + ld [$d459], a + ret +; 0x97400 + +Script_loadtrainerdata: ; 0x97400 +; script command 0x5c + + ld a, $81 + ld [$d459], a + ld a, [$d043] + ld [$d22f], a + ld a, [$d044] + ld [$d231], a + ret +; 0x97412 + +Script_loadpokedata: ; 0x97412 +; script command 0x5d +; parameters: +; pokemon (PokemonParam) +; level (DecimalParam) + + ld a, $80 + ld [$d459], a + call GetScriptByte + ld [$d22e], a + call GetScriptByte + ld [$d143], a + ret +; 0x97424 + +Script_loadtrainer: ; 0x97424 +; script command 0x5e +; parameters: +; trainer_group (TrainerGroupParam) +; trainer_id (TrainerIdParam) + + ld a, $81 + ld [$d459], a + call GetScriptByte + ld [$d22f], a + call GetScriptByte + ld [$d231], a + ret +; 0x97436 + +Script_startbattle: ; 0x97436 +; script command 0x5f + + call $2879 + ld a, $16 + call $2d83 + ld a, [$d0ee] + and $3f + ld [$c2dd], a + ret +; 0x97447 + +Script_catchtutorial: ; 0x97447 +; script command 0x61 +; parameters: +; byte (SingleByteParam) + + call GetScriptByte + ld [$d230], a + call $2879 + ld a, $13 + ld hl, $6554 + rst $8 + jp $7491 +; 0x97459 + +Script_returnafterbattle: ; 0x97459 +; script command 0x60 + + ld hl, $d459 + ld d, [hl] + ld [hl], $0 + ld a, [$d0ee] + and $3f + cp $1 + jr nz, .asm_97470 ; 0x97466 $8 + ld b, $4 + ld hl, $64c1 + jp $759d +.asm_97470 + bit 0, d + jr z, .asm_9747c ; 0x97472 $8 + ld a, $3f + ld hl, $4fec + rst $8 + jr .asm_9748e ; 0x9747a $12 +.asm_9747c + ld a, [$d0ee] + bit 7, a + jr z, .asm_9748e ; 0x97481 $b + ld b, $24 + ld de, $4255 + ld a, $25 + ld hl, $7c4f + rst $8 +.asm_9748e + jp $7491 +; 0x97491 + +Script_reloadmap: ; 0x97491 +; script command 0x7b + + xor a + ld [$d459], a + ld a, $f3 + ld [$ff9f], a + ld a, $1 + call $261b + call Unknown_0x96e11 + ret +; 0x974a2 + +Script_2call: ; 0x974a2 +; script command 0x0 +; parameters: +; pointer (ScriptPointerLabelParam) + + ld a, [ScriptBank] + ld b, a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + jr ScriptCall +; 0x974b0 + +Script_3call: ; 0x974b0 +; script command 0x1 +; parameters: +; pointer (ScriptPointerLabelBeforeBank) + + call GetScriptByte + ld b, a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + jr ScriptCall +; 0x974be + +Script_2ptcall: ; 0x974be +; script command 0x2 +; parameters: +; pointer (PointerLabelToScriptPointer) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld b, [hl] + inc hl + ld e, [hl] + inc hl + ld d, [hl] + ; fallthrough + +ScriptCall: ; 0x974cb + push de + ld hl, $d43c + ld e, [hl] + inc [hl] + ld d, $0 + ld hl, $d43d + add hl, de + add hl, de + add hl, de + pop de + ld a, [ScriptBank] + ld [hli], a + ld a, [ScriptPos] + ld [hli], a + ld a, [$d43b] + ld [hl], a + ld a, b + ld [ScriptBank], a + ld a, e + ld [ScriptPos], a + ld a, d + ld [$d43b], a + ret +; 0x974f3 + +Unknown_0x974f3: ; 0x974f3 + ld a, [ScriptBank] + or $80 + ld [ScriptBank], a + jp $74cb +; 0x974fe + +Script_2jump: ; 0x974fe +; script command 0x3 +; parameters: +; pointer (ScriptPointerLabelParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [ScriptBank] + ld b, a + jp $759d +; 0x9750d + +Script_3jump: ; 0x9750d +; script command 0x4 +; parameters: +; pointer (ScriptPointerLabelBeforeBank) + + call GetScriptByte + ld b, a + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + jp $759d +; 0x9751c + +Script_2ptjump: ; 0x9751c +; script command 0x5 +; parameters: +; pointer (PointerLabelToScriptPointer) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld b, [hl] + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + jp $759d +; 0x9752c + +Script_iffalse: ; 0x9752c +; script command 0x8 +; parameters: +; pointer (ScriptPointerLabelParam) + + ld a, [$c2dd] + and a + jp nz, $7596 + jp Script_2jump +; 0x97536 + +Script_iftrue: ; 0x97536 +; script command 0x9 +; parameters: +; pointer (ScriptPointerLabelParam) + + ld a, [$c2dd] + and a + jp nz, Script_2jump + jp $7596 +; 0x97540 + +Script_if_equal: ; 0x97540 +; script command 0x6 +; parameters: +; byte (SingleByteParam) +; pointer (ScriptPointerLabelParam) + + call GetScriptByte + ld hl, $c2dd + cp [hl] + jr z, Script_2jump ; 0x97547 $b5 + jr Unknown_97596 ; 0x97549 $4b +; 0x9754b + +Script_if_not_equal: ; 0x9754b +; script command 0x7 +; parameters: +; byte (SingleByteParam) +; pointer (ScriptPointerLabelParam) + + call GetScriptByte + ld hl, $c2dd + cp [hl] + jr nz, Script_2jump ; 0x97552 $aa + jr Unknown_97596 ; 0x97554 $40 +; 0x97556 + +Script_if_less_than: ; 0x97556 +; script command 0xa +; parameters: +; byte (SingleByteParam) +; pointer (ScriptPointerLabelParam) + + ld a, [$c2dd] + ld b, a + call GetScriptByte + cp b + jr c, Script_2jump ; 0x9755e $9e + jr Unknown_97596 ; 0x97560 $34 +; 0x97562 + +Script_if_greater_than: ; 0x97562 +; script command 0xb +; parameters: +; byte (SingleByteParam) +; pointer (ScriptPointerLabelParam) + + call GetScriptByte + ld b, a + ld a, [$c2dd] + cp b + jr c, Script_2jump ; 0x9756a $92 + jr Unknown_97596 ; 0x9756c $28 +; 0x9756e + +Script_jumpstd: ; 0x9756e +; script command 0xc +; parameters: +; predefined_script (MultiByteParam) + + call $757b + jr Unknown_9759d ; 0x97571 $2a +; 0x97573 + +Script_callstd: ; 0x97573 +; script command 0xd +; parameters: +; predefined_script (MultiByteParam) + + call $757b + ld d, h + ld e, l + jp $74cb +; 0x9757b + +Unknown_0x9757b: ; 0x9757b + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld hl, $4000 + add hl, de + add hl, de + add hl, de + ld a, $2f + call GetFarByte + ld b, a + inc hl + ld a, $2f + call GetFarHalfword + ret +; 0x97596 + +Unknown_97596: ; 0x97596 + call GetScriptByte + call GetScriptByte + ret +; 0x9759d + +Unknown_9759d: ; 0x9759d + ld a, b + ld [ScriptBank], a + ld a, l + ld [ScriptPos], a + ld a, h + ld [$d43b], a + ret +; 0x975aa + +Script_priorityjump: ; 0x975aa +; script command 0x8d +; parameters: +; pointer (ScriptPointerLabelParam) + + ld a, [ScriptBank] + ld [$d44e], a + call GetScriptByte + ld [$d44f], a + call GetScriptByte + ld [$d450], a + ld hl, $d434 + set 3, [hl] + ret +; 0x975c2 + +Script_checktriggers: ; 0x975c2 +; script command 0x13 + + call $211b + jr z, .asm_975cb ; 0x975c5 $4 + ld [$c2dd], a + ret +.asm_975cb + ld a, $ff + ld [$c2dd], a + ret +; 0x975d1 + +Script_checkmaptriggers: ; 0x975d1 +; script command 0x11 +; parameters: +; map_group (SingleByteParam) +; map_id (SingleByteParam) + + call GetScriptByte + ld b, a + call GetScriptByte + ld c, a + call $2147 + ld a, d + or e + jr z, .asm_975e5 ; 0x975de $5 + ld a, [de] + ld [$c2dd], a + ret +.asm_975e5 + ld a, $ff + ld [$c2dd], a + ret +; 0x975eb + +Script_dotrigger: ; 0x975eb +; script command 0x14 +; parameters: +; trigger_id (SingleByteParam) + + ld a, [$dcb5] + ld b, a + ld a, [$dcb6] + ld c, a + jr Unknown_975fd ; 0x975f3 $8 +; 0x975f5 + +Script_domaptrigger: ; 0x975f5 +; script command 0x12 +; parameters: +; map_group (MapGroupParam) +; map_id (MapIdParam) +; trigger_id (SingleByteParam) + + call GetScriptByte + ld b, a + call GetScriptByte + ld c, a + ; fallthrough + +Unknown_975fd: ; 0x975fd + call $2147 + ld a, d + or e + jr z, .asm_97608 ; 0x97602 $4 + call GetScriptByte + ld [de], a +.asm_97608 + ret +; 0x97609 + +Script_copybytetovar: ; 0x97609 +; script command 0x19 +; parameters: +; address (RAMAddressParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [hl] + ld [$c2dd], a + ret +; 0x97616 + +Script_copyvartobyte: ; 0x97616 +; script command 0x1a +; parameters: +; address (RAMAddressParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [$c2dd] + ld [hl], a + ret +; 0x97623 + +Script_loadvar: ; 0x97623 +; script command 0x1b +; parameters: +; address (RAMAddressParam) +; value (SingleByteParam) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + call GetScriptByte + ld [hl], a + ret +; 0x97630 + +Script_writebyte: ; 0x97630 +; script command 0x15 +; parameters: +; value (SingleByteParam) + + call GetScriptByte + ld [$c2dd], a + ret +; 0x97637 + +Script_addvar: ; 0x97637 +; script command 0x16 +; parameters: +; value (SingleByteParam) + + call GetScriptByte + ld hl, $c2dd + add [hl] + ld [hl], a + ret +; 0x97640 + +Script_random: ; 0x97640 +; script command 0x17 +; parameters: +; input (SingleByteParam) + + call GetScriptByte + ld [$c2dd], a + and a + ret z + ld c, a + call $7673 + and a + jr z, .asm_9765f ; 0x9764d $10 + ld b, a + xor a + sub b + ld b, a +.asm_97653 + push bc + call $2f8c + pop bc + ld a, [$ffe1] + cp b + jr nc, .asm_97653 ; 0x9765b $f6 + jr .asm_97666 ; 0x9765d $7 +.asm_9765f + push bc + call $2f8c + pop bc + ld a, [$ffe1] +.asm_97666 + push af + ld a, [$c2dd] + ld c, a + pop af + call $3110 + ld [$c2dd], a + ret +; 0x97673 + +Unknown_0x97673: ; 0x97673 + xor a + ld b, a + sub c +.asm_97676 + inc b + sub c + jr nc, .asm_97676 ; 0x97678 $fc + dec b + add c + ret +; 0x9767d + +Script_checkcode: ; 0x9767d +; script command 0x1c +; parameters: +; variable_id (SingleByteParam) + + call GetScriptByte + call $769e + ld a, [de] + ld [$c2dd], a + ret +; 0x97688 + +Script_writevarcode: ; 0x97688 +; script command 0x1d +; parameters: +; variable_id (SingleByteParam) + + call GetScriptByte + call $769e + ld a, [$c2dd] + ld [de], a + ret +; 0x97693 + +Script_writecode: ; 0x97693 +; script command 0x1e +; parameters: +; variable_id (SingleByteParam) +; value (SingleByteParam) + + call GetScriptByte + call $769e + call GetScriptByte + ld [de], a + ret +; 0x9769e + +Unknown_0x9769e: ; 0x9769e + ld c, a + ld a, $20 + ld hl, $4648 + rst $8 + ret +; 0x976a6 + +Script_checkver: ; 0x976a6 +; script command 0x18 + + ld a, [$76ad] + ld [$c2dd], a + ret +; 0x976ad + +INCBIN "baserom.gbc",$976ad,$976ae - $976ad + +Script_pokenamemem: ; 0x976ae +; script command 0x40 +; parameters: +; pokemon (PokemonParam) +; memory (SingleByteParam) + + call GetScriptByte + and a + jr nz, .asm_976b7 ; 0x976b2 $3 + ld a, [$c2dd] +.asm_976b7 + ld [$d265], a + call $343b + ld de, $d073 + +Unknown_976c0: ; 0x976c0 + call GetScriptByte + cp $3 + jr c, .asm_976c8 ; 0x976c5 $1 + xor a +.asm_976c8 + ld hl, $d099 + ld bc, $0013 + call AddNTimes + call CopyName2 + ret +; 0x976d5 + +Script_itemtotext: ; 0x976d5 +; script command 0x41 +; parameters: +; item (ItemLabelByte) +; memory (SingleByteParam) + + call GetScriptByte + and a + jr nz, .asm_976de ; 0x976d9 $3 + ld a, [$c2dd] +.asm_976de + ld [$d265], a + call GetItemName + ld de, $d073 + jr Unknown_976c0 ; 0x976e7 $d7 +; 0x976e9 + +Script_mapnametotext: ; 0x976e9 +; script command 0x42 +; parameters: +; memory (SingleByteParam) + + ld a, [$dcb5] + ld b, a + ld a, [$dcb6] + ld c, a + call GetWorldMapLocation + +Unknown_976f4: ; 0x976f4 + ld e, a + ld a, $72 + ld hl, $68a5 + rst $8 + ld de, $d073 + jp $76c0 +; 0x97701 + +Script_displaylocation: ; 0x97701 +; script command 0xa5 +; parameters: +; id (SingleByteParam) + + call GetScriptByte + jr Unknown_976f4 ; 0x97704 $ee +; 0x97706 + +Script_trainertotext: ; 0x97706 +; script command 0x43 +; parameters: +; trainer_id (TrainerGroupParam) +; trainer_group (TrainerIdParam) +; memory (SingleByteParam) + + call GetScriptByte + ld c, a + call GetScriptByte + ld b, a + ld a, $e + ld hl, $594c + rst $8 + jr Unknown_976c0 ; 0x97714 $aa +; 0x97716 + +Script_unknown0xa7: ; 0x97716 +; script command 0xa7 + + call GetScriptByte + ld [$cf61], a + +Unknown_9771c: ; 0x9771c + call GetScriptByte + ld [$cf60], a + call GetName + ld de, $d073 + jp $76c0 +; 0x9772b + +Script_unknown0xa6: ; 0x9772b +; script command 0xa6 + + ld a, $7 + ld [$cf61], a + jr Unknown_9771c ; 0x97730 $ea +; 0x97732 + +Script_readmoney: ; 0x97732 +; script command 0x3d +; parameters: +; account (SingleByteParam) +; memory (SingleByteParam) + + call $7771 + call $7861 + ld hl, $d073 + ld bc, $4306 + call $3198 + ld de, $d073 + jp $76c0 +; 0x97747 + +Script_readcoins: ; 0x97747 +; script command 0x3e +; parameters: +; memory (SingleByteParam) + + call $7771 + ld hl, $d073 + ld de, $d855 + ld bc, $4206 + call $3198 + ld de, $d073 + jp $76c0 +; 0x9775c + +Script_RAM2MEM: ; 0x9775c +; script command 0x3f +; parameters: +; memory (SingleByteParam) + + call $7771 + ld de, $c2dd + ld hl, $d073 + ld bc, $4103 + call $3198 + ld de, $d073 + jp $76c0 +; 0x97771 + +Unknown_0x97771: ; 0x97771 + ld hl, $d073 + ld bc, $000b + ld a, $50 + call ByteFill + ret +; 0x9777d + +Script_stringtotext: ; 0x9777d +; script command 0x44 +; parameters: +; text_pointer (EncodedTextLabelParam) +; memory (SingleByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [ScriptBank] + ld hl, $30d6 + rst $8 + ld de, $d086 + jp $76c0 +; 0x97792 + +Script_givepokeitem: ; 0x97792 +; script command 0x2f +; parameters: +; pointer (PointerParamToItemAndLetter) + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [ScriptBank] + call GetFarByte + ld b, a + push bc + inc hl + ld bc, $0020 + ld de, $d002 + ld a, [ScriptBank] + call FarCopyBytes + pop bc + ld a, $11 + ld hl, $46cc + rst $8 + ret +; 0x977b7 + +Script_checkpokeitem: ; 0x977b7 +; script command 0x30 +; parameters: +; pointer (PointerParamToItemAndLetter) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [ScriptBank] + ld b, a + ld a, $11 + ld hl, $4654 + rst $8 + ret +; 0x977ca + +Script_giveitem: ; 0x977ca +; script command 0x1f +; parameters: +; item (ItemLabelByte) +; quantity (SingleByteParam) + + call GetScriptByte + cp $ff + jr nz, .asm_977d4 ; 0x977cf $3 + ld a, [$c2dd] +.asm_977d4 + ld [$d106], a + call GetScriptByte + ld [$d10c], a + ld hl, $d892 + call $2f66 + jr nc, .asm_977eb ; 0x977e3 $6 + ld a, $1 + ld [$c2dd], a + ret +.asm_977eb + xor a + ld [$c2dd], a + ret +; 0x977f0 + +Script_takeitem: ; 0x977f0 +; script command 0x20 +; parameters: +; item (ItemLabelByte) +; quantity (DecimalParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld [$d106], a + call GetScriptByte + ld [$d10c], a + ld a, $ff + ld [$d107], a + ld hl, $d892 + call $2f53 + ret nc + ld a, $1 + ld [$c2dd], a + ret +; 0x97812 + +Script_checkitem: ; 0x97812 +; script command 0x21 +; parameters: +; item (ItemLabelByte) + + xor a + ld [$c2dd], a + call GetScriptByte + ld [$d106], a + ld hl, $d892 + call $2f79 + ret nc + ld a, $1 + ld [$c2dd], a + ret +; 0x97829 + +Script_givemoney: ; 0x97829 +; script command 0x22 +; parameters: +; account (SingleByteParam) +; money (MoneyByteParam) + + call $7861 + call $786d + ld a, $5 + ld hl, $5fd7 + rst $8 + ret +; 0x97836 + +Script_takemoney: ; 0x97836 +; script command 0x23 +; parameters: +; account (SingleByteParam) +; money (MoneyByteParam) + + call $7861 + call $786d + ld a, $5 + ld hl, $5ffa + rst $8 + ret +; 0x97843 + +Script_checkmoney: ; 0x97843 +; script command 0x24 +; parameters: +; account (SingleByteParam) +; money (MoneyByteParam) + + call $7861 + call $786d + ld a, $5 + ld hl, $600b + rst $8 +; 0x9784f + +Unknown_9784f: ; 0x9784f + jr c, .asm_9785b ; 0x9784f $a + jr z, .asm_97857 ; 0x97851 $4 + ld a, $0 + jr .asm_9785d ; 0x97855 $6 +.asm_97857 + ld a, $1 + jr .asm_9785d ; 0x97859 $2 +.asm_9785b + ld a, $2 +.asm_9785d + ld [$c2dd], a + ret +; 0x97861 + +Unknown_0x97861: ; 0x97861 + call GetScriptByte + and a + ld de, $d84e + ret z + ld de, $d851 + ret +; 0x9786d + +Unknown_0x9786d: ; 0x9786d + ld bc, $ffc3 + push bc + call GetScriptByte + ld [bc], a + inc bc + call GetScriptByte + ld [bc], a + inc bc + call GetScriptByte + ld [bc], a + pop bc + ret +; 0x97881 + +Script_givecoins: ; 0x97881 +; script command 0x25 +; parameters: +; coins (CoinByteParam) + + call $78a0 + ld a, $5 + ld hl, $606f + rst $8 + ret +; 0x9788b + +Script_takecoins: ; 0x9788b +; script command 0x26 +; parameters: +; coins (CoinByteParam) + + call $78a0 + ld a, $5 + ld hl, $608f + rst $8 + ret +; 0x97895 + +Script_checkcoins: ; 0x97895 +; script command 0x27 +; parameters: +; coins (CoinByteParam) + + call $78a0 + ld a, $5 + ld hl, $60a1 + rst $8 + jr Unknown_9784f ; 0x9789e $af + call GetScriptByte + ld [$ffc4], a + call GetScriptByte + ld [$ffc3], a + ld bc, $ffc3 + ret +; 0x978ae + +Script_checktime: ; 0x978ae +; script command 0x2b +; parameters: +; time (SingleByteParam) + + xor a + ld [$c2dd], a + ld a, $3 + ld hl, $4000 + rst $8 + call GetScriptByte + and c + ret z + ld a, $1 + ld [$c2dd], a + ret +; 0x978c3 + +Script_checkpoke: ; 0x978c3 +; script command 0x2c +; parameters: +; pkmn (PokemonParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld hl, $dcd8 + ld de, $0001 + call IsInArray + ret nc + ld a, $1 + ld [$c2dd], a + ret +; 0x978da + +Script_addcellnum: ; 0x978da +; script command 0x28 +; parameters: +; person (SingleByteParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld c, a + ld a, $24 + ld hl, $4000 + rst $8 + ret nc + ld a, $1 + ld [$c2dd], a + ret +; 0x978ef + +Script_delcellnum: ; 0x978ef +; script command 0x29 +; parameters: +; person (SingleByteParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld c, a + ld a, $24 + ld hl, $400f + rst $8 + ret nc + ld a, $1 + ld [$c2dd], a + ret +; 0x97904 + +Script_checkcellnum: ; 0x97904 +; script command 0x2a +; parameters: +; person (SingleByteParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld c, a + ld a, $24 + ld hl, $4019 + rst $8 + ret nc + ld a, $1 + ld [$c2dd], a + ret +; 0x97919 + +Script_specialphonecall: ; 0x97919 +; script command 0x9c +; parameters: +; call_id (MultiByteParam) + + call GetScriptByte + ld [$dc31], a + call GetScriptByte + ld [$dc32], a + ret +; 0x97926 + +Script_checkphonecall: ; 0x97926 +; script command 0x9d + + ld a, [$dc31] + and a + jr z, .asm_9792e ; 0x9792a $2 + ld a, $1 +.asm_9792e + ld [$c2dd], a + ret +; 0x97932 + +Script_givepoke: ; 0x97932 +; script command 0x2d +; parameters: +; pokemon (PokemonParam) +; level (DecimalParam) +; item (ItemLabelByte) +; trainer (DecimalParam) +; trainer_name_pointer (MultiByteParam) +; pkmn_nickname (MultiByteParam) + + call GetScriptByte + ld [$d108], a + call GetScriptByte + ld [$d143], a + call GetScriptByte + ld [$d106], a + call GetScriptByte + and a + ld b, a + jr z, .asm_9795d ; 0x97949 $12 + ld hl, ScriptPos + ld e, [hl] + inc hl + ld d, [hl] + call GetScriptByte + call GetScriptByte + call GetScriptByte + call GetScriptByte +.asm_9795d + ld a, $3 + ld hl, $6277 + rst $8 + ld a, b + ld [$c2dd], a + ret +; 0x97968 + +Script_giveegg: ; 0x97968 +; script command 0x2e +; parameters: +; pkmn (PokemonParam) +; level (DecimalParam) + + xor a + ld [$c2dd], a + ld [$cf5f], a + call GetScriptByte + ld [$d108], a + call GetScriptByte + ld [$d143], a + ld a, $3 + ld hl, $5f8c + rst $8 + ret nc + ld a, $2 + ld [$c2dd], a + ret +; 0x97988 + +Script_setbit1: ; 0x97988 +; script command 0x33 +; parameters: +; bit_number (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, $1 + call BitTable1Func + ret +; 0x97996 + +Script_clearbit1: ; 0x97996 +; script command 0x32 +; parameters: +; bit_number (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, $0 + call BitTable1Func + ret +; 0x979a4 + +Script_checkbit1: ; 0x979a4 +; script command 0x31 +; parameters: +; bit_number (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, $2 + call BitTable1Func + ld a, c + and a + jr z, .asm_979b7 ; 0x979b3 $2 + ld a, $1 +.asm_979b7 + ld [$c2dd], a + ret +; 0x979bb + +Script_setbit2: ; 0x979bb +; script command 0x36 +; parameters: +; bit_number (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, $1 + call $79ee + ret +; 0x979c9 + +Script_clearbit2: ; 0x979c9 +; script command 0x35 +; parameters: +; bit_number (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, $0 + call $79ee + ret +; 0x979d7 + +Script_checkbit2: ; 0x979d7 +; script command 0x34 +; parameters: +; bit_number (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, $2 + call $79ee + ld a, c + and a + jr z, .asm_979ea ; 0x979e6 $2 + ld a, $1 +.asm_979ea + ld [$c2dd], a + ret +; 0x979ee + +Unknown_0x979ee: ; 0x979ee + ld a, $20 + ld hl, $4430 + rst $8 + ret +; 0x979f5 + +Script_wildon: ; 0x979f5 +; script command 0x38 + + ld hl, $d84c + set 5, [hl] + ret +; 0x979fb + +Script_wildoff: ; 0x979fb +; script command 0x37 + + ld hl, $d84c + res 5, [hl] + ret +; 0x97a01 + +Script_xycompare: ; 0x97a01 +; script command 0x39 +; parameters: +; pointer (MultiByteParam) + + call GetScriptByte + ld [$d453], a + call GetScriptByte + ld [$d454], a + ret +; 0x97a0e + +Script_warpfacing: ; 0x97a0e +; script command 0xa3 +; parameters: +; facing (SingleByteParam) +; map_group (MapGroupParam) +; map_id (MapIdParam) +; x (SingleByteParam) +; y (SingleByteParam) + + call GetScriptByte + and $3 + ld c, a + ld a, [$d45b] + set 5, a + or c + ld [$d45b], a +; 0x97a1d + +Script_warp: ; 0x97a1d +; script command 0x3c +; parameters: +; map_group (MapGroupParam) +; map_id (MapIdParam) +; x (SingleByteParam) +; y (SingleByteParam) + + call GetScriptByte + and a + jr z, .asm_97a4a ; 0x97a21 $27 + ld [$dcb5], a + call GetScriptByte + ld [$dcb6], a + call GetScriptByte + ld [$dcb8], a + call GetScriptByte + ld [$dcb7], a + ld a, $ff + ld [$d001], a + ld a, $f1 + ld [$ff9f], a + ld a, $1 + call $261b + call Unknown_0x96e11 + ret +.asm_97a4a + call GetScriptByte + call GetScriptByte + call GetScriptByte + ld a, $ff + ld [$d001], a + ld a, $fb + ld [$ff9f], a + ld a, $1 + call $261b + call Unknown_0x96e11 + ret +; 0x97a65 + +Script_warpmod: ; 0x97a65 +; script command 0x3a +; parameters: +; warp_id (SingleByteParam) +; map_group (MapGroupParam) +; map_id (MapIdParam) + + call GetScriptByte + ld [$dcac], a + call GetScriptByte + ld [$dcad], a + call GetScriptByte + ld [$dcae], a + ret +; 0x97a78 + +Script_blackoutmod: ; 0x97a78 +; script command 0x3b +; parameters: +; map_group (MapGroupParam) +; map_id (MapIdParam) + + call GetScriptByte + ld [$dcb2], a + call GetScriptByte + ld [$dcb3], a + ret +; 0x97a85 + +Script_reloadmapmusic: ; 0x97a85 +; script command 0x83 + + ld a, $1 + ld [$c2c1], a + ret +; 0x97a8b + +Script_writecmdqueue: ; 0x97a8b +; script command 0x7d +; parameters: +; queue_pointer (MultiByteParam) + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [ScriptBank] + ld b, a + ld a, $25 + ld hl, $7e31 + rst $8 + ret +; 0x97a9e + +Script_delcmdqueue: ; 0x97a9e +; script command 0x7e +; parameters: +; byte (SingleByteParam) + + xor a + ld [$c2dd], a + call GetScriptByte + ld b, a + ld a, $25 + ld hl, $7e5c + rst $8 + ret c + ld a, $1 + ld [$c2dd], a + ret +; 0x97ab3 + +Script_changemap: ; 0x97ab3 +; script command 0x79 +; parameters: +; map_data_pointer (MapDataPointerParam) + + call GetScriptByte + ld [$d1a0], a + call GetScriptByte + ld [$d1a1], a + call GetScriptByte + ld [$d1a2], a + call $24e4 + call $2879 + ret +; 0x97acc + +Script_changeblock: ; 0x97acc +; script command 0x7a +; parameters: +; x (SingleByteParam) +; y (SingleByteParam) +; block (SingleByteParam) + + call GetScriptByte + add $4 + ld d, a + call GetScriptByte + add $4 + ld e, a + call $2a66 + call GetScriptByte + ld [hl], a + call $2879 + ret +; 0x97ae3 + +Script_reloadmappart: ; 0x97ae3 +; script command 0x7c + + xor a + ld [$ffd4], a + call $2173 + call $2914 + ld a, $41 + ld hl, $4061 + rst $8 + call $1ad2 + ret +; 0x97af6 + +Script_warpcheck: ; 0x97af6 +; script command 0x8e + + call $224a + ret nc + ld a, $25 + ld hl, $66d0 + rst $8 + ret +; 0x97b01 + +Unknown_0x97b01: ; 0x97b01 + ld a, $25 + ld hl, $66d0 + rst $8 + ret +; 0x97b08 + +Script_newloadmap: ; 0x97b08 +; script command 0x8a +; parameters: +; which_method (SingleByteParam) + + call GetScriptByte + ld [$ff9f], a + ld a, $1 + call $261b + call Unknown_0x96e11 + ret +; 0x97b16 + +Script_reloadandreturn: ; 0x97b16 +; script command 0x92 + + call $7b08 + jp $7b74 +; 0x97b1c + +Script_loadfont: ; 0x97b1c +; script command 0x47 + + call $2e08 + ret +; 0x97b20 + +Script_refreshscreen: ; 0x97b20 +; script command 0x48 +; parameters: +; dummy (SingleByteParam) + + call $2dba + call GetScriptByte + ret +; 0x97b27 + +Script_loadbytec1ce: ; 0x97b27 +; script command 0x4a +; parameters: +; byte (SingleByteParam) + + call GetScriptByte + ld [$c2cf], a + ret +; 0x97b2e + +INCBIN "baserom.gbc",$97b2e,$97b2f - $97b2e + +Script_loadmovesprites: ; 0x97b2f +; script command 0x49 + + call $2e20 + call $2dcf + ret +; 0x97b36 + +Script_passtoengine: ; 0x97b36 +; script command 0x89 +; parameters: +; data_pointer (PointerLabelBeforeBank) + + call GetScriptByte + push af + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + pop af + call StartAutoInput + ret +; 0x97b47 + +Script_pause: ; 0x97b47 +; script command 0x8b +; parameters: +; length (DecimalParam) + + call GetScriptByte + and a + jr z, .asm_97b50 ; 0x97b4b $3 + ld [$d44d], a +.asm_97b50 + ld c, $2 + call DelayFrames + ld hl, $d44d + dec [hl] + jr nz, .asm_97b50 ; 0x97b59 $f5 + ret +; 0x97b5c + +Script_deactivatefacing: ; 0x97b5c +; script command 0x8c +; parameters: +; time (SingleByteParam) + + call GetScriptByte + and a + jr z, .asm_97b65 ; 0x97b60 $3 + ld [$d44d], a +.asm_97b65 + ld a, $3 + ld [$d437], a + call Unknown_0x96e11 + ret +; 0x97b6e + +Script_ptpriorityjump: ; 0x97b6e +; script command 0x8f +; parameters: +; pointer (ScriptPointerLabelParam) + + call Unknown_0x96e11 + jp Script_2jump +; 0x97b74 + +Script_end: ; 0x97b74 +; script command 0x91 + + call $7b9a + jr c, .asm_97b7a ; 0x97b77 $1 + ret +.asm_97b7a + xor a + ld [$d438], a + ld a, $0 + ld [$d437], a + ld hl, $d434 + res 0, [hl] + call Unknown_0x96e11 + ret +; 0x97b8c + +Script_return: ; 0x97b8c +; script command 0x90 + + call $7b9a + jr c, .asm_97b91 ; 0x97b8f $0 +.asm_97b91 + ld hl, $d434 + res 0, [hl] + call Unknown_0x96e11 + ret +; 0x97b9a + +Unknown_0x97b9a: ; 0x97b9a + ld hl, $d43c + ld a, [hl] + and a + jr z, .asm_97bbe ; 0x97b9f $1d + dec [hl] + ld e, [hl] + ld d, $0 + ld hl, $d43d + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld b, a + and $7f + ld [ScriptBank], a + ld a, [hli] + ld e, a + ld [ScriptPos], a + ld a, [hl] + ld d, a + ld [$d43b], a + and a + ret +.asm_97bbe + scf + ret +; 0x97bc0 + +Script_resetfuncs: ; 0x97bc0 +; script command 0x93 + + xor a + ld [$d43c], a + ld [$d438], a + ld a, $0 + ld [$d437], a + ld hl, $d434 + res 0, [hl] + call Unknown_0x96e11 + ret +; 0x97bd5 + +Script_halloffame: ; 0x97bd5 +; script command 0xa1 + + ld hl, $cfbc + res 0, [hl] + ld a, BANK(HallOfFame1) + ld hl, HallOfFame1 + rst $8 + ld a, BANK(HallOfFame2) + ld hl, HallOfFame2 + rst $8 + ld a, BANK(HallOfFame3) + ld hl, HallOfFame3 + rst $8 + ld hl, $cfbc + set 0, [hl] + jr DisplayCredits +; 0x97bf3 + +Script_credits: ; 0x97bf3 +; script command 0xa2 + + ld a, $21 + ld hl, $6455 + rst $8 + ; fallthrough +DisplayCredits: + call $7bc0 + ld a, $3 + call $261b + call Unknown_0x96e11 + ret +; 0x97c05 + +Script_unknown0xa8: ; 0x97c05 +; script command 0xa8 +; parameters: +; unknown (SingleByteParam) + + push bc + call GetScriptByte +.asm_97c09 + push af + ld c, $6 + call DelayFrames + pop af + dec a + jr nz, .asm_97c09 ; 0x97c11 $f6 + pop bc + ret +; 0x97c15 + +Script_unknown0xa9: ; 0x97c15 +; script command 0xa9 + + ld a, $13 + ld hl, $4ffe + rst $8 + ld a, c + ld [$c2dd], a + ret +; 0x97c20 diff --git a/vblank.asm b/vblank.asm index 78d7151f0..8201c1e5c 100644 --- a/vblank.asm +++ b/vblank.asm @@ -69,13 +69,13 @@ VBlank0: ; 2b1 inc [hl] ; advance rng - ld a, [$ff04] ; divider + ld a, [rDIV] ld b, a ld a, [$ffe1] adc b ld [$ffe1], a - ld a, [$ff04] ; divider + ld a, [rDIV] ld b, a ld a, [$ffe2] sbc b @@ -87,16 +87,16 @@ VBlank0: ; 2b1 ; scroll x ld a, [$ffcf] - ld [$ff43], a ; scx + ld [rSCX], a ; scroll y ld a, [$ffd0] - ld [$ff42], a ; scy + ld [rSCY], a ; window y ld a, [$ffd2] - ld [$ff4a], a ; wy + ld [rWY], a ; window x + 7 ld a, [$ffd1] - ld [$ff4b], a ; wx + ld [rWX], a ; some time management is in order ; only have time for one of these during vblank @@ -131,7 +131,7 @@ VBlank0: ; 2b1 call $ff80 ; 403f: ; ld a, $c4 -; ld [$ff46], a ; oam dma +; ld [rDMA], a ; ld a, $28 ; .loop ; dec a @@ -216,11 +216,11 @@ VBlank1: ; 337 ; scroll x ld a, [$ffcf] - ld [$ff43], a ; scx + ld [rSCX], a ; scroll y ld a, [$ffd0] - ld [$ff42], a ; scy + ld [rSCY], a ; time-sensitive fns call UpdatePals @@ -233,7 +233,7 @@ VBlank1: ; 337 call $ff80 ; 403f: ; ld a, $c4 -; ld [$ff46], a ; oam dma +; ld [rDMA], a ; ld a, $28 ; .loop ; dec a @@ -246,20 +246,20 @@ VBlank1: ; 337 ld [VBlankOccurred], a ; get requested ints - ld a, [$ff0f] ; IF + ld a, [rIF] ld b, a ; discard requested ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; enable lcd stat ld a, %10 ; lcd stat - ld [$ffff], a ; IE + ld [rIE], a ; rerequest serial int if applicable (still disabled) ; request lcd stat ld a, b and %1000 ; serial or %10 ; lcd stat - ld [$ff0f], a ; IF + ld [rIF], a ei ; update sound @@ -272,17 +272,17 @@ VBlank1: ; 337 di ; get requested ints - ld a, [$ff0f] ; IF + ld a, [rIF] ld b, a ; discard requested ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; enable ints besides joypad ld a, %1111 ; serial timer lcdstat vblank - ld [$ffff], a ; IE + ld [rIE], a ; rerequest ints ld a, b - ld [$ff0f], a ; IF + ld [rIF], a ret ; 37f @@ -297,13 +297,13 @@ UpdatePals: ; 37f ; update gb pals ld a, [$cfc7] - ld [$ff47], a ; BGP + ld [rBGP], a ld a, [$cfc8] - ld [$ff48], a ; OBP0 + ld [rOBP0], a ld a, [$cfc9] - ld [$ff49], a ; 0BP1 + ld [rOBP1], a and a ret @@ -324,10 +324,10 @@ VBlank3: ; 396 ; scroll x ld a, [$ffcf] - ld [$ff43], a ; scx + ld [rSCX], a ; scroll y ld a, [$ffd0] - ld [$ff42], a ; scy + ld [rSCY], a ; any pals to update? ld a, [$ffe5] @@ -342,7 +342,7 @@ VBlank3: ; 396 call $ff80 ; 403f: ; ld a, $c4 ; Sprites / $100 -; ld [$ff46], a ; oam dma +; ld [rDMA], a ; ld a, $28 ; .loop ; dec a @@ -355,15 +355,15 @@ VBlank3: ; 396 ld [VBlankOccurred], a ; save int flag - ld a, [$ff0f] ; IF + ld a, [rIF] push af ; reset ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; force lcdstat int during sound update ld a, %10 ; lcd stat - ld [$ffff], a ; IE - ld [$ff0f], a ; IF + ld [rIE], a + ld [rIF], a ei ; update sound @@ -376,7 +376,7 @@ VBlank3: ; 396 di ; request lcdstat - ld a, [$ff0f] ; IF + ld a, [rIF] ld b, a ; and any other ints pop af @@ -384,13 +384,13 @@ VBlank3: ; 396 ld b, a ; reset ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; enable ints besides joypad ld a, %1111 ; serial timer lcdstat vblank - ld [$ffff], a ; IE + ld [rIE], a ; request ints ld a, b - ld [$ff0f], a ; IF + ld [rIF], a ret ; 3df @@ -414,7 +414,7 @@ VBlank4: ; 3df call $ff80 ; 403f: ; ld a, $c4 -; ld [$ff46], a ; oam dma +; ld [rDMA], a ; ld a, $28 ; .loop ; dec a @@ -456,7 +456,7 @@ VBlank5: ; 400 ; scroll x ld a, [$ffcf] - ld [$ff43], a ; scx + ld [rSCX], a ; if we can update pals, skip this part call UpdatePalsIfCGB @@ -475,12 +475,12 @@ VBlank5: ; 400 ; discard requested ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; enable lcd stat ld a, %10 ; lcd stat - ld [$ffff], a ; IE + ld [rIE], a ; request lcd stat - ld [$ff0f], a ; IF + ld [rIF], a ei ; update sound @@ -494,10 +494,10 @@ VBlank5: ; 400 ; discard requested ints xor a - ld [$ff0f], a ; IF + ld [rIF], a ; enable ints besides joypad ld a, %1111 ; serial timer lcdstat vblank - ld [$ffff], a ; IE + ld [rIE], a ret ; 436 diff --git a/wram.asm b/wram.asm index 31b292a3e..a693e28c7 100644 --- a/wram.asm +++ b/wram.asm @@ -168,7 +168,13 @@ Channel1VibratoRate: ; c121 ds 1 ; c126 ds 1 - ds 7 +; c127 + ds 1 +Channel1CryPitch: ; c128 + ds 1 +Channel1CryEcho: ; c129 + ds 1 + ds 4 Channel1NoteLength: ; c12e ; # frames per 16th note ds 1 @@ -278,9 +284,14 @@ MusicFadeIDLo: ; c2a9 ds 1 MusicFadeIDHi: ; c2aa ds 1 - ds 9 + ds 5 +CryPitch: ; c2b0 + ds 1 +CryEcho: ; c2b1 + ds 1 +CryLength: ; c2b2 + ds 2 LastVolume: ; c2b4 -; preserves volume of a song playing so cries can have their own volume ds 1 ds 1 SFXPriority: ; c2b6 @@ -643,8 +654,12 @@ OverworldMapEnd ds 12 SECTION "gfx2",BSS[$cd20] -BGMapBuffer: ; cd20 - ds 40 +BGMapBuffer: +CreditsPos: ; cd20 + ds 2 +CreditsTimer: ; cd22 + ds 1 + ds 37 BGMapPalBuffer: ; cd48 ds 40 @@ -837,11 +852,9 @@ TileSetPalettes: ; d1e6 ds 2 Buffer1: -MagikarpLength: -MagikarpLengthHi: ; d1ea +MagikarpLength: ; d1ea ds 1 -Buffer2: -MagikarpLengthLo: ; d1eb +Buffer2: ; d1eb ds 1 SECTION "prng2",BSS[$d1fa] @@ -1102,6 +1115,12 @@ OTPartyMon5Nickname: ; d416 OTPartyMon6Nickname: ; d421 ds 11 +SECTION "Scripting",BSS[$d439] + +ScriptBank: ; d439 + ds 1 +ScriptPos: ; d43a + ds 2 SECTION "Player",BSS[$d472] PlayerGender: ; d472