FC/NES PPU 示例汇编程序 简易画图
程序:简易画图
编写:女孩不哭, 6502汇编, 6502通用汇编器1.2.6
使用方法:
上下左右:移动画笔坐标
选择 :切换命名表#0,#3(因为是水平镜像)
开始 :清空当前命名表
BB :加速移动
AA :画图, 像素切换
源代码:
; start:$BFF0
; end: $FFFF
; size: $4010
.start reset
.org $BFF0 ; 文件头
.db "NES",$1A,$01,$01,$00,$00
.dw $00,$00,$00,$00
JOY_NOW = $00
JOY_LAST = $01
BTN_TIME = $04
NT_NOW = $05 ; Cur NT: 0:$2000,1:$2800
PPU_ADDR_LOW = $02
PPU_ADDR_HI = $03
.org $C000
pal_data: ; 调色板数据
.db $0F,$03,$11,$1A
.db $0F,$1A,$11,$03
reset:
sei
cld
ldx $ff ; 初始化堆栈SP
txs
_main_vb1: ; PPU预热2次
lda $2002
bpl _main_vb1
_main_vb2:
lda $2002
bpl _main_vb2
inx ; 关nmi, 关屏幕
stx $2000
stx $2001
stx JOY_NOW ; 内存初始化
stx JOY_LAST
stx PPU_ADDR_LOW
stx PPU_ADDR_HI
stx BTN_TIME
stx NT_NOW
jsr set_pal ; 设置调色板
jsr clr_spr ; 清空精灵
jsr clr_nt ; 清空命名表
lda #$07 ; 初始化精灵
sta $0200+0
lda #$01
sta $0200+1
lda #$00 ; 卷轴归位
sta $2005
sta $2005
lda #$1e ; 开屏幕
sta $2001
lda #$80 ; 开nmi中断
sta $2000
main:
jmp main ; reset中断无限循环
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
nmi:
lda #$00
sta $2001
jsr read_joy
jsr check_btn
jsr move_spr
jsr draw_item
lda #$02 ; DMA方式更新精灵
sta $4014
lda #$1e
sta $2001
rti
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
check_btn:
lda JOY_NOW
cmp #$10
beq _cb_st1
cmp #$20
beq _cb_n1
rts
_cb_st1:
cmp JOY_LAST
bne _cb_st2
rts
_cb_st2:
lda NT_NOW
cmp #$00 ; NT:$2000
bne _cb_nt1
lda #$20
jsr _sub_clr_nt
rts
_cb_nt1:
lda #$28
jsr _sub_clr_nt
rts
_cb_n1:
cmp JOY_LAST
bne _cb_n2
rts
_cb_n2:
lda NT_NOW
cmp #$00
bne _cb_nodraw
; 没有画
lda #$01 ; 已经画了
sta NT_NOW
lda #$82
sta $2000
rts
_cb_nodraw:
; 已经画
lda #$00 ; 没有画
sta NT_NOW
lda #$80
sta $2000
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
draw_item:
lda JOY_NOW
and #$80 ; 同时按下了A?
beq _di_rts ; 没有按下
lda JOY_NOW
cmp JOY_LAST
beq _di_rts
lda #$00 ; 初始化
sta PPU_ADDR_LOW
lda NT_NOW
cmp #$01 ; NT:$2800
bne _di_nt1
lda #$28
sta PPU_ADDR_HI
jmp _di_nt2
_di_nt1:
lda #$20
sta PPU_ADDR_HI
_di_nt2:
ldy $0200+0 ; Y坐标
iny ; 因为是Y-1
tya
lsr ; A/=8
lsr
lsr
tax ; 计算乘法, x*$20=>A
lda #$00
_di_loop1:
clc
adc #$20
bcc _di_lab1
inc PPU_ADDR_HI
_di_lab1:
dex
bne _di_loop1
sta PPU_ADDR_LOW
lda $0200+3 ; X坐标
lsr ; X/=8
lsr
lsr
clc
adc PPU_ADDR_LOW ; X偏移
bcc _di_lab2
inc PPU_ADDR_HI
_di_lab2:
sta PPU_ADDR_LOW
_skip:
lda PPU_ADDR_HI
sta $2006
lda PPU_ADDR_LOW
sta $2006
lda $2007
lda $2007
cmp #$00 ; 被画了吗?
beq _di_draw ; 没有
lda PPU_ADDR_HI
sta $2006
lda PPU_ADDR_LOW
sta $2006
lda #$00
sta $2007
jmp _di_rts
_di_draw:
lda PPU_ADDR_HI
sta $2006
lda PPU_ADDR_LOW
sta $2006
lda #$01
sta $2007
_di_rts:
lda #$00
sta $2005
sta $2005
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
move_spr:
lda JOY_NOW
cmp JOY_LAST
bne _ms_n0
ldx BTN_TIME
cpx #$14
bne _ms_n4
_ms_n0:
cmp #$01 ; 右
bne _ms_n1
lda $0200+3
clc
adc #$08
sta $0200+3
rts
_ms_n1:
cmp #$02 ; 左
bne _ms_n2
lda $0200+3
sec
sbc #$08
sta $0200+3
rts
_ms_n2:
cmp #$04 ; 下
bne _ms_n3
lda $0200+0
clc
adc #$08
cmp #$e7
bne _unk_1
lda #$07
_unk_1:
sta $0200+0
rts
_ms_n3:
cmp #$08 ; 上
bne _ms_n4
lda $0200+0
sec
sbc #$08
cmp #$ff
bne _unk_2
lda #$df
_unk_2:
sta $0200+0
rts
_ms_n4:
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
read_joy:
lda JOY_NOW
pha
lda #$01
sta $4016
lsr
sta $4016
ldx #$08
sta JOY_NOW
sta JOY_LAST
joy_loop:
lda $4016
and #$01
sta JOY_LAST
lda JOY_NOW
asl
ora JOY_LAST
sta JOY_NOW
dex
bne joy_loop
pla
cmp JOY_NOW ; 和前一次相比较
bne _rj_n1 ; 不相等清除计数器
cmp #$00
beq _rj_rts
inc BTN_TIME
ldy BTN_TIME
cpy #$15 ; 延迟长度
bne _rj_rts
stx JOY_LAST
_rj_n1:
stx BTN_TIME
_rj_rts:
sta JOY_LAST
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
set_pal:
lda #$3f
sta $2006
lda #$00
sta $2006
ldx #$00
_sp_loop1:
lda pal_data,x
sta $2007
inx
cpx #$04
bne _sp_loop1
lda #$3f
sta $2006
lda #$10
sta $2006
ldx #$00
_sp_loop2:
lda pal_data+4,x
sta $2007
inx
cpx #$04
bne _sp_loop2
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
clr_spr:
lda #$00
tax
_cs_cs: sta $0200,x
inx
bne _cs_cs
lda #$ef
_cs_hide:
sta $0200,x
inx
inx
inx
inx
bne _cs_hide
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
clr_nt:
lda #$20
jsr _sub_clr_nt
lda #$28
_sub_clr_nt:
sta $2006
lda #$00
sta $2006
ldy #$04
ldx #$00
_clr_nt_loop1:
sta $2007
inx
bne _clr_nt_loop1
dey
bne _clr_nt_loop1
lda #$00
sta $2005
sta $2005
rts
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
irq:
rti
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.org $FFFA
.dw nmi,reset,irq
点阵字模数据:
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
$FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00, $00, $00, $00, $00, $00, $00, $00