mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-09-09 09:51:34 -07:00
This commit is contained in:
commit
aec5a652c8
251
audio/engine.asm
251
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
|
||||
|
220
battle/magikarp_length.asm
Normal file
220
battle/magikarp_length.asm
Normal file
@ -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
|
||||
|
@ -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
|
||||
|
824
credits.asm
Normal file
824
credits.asm
Normal file
@ -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, "@"
|
||||
|
@ -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):
|
||||
|
151
extras/disassemble_map_scripts.py
Normal file
151
extras/disassemble_map_scripts.py
Normal file
@ -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)
|
@ -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)
|
||||
|
||||
|
486
extras/map_names.py
Normal file
486
extras/map_names.py
Normal file
@ -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"},
|
||||
},
|
||||
}
|
@ -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
|
||||
|
841
extras/vba.py
Normal file
841
extras/vba.py
Normal file
@ -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()
|
||||
|
15
extras/vba_config.py
Normal file
15
extras/vba_config.py
Normal file
@ -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")
|
65
gbhw.asm
Normal file
65
gbhw.asm
Normal file
@ -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)
|
||||
|
BIN
gfx/debug/color_test.2bpp
Normal file
BIN
gfx/debug/color_test.2bpp
Normal file
Binary file not shown.
BIN
gfx/evo/bubble.2bpp
Normal file
BIN
gfx/evo/bubble.2bpp
Normal file
Binary file not shown.
BIN
gfx/evo/bubble_large.2bpp
Normal file
BIN
gfx/evo/bubble_large.2bpp
Normal file
Binary file not shown.
BIN
gfx/misc/pack_f.2bpp
Normal file
BIN
gfx/misc/pack_f.2bpp
Normal file
Binary file not shown.
BIN
gfx/misc/unown_font.2bpp
Normal file
BIN
gfx/misc/unown_font.2bpp
Normal file
Binary file not shown.
BIN
gfx/ow/misc.2bpp
Normal file
BIN
gfx/ow/misc.2bpp
Normal file
Binary file not shown.
1
gfx/special/celebi/1.2bpp
Normal file
1
gfx/special/celebi/1.2bpp
Normal file
@ -0,0 +1 @@
|
||||
00.> ااd$6<12>فد<D981><D8AF>&<26><06><02><0E><>_g?83<}__{jn<0C><1C>ِِ<D990>@ـ ظ<>ب<EFBFBD>00
|
BIN
gfx/special/celebi/2.2bpp
Normal file
BIN
gfx/special/celebi/2.2bpp
Normal file
Binary file not shown.
BIN
gfx/special/celebi/3.2bpp
Normal file
BIN
gfx/special/celebi/3.2bpp
Normal file
Binary file not shown.
BIN
gfx/special/celebi/4.2bpp
Normal file
BIN
gfx/special/celebi/4.2bpp
Normal file
Binary file not shown.
BIN
gfx/special/celebi/leaf.2bpp
Normal file
BIN
gfx/special/celebi/leaf.2bpp
Normal file
Binary file not shown.
275
joypad.asm
Normal file
275
joypad.asm
Normal file
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,4 @@
|
||||
INCLUDE "wram.asm"
|
||||
INCLUDE "constants.asm"
|
||||
INCLUDE "gbhw.asm"
|
||||
INCLUDE "main.tx"
|
||||
|
@ -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)
|
||||
|
3127
scripting.asm
Normal file
3127
scripting.asm
Normal file
File diff suppressed because it is too large
Load Diff
78
vblank.asm
78
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
|
||||
|
||||
|
37
wram.asm
37
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
|
||||
|
Loading…
Reference in New Issue
Block a user