65c816 Code Snippets

Hopefully useful code snippets for the 65c816.

Math

符号無し16bit*8bit演算

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 符号無し16bit*8bit演算
; $00,$01に被乗数、$02に乗数をセットして呼び出すと
; $00~$02に結果が返ってきます
; A,Yレジスタを使用
; 42Bytes,96Cycles
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

      LDY $02
      LDA $00
      JSR Multi_8
      STY $02
      PHA
      LDY $01
      JSR Multi_8_0
      STA $00
      TYA
      CLC
      ADC $02
      STA $01
      PLA
      ADC #$00
      STA $02
      RTS

Multi_8:    STA $4202
Multi_8_0:    STY $4203
      ;NOP
      ;NOP
      ;NOP
      ;NOP
      LDA $4216
      LDY $4217
      RTS

符号無し16bit*16bit演算

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 16bit * 16bit演算
; $00,$01に被乗数、$02,$03に乗数をセットして呼び出すと
; $00~$03に結果が返ってきます
; A,Yレジスタを使用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Multi16_16:   LDA $03
      LDY $01
      JSR Multi_0
      PHA
      PHY
      LDA $03
      LDY $00
      JSR Multi_0
      STA $03
      PHY
      LDA $02
      LDY $01
      JSR Multi_0
      STA $01
      LDA $02
      STY $02
      LDY $00
      JSR Multi_0
      STA $00
      TYA
      CLC
      ADC $01
      STA $01
      PLA
      ADC $02
      PLY
      BCC Multi_1
      INY
Multi_1:    STA $02
      LDA $01
      CLC
      ADC $03
      STA $01
      PLA
      ADC $02
      BCC Multi_2
      INY
Multi_2:    STA $02
      STY $03
      RTS

Multi_0:    STA $4202
Multi_3:    STY $4203
      ;NOP
      ;NOP
      ;NOP
      ;NOP
      LDA $4216
      LDY $4217
      RTS

符号無し16bit/16bit演算

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 符号無し16bit/16bit演算
; $00~$01に被除数,$02~$03に除数をセットして呼び出すと
; $06~$07に結果,$00~$01に余りが返ってきます
; ゼロ除算が発生した場合$06~$07,$00~$01の値は$FFFFになります
; A,Yレジスタを使用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MathDiv:  REP #$20
    LDA $00   ; 被除数
    ASL A
    STA $06   ; 結果
    LDY #$0F
    TDC
.Loop   ROL A
    CMP $02
    BCC .Skip
    SBC $02
.Skip   ROL $06
    DEY
    BPL .Loop
    STA $00
    SEP #$20
    RTS

Game Specific

Super Mario World Specific

原点から目標点への角度を求める

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 原点から目標点への角度を求める
; $00,$01に原点のX,$02,$03に原点のY
; $04,$05に目標点X,$06,$07に目標点Yをセットして呼び出すと
; $00,$01に角度θ($0000~$01FF)が返ってきます
; 対応している差の範囲はX,Y共に-$01FE~$01FEです
; アークタンジェントのテーブルが256Bytesあるので
; JSLルーチン化推奨
; A,Yレジスタを使用
; 一時変数 $00~$07を使用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GetAngle:   REP #$20
      LDY #$00
      LDA $02
      SEC
      SBC $06
      BPL If_Plus20
      INY
      EOR.w #$FFFF
      INC A
If_Plus20:    STA $02
      LDA $00
      SEC
      SBC $04
      BPL If_Plus21
      INY
      INY
      EOR.w #$FFFF
      INC A
If_Plus21:    STA $00
      STY $04
      BEQ X_Zero
      CMP.w #$0100
      XBA
      ROR A
      XBA
      TAY
      LDA $02
      BEQ Y_Zero
      CMP.w #$0100
      XBA
      ROR A
      AND.w #$FF80
      STA $4204
      STY $4206
      LDA $4214
      LSR A
      LSR A
      LSR A
      LSR A
      CMP.w #$0100
      SEP #$20
      BCC NoOverFlow
      LDA #$FF
NoOverFlow:   TAY
      LDA AtanTable,y
      LSR $04
      BCS If_Plus30
      EOR #$FF    ;\
      INC A     ; | θ:360°-θ
      BEQ If_Plus30   ; |
      INC $01     ;/
If_Plus30:    LSR $04
      BCS If_Plus31
      EOR #$FF    ;\
      INC A     ; | θ:180°-θ
      BNE If_Plus31   ; |
      INC $01     ;/
If_Plus31:    STA $00
      LDA #$FE
      TRB $01
      RTS

X_Zero:     SEP #$20
      LDY #$00
      LSR $04
      BCS If_Plus32
      INY
If_Plus32:    STY $01
      LDA #$80
      STA $00
      LDY #$FF
      RTS

Y_Zero:     SEP #$20
      STZ $00
      LDY #$00
      LDA $04
      AND #$02
      BNE If_Plus33
      INY
If_Plus33:    STY $01
      LDY #$00
      RTS

AtanTable:
db $00,$05,$0A,$0F,$13,$18,$1D,$21,$25,$29,$2D,$31,$34,$37,$3A,$3D
db $40,$42,$44,$46,$49,$4A,$4C,$4E,$50,$51,$53,$54,$55,$56,$58,$59
db $5A,$5B,$5C,$5D,$5D,$5E,$5F,$60,$60,$61,$62,$62,$63,$64,$64,$65
db $65,$66,$66,$67,$67,$68,$68,$68,$69,$69,$6A,$6A,$6A,$6B,$6B,$6B
db $6C,$6C,$6C,$6C,$6D,$6D,$6D,$6D,$6E,$6E,$6E,$6E,$6F,$6F,$6F,$6F
db $6F,$70,$70,$70,$70,$70,$71,$71,$71,$71,$71,$71,$71,$72,$72,$72
db $72,$72,$72,$72,$73,$73,$73,$73,$73,$73,$73,$73,$74,$74,$74,$74
db $74,$74,$74,$74,$74,$74,$75,$75,$75,$75,$75,$75,$75,$75,$75,$75
db $75,$75,$76,$76,$76,$76,$76,$76,$76,$76,$76,$76,$76,$76,$76,$76
db $76,$77,$77,$77,$77,$77,$77,$77,$77,$77,$77,$77,$77,$77,$77,$77
db $77,$77,$77,$78,$78,$78,$78,$78,$78,$78,$78,$78,$78,$78,$78,$78
db $78,$78,$78,$78,$78,$78,$78,$78,$78,$78,$79,$79,$79,$79,$79,$79
db $79,$79,$79,$79,$79,$79,$79,$79,$79,$79,$79,$79,$79,$79,$79,$79
db $79,$79,$79,$79,$79,$79,$79,$79,$79,$7A,$7A,$7A,$7A,$7A,$7A,$7A
db $7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A
db $7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$7A,$80

原点から目標点への角度を求める(高精度版)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 原点から目標点への角度を求める(高精度版)
; 使用する一時変数はほぼ同じです
; このコードは精度が高い代わりに処理が重いです
; こっちもJSLルーチン化推奨
; A,Yレジスタを使用
; 一時変数 $00~$07を使用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GetAngle:   PHX
      REP #$20
      LDA $02
      SEC
      SBC $06
      PHP
      BPL IfPlus1
      EOR.w #$FFFF
      INC A
IfPlus1:    STA $02
      LDA $00
      SEC
      SBC $04
      PHP
      BPL IfPlus0
      EOR.w #$FFFF
      INC A
IfPlus0:    STA $00
      BEQ X_Zero
      LSR A
      TAY
      LDA $02
      BEQ Y_Zero
      CMP.w #$0100
      XBA
      ROR A
      AND.w #$FF80
      STA $4204
      STY $4206
      STZ $00
      LDA.w #$0040
      STA $02
      LDA $4214
      STA $06
Loop00:     LDA $00
      INY
      ORA $02
      ASL A
      TAX
      LDA $06
      CMP.l GetTan,x
      BCC Label00
      LDA $02
      TSB $00
Label00:    LSR $02
      BCC Loop00
      SEP #$20
      PLA
      ;EOR $01,s
      db $43,$01
      BPL Label02
      LDA $00
      EOR #$FF
      INC A
      STA $00
      BNE Label02
      INC $01
Label02:    PLP
      BMI Label03
      INC $01
Label03:    PLX
      RTS

X_Zero:     LDA.w #$0080
      STA $00
      PLP
      PLP
      BMI IfPlus4
      INC $01
IfPlus4:    PLX
      RTS

Y_Zero:     STZ $00
      PLP
      BMI IfPlus5
      INC $01
IfPlus5:    PLP
      PLX
      RTS

GetTan:     dw $0000,$0003,$0006,$0009,$000C,$000F,$0012,$0016
      dw $0019,$001C,$001F,$0022,$0025,$0029,$002C,$002F
      dw $0032,$0036,$0039,$003C,$0040,$0043,$0046,$004A
      dw $004D,$0051,$0054,$0058,$005B,$005F,$0062,$0066
      dw $006A,$006D,$0071,$0075,$0079,$007C,$0080,$0084
      dw $0088,$008C,$0091,$0095,$0099,$009D,$00A2,$00A6
      dw $00AB,$00AF,$00B4,$00B9,$00BD,$00C2,$00C7,$00CC
      dw $00D2,$00D7,$00DC,$00E2,$00E8,$00ED,$00F3,$00F9
      dw $0100,$0106,$010C,$0113,$011A,$0121,$0128,$0130
      dw $0137,$013F,$0148,$0150,$0159,$0162,$016B,$0175
      dw $017F,$0189,$0194,$019F,$01AB,$01B7,$01C3,$01D1
      dw $01DE,$01ED,$01FC,$020C,$021D,$022E,$0241,$0255
      dw $026A,$0280,$0297,$02B0,$02CB,$02E8,$0306,$0328
      dw $034B,$0372,$039D,$03CB,$03FE,$0435,$0474,$04B9
      dw $0506,$055E,$05C3,$0637,$06BD,$075C,$081B,$0904
      dw $0A27,$0B9C,$0D8E,$1046,$145A,$1B26,$28BC,$517B

ファイアボールとスプライトの当たり判定を取得

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ファイアボールと自スプライトの当たり判定を取得
; キャリーフラグに結果が返ってきます(C=1:触れている)
; A,X,Yレジスタを使用
; 一時変数 $00~$0C,$0Fを使用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

FireContact   LDY #$01
ExtLoop     LDA $1713,y
      CMP #$05
      BEQ CheckContact
NextExtSpr    DEY
      BPL ExtLoop
      RTS

CheckContact    LDA $154C,x
      ORA $1781,y
      BNE NextExtSpr
      JSR GetExtSprA
      JSL $03B6E5
      JSL $03B72B
      BCC NextExtSpr
      LDA #$01    ;\
      STA $1713,y   ; | ファイアを消滅させない場合
      LDA #$10    ; | コメント化する必要あり
      STA $1777,y   ;/
      RTS

GetExtSprA    PHX
      LDX $1713,y
      LDA $1727,y
      CLC
      ADC $02A4E7,x
      STA $04
      LDA $173B,y
      ADC #$00
      STA $0A
      LDA $02A4FF,x
      STA $06
      LDA $171D,y
      CLC
      ADC $02A4F3,x
      STA $05
      LDA $1731,y
      ADC #$00
      STA $0B
      LDA $02A50B,x
      STA $07
      PLX
      RTS