ref: 274e3b5d2111c91cd309938c77bd5f5a0c1b41e4
parent: 3681b4d555e2cc0b28fd2708142f477ea9766a73
parent: 743b14b77af5ac292a90ba5bc870cb2967b5aa81
author: YamaArashi <shadow962@live.com>
date: Tue Jan 24 15:16:28 EST 2012
Merge hg-commit-id: fb2ef1212629
--- a/common.asm
+++ b/common.asm
@@ -108,8 +108,79 @@
Section "start",HOME[$150]
Start: ; 0x150
+ cp $11 ; value that indicates Gameboy Color
+ jr z,.gbcDetected\@
+ xor a
+ jr .storeValue\@
+.gbcDetected\@
+ ld a,$00
+.storeValue\@
+ ld [$cf1a],a ; same value ($00) either way
+ jp InitGame
-INCBIN "baserom.gbc",$150,$1AE - $150
+; this function directly reads the joypad I/O register
+; it reads many times in order to give the joypad a chance to stabilize
+; it saves a result in [$fff8] in the following format
+; (set bit indicates pressed button)
+; bit 0 - A button
+; bit 1 - B button
+; bit 2 - Select button
+; bit 3 - Start button
+; bit 4 - Right
+; bit 5 - Left
+; bit 6 - Up
+; bit 7 - Down
+ReadJoypadRegister: ; 15F
+ ld a,%00100000 ; select direction keys
+ ld c,$00
+ ld [rJOYP],a
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ cpl ; complement the result so that a set bit indicates a pressed key
+ and a,%00001111
+ swap a ; put direction keys in upper nibble
+ ld b,a
+ ld a,%00010000 ; select button keys
+ ld [rJOYP],a
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ ld a,[rJOYP]
+ cpl ; complement the result so that a set bit indicates a pressed key
+ and a,%00001111
+ or b ; put button keys in lower nibble
+ ld [$fff8],a ; save joypad state
+ ld a,%00110000 ; unselect all keys
+ ld [rJOYP],a
+ ret
+
+; function to update the joypad state variables
+; output:
+; [$ffb2] = keys released since last time
+; [$ffb3] = keys pressed since last time
+; [$ffb4] = currently pressed keys
+GetJoypadState: ; 19A
+ ld a, [$ffb8]
+ push af
+ ld a,$3
+ ld [$ffb8],a
+ ld [$2000],a
+ call $4000
+ pop af
+ ld [$ff00+$b8],a
+ ld [$2000],a
+ ret
+
; see also MapHeaderBanks
MapHeaderPointers: ; $01AE
dw PalletTown_h
@@ -419,7 +490,7 @@
ld a,[$d736]
bit 6,a ; jumping down a ledge?
call nz, HandleMidJump
- ld a,[$cfc5] ; walking animation counter
+ ld a,[W_WALKCOUNTER]
and a
jp nz,.moveAhead\@ ; if the player sprite has not yet completed the walking animation
call GetJoypadStateOverworld ; get joypad state (which is possibly simulated)
@@ -622,7 +693,7 @@
jp c,OverworldLoop
.noCollision\@
ld a,$08
- ld [$cfc5],a ; walking animation counter
+ ld [W_WALKCOUNTER],a
jr .moveAhead2\@
.moveAhead\@
ld a,[$d736]
@@ -645,7 +716,7 @@
call BikeSpeedup ; if riding a bike and not jumping a ledge
.normalPlayerSpriteAdvancement\@
call AdvancePlayerSprite
- ld a,[$cfc5] ; walking animation counter
+ ld a,[W_WALKCOUNTER]
and a
jp nz,CheckMapConnections ; it seems like this check will never succeed (the other place where CheckMapConnections is run works)
; walking animation finished
@@ -799,7 +870,7 @@
jr nz,WarpFound1
push de
push bc
- call $019a ; update joypad state
+ call GetJoypadState
pop bc
pop de
ld a,[$ffb4] ; current joypad state
@@ -1823,7 +1894,7 @@
ld b,a
ld a,[$c105] ; delta X
ld c,a
- ld hl,$cfc5 ; walking animation counter
+ ld hl,W_WALKCOUNTER ; walking animation counter
dec [hl]
jr nz,.afterUpdateMapCoords\@
; if it's the end of the animation, update the player's map coordinates
@@ -1834,7 +1905,7 @@
add c
ld [W_XCOORD],a
.afterUpdateMapCoords\@
- ld a,[$cfc5] ; walking animation counter
+ ld a,[W_WALKCOUNTER] ; walking animation counter
cp a,$07
jp nz,.scrollBackgroundAndSprites\@
; if this is the first iteration of the animation
@@ -2205,7 +2276,7 @@
ld [$c103],a
ld [$c105],a
call RunMapScript
- call $019a ; update joypad state
+ call GetJoypadState
ld a,[$d733]
bit 3,a ; check if a trainer wants a challenge
jr nz,.notForcedDownwards\@
@@ -2698,7 +2769,7 @@
ld [$d526],a
ld [$ffaf],a
ld [$ffae],a
- ld [$cfc5],a
+ ld [W_WALKCOUNTER],a
ld [$d119],a
ld [$d11a],a
ld [$d3a8],a
@@ -3456,7 +3527,7 @@
; (no arguments)
TextCommand0A: ; 1C1D
push bc
- call $019a ; update joypad state
+ call GetJoypadState
ld a,[$ffb4]
and a,%00000011 ; A and B buttons
jr nz,.skipDelay\@
@@ -3533,7 +3604,7 @@
ld a,$75 ; ellipsis
ld [hli],a
push de
- call $019a ; update joypad state
+ call GetJoypadState
pop de
ld a,[$ffb4] ; joypad state
and a,%00000011 ; is A or B button pressed?
@@ -3617,8 +3688,129 @@
ld h,a
ret
-INCBIN "baserom.gbc",$1CF0,$20AF - $1CF0
+; clears a VRAM background map with blank space tiles
+; INPUT: h - high byte of background tile map address in VRAM
+ClearBgMap: ; 1CF0
+ ld a,$7f ; blank space
+ jr .next\@
+ ld a,l ; XXX does anything call this?
+.next\@
+ ld de,$400 ; size of VRAM background map
+ ld l,e
+.loop\@
+ ld [hli],a
+ dec e
+ jr nz,.loop\@
+ dec d
+ jr nz,.loop\@
+ ret
+INCBIN "baserom.gbc",$1D01,$1F54 - $1D01
+
+; initialization code
+; explanation for %11100011 (value stored in rLCDC)
+; * LCD enabled
+; * Window tile map at $9C00
+; * Window display enabled
+; * BG and window tile data at $8800
+; * BG tile map at $9800
+; * 8x8 OBJ size
+; * OBJ display enabled
+; * BG display enabled
+InitGame: ; 1F54
+ di
+; zero I/O registers
+ xor a
+ ld [$ff0f],a
+ ld [$ffff],a
+ ld [$ff43],a
+ ld [$ff42],a
+ ld [$ff01],a
+ ld [$ff02],a
+ ld [$ff4b],a
+ ld [$ff4a],a
+ ld [$ff06],a
+ ld [$ff07],a
+ ld [$ff47],a
+ ld [$ff48],a
+ ld [$ff49],a
+ ld a,%10000000 ; enable LCD
+ ld [rLCDC],a
+ call DisableLCD ; why enable then disable?
+ ld sp,$dfff ; initialize stack pointer
+ ld hl,$c000 ; start of WRAM
+ ld bc,$2000 ; size of WRAM
+.zeroWramLoop\@
+ ld [hl],0
+ inc hl
+ dec bc
+ ld a,b
+ or c
+ jr nz,.zeroWramLoop\@
+ call ZeroVram
+ ld hl,$ff80
+ ld bc,$007f
+ call $36e0 ; zero HRAM
+ call CleanLCD_OAM ; this is unnecessary since it was already cleared above
+ ld a,$01
+ ld [$ffb8],a
+ ld [$2000],a
+ call $4bed ; copy DMA code to HRAM
+ xor a
+ ld [$ffd7],a
+ ld [$ff41],a
+ ld [$ffae],a
+ ld [$ffaf],a
+ ld [$ff0f],a
+ ld a,%00001101 ; enable V-blank, timer, and serial interrupts
+ ld [rIE],a
+ ld a,$90 ; put the window off the screen
+ ld [$ffb0],a
+ ld [rWX],a
+ ld a,$07
+ ld [rWY],a
+ ld a,$ff
+ ld [$ffaa],a
+ ld h,$98
+ call ClearBgMap ; fill $9800-$9BFF (BG tile map) with $7F tiles
+ ld h,$9c
+ call ClearBgMap ; fill $9C00-$9FFF (Window tile map) with $7F tiles
+ ld a,%11100011
+ ld [rLCDC],a ; enabled LCD
+ ld a,$10
+ ld [$ff8a],a
+ call $200e
+ ei
+ ld a,$40
+ call Predef ; SGB border
+ ld a,$1f
+ ld [$c0ef],a
+ ld [$c0f0],a
+ ld a,$9c
+ ld [$ffbd],a
+ xor a
+ ld [$ffbc],a
+ dec a
+ ld [$cfcb],a
+ ld a,$32
+ call Predef ; display the copyrights, GameFreak logo, and battle animation
+ call DisableLCD
+ call ZeroVram
+ call $3ddc
+ call CleanLCD_OAM
+ ld a,%11100011
+ ld [rLCDC],a ; enable LCD
+ jp $42b7
+
+; zeroes all VRAM
+ZeroVram: ; 2004
+ ld hl,$8000
+ ld bc,$2000
+ xor a
+ jp $36e0
+
+INCBIN "baserom.gbc",$200E,$20AF - $200E
+
DelayFrame: ; 20AF
; delay for one frame
ld a,1
@@ -4101,7 +4293,7 @@
call $3865 ; wait for a button press after displaying all the text
; loop to hold the dialogue box open as long as the player keeps holding down the A button
.holdBoxOpen\@
- call $019a ; update joypad state
+ call GetJoypadState
ld a,[$ffb4]
bit 0,a ; is the A button being pressed?
jr nz,.holdBoxOpen\@
@@ -5208,7 +5400,7 @@
ld [$FFB3],a
ld [$FFB2],a
ld [$FFB4],a
- call $19A
+ call GetJoypadState
ld a,[$FFB4]
bit 0,a
jr nz,.next5\@
@@ -5226,7 +5418,7 @@
and a
jp z,$5D5F
ld a,[W_CURMAP] ; map ID
- cp a,$76 ; Hall of Fame
+ cp a,HALL_OF_FAME
jp nz,$5D5F
xor a
ld [$D71A],a
--- a/constants.asm
+++ b/constants.asm
@@ -717,10 +717,15 @@
H_WHOSETURN EQU $FFF3 ; 0 on player’s turn, 1 on enemy’s turn
; hardware registers, from the pandocs http://nocash.emubase.de/pandocs.htm
+rJOYP EQU $FF00
rDIV EQU $FF04
+rLCDC EQU $FF40
rBGP EQU $FF47
rOBP0 EQU $FF48
rOBP1 EQU $FF49
+rWX EQU $FF4A
+rWY EQU $FF4B
+rIE EQU $FFFF
; pokemon name constants