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
posted @ 2012-08-13 16:18  女孩不哭  阅读(2853)  评论(0编辑  收藏  举报