- SECTION "a",HOME
+ section "end",HOME[1024]
+ nop
+
+ SECTION "a",HOME[$00]
+
+start: jp main
+
+ section "vbl",HOME[$40]
+ jp vbl
+
+ section "lcdc",HOME[$48]
+ jp lcdc
+
+ section "tmro",HOME[$50]
+ jp tmro
main:
- ld c, $51 ; Note that we are alive.
ld a, $FF
- ld [c],a
-
+ ld c, $51
+ ld [c], a
+
ld sp, $DFF0
+ ld a, $04 ;start timer, 4.096KHz
+ ld c, $07
+ ld [c], a
+
+ ld hl, $DF81
+ xor a
+ ld [hli], a
+ ld [hli], a
+
ld hl, signon
call puts
+ ld a, $91
+ ld [$FF40], a
+
+ call putscreen
+
+ ei
+
call memtest
call insntest
call waitsw
+
+ di
jr main
signon:
db $0D,$0A,$1B,"[1mFPGABoy Diagnostic ROM",$1B,"[0m",$0D,$0A,0
+tiles:
+ db %01111100
+ db %11000110
+ db %11000110
+ db %11111110
+ db %11000110
+ db %11000110
+ db %11000110
+ db %00000000
+
+ db %11111100
+ db %11000110
+ db %11000110
+ db %11111100
+ db %11000110
+ db %11000110
+ db %11111100
+ db %00000000
+
+ db %01111100
+ db %11000110
+ db %11000010
+ db %11000000
+ db %11000010
+ db %11000110
+ db %01111100
+ db %00000000
+
+ db %11111100
+ db %11000110
+ db %11000110
+ db %11000110
+ db %11000110
+ db %11000110
+ db %11111100
+ db %00000000
+
+putscreen:
+ ; Wait for vblank
+ call .vblwait
+
+ ld hl, $8000 ; Copy two tiles.
+ ld de, tiles
+ ld c, $20
+.cloop: ld a, [de]
+ inc de
+ ld [hli], a
+ ld [hli], a
+ dec c
+ xor a
+ cp c
+ jr nz, .cloop
+
+ ld hl, $9800
+.vloop: call .vblwait
+ ld c, $40
+ ld b, 0
+.loop: ld a, b
+ inc b
+ and $03
+ ld [hli], a
+ ld a, h
+ cp $9C
+ ret z
+ dec c
+ xor a
+ cp c
+ jr nz,.loop
+ jr .vloop
+
+.vblwait:
+.stat1: ld a, [$FF41] ; STAT
+ and $03
+ cp $00
+ jp nz, .stat1
+.stat2: ld a, [$FF41]
+ and $03
+ cp $01
+ jr nz, .stat2
+ ret
+
+vbl:
+ PUSH AF
+ PUSH BC
+ PUSH DE
+ PUSH HL
+
+ xor a
+ ld [$FF0F], a
+
+ ld a, [$FF51]
+ bit 7, a
+ jr z, .nothing
+
+ bit 0, a
+ call nz, .scyup
+
+ bit 1, a
+ call nz, .scydown
+
+ bit 2, a
+ call nz, .scxup
+
+ bit 3, a
+ call nz, .scxdown
+
+.nothing:
+ POP HL
+ POP DE
+ POP BC
+ POP AF
+
+ RETI
+
+.scyup: ld hl, $FF42
+ inc [hl]
+ ret
+
+.scydown: ld hl, $FF42
+ dec [hl]
+ ret
+
+.scxup: ld hl, $FF43
+ inc [hl]
+ ret
+
+.scxdown: ld hl, $FF43
+ dec [hl]
+ ret
+
+
+lcdc:
+ PUSH AF
+ PUSH BC
+
+ xor a
+ ld [$FF0F], a
+
+ POP BC
+ POP AF
+
+ reti
+
+tmro:
+ PUSH AF
+ PUSH BC
+ PUSH DE
+ PUSH HL
+
+ xor a
+ ld [$FF0F], a
+
+ ld c, $45 ; LYC
+ ld a, [c]
+ inc a
+ ld [c], a
+
+ ld a, [$DF82]
+ cp 0
+ jr z, .noprint
+ ld a, $41 ; print A
+ call putc
+.noprint:
+ ld a, [$DF81]
+ inc a
+ ld [$DF81], a
+ ld [$FF51], a
+
+ POP HL
+ POP DE
+ POP BC
+ POP AF
+ RETI
+
; Memory tester: writes h ^ l to all addresses from C000 to DF80.
memtest:
ld hl,memteststr
call puts
- ld hl, $C001 ; Write loop
+ ld hl, $C000 ; Write loop
.wr:
ld a,h
xor l
ld [hli],a
- ld a, $DF
- cp h
+ ld a, h
+ cp $DF
jr nz, .wr
- ld a, $80
- cp l
+ ld a, l
+ cp $80
jr nz, .wr
- ld hl, $C001 ; Read loop
+ ld hl, $C000 ; Read loop
.rd:
ld a,h
xor l
cp b
jr nz, .memfail
- ld a, $DF
- cp h
+ ld a, h
+ cp $DF
jr nz, .rd
- ld a, $80
- cp l
+ ld a, l
+ cp $80
jr nz, .rd
ld hl, testokstr ; Say we're OK
ret
.memfail: ; Say we failed (sadface)
; decrement hl the easy way
- ld a,[hld]
+ dec [hl]
push hl
ld hl, failatstr
call puts
rra
rra
rra
- ld b,$0F
- and b
- ld b,$30
- add b
+ and $0F
+ add $30
call putc
pop af
- ld b,$0F
- and b
- ld b,$30
- add b
+ and $0F
+ add $30
call putc
ret
waitsw:
ld hl,waitswstr
call puts
+
+ ld hl,$DF82
+ ld a, 1
+ ld [hl], a
ld c, $51
xor a
ld [c],a
- ld b, $0
.loop1:
ld a,[c]
- cp b
+ cp $0
jr z,.loop1
.loop2:
ld a,[c]
- cp b
+ cp $0
jr nz,.loop2
ret
; Test JR
ld a, $FF
- ld b, $00
- cp b
+ cp $0
jr nz,.jr
ld hl, .jrfail
jr .fail
; Test CP.
ld hl, .cpfail
ld a, $10
- ld b, $20
- cp b
+ cp $20
jr nc,.fail
ld a, $20
- ld b, $10
- cp b
+ cp $10
jr c,.fail
; Test CPL
ld hl, .cplfail
ld a, $55
- ld b, $AA
cpl
- cp b
+ cp $AA
jr nz,.fail
+
+ ; Test DI/EI delay
+ di
+ ld hl, .dinocausefail
+ ld c, $0F ; First, wait until an interrupt happens...
+.wait: ld a, [c]
+ and $04
+ cp 0
+ jr z, .wait
+ ei ; Now make sure that an IRQ didn't happen on EI/DI
+ di
+ ld a, [c]
+ and $04
+ cp 0
+ jr z, .fail
+ ld hl, .dicausefail
+ ei ; Make sure that an IRQ does happen on EI/NOP/DI
+ nop
+ nop
+ di
+ ld a, [c]
+ and $04
+ cp 0
+ jr nz, .fail
+ ei
ld hl, .ok
call puts
ret
.fail:
+ ei
call puts
ld hl, .testfailed
call puts
db "CPL",0
.inc16fail:
db "INC16",0
+.dinocausefail:
+ db "DI/EI does not cause interrupt",0
+.dicausefail:
+ db "DI/NOP/EI cause interrupt",0
.testfailed:
db " test failed.",$0D,$0A,0
.ok:
; Serial port manipulation functions.
putc:
- ld b, 0
ld c, $50
push af
.waitport:
ld a,[c]
- cp b
+ cp $00
jr nz,.waitport
pop af
ld [c],a
puts:
ld a, [hli]
- ld b, $00
- cp b
+ cp $00
ret z
call putc
jr puts
+