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	bit PPUSTATUS
178	setb PPUADDR,0
179	setb PPUADDR,0
180
181	; Copy ascii_chr to 0
182	setb addr,<ascii_chr
183	ldx #>ascii_chr
184	ldy #0
185@page:
186	stx addr+1
187:       lda (addr),y
188	sta PPUDATA
189	iny
190	bne :-
191	inx
192	cpx #>ascii_chr_end
193	bne @page
194
195	; Fill rest
196	lda #$FF
197:       sta PPUDATA
198	iny
199	bne :-
200	inx
201	cpx #$20
202	bne :-
203.endmacro
204