ANESE/roms/tests/ppu/full_palette/full_palette_smooth.s
Daniel Prilik 5c19d78761 more tests
2017-12-12 16:56:26 -08:00

1 line
No EOL
3.1 KiB
ArmAsm
Vendored

; Displays entire 400+ color NTSC NES palette on screen.
; Disables PPU rendering so that current scanline color can be
; set directly by VRAM address, then uses cycle-timed code to
; cycle through all colors in a clean grid.
;
; ca65 -o full_palette_smooth.o full_palette_smooth.s
; ld65 -t nes full_palette_smooth.o -o full_palette_smooth.nes
;
; Shay Green <gblargg@gmail.com>
.segment "HEADER"
.byte "NES",26, 2,1, 0,0
.segment "VECTORS"
.word 0,0,0, nmi, reset, irq
.segment "CHARS"
.res 8192
.segment "STARTUP" ; avoids warning
.segment "CODE"
even_frame = $200
irq:
nmi: rti
wait_vbl:
bit $2002
: bit $2002
bpl :-
rts
blacken_palette:
; Fill palette with black. Starts at $3FE0 so that VRAM
; address will wrap around to 0 afterwards, so that BG
; rendering will work correctly.
lda #$3F
sta $2006
lda #$E0
sta $2006
lda #$0F
ldy #$20
: sta $2007
dey
bne :-
rts
reset:
sei
ldx #$FF
txs
; Init PPU
jsr wait_vbl
jsr wait_vbl
lda #0
sta $2000
sta $2001
jsr blacken_palette
; Clear nametable
lda #$20
sta $2006
lda #$00
sta $2006
ldx #4
ldy #0
: sta $2007
iny
bne :-
dex
bne :-
; Synchronize precisely to VBL. VBL occurs every 29780.67
; CPU clocks. Loop takes 27 clocks. Every 1103 iterations,
; the second LDA $2002 will read exactly 29781 clocks
; after a previous read. Thus, the loop will effectively
; read $2002 one PPU clock later each frame. It starts out
; with VBL beginning sometime after this read, so that
; eventually VBL will begin just before the $2002 read,
; and thus leave CPU exactly synchronized to VBL.
jsr wait_vbl
nop
: nop
lda $2002
lda $2002
pha
pla
pha
pla
bpl :-
lda #0
sta even_frame
begin_frame:
jsr blacken_palette
; Enable BG so that PPU will make every other frame
; shorter by one PPU clock. This allows our code to
; synchronize better and reduce horizontal shaking.
lda #$08
sta $2001
; Delay 4739 cycles, well into frame
ldx #4
ldy #176
: dey
bne :-
dex
bne :-
nop
; Disable BG. Now electron beam color can be set by
; VRAM address pointing into palette.
lda #0
sta $2001
; Draw palette
ldy #$C0 ; Y = color
triplet:
; Draws one scanline of palette. Takes 98 cycles.
.macro draw_row
tya
and #$30
ldx #$3F
stx $2006
stx $2006
tax
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
inx
stx $2007
.endmacro
nop
nop
nop
nop
draw_row
; Palette writes are delayed a line, since VRAM address
; increments just after $2007 write. So we don't set
; color tint until after first row of triplet
tya
lsr a
and #$07
tax
lda tints,x
sta $2001
draw_row
pha
pla
pha
pla
nop
draw_row
iny
beq :+ ; loop is more than 128 bytes, argh
jmp triplet
:
nop
; Delay 2869 cycles
ldy #239
: pha
pla
dey
bne :-
; Delay extra cycle every other frame
inc even_frame
lda even_frame
lsr a
bcs :+
: jmp begin_frame
; Reorder color tints to be most gradual
tints: .byte $E0,$C0,$A0,$60,$20,$40,$80,$00