1; PPU utilities
2
3bss_res ppu_not_present
4
5; Sets PPUADDR to w
6; Preserved: X, Y
7.macro set_ppuaddr w
8	bit PPUSTATUS
9	setb PPUADDR,>w
10	setb PPUADDR,<w
11.endmacro
12
13
14; Delays by no more than n scanlines
15.macro delay_scanlines n
16	.if CLOCK_RATE <> 1789773
17		.error "Currently only supports NTSC"
18	.endif
19	delay ((n)*341)/3
20.endmacro
21
22
23; Waits for VBL then disables PPU rendering.
24; Preserved: A, X, Y
25disable_rendering:
26	pha
27	jsr wait_vbl_optional
28	setb PPUMASK,0
29	pla
30	rts
31
32
33; Fills first nametable with $00
34; Preserved: Y
35clear_nametable:
36	ldx #$20
37	bne clear_nametable_
38
39clear_nametable2:
40	ldx #$24
41clear_nametable_:
42	lda #0
43	jsr fill_screen_
44
45	; Clear pattern table
46	ldx #64
47:   sta PPUDATA
48	dex
49	bne :-
50	rts
51
52
53; Fills screen with tile A
54; Preserved: A, Y
55fill_screen:
56	ldx #$20
57	bne fill_screen_
58
59; Same as fill_screen, but fills other nametable
60fill_screen2:
61	ldx #$24
62fill_screen_:
63	stx PPUADDR
64	ldx #$00
65	stx PPUADDR
66	ldx #240
67:   sta PPUDATA
68	sta PPUDATA
69	sta PPUDATA
70	sta PPUDATA
71	dex
72	bne :-
73	rts
74
75
76; Fills palette with $0F
77; Preserved: Y
78clear_palette:
79	set_ppuaddr $3F00
80	ldx #$20
81	lda #$0F
82:   sta PPUDATA
83	dex
84	bne :-
85
86
87; Fills OAM with $FF
88; Preserved: Y
89clear_oam:
90	lda #$FF
91
92; Fills OAM with A
93; Preserved: A, Y
94fill_oam:
95	ldx #0
96	stx SPRADDR
97:   sta SPRDATA
98	dex
99	bne :-
100	rts
101
102
103; Initializes wait_vbl_optional. Must be called before
104; using it.
105.align 32
106init_wait_vbl:
107	; Wait for VBL flag to be set, or ~60000
108	; clocks (2 frames) to pass
109	ldy #24
110	ldx #1
111	bit PPUSTATUS
112:   bit PPUSTATUS
113	bmi @set
114	dex
115	bne :-
116	dey
117	bpl :-
118@set:
119	; Be sure flag didn't stay set (in case
120	; PPUSTATUS always has high bit set)
121	tya
122	ora PPUSTATUS
123	sta ppu_not_present
124	rts
125
126
127; Same as wait_vbl, but returns immediately if PPU
128; isn't working or doesn't support VBL flag
129; Preserved: A, X, Y
130.align 16
131wait_vbl_optional:
132	bit ppu_not_present
133	bmi :++
134	; FALL THROUGH
135
136; Clears VBL flag then waits for it to be set.
137; Preserved: A, X, Y
138wait_vbl:
139	bit PPUSTATUS
140:   bit PPUSTATUS
141	bpl :-
142:   rts
143
144
145.macro check_ppu_region_ Len
146				; Delays since VBL began
147	jsr wait_vbl_optional   ; 10 average
148	delay Len - 18 - 200
149	lda PPUSTATUS       ; 4
150	bmi @ok         ; 2
151	delay 200
152	; Next VBL should roughly begin here if it's the
153	; one we are detecting
154	delay 200
155	lda PPUSTATUS       ; 2
156	bpl @ok
157.endmacro
158
159check_ppu_region:
160
161.ifndef REGION_FREE
162.ifdef PAL_ONLY
163	check_ppu_region_ 29781
164	print_str {newline,"Note: This test is meant for PAL NES only.",newline,newline}
165.endif
166
167.ifdef NTSC_ONLY
168	check_ppu_region_ 33248
169	print_str {newline,"Note: This test is meant for NTSC NES only.",newline,newline}
170.endif
171.endif
172@ok:    rts
173
174
175; Loads ASCII font into CHR RAM and fills rest with $FF
176.macro load_chr_ram
177	jsr wait_vbl_optional
178	mov PPUCTRL,#0
179	mov PPUMASK,#0
180	mov PPUADDR,#0
181	mov PPUADDR,#0
182
183	; Copy ascii_chr to 0
184	setb addr,<ascii_chr
185	ldx #>ascii_chr
186	ldy #0
187@page:
188	stx addr+1
189:   lda (addr),y
190	sta PPUDATA
191	iny
192	bne :-
193	inx
194	cpx #>ascii_chr_end
195	bne @page
196
197	; Fill rest
198	lda #$FF
199:   sta PPUDATA
200	iny
201	bne :-
202	inx
203	cpx #$20
204	bne :-
205.endmacro
206