diff --git a/6502_func_test.bin b/6502_func_test.bin new file mode 100644 index 0000000..f553e0c Binary files /dev/null and b/6502_func_test.bin differ diff --git a/6502_func_test.dat b/6502_func_test.dat new file mode 100644 index 0000000..cf63fc6 --- /dev/null +++ b/6502_func_test.dat @@ -0,0 +1,856 @@ +; Created with HEX2BIN (C) Marek Karcz 2016. All rights reserved. +ADDR +$0400 +ORG +$0000 +ORG +$0010 +$00 $00 $00 $c3 $82 $41 $00 $7f $00 $1f $71 $80 $0f $ff $7f $80 +$ff $0f $8f $8f $17 $02 $18 $02 $19 $02 $1a $02 $1b $02 $1f $01 +$03 $02 $04 $02 $05 $02 $06 $02 $0b $01 $4e $02 $4f $02 $50 $02 +$51 $02 $52 $02 $53 $02 $54 $02 $55 $02 $4a $02 $4b $02 $4c $02 +$4d $02 $03 $02 $04 $02 $04 $01 $05 $01 $00 $00 $00 $00 $00 $00 +ORG +$0200 +$00 $00 $00 $00 $00 $00 $00 $00 $29 $00 $60 $49 $00 $60 $09 $00 +$60 $69 $00 $60 $e9 $00 $60 $c3 $82 $41 $00 $7f $80 $80 $00 $02 +$86 $04 $82 $00 $87 $05 $83 $01 $61 $41 $20 $00 $e1 $c1 $a0 $80 +$81 $01 $80 $02 $81 $01 $80 $00 $01 $00 $01 $02 $81 $80 $81 $80 +$7f $80 $ff $00 $01 $00 $80 $80 $02 $00 $00 $1f $71 $80 $0f $ff +$7f $80 $ff $0f $8f $8f $00 $f1 $1f $00 $f0 $ff $ff $ff $ff $f0 +$f0 $0f $00 $ff $7f $80 $02 $80 $00 $80 $00 $00 $00 $00 $00 $00 +ORG +$0400 +$d8 $a2 $ff $9a $a9 $00 $8d $00 $02 $a2 $05 $4c $33 $04 $a0 $05 +$d0 $08 $4c $12 $04 $88 $88 $88 $88 $88 $88 $88 $88 $88 $88 $f0 +$17 $4c $21 $04 $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $f0 $de +$4c $30 $04 $d0 $f4 $4c $35 $04 $ad $00 $02 $c9 $00 $d0 $fe $a9 +$01 $8d $00 $02 $a0 $fe $88 $98 $aa $10 $08 $18 $69 $02 $ea $ea +$ea $ea $ea $ea $ea $ea $ea $ea $49 $7f $8d $e6 $04 $a9 $00 $4c +$e5 $04 $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $f0 $3e $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca $ca +$ca $ca $ca $ca $ca $ca $ea $ea $ea $ea $ea $f0 $08 $4c $6d $05 +$ea $ea $ea $ea $ea $ea $ea $ea $ea $ea $c0 $00 $f0 $03 $4c $46 +$04 $ad $00 $02 $c9 $01 $d0 $fe $a9 $02 $8d $00 $02 $c0 $01 $d0 +$03 $4c $91 $05 $a9 $00 $c9 $00 $d0 $fe $90 $fe $30 $fe $c9 $01 +$f0 $fe $b0 $fe $10 $fe $aa $e0 $00 $d0 $fe $90 $fe $30 $fe $e0 +$01 $f0 $fe $b0 $fe $10 $fe $a8 $c0 $00 $d0 $fe $90 $fe $30 $fe +$c0 $01 $f0 $fe $b0 $fe $10 $fe $ad $00 $02 $c9 $02 $d0 $fe $a9 +$03 $8d $00 $02 $a2 $ff $9a $a9 $55 $48 $a9 $aa $48 $cd $fe $01 +$d0 $fe $ba $8a $c9 $fd $d0 $fe $68 $c9 $aa $d0 $fe $68 $c9 $55 +$d0 $fe $cd $ff $01 $d0 $fe $ba $e0 $ff $d0 $fe $ad $00 $02 $c9 +$03 $d0 $fe $a9 $04 $8d $00 $02 $a9 $ff $48 $28 $10 $1a $50 $1b +$90 $1c $d0 $1d $30 $03 $4c $16 $06 $70 $03 $4c $1b $06 $b0 $03 +$4c $20 $06 $f0 $0f $4c $25 $06 $4c $28 $06 $4c $2b $06 $4c $2e +$06 $4c $31 $06 $08 $ba $e0 $fe $d0 $fe $68 $c9 $ff $d0 $fe $ba +$e0 $ff $d0 $fe $a9 $00 $48 $28 $30 $1a $70 $1b $b0 $1c $f0 $1d +$10 $03 $4c $52 $06 $50 $03 $4c $57 $06 $90 $03 $4c $5c $06 $d0 +$0f $4c $61 $06 $4c $64 $06 $4c $67 $06 $4c $6a $06 $4c $6d $06 +$08 $68 $c9 $30 $d0 $fe $a9 $02 $48 $28 $d0 $02 $f0 $03 $4c $7e +$06 $b0 $02 $90 $03 $4c $85 $06 $30 $02 $10 $03 $4c $8c $06 $70 +$02 $50 $03 $4c $93 $06 $a9 $01 $48 $28 $f0 $02 $d0 $03 $4c $9e +$06 $90 $02 $b0 $03 $4c $a5 $06 $30 $02 $10 $03 $4c $ac $06 $70 +$02 $50 $03 $4c $b3 $06 $a9 $80 $48 $28 $f0 $02 $d0 $03 $4c $be +$06 $b0 $02 $90 $03 $4c $c5 $06 $10 $02 $30 $03 $4c $cc $06 $70 +$02 $50 $03 $4c $d3 $06 $a9 $40 $48 $28 $f0 $02 $d0 $03 $4c $de +$06 $b0 $02 $90 $03 $4c $e5 $06 $30 $02 $10 $03 $4c $ec $06 $50 +$02 $70 $03 $4c $f3 $06 $a9 $fd $48 $28 $f0 $02 $d0 $03 $4c $fe +$06 $90 $02 $b0 $03 $4c $05 $07 $10 $02 $30 $03 $4c $0c $07 $50 +$02 $70 $03 $4c $13 $07 $a9 $fe $48 $28 $d0 $02 $f0 $03 $4c $1e +$07 $b0 $02 $90 $03 $4c $25 $07 $10 $02 $30 $03 $4c $2c $07 $50 +$02 $70 $03 $4c $33 $07 $a9 $7f $48 $28 $d0 $02 $f0 $03 $4c $3e +$07 $90 $02 $b0 $03 $4c $45 $07 $30 $02 $10 $03 $4c $4c $07 $50 +$02 $70 $03 $4c $53 $07 $a9 $bf $48 $28 $d0 $02 $f0 $03 $4c $5e +$07 $90 $02 $b0 $03 $4c $65 $07 $10 $02 $30 $03 $4c $6c $07 $70 +$02 $50 $03 $4c $73 $07 $ad $00 $02 $c9 $04 $d0 $fe $a9 $05 $8d +$00 $02 $a2 $55 $a0 $aa $a9 $ff $48 $a9 $01 $28 $48 $08 $c9 $01 +$d0 $fe $68 $48 $c9 $ff $d0 $fe $28 $a9 $00 $48 $a9 $00 $28 $48 +$08 $c9 $00 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $a9 $ff $48 $a9 +$ff $28 $48 $08 $c9 $ff $d0 $fe $68 $48 $c9 $ff $d0 $fe $28 $a9 +$00 $48 $a9 $01 $28 $48 $08 $c9 $01 $d0 $fe $68 $48 $c9 $30 $d0 +$fe $28 $a9 $ff $48 $a9 $00 $28 $48 $08 $c9 $00 $d0 $fe $68 $48 +$c9 $ff $d0 $fe $28 $a9 $00 $48 $a9 $ff $28 $48 $08 $c9 $ff $d0 +$fe $68 $48 $c9 $30 $d0 $fe $28 $a9 $ff $48 $a9 $00 $28 $68 $08 +$c9 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $a9 $00 $48 $a9 $ff +$28 $68 $08 $c9 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $a9 $ff +$48 $a9 $fe $28 $68 $08 $c9 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $00 $48 $a9 $00 $28 $68 $08 $c9 $ff $d0 $fe $68 $48 $c9 +$b0 $d0 $fe $28 $a9 $ff $48 $a9 $ff $28 $68 $08 $c9 $00 $d0 $fe +$68 $48 $c9 $7f $d0 $fe $28 $a9 $00 $48 $a9 $fe $28 $68 $08 $c9 +$01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $e0 $55 $d0 $fe $c0 $aa +$d0 $fe $ad $00 $02 $c9 $05 $d0 $fe $a9 $06 $8d $00 $02 $a9 $00 +$48 $a9 $3c $28 $49 $c3 $08 $c9 $ff $d0 $fe $68 $48 $c9 $b0 $d0 +$fe $28 $a9 $00 $48 $a9 $c3 $28 $49 $c3 $08 $c9 $00 $d0 $fe $68 +$48 $c9 $32 $d0 $fe $28 $ad $00 $02 $c9 $06 $d0 $fe $a9 $07 $8d +$00 $02 $a2 $24 $a0 $42 $a9 $00 $48 $a9 $18 $28 $ea $08 $c9 $18 +$d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $e0 $24 $d0 $fe $c0 $42 $d0 +$fe $a2 $db $a0 $bd $a9 $ff $48 $a9 $e7 $28 $ea $08 $c9 $e7 $d0 +$fe $68 $48 $c9 $ff $d0 $fe $28 $e0 $db $d0 $fe $c0 $bd $d0 $fe +$ad $00 $02 $c9 $07 $d0 $fe $a9 $08 $8d $00 $02 $a9 $00 $48 $28 +$a9 $46 $a2 $41 $a0 $52 $4c $c9 $36 $ea $ea $d0 $fe $e8 $e8 $f0 +$fe $10 $fe $90 $fe $50 $fe $c9 $ec $d0 $fe $e0 $42 $d0 $fe $c0 +$4f $d0 $fe $ca $c8 $c8 $c8 $49 $aa $4c $32 $09 $ea $ea $d0 $fe +$e8 $e8 $f0 $fe $30 $fe $90 $fe $50 $fe $c9 $46 $d0 $fe $e0 $41 +$d0 $fe $c0 $52 $d0 $fe $ad $00 $02 $c9 $08 $d0 $fe $a9 $09 $8d +$00 $02 $a9 $00 $48 $28 $a9 $49 $a2 $4e $a0 $44 $6c $f8 $36 $ea +$d0 $fe $88 $88 $08 $88 $88 $88 $28 $f0 $fe $10 $fe $90 $fe $50 +$fe $c9 $e3 $d0 $fe $e0 $4f $d0 $fe $c0 $3e $d0 $fe $ba $e0 $ff +$d0 $fe $ad $00 $02 $c9 $09 $d0 $fe $a9 $0a $8d $00 $02 $a9 $00 +$48 $28 $a9 $4a $a2 $53 $a0 $52 $20 $34 $37 $08 $88 $88 $88 $28 +$f0 $fe $10 $fe $90 $fe $50 $fe $c9 $e0 $d0 $fe $e0 $54 $d0 $fe +$c0 $4c $d0 $fe $ba $e0 $ff $d0 $fe $ad $00 $02 $c9 $0a $d0 $fe +$a9 $0b $8d $00 $02 $a9 $00 $48 $28 $a9 $42 $a2 $52 $a0 $4b $00 +$88 $08 $88 $88 $88 $c9 $e8 $d0 $fe $e0 $53 $d0 $fe $c0 $45 $d0 +$fe $68 $c9 $30 $d0 $fe $ba $e0 $ff $d0 $fe $ad $00 $02 $c9 $0b +$d0 $fe $a9 $0c $8d $00 $02 $a9 $ff $48 $28 $18 $08 $68 $48 $c9 +$fe $d0 $fe $28 $38 $08 $68 $48 $c9 $ff $d0 $fe $28 $58 $08 $68 +$48 $c9 $fb $d0 $fe $28 $78 $08 $68 $48 $c9 $ff $d0 $fe $28 $d8 +$08 $68 $48 $c9 $f7 $d0 $fe $28 $f8 $08 $68 $48 $c9 $ff $d0 $fe +$28 $b8 $08 $68 $48 $c9 $bf $d0 $fe $28 $a9 $00 $48 $28 $08 $68 +$48 $c9 $30 $d0 $fe $28 $38 $08 $68 $48 $c9 $31 $d0 $fe $28 $18 +$08 $68 $48 $c9 $30 $d0 $fe $28 $78 $08 $68 $48 $c9 $34 $d0 $fe +$28 $58 $08 $68 $48 $c9 $30 $d0 $fe $28 $f8 $08 $68 $48 $c9 $38 +$d0 $fe $28 $d8 $08 $68 $48 $c9 $30 $d0 $fe $28 $a9 $40 $48 $28 +$08 $68 $48 $c9 $70 $d0 $fe $28 $b8 $08 $68 $48 $c9 $30 $d0 $fe +$28 $ad $00 $02 $c9 $0c $d0 $fe $a9 $0d $8d $00 $02 $a2 $fe $a9 +$ff $48 $28 $e8 $08 $e0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 +$e8 $08 $e0 $00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $e8 $08 $e0 +$01 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $ca $08 $e0 $00 $d0 $fe +$68 $48 $c9 $7f $d0 $fe $28 $ca $08 $e0 $ff $d0 $fe $68 $48 $c9 +$fd $d0 $fe $28 $ca $a9 $00 $48 $28 $e8 $08 $e0 $ff $d0 $fe $68 +$48 $c9 $b0 $d0 $fe $28 $e8 $08 $e0 $00 $d0 $fe $68 $48 $c9 $32 +$d0 $fe $28 $e8 $08 $e0 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 +$ca $08 $e0 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $ca $08 $e0 +$ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a0 $fe $a9 $ff $48 $28 +$c8 $08 $c0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $c8 $08 $c0 +$00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $c8 $08 $c0 $01 $d0 $fe +$68 $48 $c9 $7d $d0 $fe $28 $88 $08 $c0 $00 $d0 $fe $68 $48 $c9 +$7f $d0 $fe $28 $88 $08 $c0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe +$28 $88 $a9 $00 $48 $28 $c8 $08 $c0 $ff $d0 $fe $68 $48 $c9 $b0 +$d0 $fe $28 $c8 $08 $c0 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 +$c8 $08 $c0 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $88 $08 $c0 +$00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $88 $08 $c0 $ff $d0 $fe +$68 $48 $c9 $b0 $d0 $fe $28 $a2 $ff $a9 $ff $48 $28 $8a $08 $c9 +$ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $08 $e8 $28 $8a $08 $c9 +$00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $08 $e8 $28 $8a $08 $c9 +$01 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $00 $48 $28 $8a $08 +$c9 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $08 $ca $28 $8a $08 +$c9 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $08 $ca $28 $8a $08 +$c9 $ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a0 $ff $a9 $ff $48 +$28 $98 $08 $c9 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $08 $c8 +$28 $98 $08 $c9 $00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $08 $c8 +$28 $98 $08 $c9 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $00 +$48 $28 $98 $08 $c9 $01 $d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $08 +$88 $28 $98 $08 $c9 $00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $08 +$88 $28 $98 $08 $c9 $ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 +$ff $48 $a2 $ff $8a $28 $a8 $08 $c0 $ff $d0 $fe $68 $48 $c9 $fd +$d0 $fe $28 $08 $e8 $8a $28 $a8 $08 $c0 $00 $d0 $fe $68 $48 $c9 +$7f $d0 $fe $28 $08 $e8 $8a $28 $a8 $08 $c0 $01 $d0 $fe $68 $48 +$c9 $7d $d0 $fe $28 $a9 $00 $48 $a9 $00 $8a $28 $a8 $08 $c0 $01 +$d0 $fe $68 $48 $c9 $30 $d0 $fe $28 $08 $ca $8a $28 $a8 $08 $c0 +$00 $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $08 $ca $8a $28 $a8 $08 +$c0 $ff $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a0 $ff +$98 $28 $aa $08 $e0 $ff $d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $08 +$c8 $98 $28 $aa $08 $e0 $00 $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 +$08 $c8 $98 $28 $aa $08 $e0 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $00 $48 $a9 $00 $98 $28 $aa $08 $e0 $01 $d0 $fe $68 $48 +$c9 $30 $d0 $fe $28 $08 $88 $98 $28 $aa $08 $e0 $00 $d0 $fe $68 +$48 $c9 $32 $d0 $fe $28 $08 $88 $98 $28 $aa $08 $e0 $ff $d0 $fe +$68 $48 $c9 $b0 $d0 $fe $28 $ad $00 $02 $c9 $0d $d0 $fe $a9 $0e +$8d $00 $02 $a2 $01 $a9 $ff $48 $28 $9a $08 $ad $01 $01 $c9 $ff +$d0 $fe $a9 $00 $48 $28 $9a $08 $ad $01 $01 $c9 $30 $d0 $fe $ca +$a9 $ff $48 $28 $9a $08 $ad $00 $01 $c9 $ff $d0 $fe $a9 $00 $48 +$28 $9a $08 $ad $00 $01 $c9 $30 $d0 $fe $ca $a9 $ff $48 $28 $9a +$08 $ad $ff $01 $c9 $ff $d0 $fe $a9 $00 $48 $28 $9a $08 $ad $ff +$01 $c9 $30 $a2 $01 $9a $a9 $ff $48 $28 $ba $08 $e0 $01 $d0 $fe +$ad $01 $01 $c9 $7d $d0 $fe $a9 $ff $48 $28 $ba $08 $e0 $00 $d0 +$fe $ad $00 $01 $c9 $7f $d0 $fe $a9 $ff $48 $28 $ba $08 $e0 $ff +$d0 $fe $ad $ff $01 $c9 $fd $d0 $fe $a2 $01 $9a $a9 $00 $48 $28 +$ba $08 $e0 $01 $d0 $fe $ad $01 $01 $c9 $30 $d0 $fe $a9 $00 $48 +$28 $ba $08 $e0 $00 $d0 $fe $ad $00 $01 $c9 $32 $d0 $fe $a9 $00 +$48 $28 $ba $08 $e0 $ff $d0 $fe $ad $ff $01 $c9 $b0 $d0 $fe $68 +$ad $00 $02 $c9 $0e $d0 $fe $a9 $0f $8d $00 $02 $a0 $03 $a9 $00 +$48 $28 $b6 $13 $08 $8a $49 $c3 $28 $99 $03 $02 $08 $49 $c3 $d9 +$17 $02 $d0 $fe $68 $49 $30 $d9 $1c $02 $d0 $fe $88 $10 $df $a0 +$03 $a9 $ff $48 $28 $b6 $13 $08 $8a $49 $c3 $28 $99 $03 $02 $08 +$49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $7d $d9 $1c $02 $d0 $fe $88 +$10 $df $a0 $03 $a9 $00 $48 $28 $be $17 $02 $08 $8a $49 $c3 $aa +$28 $96 $0c $08 $49 $c3 $d9 $13 $00 $d0 $fe $68 $49 $30 $d9 $1c +$02 $d0 $fe $88 $10 $de $a0 $03 $a9 $ff $48 $28 $be $17 $02 $08 +$8a $49 $c3 $aa $28 $96 $0c $08 $49 $c3 $d9 $13 $00 $d0 $fe $68 +$49 $7d $d9 $1c $02 $d0 $fe $88 $10 $de $a0 $03 $a2 $00 $b9 $0c +$00 $49 $c3 $d9 $13 $00 $d0 $fe $96 $0c $b9 $03 $02 $49 $c3 $d9 +$17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 $e3 $ad $00 $02 $c9 $0f +$d0 $fe $a9 $10 $8d $00 $02 $a0 $fd $b6 $19 $8a $99 $09 $01 $88 +$c0 $fa $b0 $f5 $a0 $fd $be $1d $01 $96 $12 $88 $c0 $fa $b0 $f6 +$a0 $03 $a2 $00 $b9 $0c $00 $d9 $13 $00 $d0 $fe $96 $0c $b9 $03 +$02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 $e7 $ad $00 $02 +$c9 $10 $d0 $fe $a9 $11 $8d $00 $02 $a2 $03 $a9 $00 $48 $28 $b4 +$13 $08 $98 $49 $c3 $28 $9d $03 $02 $08 $49 $c3 $dd $17 $02 $d0 +$fe $68 $49 $30 $dd $1c $02 $d0 $fe $ca $10 $df $a2 $03 $a9 $ff +$48 $28 $b4 $13 $08 $98 $49 $c3 $28 $9d $03 $02 $08 $49 $c3 $dd +$17 $02 $d0 $fe $68 $49 $7d $dd $1c $02 $d0 $fe $ca $10 $df $a2 +$03 $a9 $00 $48 $28 $bc $17 $02 $08 $98 $49 $c3 $a8 $28 $94 $0c +$08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $30 $dd $1c $02 $d0 $fe $ca +$10 $df $a2 $03 $a9 $ff $48 $28 $bc $17 $02 $08 $98 $49 $c3 $a8 +$28 $94 $0c $08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $7d $dd $1c $02 +$d0 $fe $ca $10 $df $a2 $03 $a0 $00 $b5 $0c $49 $c3 $d5 $13 $d0 +$fe $94 $0c $bd $03 $02 $49 $c3 $dd $17 $02 $d0 $fe $8a $9d $03 +$02 $ca $10 $e5 $ad $00 $02 $c9 $11 $d0 $fe $a9 $12 $8d $00 $02 +$a2 $fd $b4 $19 $98 $9d $09 $01 $ca $e0 $fa $b0 $f5 $a2 $fd $bc +$1d $01 $94 $12 $ca $e0 $fa $b0 $f6 $a2 $03 $a0 $00 $b5 $0c $d5 +$13 $d0 $fe $94 $0c $bd $03 $02 $dd $17 $02 $d0 $fe $8a $9d $03 +$02 $ca $10 $e9 $ad $00 $02 $c9 $12 $d0 $fe $a9 $13 $8d $00 $02 +$a9 $00 $48 $28 $a6 $13 $08 $8a $49 $c3 $aa $28 $8e $03 $02 $08 +$49 $c3 $aa $e0 $c3 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 +$00 $48 $28 $a6 $14 $08 $8a $49 $c3 $aa $28 $8e $04 $02 $08 $49 +$c3 $aa $e0 $82 $d0 $fe $68 $49 $30 $cd $1d $02 $d0 $fe $a9 $00 +$48 $28 $a6 $15 $08 $8a $49 $c3 $aa $28 $8e $05 $02 $08 $49 $c3 +$aa $e0 $41 $d0 $fe $68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 +$28 $a6 $16 $08 $8a $49 $c3 $aa $28 $8e $06 $02 $08 $49 $c3 $aa +$e0 $00 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 +$a6 $13 $08 $8a $49 $c3 $aa $28 $8e $03 $02 $08 $49 $c3 $aa $e0 +$c3 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $a6 +$14 $08 $8a $49 $c3 $aa $28 $8e $04 $02 $08 $49 $c3 $aa $e0 $82 +$d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $a6 $15 +$08 $8a $49 $c3 $aa $28 $8e $05 $02 $08 $49 $c3 $aa $e0 $41 $d0 +$fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $a6 $16 $08 +$8a $49 $c3 $aa $28 $8e $06 $02 $08 $49 $c3 $aa $e0 $00 $d0 $fe +$68 $49 $7d $cd $1f $02 $d0 $fe $a9 $00 $48 $28 $ae $17 $02 $08 +$8a $49 $c3 $aa $28 $86 $0c $08 $49 $c3 $c5 $13 $d0 $fe $68 $49 +$30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $ae $18 $02 $08 $8a $49 +$c3 $aa $28 $86 $0d $08 $49 $c3 $c5 $14 $d0 $fe $68 $49 $30 $cd +$1d $02 $d0 $fe $a9 $00 $48 $28 $ae $19 $02 $08 $8a $49 $c3 $aa +$28 $86 $0e $08 $49 $c3 $c5 $15 $d0 $fe $68 $49 $30 $cd $1e $02 +$d0 $fe $a9 $00 $48 $28 $ae $1a $02 $08 $8a $49 $c3 $aa $28 $86 +$0f $08 $49 $c3 $c5 $16 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe +$a9 $ff $48 $28 $ae $17 $02 $08 $8a $49 $c3 $aa $28 $86 $0c $08 +$49 $c3 $aa $e4 $13 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 +$ff $48 $28 $ae $18 $02 $08 $8a $49 $c3 $aa $28 $86 $0d $08 $49 +$c3 $aa $e4 $14 $d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff +$48 $28 $ae $19 $02 $08 $8a $49 $c3 $aa $28 $86 $0e $08 $49 $c3 +$aa $e4 $15 $d0 $fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 +$28 $ae $1a $02 $08 $8a $49 $c3 $aa $28 $86 $0f $08 $49 $c3 $aa +$e4 $16 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 $00 $48 $28 +$a2 $c3 $08 $ec $17 $02 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe +$a9 $00 $48 $28 $a2 $82 $08 $ec $18 $02 $d0 $fe $68 $49 $30 $cd +$1d $02 $d0 $fe $a9 $00 $48 $28 $a2 $41 $08 $ec $19 $02 $d0 $fe +$68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 $28 $a2 $00 $08 $ec +$1a $02 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 +$a2 $c3 $08 $ec $17 $02 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe +$a9 $ff $48 $28 $a2 $82 $08 $ec $18 $02 $d0 $fe $68 $49 $7d $cd +$1d $02 $d0 $fe $a9 $ff $48 $28 $a2 $41 $08 $ec $19 $02 $d0 $fe +$68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $a2 $00 $08 $ec +$1a $02 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a2 $00 $a5 $0c +$49 $c3 $c5 $13 $d0 $fe $86 $0c $ad $03 $02 $49 $c3 $cd $17 $02 +$d0 $fe $8e $03 $02 $a5 $0d $49 $c3 $c5 $14 $d0 $fe $86 $0d $ad +$04 $02 $49 $c3 $cd $18 $02 $d0 $fe $8e $04 $02 $a5 $0e $49 $c3 +$c5 $15 $d0 $fe $86 $0e $ad $05 $02 $49 $c3 $cd $19 $02 $d0 $fe +$8e $05 $02 $a5 $0f $49 $c3 $c5 $16 $d0 $fe $86 $0f $ad $06 $02 +$49 $c3 $cd $1a $02 $d0 $fe $8e $06 $02 $ad $00 $02 $c9 $13 $d0 +$fe $a9 $14 $8d $00 $02 $a9 $00 $48 $28 $a4 $13 $08 $98 $49 $c3 +$a8 $28 $8c $03 $02 $08 $49 $c3 $a8 $c0 $c3 $d0 $fe $68 $49 $30 +$cd $1c $02 $d0 $fe $a9 $00 $48 $28 $a4 $14 $08 $98 $49 $c3 $a8 +$28 $8c $04 $02 $08 $49 $c3 $a8 $c0 $82 $d0 $fe $68 $49 $30 $cd +$1d $02 $d0 $fe $a9 $00 $48 $28 $a4 $15 $08 $98 $49 $c3 $a8 $28 +$8c $05 $02 $08 $49 $c3 $a8 $c0 $41 $d0 $fe $68 $49 $30 $cd $1e +$02 $d0 $fe $a9 $00 $48 $28 $a4 $16 $08 $98 $49 $c3 $a8 $28 $8c +$06 $02 $08 $49 $c3 $a8 $c0 $00 $d0 $fe $68 $49 $30 $cd $1f $02 +$d0 $fe $a9 $ff $48 $28 $a4 $13 $08 $98 $49 $c3 $a8 $28 $8c $03 +$02 $08 $49 $c3 $a8 $c0 $c3 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 +$fe $a9 $ff $48 $28 $a4 $14 $08 $98 $49 $c3 $a8 $28 $8c $04 $02 +$08 $49 $c3 $a8 $c0 $82 $d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe +$a9 $ff $48 $28 $a4 $15 $08 $98 $49 $c3 $a8 $28 $8c $05 $02 $08 +$49 $c3 $a8 $c0 $41 $d0 $fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 +$ff $48 $28 $a4 $16 $08 $98 $49 $c3 $a8 $28 $8c $06 $02 $08 $49 +$c3 $a8 $c0 $00 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 $00 +$48 $28 $ac $17 $02 $08 $98 $49 $c3 $a8 $28 $84 $0c $08 $49 $c3 +$a8 $c4 $13 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 +$28 $ac $18 $02 $08 $98 $49 $c3 $a8 $28 $84 $0d $08 $49 $c3 $a8 +$c4 $14 $d0 $fe $68 $49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 +$ac $19 $02 $08 $98 $49 $c3 $a8 $28 $84 $0e $08 $49 $c3 $a8 $c4 +$15 $d0 $fe $68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 $28 $ac +$1a $02 $08 $98 $49 $c3 $a8 $28 $84 $0f $08 $49 $c3 $a8 $c4 $16 +$d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 $ac $17 +$02 $08 $98 $49 $c3 $a8 $28 $84 $0c $08 $49 $c3 $a8 $c5 $13 $d0 +$fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $ac $18 $02 +$08 $98 $49 $c3 $a8 $28 $84 $0d $08 $49 $c3 $a8 $c5 $14 $d0 $fe +$68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $ac $19 $02 $08 +$98 $49 $c3 $a8 $28 $84 $0e $08 $49 $c3 $a8 $c5 $15 $d0 $fe $68 +$49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $ac $1a $02 $08 $98 +$49 $c3 $a8 $28 $84 $0f $08 $49 $c3 $a8 $c5 $16 $d0 $fe $68 $49 +$7d $cd $1f $02 $d0 $fe $a9 $00 $48 $28 $a0 $c3 $08 $cc $17 $02 +$d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $a0 $82 +$08 $cc $18 $02 $d0 $fe $68 $49 $30 $cd $1d $02 $d0 $fe $a9 $00 +$48 $28 $a0 $41 $08 $cc $19 $02 $d0 $fe $68 $49 $30 $cd $1e $02 +$d0 $fe $a9 $00 $48 $28 $a0 $00 $08 $cc $1a $02 $d0 $fe $68 $49 +$30 $cd $1f $02 $d0 $fe $a9 $ff $48 $28 $a0 $c3 $08 $cc $17 $02 +$d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $a0 $82 +$08 $cc $18 $02 $d0 $fe $68 $49 $7d $cd $1d $02 $d0 $fe $a9 $ff +$48 $28 $a0 $41 $08 $cc $19 $02 $d0 $fe $68 $49 $7d $cd $1e $02 +$d0 $fe $a9 $ff $48 $28 $a0 $00 $08 $cc $1a $02 $d0 $fe $68 $49 +$7d $cd $1f $02 $d0 $fe $a0 $00 $a5 $0c $49 $c3 $c5 $13 $d0 $fe +$84 $0c $ad $03 $02 $49 $c3 $cd $17 $02 $d0 $fe $8c $03 $02 $a5 +$0d $49 $c3 $c5 $14 $d0 $fe $84 $0d $ad $04 $02 $49 $c3 $cd $18 +$02 $d0 $fe $8c $04 $02 $a5 $0e $49 $c3 $c5 $15 $d0 $fe $84 $0e +$ad $05 $02 $49 $c3 $cd $19 $02 $d0 $fe $8c $05 $02 $a5 $0f $49 +$c3 $c5 $16 $d0 $fe $84 $0f $ad $06 $02 $49 $c3 $cd $1a $02 $d0 +$fe $8c $06 $02 $ad $00 $02 $c9 $14 $d0 $fe $a9 $15 $8d $00 $02 +$a2 $03 $a9 $00 $48 $28 $b5 $13 $08 $49 $c3 $28 $9d $03 $02 $08 +$49 $c3 $dd $17 $02 $d0 $fe $68 $49 $30 $dd $1c $02 $d0 $fe $ca +$10 $e0 $a2 $03 $a9 $ff $48 $28 $b5 $13 $08 $49 $c3 $28 $9d $03 +$02 $08 $49 $c3 $dd $17 $02 $d0 $fe $68 $49 $7d $dd $1c $02 $d0 +$fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $28 $bd $17 $02 $08 $49 $c3 +$28 $95 $0c $08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $30 $dd $1c $02 +$d0 $fe $ca $10 $e1 $a2 $03 $a9 $ff $48 $28 $bd $17 $02 $08 $49 +$c3 $28 $95 $0c $08 $49 $c3 $d5 $13 $d0 $fe $68 $49 $7d $dd $1c +$02 $d0 $fe $ca $10 $e1 $a2 $03 $a0 $00 $b5 $0c $49 $c3 $d5 $13 +$d0 $fe $94 $0c $bd $03 $02 $49 $c3 $dd $17 $02 $d0 $fe $8a $9d +$03 $02 $ca $10 $e5 $ad $00 $02 $c9 $15 $d0 $fe $a9 $16 $8d $00 +$02 $a0 $03 $a9 $00 $48 $28 $b1 $24 $08 $49 $c3 $28 $99 $03 $02 +$08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $30 $d9 $1c $02 $d0 $fe +$88 $10 $e0 $a0 $03 $a9 $ff $48 $28 $b1 $24 $08 $49 $c3 $28 $99 +$03 $02 $08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $7d $d9 $1c $02 +$d0 $fe $88 $10 $e0 $a0 $03 $a2 $00 $b9 $03 $02 $49 $c3 $d9 $17 +$02 $d0 $fe $8a $99 $03 $02 $88 $10 $ef $a0 $03 $a9 $00 $48 $28 +$b9 $17 $02 $08 $49 $c3 $28 $91 $30 $08 $49 $c3 $d1 $24 $d0 $fe +$68 $49 $30 $d9 $1c $02 $d0 $fe $88 $10 $e1 $a0 $03 $a9 $ff $48 +$28 $b9 $17 $02 $08 $49 $c3 $28 $91 $30 $08 $49 $c3 $d1 $24 $d0 +$fe $68 $49 $7d $d9 $1c $02 $d0 $fe $88 $10 $e1 $a0 $03 $a2 $00 +$b9 $03 $02 $49 $c3 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 +$ef $a2 $06 $a0 $03 $a9 $00 $48 $28 $a1 $24 $08 $49 $c3 $28 $81 +$30 $08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 $30 $d9 $1c $02 $d0 +$fe $ca $ca $88 $10 $df $a2 $06 $a0 $03 $a9 $ff $48 $28 $a1 $24 +$08 $49 $c3 $28 $81 $30 $08 $49 $c3 $d9 $17 $02 $d0 $fe $68 $49 +$7d $d9 $1c $02 $d0 $fe $ca $ca $88 $10 $df $a0 $03 $a2 $00 $b9 +$03 $02 $49 $c3 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 $ef +$ad $00 $02 $c9 $16 $d0 $fe $a9 $17 $8d $00 $02 $a2 $fd $b5 $19 +$9d $09 $01 $ca $e0 $fa $b0 $f6 $a2 $fd $bd $1d $01 $95 $12 $ca +$e0 $fa $b0 $f6 $a2 $03 $a0 $00 $b5 $0c $d5 $13 $d0 $fe $94 $0c +$bd $03 $02 $dd $17 $02 $d0 $fe $8a $9d $03 $02 $ca $10 $e9 $a0 +$fb $a2 $fe $a1 $2c $99 $0b $01 $ca $ca $88 $c0 $f8 $b0 $f4 $a0 +$03 $a2 $00 $b9 $03 $02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 +$10 $f1 $a0 $fb $b9 $1f $01 $91 $38 $88 $c0 $f8 $b0 $f6 $a0 $03 +$a2 $00 $b9 $03 $02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 $88 $10 +$f1 $a0 $fb $a2 $fe $b1 $2e $81 $38 $ca $ca $88 $c0 $f8 $b0 $f5 +$a0 $03 $a2 $00 $b9 $03 $02 $d9 $17 $02 $d0 $fe $8a $99 $03 $02 +$88 $10 $f1 $ad $00 $02 $c9 $17 $d0 $fe $a9 $18 $8d $00 $02 $a9 +$00 $48 $28 $a5 $13 $08 $49 $c3 $28 $8d $03 $02 $08 $49 $c3 $c9 +$c3 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $a5 +$14 $08 $49 $c3 $28 $8d $04 $02 $08 $49 $c3 $c9 $82 $d0 $fe $68 +$49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 $a5 $15 $08 $49 $c3 +$28 $8d $05 $02 $08 $49 $c3 $c9 $41 $d0 $fe $68 $49 $30 $cd $1e +$02 $d0 $fe $a9 $00 $48 $28 $a5 $16 $08 $49 $c3 $28 $8d $06 $02 +$08 $49 $c3 $c9 $00 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 +$ff $48 $28 $a5 $13 $08 $49 $c3 $28 $8d $03 $02 $08 $49 $c3 $c9 +$c3 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $a5 +$14 $08 $49 $c3 $28 $8d $04 $02 $08 $49 $c3 $c9 $82 $d0 $fe $68 +$49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $a5 $15 $08 $49 $c3 +$28 $8d $05 $02 $08 $49 $c3 $c9 $41 $d0 $fe $68 $49 $7d $cd $1e +$02 $d0 $fe $a9 $ff $48 $28 $a5 $16 $08 $49 $c3 $28 $8d $06 $02 +$08 $49 $c3 $c9 $00 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 +$00 $48 $28 $ad $17 $02 $08 $49 $c3 $28 $85 $0c $08 $49 $c3 $c5 +$13 $d0 $fe $68 $49 $30 $cd $1c $02 $d0 $fe $a9 $00 $48 $28 $ad +$18 $02 $08 $49 $c3 $28 $85 $0d $08 $49 $c3 $c5 $14 $d0 $fe $68 +$49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 $ad $19 $02 $08 $49 +$c3 $28 $85 $0e $08 $49 $c3 $c5 $15 $d0 $fe $68 $49 $30 $cd $1e +$02 $d0 $fe $a9 $00 $48 $28 $ad $1a $02 $08 $49 $c3 $28 $85 $0f +$08 $49 $c3 $c5 $16 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 +$ff $48 $28 $ad $17 $02 $08 $49 $c3 $28 $85 $0c $08 $49 $c3 $c5 +$13 $d0 $fe $68 $49 $7d $cd $1c $02 $d0 $fe $a9 $ff $48 $28 $ad +$18 $02 $08 $49 $c3 $28 $85 $0d $08 $49 $c3 $c5 $14 $d0 $fe $68 +$49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $ad $19 $02 $08 $49 +$c3 $28 $85 $0e $08 $49 $c3 $c5 $15 $d0 $fe $68 $49 $7d $cd $1e +$02 $d0 $fe $a9 $ff $48 $28 $ad $1a $02 $08 $49 $c3 $28 $85 $0f +$08 $49 $c3 $c5 $16 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a9 +$00 $48 $28 $a9 $c3 $08 $cd $17 $02 $d0 $fe $68 $49 $30 $cd $1c +$02 $d0 $fe $a9 $00 $48 $28 $a9 $82 $08 $cd $18 $02 $d0 $fe $68 +$49 $30 $cd $1d $02 $d0 $fe $a9 $00 $48 $28 $a9 $41 $08 $cd $19 +$02 $d0 $fe $68 $49 $30 $cd $1e $02 $d0 $fe $a9 $00 $48 $28 $a9 +$00 $08 $cd $1a $02 $d0 $fe $68 $49 $30 $cd $1f $02 $d0 $fe $a9 +$ff $48 $28 $a9 $c3 $08 $cd $17 $02 $d0 $fe $68 $49 $7d $cd $1c +$02 $d0 $fe $a9 $ff $48 $28 $a9 $82 $08 $cd $18 $02 $d0 $fe $68 +$49 $7d $cd $1d $02 $d0 $fe $a9 $ff $48 $28 $a9 $41 $08 $cd $19 +$02 $d0 $fe $68 $49 $7d $cd $1e $02 $d0 $fe $a9 $ff $48 $28 $a9 +$00 $08 $cd $1a $02 $d0 $fe $68 $49 $7d $cd $1f $02 $d0 $fe $a2 +$00 $a5 $0c $49 $c3 $c5 $13 $d0 $fe $86 $0c $ad $03 $02 $49 $c3 +$cd $17 $02 $d0 $fe $8e $03 $02 $a5 $0d $49 $c3 $c5 $14 $d0 $fe +$86 $0d $ad $04 $02 $49 $c3 $cd $18 $02 $d0 $fe $8e $04 $02 $a5 +$0e $49 $c3 $c5 $15 $d0 $fe $86 $0e $ad $05 $02 $49 $c3 $cd $19 +$02 $d0 $fe $8e $05 $02 $a5 $0f $49 $c3 $c5 $16 $d0 $fe $86 $0f +$ad $06 $02 $49 $c3 $cd $1a $02 $d0 $fe $8e $06 $02 $ad $00 $02 +$c9 $18 $d0 $fe $a9 $19 $8d $00 $02 $a9 $00 $48 $a9 $ff $28 $24 +$16 $08 $c9 $ff $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $a9 $00 $48 +$a9 $01 $28 $24 $15 $08 $c9 $01 $d0 $fe $68 $48 $c9 $70 $d0 $fe +$28 $a9 $00 $48 $a9 $01 $28 $24 $14 $08 $c9 $01 $d0 $fe $68 $48 +$c9 $b2 $d0 $fe $28 $a9 $00 $48 $a9 $01 $28 $24 $13 $08 $c9 $01 +$d0 $fe $68 $48 $c9 $f0 $d0 $fe $28 $a9 $ff $48 $a9 $ff $28 $24 +$16 $08 $c9 $ff $d0 $fe $68 $48 $c9 $3f $d0 $fe $28 $a9 $ff $48 +$a9 $01 $28 $24 $15 $08 $c9 $01 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $ff $48 $a9 $01 $28 $24 $14 $08 $c9 $01 $d0 $fe $68 $48 +$c9 $bf $d0 $fe $28 $a9 $ff $48 $a9 $01 $28 $24 $13 $08 $c9 $01 +$d0 $fe $68 $48 $c9 $fd $d0 $fe $28 $a9 $00 $48 $a9 $ff $28 $2c +$1a $02 $08 $c9 $ff $d0 $fe $68 $48 $c9 $32 $d0 $fe $28 $a9 $00 +$48 $a9 $01 $28 $2c $19 $02 $08 $c9 $01 $d0 $fe $68 $48 $c9 $70 +$d0 $fe $28 $a9 $00 $48 $a9 $01 $28 $2c $18 $02 $08 $c9 $01 $d0 +$fe $68 $48 $c9 $b2 $d0 $fe $28 $a9 $00 $48 $a9 $01 $28 $2c $17 +$02 $08 $c9 $01 $d0 $fe $68 $48 $c9 $f0 $d0 $fe $28 $a9 $ff $48 +$a9 $ff $28 $2c $1a $02 $08 $c9 $ff $d0 $fe $68 $48 $c9 $3f $d0 +$fe $28 $a9 $ff $48 $a9 $01 $28 $2c $19 $02 $08 $c9 $01 $d0 $fe +$68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $01 $28 $2c $18 $02 +$08 $c9 $01 $d0 $fe $68 $48 $c9 $bf $d0 $fe $28 $a9 $ff $48 $a9 +$01 $28 $2c $17 $02 $08 $c9 $01 $d0 $fe $68 $48 $c9 $fd $d0 $fe +$28 $ad $00 $02 $c9 $19 $d0 $fe $a9 $1a $8d $00 $02 $a9 $00 $48 +$a2 $80 $28 $e4 $17 $08 $68 $48 $c9 $31 $d0 $fe $28 $ca $e4 $17 +$08 $68 $48 $c9 $33 $d0 $fe $28 $ca $e4 $17 $08 $e0 $7e $d0 $fe +$68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a2 $80 $28 $e4 $17 $08 +$68 $48 $c9 $7d $d0 $fe $28 $ca $e4 $17 $08 $68 $48 $c9 $7f $d0 +$fe $28 $ca $e4 $17 $08 $e0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a2 $80 $28 $ec $1b $02 $08 $68 $48 $c9 $31 $d0 +$fe $28 $ca $ec $1b $02 $08 $68 $48 $c9 $33 $d0 $fe $28 $ca $ec +$1b $02 $08 $e0 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff +$48 $a2 $80 $28 $ec $1b $02 $08 $68 $48 $c9 $7d $d0 $fe $28 $ca +$ec $1b $02 $08 $68 $48 $c9 $7f $d0 $fe $28 $ca $ec $1b $02 $08 +$e0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 $00 $48 $a2 $80 +$28 $e0 $7f $08 $68 $48 $c9 $31 $d0 $fe $28 $ca $e0 $7f $08 $68 +$48 $c9 $33 $d0 $fe $28 $ca $e0 $7f $08 $e0 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a2 $80 $28 $e0 $7f $08 $68 $48 +$c9 $7d $d0 $fe $28 $ca $e0 $7f $08 $68 $48 $c9 $7f $d0 $fe $28 +$ca $e0 $7f $08 $e0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $ad +$00 $02 $c9 $1a $d0 $fe $a9 $1b $8d $00 $02 $a9 $00 $48 $a0 $80 +$28 $c4 $17 $08 $68 $48 $c9 $31 $d0 $fe $28 $88 $c4 $17 $08 $68 +$48 $c9 $33 $d0 $fe $28 $88 $c4 $17 $08 $c0 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a0 $80 $28 $c4 $17 $08 $68 $48 +$c9 $7d $d0 $fe $28 $88 $c4 $17 $08 $68 $48 $c9 $7f $d0 $fe $28 +$88 $c4 $17 $08 $c0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 +$00 $48 $a0 $80 $28 $cc $1b $02 $08 $68 $48 $c9 $31 $d0 $fe $28 +$88 $cc $1b $02 $08 $68 $48 $c9 $33 $d0 $fe $28 $88 $cc $1b $02 +$08 $c0 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a0 +$80 $28 $cc $1b $02 $08 $68 $48 $c9 $7d $d0 $fe $28 $88 $cc $1b +$02 $08 $68 $48 $c9 $7f $d0 $fe $28 $88 $cc $1b $02 $08 $c0 $7e +$d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 $00 $48 $a0 $80 $28 $c0 +$7f $08 $68 $48 $c9 $31 $d0 $fe $28 $88 $c0 $7f $08 $68 $48 $c9 +$33 $d0 $fe $28 $88 $c0 $7f $08 $c0 $7e $d0 $fe $68 $48 $c9 $b0 +$d0 $fe $28 $a9 $ff $48 $a0 $80 $28 $c0 $7f $08 $68 $48 $c9 $7d +$d0 $fe $28 $88 $c0 $7f $08 $68 $48 $c9 $7f $d0 $fe $28 $88 $c0 +$7f $08 $c0 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $ad $00 $02 +$c9 $1b $d0 $fe $a9 $1c $8d $00 $02 $a9 $00 $48 $a9 $80 $28 $c5 +$17 $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 +$a9 $7f $28 $c5 $17 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe +$28 $a9 $00 $48 $a9 $7e $28 $c5 $17 $08 $c9 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 $28 $c5 $17 $08 $c9 $80 +$d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $c5 +$17 $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 +$a9 $7e $28 $c5 $17 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a9 $80 $28 $cd $1b $02 $08 $c9 $80 $d0 $fe $68 +$48 $c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $cd $1b $02 $08 +$c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e +$28 $cd $1b $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 +$a9 $ff $48 $a9 $80 $28 $cd $1b $02 $08 $c9 $80 $d0 $fe $68 $48 +$c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $cd $1b $02 $08 $c9 +$7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 $7e $28 +$cd $1b $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 +$00 $48 $a9 $80 $28 $c9 $7f $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 +$d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $c9 $7f $08 $c9 $7f $d0 $fe +$68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e $28 $c9 $7f $08 +$c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 +$28 $c9 $7f $08 $c9 $80 $d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 +$ff $48 $a9 $7f $28 $c9 $7f $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f +$d0 $fe $28 $a9 $ff $48 $a9 $7e $28 $c9 $7f $08 $c9 $7e $d0 $fe +$68 $48 $c9 $fc $d0 $fe $28 $a2 $04 $a9 $00 $48 $a9 $80 $28 $d5 +$13 $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 +$a9 $7f $28 $d5 $13 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe +$28 $a9 $00 $48 $a9 $7e $28 $d5 $13 $08 $c9 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 $28 $d5 $13 $08 $c9 $80 +$d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $d5 +$13 $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 +$a9 $7e $28 $d5 $13 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a9 $80 $28 $dd $17 $02 $08 $c9 $80 $d0 $fe $68 +$48 $c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $dd $17 $02 $08 +$c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e +$28 $dd $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 +$a9 $ff $48 $a9 $80 $28 $dd $17 $02 $08 $c9 $80 $d0 $fe $68 $48 +$c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $dd $17 $02 $08 $c9 +$7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 $7e $28 +$dd $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a0 +$04 $a2 $08 $a9 $00 $48 $a9 $80 $28 $d9 $17 $02 $08 $c9 $80 $d0 +$fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $d9 $17 +$02 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 +$a9 $7e $28 $d9 $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 +$fe $28 $a9 $ff $48 $a9 $80 $28 $d9 $17 $02 $08 $c9 $80 $d0 $fe +$68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $d9 $17 $02 +$08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 +$7e $28 $d9 $17 $02 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $a9 $00 $48 $a9 $80 $28 $c1 $24 $08 $c9 $80 $d0 $fe $68 $48 +$c9 $31 $d0 $fe $28 $a9 $00 $48 $a9 $7f $28 $c1 $24 $08 $c9 $7f +$d0 $fe $68 $48 $c9 $33 $d0 $fe $28 $a9 $00 $48 $a9 $7e $28 $c1 +$24 $08 $c9 $7e $d0 $fe $68 $48 $c9 $b0 $d0 $fe $28 $a9 $ff $48 +$a9 $80 $28 $c1 $24 $08 $c9 $80 $d0 $fe $68 $48 $c9 $7d $d0 $fe +$28 $a9 $ff $48 $a9 $7f $28 $c1 $24 $08 $c9 $7f $d0 $fe $68 $48 +$c9 $7f $d0 $fe $28 $a9 $ff $48 $a9 $7e $28 $c1 $24 $08 $c9 $7e +$d0 $fe $68 $48 $c9 $fc $d0 $fe $28 $a9 $00 $48 $a9 $80 $28 $d1 +$24 $08 $c9 $80 $d0 $fe $68 $48 $c9 $31 $d0 $fe $28 $a9 $00 $48 +$a9 $7f $28 $d1 $24 $08 $c9 $7f $d0 $fe $68 $48 $c9 $33 $d0 $fe +$28 $a9 $00 $48 $a9 $7e $28 $d1 $24 $08 $c9 $7e $d0 $fe $68 $48 +$c9 $b0 $d0 $fe $28 $a9 $ff $48 $a9 $80 $28 $d1 $24 $08 $c9 $80 +$d0 $fe $68 $48 $c9 $7d $d0 $fe $28 $a9 $ff $48 $a9 $7f $28 $d1 +$24 $08 $c9 $7f $d0 $fe $68 $48 $c9 $7f $d0 $fe $28 $a9 $ff $48 +$a9 $7e $28 $d1 $24 $08 $c9 $7e $d0 $fe $68 $48 $c9 $fc $d0 $fe +$28 $ad $00 $02 $c9 $1c $d0 $fe $a9 $1d $8d $00 $02 $a2 $03 $a9 +$00 $48 $b5 $13 $28 $0a $08 $dd $20 $02 $d0 $fe $68 $49 $30 $dd +$30 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $ff $48 $b5 $13 $28 $0a +$08 $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 +$e8 $a2 $03 $a9 $00 $48 $b5 $13 $28 $4a $08 $dd $28 $02 $d0 $fe +$68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $ff $48 +$b5 $13 $28 $4a $08 $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 +$d0 $fe $ca $10 $e8 $a2 $03 $a9 $00 $48 $b5 $13 $28 $2a $08 $dd +$20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e8 $a2 +$03 $a9 $fe $48 $b5 $13 $28 $2a $08 $dd $20 $02 $d0 $fe $68 $49 +$7c $dd $30 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $01 $48 $b5 $13 +$28 $2a $08 $dd $24 $02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe +$ca $10 $e8 $a2 $03 $a9 $ff $48 $b5 $13 $28 $2a $08 $dd $24 $02 +$d0 $fe $68 $49 $7c $dd $34 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 +$00 $48 $b5 $13 $28 $6a $08 $dd $28 $02 $d0 $fe $68 $49 $30 $dd +$38 $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $fe $48 $b5 $13 $28 $6a +$08 $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 +$e8 $a2 $03 $a9 $01 $48 $b5 $13 $28 $6a $08 $dd $2c $02 $d0 $fe +$68 $49 $30 $dd $3c $02 $d0 $fe $ca $10 $e8 $a2 $03 $a9 $ff $48 +$b5 $13 $28 $6a $08 $dd $2c $02 $d0 $fe $68 $49 $7c $dd $3c $02 +$d0 $fe $ca $10 $e8 $ad $00 $02 $c9 $1d $d0 $fe $a9 $1e $8d $00 +$02 $a2 $03 $a9 $00 $48 $b5 $13 $85 $0c $28 $06 $0c $08 $a5 $0c +$dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e3 +$a2 $03 $a9 $ff $48 $b5 $13 $85 $0c $28 $06 $0c $08 $a5 $0c $dd +$20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 +$03 $a9 $00 $48 $b5 $13 $85 $0c $28 $46 $0c $08 $a5 $0c $dd $28 +$02 $d0 $fe $68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 +$a9 $ff $48 $b5 $13 $85 $0c $28 $46 $0c $08 $a5 $0c $dd $28 $02 +$d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 +$00 $48 $b5 $13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $20 $02 $d0 +$fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $fe +$48 $b5 $13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $20 $02 $d0 $fe +$68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $01 $48 +$b5 $13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $24 $02 $d0 $fe $68 +$49 $30 $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 +$13 $85 $0c $28 $26 $0c $08 $a5 $0c $dd $24 $02 $d0 $fe $68 $49 +$7c $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $00 $48 $b5 $13 +$85 $0c $28 $66 $0c $08 $a5 $0c $dd $28 $02 $d0 $fe $68 $49 $30 +$dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $fe $48 $b5 $13 $85 +$0c $28 $66 $0c $08 $a5 $0c $dd $28 $02 $d0 $fe $68 $49 $7c $dd +$38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $01 $48 $b5 $13 $85 $0c +$28 $66 $0c $08 $a5 $0c $dd $2c $02 $d0 $fe $68 $49 $30 $dd $3c +$02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 $13 $85 $0c $28 +$66 $0c $08 $a5 $0c $dd $2c $02 $d0 $fe $68 $49 $7c $dd $3c $02 +$d0 $fe $ca $10 $e3 $ad $00 $02 $c9 $1e $d0 $fe $a9 $1f $8d $00 +$02 $a2 $03 $a9 $00 $48 $b5 $13 $8d $03 $02 $28 $0e $03 $02 $08 +$ad $03 $02 $dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $8d $03 $02 $28 $0e $03 +$02 $08 $ad $03 $02 $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 $8d $03 $02 $28 +$4e $03 $02 $08 $ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 $30 $dd +$38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $8d $03 +$02 $28 $4e $03 $02 $08 $ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 +$7c $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 +$8d $03 $02 $28 $2e $03 $02 $08 $ad $03 $02 $dd $20 $02 $d0 $fe +$68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $fe $48 +$b5 $13 $8d $03 $02 $28 $2e $03 $02 $08 $ad $03 $02 $dd $20 $02 +$d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 +$01 $48 $b5 $13 $8d $03 $02 $28 $2e $03 $02 $08 $ad $03 $02 $dd +$24 $02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $a9 $ff $48 $b5 $13 $8d $03 $02 $28 $2e $03 $02 $08 $ad $03 +$02 $dd $24 $02 $d0 $fe $68 $49 $7c $dd $34 $02 $d0 $fe $ca $10 +$e0 $a2 $03 $a9 $00 $48 $b5 $13 $8d $03 $02 $28 $6e $03 $02 $08 +$ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 $30 $dd $38 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $a9 $fe $48 $b5 $13 $8d $03 $02 $28 $6e $03 +$02 $08 $ad $03 $02 $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $a9 $01 $48 $b5 $13 $8d $03 $02 $28 +$6e $03 $02 $08 $ad $03 $02 $dd $2c $02 $d0 $fe $68 $49 $30 $dd +$3c $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $8d $03 +$02 $28 $6e $03 $02 $08 $ad $03 $02 $dd $2c $02 $d0 $fe $68 $49 +$7c $dd $3c $02 $d0 $fe $ca $10 $e0 $ad $00 $02 $c9 $1f $d0 $fe +$a9 $20 $8d $00 $02 $a2 $03 $a9 $00 $48 $b5 $13 $95 $0c $28 $16 +$0c $08 $b5 $0c $dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 +$fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 $13 $95 $0c $28 $16 $0c +$08 $b5 $0c $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe +$ca $10 $e3 $a2 $03 $a9 $00 $48 $b5 $13 $95 $0c $28 $56 $0c $08 +$b5 $0c $dd $28 $02 $d0 $fe $68 $49 $30 $dd $38 $02 $d0 $fe $ca +$10 $e3 $a2 $03 $a9 $ff $48 $b5 $13 $95 $0c $28 $56 $0c $08 $b5 +$0c $dd $28 $02 $d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 +$e3 $a2 $03 $a9 $00 $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c +$dd $20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e3 +$a2 $03 $a9 $fe $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c $dd +$20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 $e3 $a2 +$03 $a9 $01 $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c $dd $24 +$02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 +$a9 $ff $48 $b5 $13 $95 $0c $28 $36 $0c $08 $b5 $0c $dd $24 $02 +$d0 $fe $68 $49 $7c $dd $34 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 +$00 $48 $b5 $13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $28 $02 $d0 +$fe $68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $fe +$48 $b5 $13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $28 $02 $d0 $fe +$68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $01 $48 +$b5 $13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $2c $02 $d0 $fe $68 +$49 $30 $dd $3c $02 $d0 $fe $ca $10 $e3 $a2 $03 $a9 $ff $48 $b5 +$13 $95 $0c $28 $76 $0c $08 $b5 $0c $dd $2c $02 $d0 $fe $68 $49 +$7c $dd $3c $02 $d0 $fe $ca $10 $e3 $ad $00 $02 $c9 $20 $d0 $fe +$a9 $21 $8d $00 $02 $a2 $03 $a9 $00 $48 $b5 $13 $9d $03 $02 $28 +$1e $03 $02 $08 $bd $03 $02 $dd $20 $02 $d0 $fe $68 $49 $30 $dd +$30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $9d $03 +$02 $28 $1e $03 $02 $08 $bd $03 $02 $dd $20 $02 $d0 $fe $68 $49 +$7c $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 +$9d $03 $02 $28 $5e $03 $02 $08 $bd $03 $02 $dd $28 $02 $d0 $fe +$68 $49 $30 $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 +$b5 $13 $9d $03 $02 $28 $5e $03 $02 $08 $bd $03 $02 $dd $28 $02 +$d0 $fe $68 $49 $7c $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 +$00 $48 $b5 $13 $9d $03 $02 $28 $3e $03 $02 $08 $bd $03 $02 $dd +$20 $02 $d0 $fe $68 $49 $30 $dd $30 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $a9 $fe $48 $b5 $13 $9d $03 $02 $28 $3e $03 $02 $08 $bd $03 +$02 $dd $20 $02 $d0 $fe $68 $49 $7c $dd $30 $02 $d0 $fe $ca $10 +$e0 $a2 $03 $a9 $01 $48 $b5 $13 $9d $03 $02 $28 $3e $03 $02 $08 +$bd $03 $02 $dd $24 $02 $d0 $fe $68 $49 $30 $dd $34 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $a9 $ff $48 $b5 $13 $9d $03 $02 $28 $3e $03 +$02 $08 $bd $03 $02 $dd $24 $02 $d0 $fe $68 $49 $7c $dd $34 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $a9 $00 $48 $b5 $13 $9d $03 $02 $28 +$7e $03 $02 $08 $bd $03 $02 $dd $28 $02 $d0 $fe $68 $49 $30 $dd +$38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $fe $48 $b5 $13 $9d $03 +$02 $28 $7e $03 $02 $08 $bd $03 $02 $dd $28 $02 $d0 $fe $68 $49 +$7c $dd $38 $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $01 $48 $b5 $13 +$9d $03 $02 $28 $7e $03 $02 $08 $bd $03 $02 $dd $2c $02 $d0 $fe +$68 $49 $30 $dd $3c $02 $d0 $fe $ca $10 $e0 $a2 $03 $a9 $ff $48 +$b5 $13 $9d $03 $02 $28 $7e $03 $02 $08 $bd $03 $02 $dd $2c $02 +$d0 $fe $68 $49 $7c $dd $3c $02 $d0 $fe $ca $10 $e0 $ad $00 $02 +$c9 $21 $d0 $fe $a9 $22 $8d $00 $02 $a2 $00 $a9 $7e $85 $0c $a9 +$00 $48 $28 $e6 $0c $08 $a5 $0c $dd $40 $02 $d0 $fe $68 $49 $30 +$dd $45 $02 $d0 $fe $e8 $e0 $02 $d0 $04 $a9 $fe $85 $0c $e0 $05 +$d0 $dd $ca $e6 $0c $a9 $00 $48 $28 $c6 $0c $08 $a5 $0c $dd $40 +$02 $d0 $fe $68 $49 $30 $dd $45 $02 $d0 $fe $ca $30 $0a $e0 $01 +$d0 $e3 $a9 $81 $85 $0c $d0 $dd $a2 $00 $a9 $7e $85 $0c $a9 $ff +$48 $28 $e6 $0c $08 $a5 $0c $dd $40 $02 $d0 $fe $68 $49 $7d $dd +$45 $02 $d0 $fe $e8 $e0 $02 $d0 $04 $a9 $fe $85 $0c $e0 $05 $d0 +$dd $ca $e6 $0c $a9 $ff $48 $28 $c6 $0c $08 $a5 $0c $dd $40 $02 +$d0 $fe $68 $49 $7d $dd $45 $02 $d0 $fe $ca $30 $0a $e0 $01 $d0 +$e3 $a9 $81 $85 $0c $d0 $dd $ad $00 $02 $c9 $22 $d0 $fe $a9 $23 +$8d $00 $02 $a2 $00 $a9 $7e $8d $03 $02 $a9 $00 $48 $28 $ee $03 +$02 $08 $ad $03 $02 $dd $40 $02 $d0 $fe $68 $49 $30 $dd $45 $02 +$d0 $fe $e8 $e0 $02 $d0 $05 $a9 $fe $8d $03 $02 $e0 $05 $d0 $da +$ca $ee $03 $02 $a9 $00 $48 $28 $ce $03 $02 $08 $ad $03 $02 $dd +$40 $02 $d0 $fe $68 $49 $30 $dd $45 $02 $d0 $fe $ca $30 $0b $e0 +$01 $d0 $e1 $a9 $81 $8d $03 $02 $d0 $da $a2 $00 $a9 $7e $8d $03 +$02 $a9 $ff $48 $28 $ee $03 $02 $08 $ad $03 $02 $dd $40 $02 $d0 +$fe $68 $49 $7d $dd $45 $02 $d0 $fe $e8 $e0 $02 $d0 $05 $a9 $fe +$8d $03 $02 $e0 $05 $d0 $da $ca $ee $03 $02 $a9 $ff $48 $28 $ce +$03 $02 $08 $ad $03 $02 $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 +$02 $d0 $fe $ca $30 $0b $e0 $01 $d0 $e1 $a9 $81 $8d $03 $02 $d0 +$da $ad $00 $02 $c9 $23 $d0 $fe $a9 $24 $8d $00 $02 $a2 $00 $a9 +$7e $95 $0c $a9 $00 $48 $28 $f6 $0c $08 $b5 $0c $dd $40 $02 $d0 +$fe $68 $49 $30 $dd $45 $02 $d0 $fe $b5 $0c $e8 $e0 $02 $d0 $02 +$a9 $fe $e0 $05 $d0 $db $ca $a9 $02 $95 $0c $a9 $00 $48 $28 $d6 +$0c $08 $b5 $0c $dd $40 $02 $d0 $fe $68 $49 $30 $dd $45 $02 $d0 +$fe $b5 $0c $ca $30 $08 $e0 $01 $d0 $df $a9 $81 $d0 $db $a2 $00 +$a9 $7e $95 $0c $a9 $ff $48 $28 $f6 $0c $08 $b5 $0c $dd $40 $02 +$d0 $fe $68 $49 $7d $dd $45 $02 $d0 $fe $b5 $0c $e8 $e0 $02 $d0 +$02 $a9 $fe $e0 $05 $d0 $db $ca $a9 $02 $95 $0c $a9 $ff $48 $28 +$d6 $0c $08 $b5 $0c $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 $02 +$d0 $fe $b5 $0c $ca $30 $08 $e0 $01 $d0 $df $a9 $81 $d0 $db $ad +$00 $02 $c9 $24 $d0 $fe $a9 $25 $8d $00 $02 $a2 $00 $a9 $7e $9d +$03 $02 $a9 $00 $48 $28 $fe $03 $02 $08 $bd $03 $02 $dd $40 $02 +$d0 $fe $68 $49 $30 $dd $45 $02 $d0 $fe $bd $03 $02 $e8 $e0 $02 +$d0 $02 $a9 $fe $e0 $05 $d0 $d7 $ca $a9 $02 $9d $03 $02 $a9 $00 +$48 $28 $de $03 $02 $08 $bd $03 $02 $dd $40 $02 $d0 $fe $68 $49 +$30 $dd $45 $02 $d0 $fe $bd $03 $02 $ca $30 $08 $e0 $01 $d0 $db +$a9 $81 $d0 $d7 $a2 $00 $a9 $7e $9d $03 $02 $a9 $ff $48 $28 $fe +$03 $02 $08 $bd $03 $02 $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 +$02 $d0 $fe $bd $03 $02 $e8 $e0 $02 $d0 $02 $a9 $fe $e0 $05 $d0 +$d7 $ca $a9 $02 $9d $03 $02 $a9 $ff $48 $28 $de $03 $02 $08 $bd +$03 $02 $dd $40 $02 $d0 $fe $68 $49 $7d $dd $45 $02 $d0 $fe $bd +$03 $02 $ca $30 $08 $e0 $01 $d0 $db $a9 $81 $d0 $d7 $ad $00 $02 +$c9 $25 $d0 $fe $a9 $26 $8d $00 $02 $a2 $03 $b5 $1c $8d $09 $02 +$a9 $00 $48 $bd $5a $02 $28 $20 $08 $02 $08 $dd $62 $02 $d0 $fe +$68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 $1c $8d +$09 $02 $a9 $ff $48 $bd $5a $02 $28 $20 $08 $02 $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 +$1c $85 $0c $a9 $00 $48 $bd $5a $02 $28 $25 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$1c $85 $0c $a9 $ff $48 $bd $5a $02 $28 $25 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$1c $8d $03 $02 $a9 $00 $48 $bd $5a $02 $28 $2d $03 $02 $08 $dd +$62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $b5 $1c $8d $03 $02 $a9 $ff $48 $bd $5a $02 $28 $2d $03 $02 +$08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 +$02 $a2 $03 $a9 $00 $48 $bd $5a $02 $28 $35 $1c $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 +$ff $48 $bd $5a $02 $28 $35 $1c $08 $dd $62 $02 $d0 $fe $68 $49 +$7d $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 $00 $48 $bd $5a +$02 $28 $3d $4e $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 +$02 $d0 $fe $ca $10 $e5 $a2 $03 $a9 $ff $48 $bd $5a $02 $28 $3d +$4e $02 $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe +$ca $10 $e5 $a0 $03 $a9 $00 $48 $b9 $5a $02 $28 $39 $4e $02 $08 +$d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe $88 $10 $e5 +$a0 $03 $a9 $ff $48 $b9 $5a $02 $28 $39 $4e $02 $08 $d9 $62 $02 +$d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe $88 $10 $e5 $a2 $06 $a0 +$03 $a9 $00 $48 $b9 $5a $02 $28 $21 $3a $08 $d9 $62 $02 $d0 $fe +$68 $49 $30 $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a2 $06 $a0 +$03 $a9 $ff $48 $b9 $5a $02 $28 $21 $3a $08 $d9 $62 $02 $d0 $fe +$68 $49 $7d $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a0 $03 $a9 +$00 $48 $b9 $5a $02 $28 $31 $3a $08 $d9 $62 $02 $d0 $fe $68 $49 +$30 $d9 $66 $02 $d0 $fe $88 $10 $e6 $a0 $03 $a9 $ff $48 $b9 $5a +$02 $28 $31 $3a $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 +$d0 $fe $88 $10 $e6 $ad $00 $02 $c9 $26 $d0 $fe $a9 $27 $8d $00 +$02 $a2 $03 $b5 $20 $8d $0c $02 $a9 $00 $48 $bd $5e $02 $28 $20 +$0b $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe +$ca $10 $e0 $a2 $03 $b5 $20 $8d $0c $02 $a9 $ff $48 $bd $5e $02 +$28 $20 $0b $02 $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 +$d0 $fe $ca $10 $e0 $a2 $03 $b5 $20 $85 $0c $a9 $00 $48 $bd $5e +$02 $28 $45 $0c $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 +$d0 $fe $ca $10 $e2 $a2 $03 $b5 $20 $85 $0c $a9 $ff $48 $bd $5e +$02 $28 $45 $0c $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 +$d0 $fe $ca $10 $e2 $a2 $03 $b5 $20 $8d $03 $02 $a9 $00 $48 $bd +$5e $02 $28 $4d $03 $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd +$66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 $20 $8d $03 $02 $a9 $ff +$48 $bd $5e $02 $28 $4d $03 $02 $08 $dd $62 $02 $d0 $fe $68 $49 +$7d $dd $66 $02 $d0 $fe $ca $10 $02 $a2 $03 $a9 $00 $48 $bd $5e +$02 $28 $55 $20 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 +$d0 $fe $ca $10 $e6 $a2 $03 $a9 $ff $48 $bd $5e $02 $28 $55 $20 +$08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 +$e6 $a2 $03 $a9 $00 $48 $bd $5e $02 $28 $5d $52 $02 $08 $dd $62 +$02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e5 $a2 $03 +$a9 $ff $48 $bd $5e $02 $28 $5d $52 $02 $08 $dd $62 $02 $d0 $fe +$68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e5 $a0 $03 $a9 $00 $48 +$b9 $5e $02 $28 $59 $52 $02 $08 $d9 $62 $02 $d0 $fe $68 $49 $30 +$d9 $66 $02 $d0 $fe $88 $10 $e5 $a0 $03 $a9 $ff $48 $b9 $5e $02 +$28 $59 $52 $02 $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 +$d0 $fe $88 $10 $e5 $a2 $06 $a0 $03 $a9 $00 $48 $b9 $5e $02 $28 +$41 $42 $08 $d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe +$ca $ca $88 $10 $e4 $a2 $06 $a0 $03 $a9 $ff $48 $b9 $5e $02 $28 +$41 $42 $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe +$ca $ca $88 $10 $e4 $a0 $03 $a9 $00 $48 $b9 $5e $02 $28 $51 $42 +$08 $d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe $88 $10 +$e6 $a0 $03 $a9 $ff $48 $b9 $5e $02 $28 $51 $42 $08 $d9 $62 $02 +$d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe $88 $10 $e6 $ad $00 $02 +$c9 $27 $d0 $fe $a9 $28 $8d $00 $02 $a2 $03 $b5 $18 $8d $0f $02 +$a9 $00 $48 $bd $56 $02 $28 $20 $0e $02 $08 $dd $62 $02 $d0 $fe +$68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 $18 $8d +$0f $02 $a9 $ff $48 $bd $56 $02 $28 $20 $0e $02 $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 $03 $b5 +$18 $85 $0c $a9 $00 $48 $bd $56 $02 $28 $05 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$18 $85 $0c $a9 $ff $48 $bd $56 $02 $28 $05 $0c $08 $dd $62 $02 +$d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 $e2 $a2 $03 $b5 +$18 $8d $03 $02 $a9 $00 $48 $bd $56 $02 $28 $0d $03 $02 $08 $dd +$62 $02 $d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e0 $a2 +$03 $b5 $18 $8d $03 $02 $a9 $ff $48 $bd $56 $02 $28 $0d $03 $02 +$08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe $ca $10 +$02 $a2 $03 $a9 $00 $48 $bd $56 $02 $28 $15 $18 $08 $dd $62 $02 +$d0 $fe $68 $49 $30 $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 +$ff $48 $bd $56 $02 $28 $15 $18 $08 $dd $62 $02 $d0 $fe $68 $49 +$7d $dd $66 $02 $d0 $fe $ca $10 $e6 $a2 $03 $a9 $00 $48 $bd $56 +$02 $28 $1d $4a $02 $08 $dd $62 $02 $d0 $fe $68 $49 $30 $dd $66 +$02 $d0 $fe $ca $10 $e5 $a2 $03 $a9 $ff $48 $bd $56 $02 $28 $1d +$4a $02 $08 $dd $62 $02 $d0 $fe $68 $49 $7d $dd $66 $02 $d0 $fe +$ca $10 $e5 $a0 $03 $a9 $00 $48 $b9 $56 $02 $28 $19 $4a $02 $08 +$d9 $62 $02 $d0 $fe $68 $49 $30 $d9 $66 $02 $d0 $fe $88 $10 $e5 +$a0 $03 $a9 $ff $48 $b9 $56 $02 $28 $19 $4a $02 $08 $d9 $62 $02 +$d0 $fe $68 $49 $7d $d9 $66 $02 $d0 $fe $88 $10 $e5 $a2 $06 $a0 +$03 $a9 $00 $48 $b9 $56 $02 $28 $01 $4a $08 $d9 $62 $02 $d0 $fe +$68 $49 $30 $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a2 $06 $a0 +$03 $a9 $ff $48 $b9 $56 $02 $28 $01 $4a $08 $d9 $62 $02 $d0 $fe +$68 $49 $7d $d9 $66 $02 $d0 $fe $ca $ca $88 $10 $e4 $a0 $03 $a9 +$00 $48 $b9 $56 $02 $28 $11 $4a $08 $d9 $62 $02 $d0 $fe $68 $49 +$30 $d9 $66 $02 $d0 $fe $88 $10 $e6 $a0 $03 $a9 $ff $48 $b9 $56 +$02 $28 $11 $4a $08 $d9 $62 $02 $d0 $fe $68 $49 $7d $d9 $66 $02 +$d0 $fe $88 $10 $e6 $58 $ad $00 $02 $c9 $28 $d0 $fe $a9 $29 $8d +$00 $02 $d8 $a2 $0e $a0 $ff $a9 $00 $85 $0c $85 $0d $85 $0e $8d +$03 $02 $85 $0f $85 $10 $a9 $ff $85 $12 $8d $04 $02 $a9 $02 $85 +$11 $18 $20 $7c $35 $e6 $0c $e6 $0f $08 $08 $68 $29 $82 $28 $d0 +$02 $e6 $10 $05 $10 $85 $11 $38 $20 $7c $35 $c6 $0c $e6 $0d $d0 +$e0 $a9 $00 $85 $10 $ee $03 $02 $e6 $0e $08 $68 $29 $82 $85 $11 +$c6 $12 $ce $04 $02 $a5 $0e $85 $0f $d0 $c6 $ad $00 $02 $c9 $29 +$d0 $fe $a9 $2a $8d $00 $02 $f8 $a2 $0e $a0 $ff $a9 $99 $85 $0d +$85 $0e $8d $03 $02 $85 $0f $a9 $01 $85 $0c $85 $10 $a9 $00 $85 +$12 $8d $04 $02 $38 $20 $49 $34 $c6 $0c $a5 $0f $d0 $08 $c6 $10 +$a9 $99 $85 $0f $d0 $12 $29 $0f $d0 $0c $c6 $0f $c6 $0f $c6 $0f +$c6 $0f $c6 $0f $c6 $0f $c6 $0f $18 $20 $49 $34 $e6 $0c $a5 $0d +$f0 $15 $29 $0f $d0 $0c $c6 $0d $c6 $0d $c6 $0d $c6 $0d $c6 $0d +$c6 $0d $c6 $0d $4c $64 $33 $a9 $99 $85 $0d $a5 $0e $f0 $30 $29 +$0f $d0 $18 $c6 $0e $c6 $0e $c6 $0e $c6 $0e $c6 $0e $c6 $0e $e6 +$12 $e6 $12 $e6 $12 $e6 $12 $e6 $12 $e6 $12 $c6 $0e $e6 $12 $a5 +$12 $8d $04 $02 $a5 $0e $8d $03 $02 $85 $0f $e6 $10 $d0 $85 $ad +$00 $02 $c9 $2a $d0 $fe $a9 $2b $8d $00 $02 $18 $d8 $08 $a9 $55 +$69 $55 $c9 $aa $d0 $fe $18 $f8 $08 $a9 $55 $69 $55 $c9 $10 $d0 +$fe $d8 $28 $a9 $55 $69 $55 $c9 $10 $d0 $fe $28 $a9 $55 $69 $55 +$c9 $aa $d0 $fe $18 $a9 $34 $48 $a9 $2f $48 $08 $f8 $a9 $34 $48 +$a9 $26 $48 $08 $d8 $40 $a9 $55 $69 $55 $c9 $10 $d0 $fe $40 $a9 +$55 $69 $55 $c9 $aa $d0 $fe $ad $00 $02 $c9 $2b $d0 $fe $a9 $f0 +$8d $00 $02 $4c $43 $34 $4c $00 $04 $08 $a5 $0d $65 $0e $08 $c5 +$0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $e5 $12 +$08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d +$6d $03 $02 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 +$08 $a5 $0d $ed $04 $02 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 +$d0 $fe $28 $08 $a5 $0e $8d $12 $02 $a5 $0d $20 $11 $02 $08 $c5 +$0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $12 $8d $15 +$02 $a5 $0d $20 $14 $02 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 +$d0 $fe $28 $08 $a5 $0d $75 $00 $08 $c5 $0f $d0 $fe $68 $29 $01 +$c5 $10 $d0 $fe $28 $08 $a5 $0d $f5 $04 $08 $c5 $0f $d0 $fe $68 +$29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $7d $f5 $01 $08 $c5 $0f +$d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $fd $f6 $01 +$08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d +$79 $04 $01 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 +$08 $a5 $0d $f9 $05 $01 $08 $c5 $0f $d0 $fe $68 $29 $01 $c5 $10 +$d0 $fe $28 $08 $a5 $0d $61 $44 $08 $c5 $0f $d0 $fe $68 $29 $01 +$c5 $10 $d0 $fe $28 $08 $a5 $0d $e1 $46 $08 $c5 $0f $d0 $fe $68 +$29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $71 $56 $08 $c5 $0f $d0 +$fe $68 $29 $01 $c5 $10 $d0 $fe $28 $08 $a5 $0d $f1 $58 $08 $c5 +$0f $d0 $fe $68 $29 $01 $c5 $10 $d0 $fe $28 $60 $a5 $11 $29 $83 +$48 $a5 $0d $45 $0e $30 $0a $a5 $0d $45 $0f $10 $04 $68 $09 $40 +$48 $68 $85 $11 $08 $a5 $0d $65 $0e $08 $c5 $0f $d0 $fe $68 $29 +$c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $e5 $12 $08 $c5 $0f $d0 $fe +$68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $6d $03 $02 $08 $c5 +$0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $ed $04 +$02 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 +$0e $8d $12 $02 $a5 $0d $20 $11 $02 $08 $c5 $0f $d0 $fe $68 $29 +$c3 $c5 $11 $d0 $fe $28 $08 $a5 $12 $8d $15 $02 $a5 $0d $20 $14 +$02 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 +$0d $75 $00 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 +$08 $a5 $0d $f5 $04 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 +$fe $28 $08 $a5 $0d $7d $f5 $01 $08 $c5 $0f $d0 $fe $68 $29 $c3 +$c5 $11 $d0 $fe $28 $08 $a5 $0d $fd $f6 $01 $08 $c5 $0f $d0 $fe +$68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $79 $04 $01 $08 $c5 +$0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 $0d $f9 $05 +$01 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 $08 $a5 +$0d $61 $44 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 $fe $28 +$08 $a5 $0d $e1 $46 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 $11 $d0 +$fe $28 $08 $a5 $0d $71 $56 $08 $c5 $0f $d0 $fe $68 $29 $c3 $c5 +$11 $d0 $fe $28 $08 $a5 $0d $f1 $58 $08 $c5 $0f $d0 $fe $68 $29 +$c3 $c5 $11 $d0 $fe $28 $60 $88 $88 $08 $88 $88 $88 $28 $b0 $fe +$70 $fe $30 $fe $f0 $fe $c9 $46 $d0 $fe $e0 $41 $d0 $fe $c0 $4f +$d0 $fe $48 $8a $48 $ba $e0 $fd $d0 $fe $68 $aa $a9 $ff $48 $28 +$68 $e8 $49 $aa $4c $0f $09 $00 $01 $37 $64 $09 $4c $fc $36 $88 +$88 $08 $88 $88 $88 $28 $b0 $fe $70 $fe $30 $fe $f0 $fe $c9 $49 +$d0 $fe $e0 $4e $d0 $fe $c0 $41 $d0 $fe $48 $8a $48 $ba $e0 $fd +$d0 $fe $68 $aa $a9 $ff $48 $28 $68 $e8 $49 $aa $6c $fa $36 $4c +$2f $37 $88 $88 $08 $88 $88 $88 $28 $b0 $fe $70 $fe $30 $fe $f0 +$fe $c9 $4a $d0 $fe $e0 $53 $d0 $fe $c0 $4f $d0 $fe $48 $8a $48 +$ba $e0 $fb $d0 $fe $ad $ff $01 $c9 $09 $d0 $fe $ad $fe $01 $c9 +$9a $d0 $fe $a9 $ff $48 $28 $68 $aa $68 $e8 $49 $aa $60 $4c $6e +$37 $4c $71 $37 $4c $74 $37 $88 $88 $08 $88 $88 $88 $c9 $42 $d0 +$fe $e0 $52 $d0 $fe $c0 $48 $d0 $fe $85 $0a $86 $0b $ba $bd $02 +$01 $c9 $30 $d0 $fe $68 $c9 $34 $d0 $fe $ba $e0 $fc $d0 $fe $ad +$ff $01 $c9 $09 $d0 $fe $ad $fe $01 $c9 $d1 $d0 $fe $a9 $ff $48 +$28 $a6 $0b $e8 $a5 $0a $49 $aa $40 $4c $b9 $37 $00 $00 $00 $00 +ORG +$fff0 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $71 $37 $74 $37 $79 $37 +EXEC +$0400 diff --git a/6502_func_test.lst b/6502_func_test.lst new file mode 100644 index 0000000..02f070b --- /dev/null +++ b/6502_func_test.lst @@ -0,0 +1,14236 @@ +AS65 Assembler for R6502 [1.42]. Page 1 +-------------------------- 6502_functional_test.asm -------------------------- + +6010 lines read, no errors in pass 1. + ; + ; 6 5 0 2 F U N C T I O N A L T E S T + ; + ; Copyright (C) 2012-2015 Klaus Dormann + ; + ; This program is free software: you can redistribute + ; it under the terms of the GNU General Public License + ; the Free Software Foundation, either version 3 of th + ; (at your option) any later version. + ; + ; This program is distributed in the hope that it will + ; but WITHOUT ANY WARRANTY; without even the implied w + ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + ; GNU General Public License for more details. + ; + ; You should have received a copy of the GNU General P + ; along with this program. If not, see -1 + check_ram macro + cld + lda #0 + sta zpt ;set low byte of indirect + sta zpt+3 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write te + ccs3\? adc zero_page,x + bcc ccs2\? + inc zpt+3 ;carry to high byte + clc + ccs2\? inx + bne ccs3\? + ldx #hi(abs1) ;set high byte of indirect + stx zpt+1 + ldy #lo(abs1) ;data after write & execut + ccs5\? adc (zpt),y + bcc ccs4\? + inc zpt+3 ;carry to high byte + clc + ccs4\? iny + bne ccs5\? + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne ccs5\? + sta zpt+2 ;checksum low is + cmp ram_chksm ;checksum low expected + trap_ne ;checksum mismatch + lda zpt+3 ;checksum high is + cmp ram_chksm+1 ;checksum high expected + trap_ne ;checksum mismatch + endm + else + check_ram macro + ;RAM check disabled - RAM size not set + endm + endif + + next_test macro ;make sure, tests don't ju + lda test_case ;previous test + cmp #test_num + trap_ne ;test is out of sequence + test_num = test_num + 1 + lda #test_num ;*** next tests' number + sta test_case + ;check_ram ;uncomment to find altere + endm + + if load_data_direct = 1 + data + else + bss ;uninitialized segment, co + endif +0000 = org 0 ;edited to load from 0x0000 (w +0000 : 00000000000000.. ds zero_page ;see above (this line added) + ;break test interrupt save +000a : 00 irq_a ds 1 ;a register +000b : 00 irq_x ds 1 ;x register + if I_flag = 2 + ;masking for I bit in status + flag_I_on ds 1 ;or mask to load flags + flag_I_off ds 1 ;and mask to load flags + endif +000c : zpt ;5 bytes store/modify test + ;add/subtract operand generation and result/flag predi +000c : 00 adfc ds 1 ;carry flag before op +000d : 00 ad1 ds 1 ;operand 1 - accumulator +000e : 00 ad2 ds 1 ;operand 2 - memory / imme +000f : 00 adrl ds 1 ;expected result bits 0-7 +0010 : 00 adrh ds 1 ;expected result bit 8 (ca +0011 : 00 adrf ds 1 ;expected flags NV0000ZC ( +0012 : 00 sb2 ds 1 ;operand 2 complemented fo +0013 : zp_bss +0013 : c3824100 zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT +0017 : 7f zp7f db $7f ;test pattern for compare + ;logical zeropage operands +0018 : 001f7180 zpOR db 0,$1f,$71,$80 ;test pattern for OR +001c : 0fff7f80 zpAN db $0f,$ff,$7f,$80 ;test pattern for AND +0020 : ff0f8f8f zpEO db $ff,$0f,$8f,$8f ;test pattern for EOR + ;indirect addressing pointers +0024 : 1702 ind1 dw abs1 ;indirect pointer to patte +0026 : 1802 dw abs1+1 +0028 : 1902 dw abs1+2 +002a : 1a02 dw abs1+3 +002c : 1b02 dw abs7f +002e : 1f01 inw1 dw abs1-$f8 ;indirect pointer for wrap +0030 : 0302 indt dw abst ;indirect pointer to store +0032 : 0402 dw abst+1 +0034 : 0502 dw abst+2 +0036 : 0602 dw abst+3 +0038 : 0b01 inwt dw abst-$f8 ;indirect pointer for wrap +003a : 4e02 indAN dw absAN ;indirect pointer to AND p +003c : 4f02 dw absAN+1 +003e : 5002 dw absAN+2 +0040 : 5102 dw absAN+3 +0042 : 5202 indEO dw absEO ;indirect pointer to EOR p +0044 : 5302 dw absEO+1 +0046 : 5402 dw absEO+2 +0048 : 5502 dw absEO+3 +004a : 4a02 indOR dw absOR ;indirect pointer to OR pa +004c : 4b02 dw absOR+1 +004e : 4c02 dw absOR+2 +0050 : 4d02 dw absOR+3 + ;add/subtract indirect pointers +0052 : 0302 adi2 dw ada2 ;indirect pointer to opera +0054 : 0402 sbi2 dw sba2 ;indirect pointer to compl +0056 : 0401 adiy2 dw ada2-$ff ;with offset for indirect +0058 : 0501 sbiy2 dw sba2-$ff +005a : zp_bss_end + +0200 = org data_segment +0200 : 00 test_case ds 1 ;current test number +0201 : 0000 ram_chksm ds 2 ;checksum for RAM integrit + ;add/subtract operand copy - abs tests write area +0203 : abst ;5 bytes store/modify test +0203 : 00 ada2 ds 1 ;operand 2 +0204 : 00 sba2 ds 1 ;operand 2 complemented fo +0205 : 000000 ds 3 ;fill remaining bytes +0208 : data_bss + if load_data_direct = 1 +0208 : 2900 ex_andi and #0 ;execute immediate opcodes +020a : 60 rts +020b : 4900 ex_eori eor #0 ;execute immediate opcodes +020d : 60 rts +020e : 0900 ex_orai ora #0 ;execute immediate opcodes +0210 : 60 rts +0211 : 6900 ex_adci adc #0 ;execute immediate opcodes +0213 : 60 rts +0214 : e900 ex_sbci sbc #0 ;execute immediate opcodes +0216 : 60 rts + else + ex_andi ds 3 + ex_eori ds 3 + ex_orai ds 3 + ex_adci ds 3 + ex_sbci ds 3 + endif +0217 : c3824100 abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT +021b : 7f abs7f db $7f ;test pattern for compare + ;loads +021c : 80800002 fLDx db fn,fn,0,fz ;expected flags for load + ;shifts +0220 : rASL ;expected result ASL & ROL +0220 : 86048200 rROL db $86,$04,$82,0 ; " +0224 : 87058301 rROLc db $87,$05,$83,1 ;expected result ROL +carr +0228 : rLSR ;expected result LSR & ROR +0228 : 61412000 rROR db $61,$41,$20,0 ; " +022c : e1c1a080 rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carr +0230 : fASL ;expected flags for shifts +0230 : 81018002 fROL db fnc,fc,fn,fz ;no carry in +0234 : 81018000 fROLc db fnc,fc,fn,0 ;carry in +0238 : fLSR +0238 : 01000102 fROR db fc,0,fc,fz ;no carry in +023c : 81808180 fRORc db fnc,fn,fnc,fn ;carry in + ;increments (decrements) +0240 : 7f80ff0001 rINC db $7f,$80,$ff,0,1 ;expected result for INC/D +0245 : 0080800200 fINC db 0,fn,fn,fz,0 ;expected flags for INC/DE + ;logical memory operand +024a : 001f7180 absOR db 0,$1f,$71,$80 ;test pattern for OR +024e : 0fff7f80 absAN db $0f,$ff,$7f,$80 ;test pattern for AND +0252 : ff0f8f8f absEO db $ff,$0f,$8f,$8f ;test pattern for EOR + ;logical accu operand +0256 : 00f11f00 absORa db 0,$f1,$1f,0 ;test pattern for OR +025a : f0ffffff absANa db $f0,$ff,$ff,$ff ;test pattern for AND +025e : fff0f00f absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR + ;logical results +0262 : 00ff7f80 absrlo db 0,$ff,$7f,$80 +0266 : 02800080 absflo db fz,fn,0,fn +026a : data_bss_end + + + code +0400 = org code_segment +0400 : d8 start cld +0401 : a2ff ldx #$ff +0403 : 9a txs +0404 : a900 lda #0 ;*** test 0 = initialize +0406 : 8d0002 sta test_case +0000 = test_num = 0 + + ;stop interrupts before initializing BSS + if I_flag = 1 + sei + endif + + ;initialize I/O for report channel + if report = 1 + jsr report_init + endif + + ;pretest small branch offset +0409 : a205 ldx #5 +040b : 4c3304 jmp psb_test +040e : psb_bwok +040e : a005 ldy #5 +0410 : d008 bne psb_forw + trap ;branch should be taken +0412 : 4c1204 > jmp * ;failed anyway + +0415 : 88 dey ;forward landing zone +0416 : 88 dey +0417 : 88 dey +0418 : 88 dey +0419 : 88 dey +041a : psb_forw +041a : 88 dey +041b : 88 dey +041c : 88 dey +041d : 88 dey +041e : 88 dey +041f : f017 beq psb_fwok + trap ;forward offset +0421 : 4c2104 > jmp * ;failed anyway + + +0424 : ca dex ;backward landing zone +0425 : ca dex +0426 : ca dex +0427 : ca dex +0428 : ca dex +0429 : psb_back +0429 : ca dex +042a : ca dex +042b : ca dex +042c : ca dex +042d : ca dex +042e : f0de beq psb_bwok + trap ;backward offset +0430 : 4c3004 > jmp * ;failed anyway + +0433 : psb_test +0433 : d0f4 bne psb_back + trap ;branch should be taken +0435 : 4c3504 > jmp * ;failed anyway + +0438 : psb_fwok + + ;initialize BSS segment + if load_data_direct != 1 + ldx #zp_end-zp_init-1 + ld_zp lda zp_init,x + sta zp_bss,x + dex + bpl ld_zp + ldx #data_end-data_init-1 + ld_data lda data_init,x + sta data_bss,x + dex + bpl ld_data + if ROM_vectors = 1 + ldx #5 + ld_vect lda vec_init,x + sta vec_bss,x + dex + bpl ld_vect + endif + endif + + ;retain status of interrupt flag + if I_flag = 2 + php + pla + and #4 ;isolate flag + sta flag_I_on ;or mask + eor #lo(~4) ;reverse + sta flag_I_off ;and mask + endif + + ;generate checksum for RAM integrity test + if ram_top > -1 + lda #0 + sta zpt ;set low byte of indirect poin + sta ram_chksm+1 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write test a + gcs3 adc zero_page,x + bcc gcs2 + inc ram_chksm+1 ;carry to high byte + clc + gcs2 inx + bne gcs3 + ldx #hi(abs1) ;set high byte of indirect poi + stx zpt+1 + ldy #lo(abs1) ;data after write & execute te + gcs5 adc (zpt),y + bcc gcs4 + inc ram_chksm+1 ;carry to high byte + clc + gcs4 iny + bne gcs5 + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne gcs5 + sta ram_chksm ;checksum complete + endif + next_test +0438 : ad0002 > lda test_case ;previous test +043b : c900 > cmp #test_num + > trap_ne ;test is out of sequence +043d : d0fe > bne * ;failed not equal (non zero) + > +0001 = >test_num = test_num + 1 +043f : a901 > lda #test_num ;*** next tests' number +0441 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + if disable_selfmod = 0 + ;testing relative addressing with BEQ +0444 : a0fe ldy #$fe ;testing maximum range, not -1 +0446 : range_loop +0446 : 88 dey ;next relative address +0447 : 98 tya +0448 : aa tax ;precharge count to end of loo +0449 : 1008 bpl range_fw ;calculate relative address +044b : 18 clc ;avoid branch self or to relat +044c : 6902 adc #2 +044e : ea nop ;offset landing zone - tolerat +044f : ea nop +0450 : ea nop +0451 : ea nop +0452 : ea nop +0453 : range_fw +0453 : ea nop +0454 : ea nop +0455 : ea nop +0456 : ea nop +0457 : ea nop +0458 : 497f eor #$7f ;complement except sign +045a : 8de604 sta range_adr ;load into test target +045d : a900 lda #0 ;should set zero flag in statu +045f : 4ce504 jmp range_op + +0462 : ca dex ; offset landing zone - backwa +0463 : ca dex +0464 : ca dex +0465 : ca dex +0466 : ca dex + ;relative address target field with branch und +0467 : ca dex ;-128 - max backward +0468 : ca dex +0469 : ca dex +046a : ca dex +046b : ca dex +046c : ca dex +046d : ca dex +046e : ca dex +046f : ca dex ;-120 +0470 : ca dex +0471 : ca dex +0472 : ca dex +0473 : ca dex +0474 : ca dex +0475 : ca dex +0476 : ca dex +0477 : ca dex +0478 : ca dex +0479 : ca dex ;-110 +047a : ca dex +047b : ca dex +047c : ca dex +047d : ca dex +047e : ca dex +047f : ca dex +0480 : ca dex +0481 : ca dex +0482 : ca dex +0483 : ca dex ;-100 +0484 : ca dex +0485 : ca dex +0486 : ca dex +0487 : ca dex +0488 : ca dex +0489 : ca dex +048a : ca dex +048b : ca dex +048c : ca dex +048d : ca dex ;-90 +048e : ca dex +048f : ca dex +0490 : ca dex +0491 : ca dex +0492 : ca dex +0493 : ca dex +0494 : ca dex +0495 : ca dex +0496 : ca dex +0497 : ca dex ;-80 +0498 : ca dex +0499 : ca dex +049a : ca dex +049b : ca dex +049c : ca dex +049d : ca dex +049e : ca dex +049f : ca dex +04a0 : ca dex +04a1 : ca dex ;-70 +04a2 : ca dex +04a3 : ca dex +04a4 : ca dex +04a5 : ca dex +04a6 : ca dex +04a7 : ca dex +04a8 : ca dex +04a9 : ca dex +04aa : ca dex +04ab : ca dex ;-60 +04ac : ca dex +04ad : ca dex +04ae : ca dex +04af : ca dex +04b0 : ca dex +04b1 : ca dex +04b2 : ca dex +04b3 : ca dex +04b4 : ca dex +04b5 : ca dex ;-50 +04b6 : ca dex +04b7 : ca dex +04b8 : ca dex +04b9 : ca dex +04ba : ca dex +04bb : ca dex +04bc : ca dex +04bd : ca dex +04be : ca dex +04bf : ca dex ;-40 +04c0 : ca dex +04c1 : ca dex +04c2 : ca dex +04c3 : ca dex +04c4 : ca dex +04c5 : ca dex +04c6 : ca dex +04c7 : ca dex +04c8 : ca dex +04c9 : ca dex ;-30 +04ca : ca dex +04cb : ca dex +04cc : ca dex +04cd : ca dex +04ce : ca dex +04cf : ca dex +04d0 : ca dex +04d1 : ca dex +04d2 : ca dex +04d3 : ca dex ;-20 +04d4 : ca dex +04d5 : ca dex +04d6 : ca dex +04d7 : ca dex +04d8 : ca dex +04d9 : ca dex +04da : ca dex +04db : ca dex +04dc : ca dex +04dd : ca dex ;-10 +04de : ca dex +04df : ca dex +04e0 : ca dex +04e1 : ca dex +04e2 : ca dex +04e3 : ca dex +04e4 : ca dex ;-3 +04e5 : range_op ;test target with zero flag=0, +04e6 = range_adr = *+1 ;modifiable relative address +04e5 : f03e beq *+64 ;+64 if called without modific +04e7 : ca dex ;+0 +04e8 : ca dex +04e9 : ca dex +04ea : ca dex +04eb : ca dex +04ec : ca dex +04ed : ca dex +04ee : ca dex +04ef : ca dex +04f0 : ca dex +04f1 : ca dex ;+10 +04f2 : ca dex +04f3 : ca dex +04f4 : ca dex +04f5 : ca dex +04f6 : ca dex +04f7 : ca dex +04f8 : ca dex +04f9 : ca dex +04fa : ca dex +04fb : ca dex ;+20 +04fc : ca dex +04fd : ca dex +04fe : ca dex +04ff : ca dex +0500 : ca dex +0501 : ca dex +0502 : ca dex +0503 : ca dex +0504 : ca dex +0505 : ca dex ;+30 +0506 : ca dex +0507 : ca dex +0508 : ca dex +0509 : ca dex +050a : ca dex +050b : ca dex +050c : ca dex +050d : ca dex +050e : ca dex +050f : ca dex ;+40 +0510 : ca dex +0511 : ca dex +0512 : ca dex +0513 : ca dex +0514 : ca dex +0515 : ca dex +0516 : ca dex +0517 : ca dex +0518 : ca dex +0519 : ca dex ;+50 +051a : ca dex +051b : ca dex +051c : ca dex +051d : ca dex +051e : ca dex +051f : ca dex +0520 : ca dex +0521 : ca dex +0522 : ca dex +0523 : ca dex ;+60 +0524 : ca dex +0525 : ca dex +0526 : ca dex +0527 : ca dex +0528 : ca dex +0529 : ca dex +052a : ca dex +052b : ca dex +052c : ca dex +052d : ca dex ;+70 +052e : ca dex +052f : ca dex +0530 : ca dex +0531 : ca dex +0532 : ca dex +0533 : ca dex +0534 : ca dex +0535 : ca dex +0536 : ca dex +0537 : ca dex ;+80 +0538 : ca dex +0539 : ca dex +053a : ca dex +053b : ca dex +053c : ca dex +053d : ca dex +053e : ca dex +053f : ca dex +0540 : ca dex +0541 : ca dex ;+90 +0542 : ca dex +0543 : ca dex +0544 : ca dex +0545 : ca dex +0546 : ca dex +0547 : ca dex +0548 : ca dex +0549 : ca dex +054a : ca dex +054b : ca dex ;+100 +054c : ca dex +054d : ca dex +054e : ca dex +054f : ca dex +0550 : ca dex +0551 : ca dex +0552 : ca dex +0553 : ca dex +0554 : ca dex +0555 : ca dex ;+110 +0556 : ca dex +0557 : ca dex +0558 : ca dex +0559 : ca dex +055a : ca dex +055b : ca dex +055c : ca dex +055d : ca dex +055e : ca dex +055f : ca dex ;+120 +0560 : ca dex +0561 : ca dex +0562 : ca dex +0563 : ca dex +0564 : ca dex +0565 : ca dex +0566 : ea nop ;offset landing zone - forward +0567 : ea nop +0568 : ea nop +0569 : ea nop +056a : ea nop +056b : f008 beq range_ok ;+127 - max forward + trap ; bad range +056d : 4c6d05 > jmp * ;failed anyway + +0570 : ea nop ;offset landing zone - tolerat +0571 : ea nop +0572 : ea nop +0573 : ea nop +0574 : ea nop +0575 : range_ok +0575 : ea nop +0576 : ea nop +0577 : ea nop +0578 : ea nop +0579 : ea nop +057a : c000 cpy #0 +057c : f003 beq range_end +057e : 4c4604 jmp range_loop +0581 : range_end ;range test successful + endif + next_test +0581 : ad0002 > lda test_case ;previous test +0584 : c901 > cmp #test_num + > trap_ne ;test is out of sequence +0586 : d0fe > bne * ;failed not equal (non zero) + > +0002 = >test_num = test_num + 1 +0588 : a902 > lda #test_num ;*** next tests' number +058a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ;partial test BNE & CMP, CPX, CPY immediate +058d : c001 cpy #1 ;testing BNE true +058f : d003 bne test_bne + trap +0591 : 4c9105 > jmp * ;failed anyway + +0594 : test_bne +0594 : a900 lda #0 +0596 : c900 cmp #0 ;test compare immediate + trap_ne +0598 : d0fe > bne * ;failed not equal (non zero) + + trap_cc +059a : 90fe > bcc * ;failed carry clear + + trap_mi +059c : 30fe > bmi * ;failed minus (bit 7 set) + +059e : c901 cmp #1 + trap_eq +05a0 : f0fe > beq * ;failed equal (zero) + + trap_cs +05a2 : b0fe > bcs * ;failed carry set + + trap_pl +05a4 : 10fe > bpl * ;failed plus (bit 7 clear) + +05a6 : aa tax +05a7 : e000 cpx #0 ;test compare x immediate + trap_ne +05a9 : d0fe > bne * ;failed not equal (non zero) + + trap_cc +05ab : 90fe > bcc * ;failed carry clear + + trap_mi +05ad : 30fe > bmi * ;failed minus (bit 7 set) + +05af : e001 cpx #1 + trap_eq +05b1 : f0fe > beq * ;failed equal (zero) + + trap_cs +05b3 : b0fe > bcs * ;failed carry set + + trap_pl +05b5 : 10fe > bpl * ;failed plus (bit 7 clear) + +05b7 : a8 tay +05b8 : c000 cpy #0 ;test compare y immediate + trap_ne +05ba : d0fe > bne * ;failed not equal (non zero) + + trap_cc +05bc : 90fe > bcc * ;failed carry clear + + trap_mi +05be : 30fe > bmi * ;failed minus (bit 7 set) + +05c0 : c001 cpy #1 + trap_eq +05c2 : f0fe > beq * ;failed equal (zero) + + trap_cs +05c4 : b0fe > bcs * ;failed carry set + + trap_pl +05c6 : 10fe > bpl * ;failed plus (bit 7 clear) + + next_test +05c8 : ad0002 > lda test_case ;previous test +05cb : c902 > cmp #test_num + > trap_ne ;test is out of sequence +05cd : d0fe > bne * ;failed not equal (non zero) + > +0003 = >test_num = test_num + 1 +05cf : a903 > lda #test_num ;*** next tests' number +05d1 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + ;testing stack operations PHA PHP PLA PLP + +05d4 : a2ff ldx #$ff ;initialize stack +05d6 : 9a txs +05d7 : a955 lda #$55 +05d9 : 48 pha +05da : a9aa lda #$aa +05dc : 48 pha +05dd : cdfe01 cmp $1fe ;on stack ? + trap_ne +05e0 : d0fe > bne * ;failed not equal (non zero) + +05e2 : ba tsx +05e3 : 8a txa ;overwrite accu +05e4 : c9fd cmp #$fd ;sp decremented? + trap_ne +05e6 : d0fe > bne * ;failed not equal (non zero) + +05e8 : 68 pla +05e9 : c9aa cmp #$aa ;successful retreived from sta + trap_ne +05eb : d0fe > bne * ;failed not equal (non zero) + +05ed : 68 pla +05ee : c955 cmp #$55 + trap_ne +05f0 : d0fe > bne * ;failed not equal (non zero) + +05f2 : cdff01 cmp $1ff ;remains on stack? + trap_ne +05f5 : d0fe > bne * ;failed not equal (non zero) + +05f7 : ba tsx +05f8 : e0ff cpx #$ff ;sp incremented? + trap_ne +05fa : d0fe > bne * ;failed not equal (non zero) + + next_test +05fc : ad0002 > lda test_case ;previous test +05ff : c903 > cmp #test_num + > trap_ne ;test is out of sequence +0601 : d0fe > bne * ;failed not equal (non zero) + > +0004 = >test_num = test_num + 1 +0603 : a904 > lda #test_num ;*** next tests' number +0605 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ;testing branch decisions BPL BMI BVC BVS BCC BCS BNE + set_stat $ff ;all on + > load_flag $ff +0608 : a9ff > lda #$ff ;allow test to ch + > +060a : 48 > pha ;use stack to load status +060b : 28 > plp + +060c : 101a bpl nbr1 ;branches should not be taken +060e : 501b bvc nbr2 +0610 : 901c bcc nbr3 +0612 : d01d bne nbr4 +0614 : 3003 bmi br1 ;branches should be taken + trap +0616 : 4c1606 > jmp * ;failed anyway + +0619 : 7003 br1 bvs br2 + trap +061b : 4c1b06 > jmp * ;failed anyway + +061e : b003 br2 bcs br3 + trap +0620 : 4c2006 > jmp * ;failed anyway + +0623 : f00f br3 beq br4 + trap +0625 : 4c2506 > jmp * ;failed anyway + +0628 : nbr1 + trap ;previous bpl taken +0628 : 4c2806 > jmp * ;failed anyway + +062b : nbr2 + trap ;previous bvc taken +062b : 4c2b06 > jmp * ;failed anyway + +062e : nbr3 + trap ;previous bcc taken +062e : 4c2e06 > jmp * ;failed anyway + +0631 : nbr4 + trap ;previous bne taken +0631 : 4c3106 > jmp * ;failed anyway + +0634 : 08 br4 php +0635 : ba tsx +0636 : e0fe cpx #$fe ;sp after php? + trap_ne +0638 : d0fe > bne * ;failed not equal (non zero) + +063a : 68 pla + cmp_flag $ff ;returned all flags on? +063b : c9ff > cmp #($ff |fao)&m8 ;expected flags + + + trap_ne +063d : d0fe > bne * ;failed not equal (non zero) + +063f : ba tsx +0640 : e0ff cpx #$ff ;sp after php? + trap_ne +0642 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 ;all off + > load_flag 0 +0644 : a900 > lda #0 ;allow test to ch + > +0646 : 48 > pha ;use stack to load status +0647 : 28 > plp + +0648 : 301a bmi nbr11 ;branches should not be taken +064a : 701b bvs nbr12 +064c : b01c bcs nbr13 +064e : f01d beq nbr14 +0650 : 1003 bpl br11 ;branches should be taken + trap +0652 : 4c5206 > jmp * ;failed anyway + +0655 : 5003 br11 bvc br12 + trap +0657 : 4c5706 > jmp * ;failed anyway + +065a : 9003 br12 bcc br13 + trap +065c : 4c5c06 > jmp * ;failed anyway + +065f : d00f br13 bne br14 + trap +0661 : 4c6106 > jmp * ;failed anyway + +0664 : nbr11 + trap ;previous bmi taken +0664 : 4c6406 > jmp * ;failed anyway + +0667 : nbr12 + trap ;previous bvs taken +0667 : 4c6706 > jmp * ;failed anyway + +066a : nbr13 + trap ;previous bcs taken +066a : 4c6a06 > jmp * ;failed anyway + +066d : nbr14 + trap ;previous beq taken +066d : 4c6d06 > jmp * ;failed anyway + +0670 : 08 br14 php +0671 : 68 pla + cmp_flag 0 ;flags off except break (pushe +0672 : c930 > cmp #(0 |fao)&m8 ;expected flags + + + trap_ne +0674 : d0fe > bne * ;failed not equal (non zero) + + ;crosscheck flags + set_stat zero + > load_flag zero +0676 : a902 > lda #zero ;allow test to chang + > +0678 : 48 > pha ;use stack to load status +0679 : 28 > plp + +067a : d002 bne brzs1 +067c : f003 beq brzs2 +067e : brzs1 + trap ;branch zero/non zero +067e : 4c7e06 > jmp * ;failed anyway + +0681 : b002 brzs2 bcs brzs3 +0683 : 9003 bcc brzs4 +0685 : brzs3 + trap ;branch carry/no carry +0685 : 4c8506 > jmp * ;failed anyway + +0688 : 3002 brzs4 bmi brzs5 +068a : 1003 bpl brzs6 +068c : brzs5 + trap ;branch minus/plus +068c : 4c8c06 > jmp * ;failed anyway + +068f : 7002 brzs6 bvs brzs7 +0691 : 5003 bvc brzs8 +0693 : brzs7 + trap ;branch overflow/no overflow +0693 : 4c9306 > jmp * ;failed anyway + +0696 : brzs8 + set_stat carry + > load_flag carry +0696 : a901 > lda #carry ;allow test to chan + > +0698 : 48 > pha ;use stack to load status +0699 : 28 > plp + +069a : f002 beq brcs1 +069c : d003 bne brcs2 +069e : brcs1 + trap ;branch zero/non zero +069e : 4c9e06 > jmp * ;failed anyway + +06a1 : 9002 brcs2 bcc brcs3 +06a3 : b003 bcs brcs4 +06a5 : brcs3 + trap ;branch carry/no carry +06a5 : 4ca506 > jmp * ;failed anyway + +06a8 : 3002 brcs4 bmi brcs5 +06aa : 1003 bpl brcs6 +06ac : brcs5 + trap ;branch minus/plus +06ac : 4cac06 > jmp * ;failed anyway + +06af : 7002 brcs6 bvs brcs7 +06b1 : 5003 bvc brcs8 +06b3 : brcs7 + trap ;branch overflow/no overflow +06b3 : 4cb306 > jmp * ;failed anyway + + +06b6 : brcs8 + set_stat minus + > load_flag minus +06b6 : a980 > lda #minus ;allow test to chan + > +06b8 : 48 > pha ;use stack to load status +06b9 : 28 > plp + +06ba : f002 beq brmi1 +06bc : d003 bne brmi2 +06be : brmi1 + trap ;branch zero/non zero +06be : 4cbe06 > jmp * ;failed anyway + +06c1 : b002 brmi2 bcs brmi3 +06c3 : 9003 bcc brmi4 +06c5 : brmi3 + trap ;branch carry/no carry +06c5 : 4cc506 > jmp * ;failed anyway + +06c8 : 1002 brmi4 bpl brmi5 +06ca : 3003 bmi brmi6 +06cc : brmi5 + trap ;branch minus/plus +06cc : 4ccc06 > jmp * ;failed anyway + +06cf : 7002 brmi6 bvs brmi7 +06d1 : 5003 bvc brmi8 +06d3 : brmi7 + trap ;branch overflow/no overflow +06d3 : 4cd306 > jmp * ;failed anyway + +06d6 : brmi8 + set_stat overfl + > load_flag overfl +06d6 : a940 > lda #overfl ;allow test to cha + > +06d8 : 48 > pha ;use stack to load status +06d9 : 28 > plp + +06da : f002 beq brvs1 +06dc : d003 bne brvs2 +06de : brvs1 + trap ;branch zero/non zero +06de : 4cde06 > jmp * ;failed anyway + +06e1 : b002 brvs2 bcs brvs3 +06e3 : 9003 bcc brvs4 +06e5 : brvs3 + trap ;branch carry/no carry +06e5 : 4ce506 > jmp * ;failed anyway + +06e8 : 3002 brvs4 bmi brvs5 +06ea : 1003 bpl brvs6 +06ec : brvs5 + trap ;branch minus/plus +06ec : 4cec06 > jmp * ;failed anyway + +06ef : 5002 brvs6 bvc brvs7 +06f1 : 7003 bvs brvs8 +06f3 : brvs7 + trap ;branch overflow/no overflow +06f3 : 4cf306 > jmp * ;failed anyway + +06f6 : brvs8 + set_stat $ff-zero + > load_flag $ff-zero +06f6 : a9fd > lda #$ff-zero ;allow test to c + > +06f8 : 48 > pha ;use stack to load status +06f9 : 28 > plp + +06fa : f002 beq brzc1 +06fc : d003 bne brzc2 +06fe : brzc1 + trap ;branch zero/non zero +06fe : 4cfe06 > jmp * ;failed anyway + +0701 : 9002 brzc2 bcc brzc3 +0703 : b003 bcs brzc4 +0705 : brzc3 + trap ;branch carry/no carry +0705 : 4c0507 > jmp * ;failed anyway + +0708 : 1002 brzc4 bpl brzc5 +070a : 3003 bmi brzc6 +070c : brzc5 + trap ;branch minus/plus +070c : 4c0c07 > jmp * ;failed anyway + +070f : 5002 brzc6 bvc brzc7 +0711 : 7003 bvs brzc8 +0713 : brzc7 + trap ;branch overflow/no overflow +0713 : 4c1307 > jmp * ;failed anyway + +0716 : brzc8 + set_stat $ff-carry + > load_flag $ff-carry +0716 : a9fe > lda #$ff-carry ;allow test to + > +0718 : 48 > pha ;use stack to load status +0719 : 28 > plp + +071a : d002 bne brcc1 +071c : f003 beq brcc2 +071e : brcc1 + trap ;branch zero/non zero +071e : 4c1e07 > jmp * ;failed anyway + +0721 : b002 brcc2 bcs brcc3 +0723 : 9003 bcc brcc4 +0725 : brcc3 + trap ;branch carry/no carry +0725 : 4c2507 > jmp * ;failed anyway + +0728 : 1002 brcc4 bpl brcc5 +072a : 3003 bmi brcc6 +072c : brcc5 + trap ;branch minus/plus +072c : 4c2c07 > jmp * ;failed anyway + +072f : 5002 brcc6 bvc brcc7 +0731 : 7003 bvs brcc8 +0733 : brcc7 + trap ;branch overflow/no overflow +0733 : 4c3307 > jmp * ;failed anyway + +0736 : brcc8 + set_stat $ff-minus + > load_flag $ff-minus +0736 : a97f > lda #$ff-minus ;allow test to + > +0738 : 48 > pha ;use stack to load status +0739 : 28 > plp + +073a : d002 bne brpl1 +073c : f003 beq brpl2 +073e : brpl1 + trap ;branch zero/non zero +073e : 4c3e07 > jmp * ;failed anyway + +0741 : 9002 brpl2 bcc brpl3 +0743 : b003 bcs brpl4 +0745 : brpl3 + trap ;branch carry/no carry +0745 : 4c4507 > jmp * ;failed anyway + +0748 : 3002 brpl4 bmi brpl5 +074a : 1003 bpl brpl6 +074c : brpl5 + trap ;branch minus/plus +074c : 4c4c07 > jmp * ;failed anyway + +074f : 5002 brpl6 bvc brpl7 +0751 : 7003 bvs brpl8 +0753 : brpl7 + trap ;branch overflow/no overflow +0753 : 4c5307 > jmp * ;failed anyway + +0756 : brpl8 + set_stat $ff-overfl + > load_flag $ff-overfl +0756 : a9bf > lda #$ff-overfl ;allow test to + > +0758 : 48 > pha ;use stack to load status +0759 : 28 > plp + +075a : d002 bne brvc1 +075c : f003 beq brvc2 +075e : brvc1 + trap ;branch zero/non zero +075e : 4c5e07 > jmp * ;failed anyway + +0761 : 9002 brvc2 bcc brvc3 +0763 : b003 bcs brvc4 +0765 : brvc3 + trap ;branch carry/no carry +0765 : 4c6507 > jmp * ;failed anyway + +0768 : 1002 brvc4 bpl brvc5 +076a : 3003 bmi brvc6 +076c : brvc5 + trap ;branch minus/plus +076c : 4c6c07 > jmp * ;failed anyway + +076f : 7002 brvc6 bvs brvc7 +0771 : 5003 bvc brvc8 +0773 : brvc7 + trap ;branch overflow/no overflow +0773 : 4c7307 > jmp * ;failed anyway + +0776 : brvc8 + next_test +0776 : ad0002 > lda test_case ;previous test +0779 : c904 > cmp #test_num + > trap_ne ;test is out of sequence +077b : d0fe > bne * ;failed not equal (non zero) + > +0005 = >test_num = test_num + 1 +077d : a905 > lda #test_num ;*** next tests' number +077f : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; test PHA does not alter flags or accumulator but PLA +0782 : a255 ldx #$55 ;x & y protected +0784 : a0aa ldy #$aa + set_a 1,$ff ;push + > load_flag $ff +0786 : a9ff > lda #$ff ;allow test to c + > +0788 : 48 > pha ;use stack to load status +0789 : a901 > lda #1 ;precharge accu +078b : 28 > plp + +078c : 48 pha + tst_a 1,$ff +078d : 08 > php ;save flags +078e : c901 > cmp #1 ;test result + > trap_ne +0790 : d0fe > bne * ;failed not equal (non zero) + > +0792 : 68 > pla ;load status +0793 : 48 > pha + > cmp_flag $ff +0794 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0796 : d0fe > bne * ;failed not equal (non zero) + > +0798 : 28 > plp ;restore status + + set_a 0,0 + > load_flag 0 +0799 : a900 > lda #0 ;allow test to change I + > +079b : 48 > pha ;use stack to load status +079c : a900 > lda #0 ;precharge accu +079e : 28 > plp + +079f : 48 pha + tst_a 0,0 +07a0 : 08 > php ;save flags +07a1 : c900 > cmp #0 ;test result + > trap_ne +07a3 : d0fe > bne * ;failed not equal (non zero) + > +07a5 : 68 > pla ;load status +07a6 : 48 > pha + > cmp_flag 0 +07a7 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +07a9 : d0fe > bne * ;failed not equal (non zero) + > +07ab : 28 > plp ;restore status + + set_a $ff,$ff + > load_flag $ff +07ac : a9ff > lda #$ff ;allow test to change + > +07ae : 48 > pha ;use stack to load status +07af : a9ff > lda #$ff ;precharge accu +07b1 : 28 > plp + +07b2 : 48 pha + tst_a $ff,$ff +07b3 : 08 > php ;save flags +07b4 : c9ff > cmp #$ff ;test result + > trap_ne +07b6 : d0fe > bne * ;failed not equal (non zero) + > +07b8 : 68 > pla ;load status +07b9 : 48 > pha + > cmp_flag $ff +07ba : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +07bc : d0fe > bne * ;failed not equal (non zero) + > +07be : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +07bf : a900 > lda #0 ;allow test to change I + > +07c1 : 48 > pha ;use stack to load status +07c2 : a901 > lda #1 ;precharge accu +07c4 : 28 > plp + +07c5 : 48 pha + tst_a 1,0 +07c6 : 08 > php ;save flags +07c7 : c901 > cmp #1 ;test result + > trap_ne +07c9 : d0fe > bne * ;failed not equal (non zero) + > +07cb : 68 > pla ;load status +07cc : 48 > pha + > cmp_flag 0 +07cd : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +07cf : d0fe > bne * ;failed not equal (non zero) + > +07d1 : 28 > plp ;restore status + + set_a 0,$ff + > load_flag $ff +07d2 : a9ff > lda #$ff ;allow test to change + > +07d4 : 48 > pha ;use stack to load status +07d5 : a900 > lda #0 ;precharge accu +07d7 : 28 > plp + +07d8 : 48 pha + tst_a 0,$ff +07d9 : 08 > php ;save flags +07da : c900 > cmp #0 ;test result + > trap_ne +07dc : d0fe > bne * ;failed not equal (non zero) + > +07de : 68 > pla ;load status +07df : 48 > pha + > cmp_flag $ff +07e0 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +07e2 : d0fe > bne * ;failed not equal (non zero) + > +07e4 : 28 > plp ;restore status + + set_a $ff,0 + > load_flag 0 +07e5 : a900 > lda #0 ;allow test to change I + > +07e7 : 48 > pha ;use stack to load status +07e8 : a9ff > lda #$ff ;precharge accu +07ea : 28 > plp + +07eb : 48 pha + tst_a $ff,0 +07ec : 08 > php ;save flags +07ed : c9ff > cmp #$ff ;test result + > trap_ne +07ef : d0fe > bne * ;failed not equal (non zero) + > +07f1 : 68 > pla ;load status +07f2 : 48 > pha + > cmp_flag 0 +07f3 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +07f5 : d0fe > bne * ;failed not equal (non zero) + > +07f7 : 28 > plp ;restore status + + set_a 0,$ff ;pull + > load_flag $ff +07f8 : a9ff > lda #$ff ;allow test to c + > +07fa : 48 > pha ;use stack to load status +07fb : a900 > lda #0 ;precharge accu +07fd : 28 > plp + +07fe : 68 pla + tst_a $ff,$ff-zero +07ff : 08 > php ;save flags +0800 : c9ff > cmp #$ff ;test result + > trap_ne +0802 : d0fe > bne * ;failed not equal (non zero) + > +0804 : 68 > pla ;load status +0805 : 48 > pha + > cmp_flag $ff-zero +0806 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0808 : d0fe > bne * ;failed not equal (non zero) + > +080a : 28 > plp ;restore status + + set_a $ff,0 + > load_flag 0 +080b : a900 > lda #0 ;allow test to change I + > +080d : 48 > pha ;use stack to load status +080e : a9ff > lda #$ff ;precharge accu +0810 : 28 > plp + +0811 : 68 pla + tst_a 0,zero +0812 : 08 > php ;save flags +0813 : c900 > cmp #0 ;test result + > trap_ne +0815 : d0fe > bne * ;failed not equal (non zero) + > +0817 : 68 > pla ;load status +0818 : 48 > pha + > cmp_flag zero +0819 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +081b : d0fe > bne * ;failed not equal (non zero) + > +081d : 28 > plp ;restore status + + set_a $fe,$ff + > load_flag $ff +081e : a9ff > lda #$ff ;allow test to change + > +0820 : 48 > pha ;use stack to load status +0821 : a9fe > lda #$fe ;precharge accu +0823 : 28 > plp + +0824 : 68 pla + tst_a 1,$ff-zero-minus +0825 : 08 > php ;save flags +0826 : c901 > cmp #1 ;test result + > trap_ne +0828 : d0fe > bne * ;failed not equal (non zero) + > +082a : 68 > pla ;load status +082b : 48 > pha + > cmp_flag $ff-zero-minus +082c : c97d > cmp #($ff-zero-minus|fao)&m8 ;expected + > + > trap_ne +082e : d0fe > bne * ;failed not equal (non zero) + > +0830 : 28 > plp ;restore status + + set_a 0,0 + > load_flag 0 +0831 : a900 > lda #0 ;allow test to change I + > +0833 : 48 > pha ;use stack to load status +0834 : a900 > lda #0 ;precharge accu +0836 : 28 > plp + +0837 : 68 pla + tst_a $ff,minus +0838 : 08 > php ;save flags +0839 : c9ff > cmp #$ff ;test result + > trap_ne +083b : d0fe > bne * ;failed not equal (non zero) + > +083d : 68 > pla ;load status +083e : 48 > pha + > cmp_flag minus +083f : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0841 : d0fe > bne * ;failed not equal (non zero) + > +0843 : 28 > plp ;restore status + + set_a $ff,$ff + > load_flag $ff +0844 : a9ff > lda #$ff ;allow test to change + > +0846 : 48 > pha ;use stack to load status +0847 : a9ff > lda #$ff ;precharge accu +0849 : 28 > plp + +084a : 68 pla + tst_a 0,$ff-minus +084b : 08 > php ;save flags +084c : c900 > cmp #0 ;test result + > trap_ne +084e : d0fe > bne * ;failed not equal (non zero) + > +0850 : 68 > pla ;load status +0851 : 48 > pha + > cmp_flag $ff-minus +0852 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0854 : d0fe > bne * ;failed not equal (non zero) + > +0856 : 28 > plp ;restore status + + set_a $fe,0 + > load_flag 0 +0857 : a900 > lda #0 ;allow test to change I + > +0859 : 48 > pha ;use stack to load status +085a : a9fe > lda #$fe ;precharge accu +085c : 28 > plp + +085d : 68 pla + tst_a 1,0 +085e : 08 > php ;save flags +085f : c901 > cmp #1 ;test result + > trap_ne +0861 : d0fe > bne * ;failed not equal (non zero) + > +0863 : 68 > pla ;load status +0864 : 48 > pha + > cmp_flag 0 +0865 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0867 : d0fe > bne * ;failed not equal (non zero) + > +0869 : 28 > plp ;restore status + +086a : e055 cpx #$55 ;x & y unchanged? + trap_ne +086c : d0fe > bne * ;failed not equal (non zero) + +086e : c0aa cpy #$aa + trap_ne +0870 : d0fe > bne * ;failed not equal (non zero) + + next_test +0872 : ad0002 > lda test_case ;previous test +0875 : c905 > cmp #test_num + > trap_ne ;test is out of sequence +0877 : d0fe > bne * ;failed not equal (non zero) + > +0006 = >test_num = test_num + 1 +0879 : a906 > lda #test_num ;*** next tests' number +087b : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; partial pretest EOR # + set_a $3c,0 + > load_flag 0 +087e : a900 > lda #0 ;allow test to change I + > +0880 : 48 > pha ;use stack to load status +0881 : a93c > lda #$3c ;precharge accu +0883 : 28 > plp + +0884 : 49c3 eor #$c3 + tst_a $ff,fn +0886 : 08 > php ;save flags +0887 : c9ff > cmp #$ff ;test result + > trap_ne +0889 : d0fe > bne * ;failed not equal (non zero) + > +088b : 68 > pla ;load status +088c : 48 > pha + > cmp_flag fn +088d : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +088f : d0fe > bne * ;failed not equal (non zero) + > +0891 : 28 > plp ;restore status + + set_a $c3,0 + > load_flag 0 +0892 : a900 > lda #0 ;allow test to change I + > +0894 : 48 > pha ;use stack to load status +0895 : a9c3 > lda #$c3 ;precharge accu +0897 : 28 > plp + +0898 : 49c3 eor #$c3 + tst_a 0,fz +089a : 08 > php ;save flags +089b : c900 > cmp #0 ;test result + > trap_ne +089d : d0fe > bne * ;failed not equal (non zero) + > +089f : 68 > pla ;load status +08a0 : 48 > pha + > cmp_flag fz +08a1 : c932 > cmp #(fz|fao)&m8 ;expected flags + alwa + > + > trap_ne +08a3 : d0fe > bne * ;failed not equal (non zero) + > +08a5 : 28 > plp ;restore status + + next_test +08a6 : ad0002 > lda test_case ;previous test +08a9 : c906 > cmp #test_num + > trap_ne ;test is out of sequence +08ab : d0fe > bne * ;failed not equal (non zero) + > +0007 = >test_num = test_num + 1 +08ad : a907 > lda #test_num ;*** next tests' number +08af : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; PC modifying instructions except branches (NOP, JMP, + ; testing NOP +08b2 : a224 ldx #$24 +08b4 : a042 ldy #$42 + set_a $18,0 + > load_flag 0 +08b6 : a900 > lda #0 ;allow test to change I + > +08b8 : 48 > pha ;use stack to load status +08b9 : a918 > lda #$18 ;precharge accu +08bb : 28 > plp + +08bc : ea nop + tst_a $18,0 +08bd : 08 > php ;save flags +08be : c918 > cmp #$18 ;test result + > trap_ne +08c0 : d0fe > bne * ;failed not equal (non zero) + > +08c2 : 68 > pla ;load status +08c3 : 48 > pha + > cmp_flag 0 +08c4 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +08c6 : d0fe > bne * ;failed not equal (non zero) + > +08c8 : 28 > plp ;restore status + +08c9 : e024 cpx #$24 + trap_ne +08cb : d0fe > bne * ;failed not equal (non zero) + +08cd : c042 cpy #$42 + trap_ne +08cf : d0fe > bne * ;failed not equal (non zero) + +08d1 : a2db ldx #$db +08d3 : a0bd ldy #$bd + set_a $e7,$ff + > load_flag $ff +08d5 : a9ff > lda #$ff ;allow test to change + > +08d7 : 48 > pha ;use stack to load status +08d8 : a9e7 > lda #$e7 ;precharge accu +08da : 28 > plp + +08db : ea nop + tst_a $e7,$ff +08dc : 08 > php ;save flags +08dd : c9e7 > cmp #$e7 ;test result + > trap_ne +08df : d0fe > bne * ;failed not equal (non zero) + > +08e1 : 68 > pla ;load status +08e2 : 48 > pha + > cmp_flag $ff +08e3 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +08e5 : d0fe > bne * ;failed not equal (non zero) + > +08e7 : 28 > plp ;restore status + +08e8 : e0db cpx #$db + trap_ne +08ea : d0fe > bne * ;failed not equal (non zero) + +08ec : c0bd cpy #$bd + trap_ne +08ee : d0fe > bne * ;failed not equal (non zero) + + next_test +08f0 : ad0002 > lda test_case ;previous test +08f3 : c907 > cmp #test_num + > trap_ne ;test is out of sequence +08f5 : d0fe > bne * ;failed not equal (non zero) + > +0008 = >test_num = test_num + 1 +08f7 : a908 > lda #test_num ;*** next tests' number +08f9 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; jump absolute + set_stat $0 + > load_flag $0 +08fc : a900 > lda #$0 ;allow test to change + > +08fe : 48 > pha ;use stack to load status +08ff : 28 > plp + +0900 : a946 lda #'F' +0902 : a241 ldx #'A' +0904 : a052 ldy #'R' ;N=0, V=0, Z=0, C=0 +0906 : 4cc936 jmp test_far +0909 : ea nop +090a : ea nop + trap_ne ;runover protection +090b : d0fe > bne * ;failed not equal (non zero) + +090d : e8 inx +090e : e8 inx +090f : far_ret + trap_eq ;returned flags OK? +090f : f0fe > beq * ;failed equal (zero) + + trap_pl +0911 : 10fe > bpl * ;failed plus (bit 7 clear) + + trap_cc +0913 : 90fe > bcc * ;failed carry clear + + trap_vc +0915 : 50fe > bvc * ;failed overflow clear + +0917 : c9ec cmp #('F'^$aa) ;returned registers OK? + trap_ne +0919 : d0fe > bne * ;failed not equal (non zero) + +091b : e042 cpx #('A'+1) + trap_ne +091d : d0fe > bne * ;failed not equal (non zero) + +091f : c04f cpy #('R'-3) + trap_ne +0921 : d0fe > bne * ;failed not equal (non zero) + +0923 : ca dex +0924 : c8 iny +0925 : c8 iny +0926 : c8 iny +0927 : 49aa eor #$aa ;N=0, V=1, Z=0, C=1 +0929 : 4c3209 jmp test_near +092c : ea nop +092d : ea nop + trap_ne ;runover protection +092e : d0fe > bne * ;failed not equal (non zero) + +0930 : e8 inx +0931 : e8 inx +0932 : test_near + trap_eq ;passed flags OK? +0932 : f0fe > beq * ;failed equal (zero) + + trap_mi +0934 : 30fe > bmi * ;failed minus (bit 7 set) + + trap_cc +0936 : 90fe > bcc * ;failed carry clear + + trap_vc +0938 : 50fe > bvc * ;failed overflow clear + +093a : c946 cmp #'F' ;passed registers OK? + trap_ne +093c : d0fe > bne * ;failed not equal (non zero) + +093e : e041 cpx #'A' + trap_ne +0940 : d0fe > bne * ;failed not equal (non zero) + +0942 : c052 cpy #'R' + trap_ne +0944 : d0fe > bne * ;failed not equal (non zero) + + next_test +0946 : ad0002 > lda test_case ;previous test +0949 : c908 > cmp #test_num + > trap_ne ;test is out of sequence +094b : d0fe > bne * ;failed not equal (non zero) + > +0009 = >test_num = test_num + 1 +094d : a909 > lda #test_num ;*** next tests' number +094f : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; jump indirect + set_stat 0 + > load_flag 0 +0952 : a900 > lda #0 ;allow test to change I + > +0954 : 48 > pha ;use stack to load status +0955 : 28 > plp + +0956 : a949 lda #'I' +0958 : a24e ldx #'N' +095a : a044 ldy #'D' ;N=0, V=0, Z=0, C=0 +095c : 6cf836 jmp (ptr_tst_ind) +095f : ea nop + trap_ne ;runover protection +0960 : d0fe > bne * ;failed not equal (non zero) + +0962 : 88 dey +0963 : 88 dey +0964 : ind_ret +0964 : 08 php ;either SP or Y count will fai +0965 : 88 dey +0966 : 88 dey +0967 : 88 dey +0968 : 28 plp + trap_eq ;returned flags OK? +0969 : f0fe > beq * ;failed equal (zero) + + trap_pl +096b : 10fe > bpl * ;failed plus (bit 7 clear) + + trap_cc +096d : 90fe > bcc * ;failed carry clear + + trap_vc +096f : 50fe > bvc * ;failed overflow clear + +0971 : c9e3 cmp #('I'^$aa) ;returned registers OK? + trap_ne +0973 : d0fe > bne * ;failed not equal (non zero) + +0975 : e04f cpx #('N'+1) + trap_ne +0977 : d0fe > bne * ;failed not equal (non zero) + +0979 : c03e cpy #('D'-6) + trap_ne +097b : d0fe > bne * ;failed not equal (non zero) + +097d : ba tsx ;SP check +097e : e0ff cpx #$ff + trap_ne +0980 : d0fe > bne * ;failed not equal (non zero) + + next_test +0982 : ad0002 > lda test_case ;previous test +0985 : c909 > cmp #test_num + > trap_ne ;test is out of sequence +0987 : d0fe > bne * ;failed not equal (non zero) + > +000a = >test_num = test_num + 1 +0989 : a90a > lda #test_num ;*** next tests' number +098b : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; jump subroutine & return from subroutine + set_stat 0 + > load_flag 0 +098e : a900 > lda #0 ;allow test to change I + > +0990 : 48 > pha ;use stack to load status +0991 : 28 > plp + +0992 : a94a lda #'J' +0994 : a253 ldx #'S' +0996 : a052 ldy #'R' ;N=0, V=0, Z=0, C=0 +0998 : 203437 jsr test_jsr +099a = jsr_ret = *-1 ;last address of jsr = return +099b : 08 php ;either SP or Y count will fai +099c : 88 dey +099d : 88 dey +099e : 88 dey +099f : 28 plp + trap_eq ;returned flags OK? +09a0 : f0fe > beq * ;failed equal (zero) + + trap_pl +09a2 : 10fe > bpl * ;failed plus (bit 7 clear) + + trap_cc +09a4 : 90fe > bcc * ;failed carry clear + + trap_vc +09a6 : 50fe > bvc * ;failed overflow clear + +09a8 : c9e0 cmp #('J'^$aa) ;returned registers OK? + trap_ne +09aa : d0fe > bne * ;failed not equal (non zero) + +09ac : e054 cpx #('S'+1) + trap_ne +09ae : d0fe > bne * ;failed not equal (non zero) + +09b0 : c04c cpy #('R'-6) + trap_ne +09b2 : d0fe > bne * ;failed not equal (non zero) + +09b4 : ba tsx ;sp? +09b5 : e0ff cpx #$ff + trap_ne +09b7 : d0fe > bne * ;failed not equal (non zero) + + next_test +09b9 : ad0002 > lda test_case ;previous test +09bc : c90a > cmp #test_num + > trap_ne ;test is out of sequence +09be : d0fe > bne * ;failed not equal (non zero) + > +000b = >test_num = test_num + 1 +09c0 : a90b > lda #test_num ;*** next tests' number +09c2 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; break & return from interrupt + if ROM_vectors = 1 + set_stat 0 + > load_flag 0 +09c5 : a900 > lda #0 ;allow test to change I + > +09c7 : 48 > pha ;use stack to load status +09c8 : 28 > plp + +09c9 : a942 lda #'B' +09cb : a252 ldx #'R' +09cd : a04b ldy #'K' ;N=0, V=0, Z=0, C=0 +09cf : 00 brk + else + lda #hi brk_ret ;emulated break + pha + lda #lo brk_ret + pha + lda #fao ;set break & unused on stack + pha + set_stat intdis + lda #'B' + ldx #'R' + ldy #'K' ;N=0, V=0, Z=0, C=0 + jmp irq_trap + endif +09d0 : 88 dey ;should not be executed +09d1 : brk_ret ;address of break return +09d1 : 08 php ;either SP or Y count will fai +09d2 : 88 dey +09d3 : 88 dey +09d4 : 88 dey +09d5 : c9e8 cmp #('B'^$aa) ;returned registers OK? + trap_ne +09d7 : d0fe > bne * ;failed not equal (non zero) + +09d9 : e053 cpx #('R'+1) + trap_ne +09db : d0fe > bne * ;failed not equal (non zero) + +09dd : c045 cpy #('K'-6) + trap_ne +09df : d0fe > bne * ;failed not equal (non zero) + +09e1 : 68 pla ;returned flags OK (unchanged) + cmp_flag 0 +09e2 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +09e4 : d0fe > bne * ;failed not equal (non zero) + +09e6 : ba tsx ;sp? +09e7 : e0ff cpx #$ff + trap_ne +09e9 : d0fe > bne * ;failed not equal (non zero) + + next_test +09eb : ad0002 > lda test_case ;previous test +09ee : c90b > cmp #test_num + > trap_ne ;test is out of sequence +09f0 : d0fe > bne * ;failed not equal (non zero) + > +000c = >test_num = test_num + 1 +09f2 : a90c > lda #test_num ;*** next tests' number +09f4 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; test set and clear flags CLC CLI CLD CLV SEC SEI SED + set_stat $ff + > load_flag $ff +09f7 : a9ff > lda #$ff ;allow test to change + > +09f9 : 48 > pha ;use stack to load status +09fa : 28 > plp + +09fb : 18 clc + tst_stat $ff-carry +09fc : 08 > php ;save status +09fd : 68 > pla ;use stack to retrieve status +09fe : 48 > pha + > cmp_flag $ff-carry +09ff : c9fe > cmp #($ff-carry|fao)&m8 ;expected flags + > + > trap_ne +0a01 : d0fe > bne * ;failed not equal (non zero) + > +0a03 : 28 > plp ;restore status + +0a04 : 38 sec + tst_stat $ff +0a05 : 08 > php ;save status +0a06 : 68 > pla ;use stack to retrieve status +0a07 : 48 > pha + > cmp_flag $ff +0a08 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0a0a : d0fe > bne * ;failed not equal (non zero) + > +0a0c : 28 > plp ;restore status + + if I_flag = 3 +0a0d : 58 cli + tst_stat $ff-intdis +0a0e : 08 > php ;save status +0a0f : 68 > pla ;use stack to retrieve status +0a10 : 48 > pha + > cmp_flag $ff-intdis +0a11 : c9fb > cmp #($ff-intdis|fao)&m8 ;expected flag + > + > trap_ne +0a13 : d0fe > bne * ;failed not equal (non zero) + > +0a15 : 28 > plp ;restore status + +0a16 : 78 sei + tst_stat $ff +0a17 : 08 > php ;save status +0a18 : 68 > pla ;use stack to retrieve status +0a19 : 48 > pha + > cmp_flag $ff +0a1a : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0a1c : d0fe > bne * ;failed not equal (non zero) + > +0a1e : 28 > plp ;restore status + + endif +0a1f : d8 cld + tst_stat $ff-decmode +0a20 : 08 > php ;save status +0a21 : 68 > pla ;use stack to retrieve status +0a22 : 48 > pha + > cmp_flag $ff-decmode +0a23 : c9f7 > cmp #($ff-decmode|fao)&m8 ;expected fla + > + > trap_ne +0a25 : d0fe > bne * ;failed not equal (non zero) + > +0a27 : 28 > plp ;restore status + +0a28 : f8 sed + tst_stat $ff +0a29 : 08 > php ;save status +0a2a : 68 > pla ;use stack to retrieve status +0a2b : 48 > pha + > cmp_flag $ff +0a2c : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + > + > trap_ne +0a2e : d0fe > bne * ;failed not equal (non zero) + > +0a30 : 28 > plp ;restore status + +0a31 : b8 clv + tst_stat $ff-overfl +0a32 : 08 > php ;save status +0a33 : 68 > pla ;use stack to retrieve status +0a34 : 48 > pha + > cmp_flag $ff-overfl +0a35 : c9bf > cmp #($ff-overfl|fao)&m8 ;expected flag + > + > trap_ne +0a37 : d0fe > bne * ;failed not equal (non zero) + > +0a39 : 28 > plp ;restore status + + set_stat 0 + > load_flag 0 +0a3a : a900 > lda #0 ;allow test to change I + > +0a3c : 48 > pha ;use stack to load status +0a3d : 28 > plp + + tst_stat 0 +0a3e : 08 > php ;save status +0a3f : 68 > pla ;use stack to retrieve status +0a40 : 48 > pha + > cmp_flag 0 +0a41 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0a43 : d0fe > bne * ;failed not equal (non zero) + > +0a45 : 28 > plp ;restore status + +0a46 : 38 sec + tst_stat carry +0a47 : 08 > php ;save status +0a48 : 68 > pla ;use stack to retrieve status +0a49 : 48 > pha + > cmp_flag carry +0a4a : c931 > cmp #(carry|fao)&m8 ;expected flags + a + > + > trap_ne +0a4c : d0fe > bne * ;failed not equal (non zero) + > +0a4e : 28 > plp ;restore status + +0a4f : 18 clc + tst_stat 0 +0a50 : 08 > php ;save status +0a51 : 68 > pla ;use stack to retrieve status +0a52 : 48 > pha + > cmp_flag 0 +0a53 : c930 > cmp #(0 |fao)&m8 ;expected flags + alw + > + > trap_ne +0a55 : d0fe > bne * ;failed not equal (non zero) + > +0a57 : 28 > plp ;restore status + + if I_flag = 3 +0a58 : 78 sei + tst_stat intdis +0a59 : 08 > php ;save status +0a5a : 68 > pla ;use stack to retrieve status +0a5b : 48 > pha + > cmp_flag intdis +0a5c : c934 > cmp #(intdis|fao)&m8 ;expected flags + + > + > trap_ne +0a5e : d0fe > bne * ;failed not equal (non zero) + > +0a60 : 28 > plp ;restore status + +0a61 : 58 cli + tst_stat 0 +0a62 : 08 > php ;save status +0a63 : 68 > pla ;use stack to retrieve status +0a64 : 48 > pha + > cmp_flag 0 +0a65 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0a67 : d0fe > bne * ;failed not equal (non zero) + > +0a69 : 28 > plp ;restore status + + endif +0a6a : f8 sed + tst_stat decmode +0a6b : 08 > php ;save status +0a6c : 68 > pla ;use stack to retrieve status +0a6d : 48 > pha + > cmp_flag decmode +0a6e : c938 > cmp #(decmode|fao)&m8 ;expected flags + + > + > trap_ne +0a70 : d0fe > bne * ;failed not equal (non zero) + > +0a72 : 28 > plp ;restore status + +0a73 : d8 cld + tst_stat 0 +0a74 : 08 > php ;save status +0a75 : 68 > pla ;use stack to retrieve status +0a76 : 48 > pha + > cmp_flag 0 +0a77 : c930 > cmp #(0 |fao)&m8 ;expected flags + alw + > + > trap_ne +0a79 : d0fe > bne * ;failed not equal (non zero) + > +0a7b : 28 > plp ;restore status + + set_stat overfl + > load_flag overfl +0a7c : a940 > lda #overfl ;allow test to cha + > +0a7e : 48 > pha ;use stack to load status +0a7f : 28 > plp + + tst_stat overfl +0a80 : 08 > php ;save status +0a81 : 68 > pla ;use stack to retrieve status +0a82 : 48 > pha + > cmp_flag overfl +0a83 : c970 > cmp #(overfl|fao)&m8 ;expected flags + + > + > trap_ne +0a85 : d0fe > bne * ;failed not equal (non zero) + > +0a87 : 28 > plp ;restore status + +0a88 : b8 clv + tst_stat 0 +0a89 : 08 > php ;save status +0a8a : 68 > pla ;use stack to retrieve status +0a8b : 48 > pha + > cmp_flag 0 +0a8c : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0a8e : d0fe > bne * ;failed not equal (non zero) + > +0a90 : 28 > plp ;restore status + + next_test +0a91 : ad0002 > lda test_case ;previous test +0a94 : c90c > cmp #test_num + > trap_ne ;test is out of sequence +0a96 : d0fe > bne * ;failed not equal (non zero) + > +000d = >test_num = test_num + 1 +0a98 : a90d > lda #test_num ;*** next tests' number +0a9a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + ; testing index register increment/decrement and trans + ; INX INY DEX DEY TAX TXA TAY TYA +0a9d : a2fe ldx #$fe + set_stat $ff + > load_flag $ff +0a9f : a9ff > lda #$ff ;allow test to change + > +0aa1 : 48 > pha ;use stack to load status +0aa2 : 28 > plp + +0aa3 : e8 inx ;ff + tst_x $ff,$ff-zero +0aa4 : 08 > php ;save flags +0aa5 : e0ff > cpx #$ff ;test result + > trap_ne +0aa7 : d0fe > bne * ;failed not equal (non zero) + > +0aa9 : 68 > pla ;load status +0aaa : 48 > pha + > cmp_flag $ff-zero +0aab : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0aad : d0fe > bne * ;failed not equal (non zero) + > +0aaf : 28 > plp ;restore status + +0ab0 : e8 inx ;00 + tst_x 0,$ff-minus +0ab1 : 08 > php ;save flags +0ab2 : e000 > cpx #0 ;test result + > trap_ne +0ab4 : d0fe > bne * ;failed not equal (non zero) + > +0ab6 : 68 > pla ;load status +0ab7 : 48 > pha + > cmp_flag $ff-minus +0ab8 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0aba : d0fe > bne * ;failed not equal (non zero) + > +0abc : 28 > plp ;restore status + +0abd : e8 inx ;01 + tst_x 1,$ff-minus-zero +0abe : 08 > php ;save flags +0abf : e001 > cpx #1 ;test result + > trap_ne +0ac1 : d0fe > bne * ;failed not equal (non zero) + > +0ac3 : 68 > pla ;load status +0ac4 : 48 > pha + > cmp_flag $ff-minus-zero +0ac5 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0ac7 : d0fe > bne * ;failed not equal (non zero) + > +0ac9 : 28 > plp ;restore status + +0aca : ca dex ;00 + tst_x 0,$ff-minus +0acb : 08 > php ;save flags +0acc : e000 > cpx #0 ;test result + > trap_ne +0ace : d0fe > bne * ;failed not equal (non zero) + > +0ad0 : 68 > pla ;load status +0ad1 : 48 > pha + > cmp_flag $ff-minus +0ad2 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0ad4 : d0fe > bne * ;failed not equal (non zero) + > +0ad6 : 28 > plp ;restore status + +0ad7 : ca dex ;ff + tst_x $ff,$ff-zero +0ad8 : 08 > php ;save flags +0ad9 : e0ff > cpx #$ff ;test result + > trap_ne +0adb : d0fe > bne * ;failed not equal (non zero) + > +0add : 68 > pla ;load status +0ade : 48 > pha + > cmp_flag $ff-zero +0adf : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0ae1 : d0fe > bne * ;failed not equal (non zero) + > +0ae3 : 28 > plp ;restore status + +0ae4 : ca dex ;fe + set_stat 0 + > load_flag 0 +0ae5 : a900 > lda #0 ;allow test to change I + > +0ae7 : 48 > pha ;use stack to load status +0ae8 : 28 > plp + +0ae9 : e8 inx ;ff + tst_x $ff,minus +0aea : 08 > php ;save flags +0aeb : e0ff > cpx #$ff ;test result + > trap_ne +0aed : d0fe > bne * ;failed not equal (non zero) + > +0aef : 68 > pla ;load status +0af0 : 48 > pha + > cmp_flag minus +0af1 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0af3 : d0fe > bne * ;failed not equal (non zero) + > +0af5 : 28 > plp ;restore status + +0af6 : e8 inx ;00 + tst_x 0,zero +0af7 : 08 > php ;save flags +0af8 : e000 > cpx #0 ;test result + > trap_ne +0afa : d0fe > bne * ;failed not equal (non zero) + > +0afc : 68 > pla ;load status +0afd : 48 > pha + > cmp_flag zero +0afe : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0b00 : d0fe > bne * ;failed not equal (non zero) + > +0b02 : 28 > plp ;restore status + +0b03 : e8 inx ;01 + tst_x 1,0 +0b04 : 08 > php ;save flags +0b05 : e001 > cpx #1 ;test result + > trap_ne +0b07 : d0fe > bne * ;failed not equal (non zero) + > +0b09 : 68 > pla ;load status +0b0a : 48 > pha + > cmp_flag 0 +0b0b : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0b0d : d0fe > bne * ;failed not equal (non zero) + > +0b0f : 28 > plp ;restore status + +0b10 : ca dex ;00 + tst_x 0,zero +0b11 : 08 > php ;save flags +0b12 : e000 > cpx #0 ;test result + > trap_ne +0b14 : d0fe > bne * ;failed not equal (non zero) + > +0b16 : 68 > pla ;load status +0b17 : 48 > pha + > cmp_flag zero +0b18 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0b1a : d0fe > bne * ;failed not equal (non zero) + > +0b1c : 28 > plp ;restore status + +0b1d : ca dex ;ff + tst_x $ff,minus +0b1e : 08 > php ;save flags +0b1f : e0ff > cpx #$ff ;test result + > trap_ne +0b21 : d0fe > bne * ;failed not equal (non zero) + > +0b23 : 68 > pla ;load status +0b24 : 48 > pha + > cmp_flag minus +0b25 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0b27 : d0fe > bne * ;failed not equal (non zero) + > +0b29 : 28 > plp ;restore status + + +0b2a : a0fe ldy #$fe + set_stat $ff + > load_flag $ff +0b2c : a9ff > lda #$ff ;allow test to change + > +0b2e : 48 > pha ;use stack to load status +0b2f : 28 > plp + +0b30 : c8 iny ;ff + tst_y $ff,$ff-zero +0b31 : 08 > php ;save flags +0b32 : c0ff > cpy #$ff ;test result + > trap_ne +0b34 : d0fe > bne * ;failed not equal (non zero) + > +0b36 : 68 > pla ;load status +0b37 : 48 > pha + > cmp_flag $ff-zero +0b38 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0b3a : d0fe > bne * ;failed not equal (non zero) + > +0b3c : 28 > plp ;restore status + +0b3d : c8 iny ;00 + tst_y 0,$ff-minus +0b3e : 08 > php ;save flags +0b3f : c000 > cpy #0 ;test result + > trap_ne +0b41 : d0fe > bne * ;failed not equal (non zero) + > +0b43 : 68 > pla ;load status +0b44 : 48 > pha + > cmp_flag $ff-minus +0b45 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0b47 : d0fe > bne * ;failed not equal (non zero) + > +0b49 : 28 > plp ;restore status + +0b4a : c8 iny ;01 + tst_y 1,$ff-minus-zero +0b4b : 08 > php ;save flags +0b4c : c001 > cpy #1 ;test result + > trap_ne +0b4e : d0fe > bne * ;failed not equal (non zero) + > +0b50 : 68 > pla ;load status +0b51 : 48 > pha + > cmp_flag $ff-minus-zero +0b52 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0b54 : d0fe > bne * ;failed not equal (non zero) + > +0b56 : 28 > plp ;restore status + +0b57 : 88 dey ;00 + tst_y 0,$ff-minus +0b58 : 08 > php ;save flags +0b59 : c000 > cpy #0 ;test result + > trap_ne +0b5b : d0fe > bne * ;failed not equal (non zero) + > +0b5d : 68 > pla ;load status +0b5e : 48 > pha + > cmp_flag $ff-minus +0b5f : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0b61 : d0fe > bne * ;failed not equal (non zero) + > +0b63 : 28 > plp ;restore status + +0b64 : 88 dey ;ff + tst_y $ff,$ff-zero +0b65 : 08 > php ;save flags +0b66 : c0ff > cpy #$ff ;test result + > trap_ne +0b68 : d0fe > bne * ;failed not equal (non zero) + > +0b6a : 68 > pla ;load status +0b6b : 48 > pha + > cmp_flag $ff-zero +0b6c : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0b6e : d0fe > bne * ;failed not equal (non zero) + > +0b70 : 28 > plp ;restore status + +0b71 : 88 dey ;fe + set_stat 0 + > load_flag 0 +0b72 : a900 > lda #0 ;allow test to change I + > +0b74 : 48 > pha ;use stack to load status +0b75 : 28 > plp + +0b76 : c8 iny ;ff + tst_y $ff,0+minus +0b77 : 08 > php ;save flags +0b78 : c0ff > cpy #$ff ;test result + > trap_ne +0b7a : d0fe > bne * ;failed not equal (non zero) + > +0b7c : 68 > pla ;load status +0b7d : 48 > pha + > cmp_flag 0+minus +0b7e : c9b0 > cmp #(0+minus|fao)&m8 ;expected flags + + > + > trap_ne +0b80 : d0fe > bne * ;failed not equal (non zero) + > +0b82 : 28 > plp ;restore status + +0b83 : c8 iny ;00 + tst_y 0,zero +0b84 : 08 > php ;save flags +0b85 : c000 > cpy #0 ;test result + > trap_ne +0b87 : d0fe > bne * ;failed not equal (non zero) + > +0b89 : 68 > pla ;load status +0b8a : 48 > pha + > cmp_flag zero +0b8b : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0b8d : d0fe > bne * ;failed not equal (non zero) + > +0b8f : 28 > plp ;restore status + +0b90 : c8 iny ;01 + tst_y 1,0 +0b91 : 08 > php ;save flags +0b92 : c001 > cpy #1 ;test result + > trap_ne +0b94 : d0fe > bne * ;failed not equal (non zero) + > +0b96 : 68 > pla ;load status +0b97 : 48 > pha + > cmp_flag 0 +0b98 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0b9a : d0fe > bne * ;failed not equal (non zero) + > +0b9c : 28 > plp ;restore status + +0b9d : 88 dey ;00 + tst_y 0,zero +0b9e : 08 > php ;save flags +0b9f : c000 > cpy #0 ;test result + > trap_ne +0ba1 : d0fe > bne * ;failed not equal (non zero) + > +0ba3 : 68 > pla ;load status +0ba4 : 48 > pha + > cmp_flag zero +0ba5 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0ba7 : d0fe > bne * ;failed not equal (non zero) + > +0ba9 : 28 > plp ;restore status + +0baa : 88 dey ;ff + tst_y $ff,minus +0bab : 08 > php ;save flags +0bac : c0ff > cpy #$ff ;test result + > trap_ne +0bae : d0fe > bne * ;failed not equal (non zero) + > +0bb0 : 68 > pla ;load status +0bb1 : 48 > pha + > cmp_flag minus +0bb2 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0bb4 : d0fe > bne * ;failed not equal (non zero) + > +0bb6 : 28 > plp ;restore status + + +0bb7 : a2ff ldx #$ff + set_stat $ff + > load_flag $ff +0bb9 : a9ff > lda #$ff ;allow test to change + > +0bbb : 48 > pha ;use stack to load status +0bbc : 28 > plp + +0bbd : 8a txa + tst_a $ff,$ff-zero +0bbe : 08 > php ;save flags +0bbf : c9ff > cmp #$ff ;test result + > trap_ne +0bc1 : d0fe > bne * ;failed not equal (non zero) + > +0bc3 : 68 > pla ;load status +0bc4 : 48 > pha + > cmp_flag $ff-zero +0bc5 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0bc7 : d0fe > bne * ;failed not equal (non zero) + > +0bc9 : 28 > plp ;restore status + +0bca : 08 php +0bcb : e8 inx ;00 +0bcc : 28 plp +0bcd : 8a txa + tst_a 0,$ff-minus +0bce : 08 > php ;save flags +0bcf : c900 > cmp #0 ;test result + > trap_ne +0bd1 : d0fe > bne * ;failed not equal (non zero) + > +0bd3 : 68 > pla ;load status +0bd4 : 48 > pha + > cmp_flag $ff-minus +0bd5 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0bd7 : d0fe > bne * ;failed not equal (non zero) + > +0bd9 : 28 > plp ;restore status + +0bda : 08 php +0bdb : e8 inx ;01 +0bdc : 28 plp +0bdd : 8a txa + tst_a 1,$ff-minus-zero +0bde : 08 > php ;save flags +0bdf : c901 > cmp #1 ;test result + > trap_ne +0be1 : d0fe > bne * ;failed not equal (non zero) + > +0be3 : 68 > pla ;load status +0be4 : 48 > pha + > cmp_flag $ff-minus-zero +0be5 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0be7 : d0fe > bne * ;failed not equal (non zero) + > +0be9 : 28 > plp ;restore status + + set_stat 0 + > load_flag 0 +0bea : a900 > lda #0 ;allow test to change I + > +0bec : 48 > pha ;use stack to load status +0bed : 28 > plp + +0bee : 8a txa + tst_a 1,0 +0bef : 08 > php ;save flags +0bf0 : c901 > cmp #1 ;test result + > trap_ne +0bf2 : d0fe > bne * ;failed not equal (non zero) + > +0bf4 : 68 > pla ;load status +0bf5 : 48 > pha + > cmp_flag 0 +0bf6 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0bf8 : d0fe > bne * ;failed not equal (non zero) + > +0bfa : 28 > plp ;restore status + +0bfb : 08 php +0bfc : ca dex ;00 +0bfd : 28 plp +0bfe : 8a txa + tst_a 0,zero +0bff : 08 > php ;save flags +0c00 : c900 > cmp #0 ;test result + > trap_ne +0c02 : d0fe > bne * ;failed not equal (non zero) + > +0c04 : 68 > pla ;load status +0c05 : 48 > pha + > cmp_flag zero +0c06 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0c08 : d0fe > bne * ;failed not equal (non zero) + > +0c0a : 28 > plp ;restore status + +0c0b : 08 php +0c0c : ca dex ;ff +0c0d : 28 plp +0c0e : 8a txa + tst_a $ff,minus +0c0f : 08 > php ;save flags +0c10 : c9ff > cmp #$ff ;test result + > trap_ne +0c12 : d0fe > bne * ;failed not equal (non zero) + > +0c14 : 68 > pla ;load status +0c15 : 48 > pha + > cmp_flag minus +0c16 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0c18 : d0fe > bne * ;failed not equal (non zero) + > +0c1a : 28 > plp ;restore status + + +0c1b : a0ff ldy #$ff + set_stat $ff + > load_flag $ff +0c1d : a9ff > lda #$ff ;allow test to change + > +0c1f : 48 > pha ;use stack to load status +0c20 : 28 > plp + +0c21 : 98 tya + tst_a $ff,$ff-zero +0c22 : 08 > php ;save flags +0c23 : c9ff > cmp #$ff ;test result + > trap_ne +0c25 : d0fe > bne * ;failed not equal (non zero) + > +0c27 : 68 > pla ;load status +0c28 : 48 > pha + > cmp_flag $ff-zero +0c29 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0c2b : d0fe > bne * ;failed not equal (non zero) + > +0c2d : 28 > plp ;restore status + +0c2e : 08 php +0c2f : c8 iny ;00 +0c30 : 28 plp +0c31 : 98 tya + tst_a 0,$ff-minus +0c32 : 08 > php ;save flags +0c33 : c900 > cmp #0 ;test result + > trap_ne +0c35 : d0fe > bne * ;failed not equal (non zero) + > +0c37 : 68 > pla ;load status +0c38 : 48 > pha + > cmp_flag $ff-minus +0c39 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0c3b : d0fe > bne * ;failed not equal (non zero) + > +0c3d : 28 > plp ;restore status + +0c3e : 08 php +0c3f : c8 iny ;01 +0c40 : 28 plp +0c41 : 98 tya + tst_a 1,$ff-minus-zero +0c42 : 08 > php ;save flags +0c43 : c901 > cmp #1 ;test result + > trap_ne +0c45 : d0fe > bne * ;failed not equal (non zero) + > +0c47 : 68 > pla ;load status +0c48 : 48 > pha + > cmp_flag $ff-minus-zero +0c49 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0c4b : d0fe > bne * ;failed not equal (non zero) + > +0c4d : 28 > plp ;restore status + + set_stat 0 + > load_flag 0 +0c4e : a900 > lda #0 ;allow test to change I + > +0c50 : 48 > pha ;use stack to load status +0c51 : 28 > plp + +0c52 : 98 tya + tst_a 1,0 +0c53 : 08 > php ;save flags +0c54 : c901 > cmp #1 ;test result + > trap_ne +0c56 : d0fe > bne * ;failed not equal (non zero) + > +0c58 : 68 > pla ;load status +0c59 : 48 > pha + > cmp_flag 0 +0c5a : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0c5c : d0fe > bne * ;failed not equal (non zero) + > +0c5e : 28 > plp ;restore status + +0c5f : 08 php +0c60 : 88 dey ;00 +0c61 : 28 plp +0c62 : 98 tya + tst_a 0,zero +0c63 : 08 > php ;save flags +0c64 : c900 > cmp #0 ;test result + > trap_ne +0c66 : d0fe > bne * ;failed not equal (non zero) + > +0c68 : 68 > pla ;load status +0c69 : 48 > pha + > cmp_flag zero +0c6a : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0c6c : d0fe > bne * ;failed not equal (non zero) + > +0c6e : 28 > plp ;restore status + +0c6f : 08 php +0c70 : 88 dey ;ff +0c71 : 28 plp +0c72 : 98 tya + tst_a $ff,minus +0c73 : 08 > php ;save flags +0c74 : c9ff > cmp #$ff ;test result + > trap_ne +0c76 : d0fe > bne * ;failed not equal (non zero) + > +0c78 : 68 > pla ;load status +0c79 : 48 > pha + > cmp_flag minus +0c7a : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0c7c : d0fe > bne * ;failed not equal (non zero) + > +0c7e : 28 > plp ;restore status + + + load_flag $ff +0c7f : a9ff > lda #$ff ;allow test to change + +0c81 : 48 pha +0c82 : a2ff ldx #$ff ;ff +0c84 : 8a txa +0c85 : 28 plp +0c86 : a8 tay + tst_y $ff,$ff-zero +0c87 : 08 > php ;save flags +0c88 : c0ff > cpy #$ff ;test result + > trap_ne +0c8a : d0fe > bne * ;failed not equal (non zero) + > +0c8c : 68 > pla ;load status +0c8d : 48 > pha + > cmp_flag $ff-zero +0c8e : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0c90 : d0fe > bne * ;failed not equal (non zero) + > +0c92 : 28 > plp ;restore status + +0c93 : 08 php +0c94 : e8 inx ;00 +0c95 : 8a txa +0c96 : 28 plp +0c97 : a8 tay + tst_y 0,$ff-minus +0c98 : 08 > php ;save flags +0c99 : c000 > cpy #0 ;test result + > trap_ne +0c9b : d0fe > bne * ;failed not equal (non zero) + > +0c9d : 68 > pla ;load status +0c9e : 48 > pha + > cmp_flag $ff-minus +0c9f : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0ca1 : d0fe > bne * ;failed not equal (non zero) + > +0ca3 : 28 > plp ;restore status + +0ca4 : 08 php +0ca5 : e8 inx ;01 +0ca6 : 8a txa +0ca7 : 28 plp +0ca8 : a8 tay + tst_y 1,$ff-minus-zero +0ca9 : 08 > php ;save flags +0caa : c001 > cpy #1 ;test result + > trap_ne +0cac : d0fe > bne * ;failed not equal (non zero) + > +0cae : 68 > pla ;load status +0caf : 48 > pha + > cmp_flag $ff-minus-zero +0cb0 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0cb2 : d0fe > bne * ;failed not equal (non zero) + > +0cb4 : 28 > plp ;restore status + + load_flag 0 +0cb5 : a900 > lda #0 ;allow test to change I + +0cb7 : 48 pha +0cb8 : a900 lda #0 +0cba : 8a txa +0cbb : 28 plp +0cbc : a8 tay + tst_y 1,0 +0cbd : 08 > php ;save flags +0cbe : c001 > cpy #1 ;test result + > trap_ne +0cc0 : d0fe > bne * ;failed not equal (non zero) + > +0cc2 : 68 > pla ;load status +0cc3 : 48 > pha + > cmp_flag 0 +0cc4 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0cc6 : d0fe > bne * ;failed not equal (non zero) + > +0cc8 : 28 > plp ;restore status + +0cc9 : 08 php +0cca : ca dex ;00 +0ccb : 8a txa +0ccc : 28 plp +0ccd : a8 tay + tst_y 0,zero +0cce : 08 > php ;save flags +0ccf : c000 > cpy #0 ;test result + > trap_ne +0cd1 : d0fe > bne * ;failed not equal (non zero) + > +0cd3 : 68 > pla ;load status +0cd4 : 48 > pha + > cmp_flag zero +0cd5 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0cd7 : d0fe > bne * ;failed not equal (non zero) + > +0cd9 : 28 > plp ;restore status + +0cda : 08 php +0cdb : ca dex ;ff +0cdc : 8a txa +0cdd : 28 plp +0cde : a8 tay + tst_y $ff,minus +0cdf : 08 > php ;save flags +0ce0 : c0ff > cpy #$ff ;test result + > trap_ne +0ce2 : d0fe > bne * ;failed not equal (non zero) + > +0ce4 : 68 > pla ;load status +0ce5 : 48 > pha + > cmp_flag minus +0ce6 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0ce8 : d0fe > bne * ;failed not equal (non zero) + > +0cea : 28 > plp ;restore status + + + + load_flag $ff +0ceb : a9ff > lda #$ff ;allow test to change + +0ced : 48 pha +0cee : a0ff ldy #$ff ;ff +0cf0 : 98 tya +0cf1 : 28 plp +0cf2 : aa tax + tst_x $ff,$ff-zero +0cf3 : 08 > php ;save flags +0cf4 : e0ff > cpx #$ff ;test result + > trap_ne +0cf6 : d0fe > bne * ;failed not equal (non zero) + > +0cf8 : 68 > pla ;load status +0cf9 : 48 > pha + > cmp_flag $ff-zero +0cfa : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + > + > trap_ne +0cfc : d0fe > bne * ;failed not equal (non zero) + > +0cfe : 28 > plp ;restore status + +0cff : 08 php +0d00 : c8 iny ;00 +0d01 : 98 tya +0d02 : 28 plp +0d03 : aa tax + tst_x 0,$ff-minus +0d04 : 08 > php ;save flags +0d05 : e000 > cpx #0 ;test result + > trap_ne +0d07 : d0fe > bne * ;failed not equal (non zero) + > +0d09 : 68 > pla ;load status +0d0a : 48 > pha + > cmp_flag $ff-minus +0d0b : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + > + > trap_ne +0d0d : d0fe > bne * ;failed not equal (non zero) + > +0d0f : 28 > plp ;restore status + +0d10 : 08 php +0d11 : c8 iny ;01 +0d12 : 98 tya +0d13 : 28 plp +0d14 : aa tax + tst_x 1,$ff-minus-zero +0d15 : 08 > php ;save flags +0d16 : e001 > cpx #1 ;test result + > trap_ne +0d18 : d0fe > bne * ;failed not equal (non zero) + > +0d1a : 68 > pla ;load status +0d1b : 48 > pha + > cmp_flag $ff-minus-zero +0d1c : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + > + > trap_ne +0d1e : d0fe > bne * ;failed not equal (non zero) + > +0d20 : 28 > plp ;restore status + + load_flag 0 +0d21 : a900 > lda #0 ;allow test to change I + +0d23 : 48 pha +0d24 : a900 lda #0 ;preset status +0d26 : 98 tya +0d27 : 28 plp +0d28 : aa tax + tst_x 1,0 +0d29 : 08 > php ;save flags +0d2a : e001 > cpx #1 ;test result + > trap_ne +0d2c : d0fe > bne * ;failed not equal (non zero) + > +0d2e : 68 > pla ;load status +0d2f : 48 > pha + > cmp_flag 0 +0d30 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + > + > trap_ne +0d32 : d0fe > bne * ;failed not equal (non zero) + > +0d34 : 28 > plp ;restore status + +0d35 : 08 php +0d36 : 88 dey ;00 +0d37 : 98 tya +0d38 : 28 plp +0d39 : aa tax + tst_x 0,zero +0d3a : 08 > php ;save flags +0d3b : e000 > cpx #0 ;test result + > trap_ne +0d3d : d0fe > bne * ;failed not equal (non zero) + > +0d3f : 68 > pla ;load status +0d40 : 48 > pha + > cmp_flag zero +0d41 : c932 > cmp #(zero|fao)&m8 ;expected flags + al + > + > trap_ne +0d43 : d0fe > bne * ;failed not equal (non zero) + > +0d45 : 28 > plp ;restore status + +0d46 : 08 php +0d47 : 88 dey ;ff +0d48 : 98 tya +0d49 : 28 plp +0d4a : aa tax + tst_x $ff,minus +0d4b : 08 > php ;save flags +0d4c : e0ff > cpx #$ff ;test result + > trap_ne +0d4e : d0fe > bne * ;failed not equal (non zero) + > +0d50 : 68 > pla ;load status +0d51 : 48 > pha + > cmp_flag minus +0d52 : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + > + > trap_ne +0d54 : d0fe > bne * ;failed not equal (non zero) + > +0d56 : 28 > plp ;restore status + + next_test +0d57 : ad0002 > lda test_case ;previous test +0d5a : c90d > cmp #test_num + > trap_ne ;test is out of sequence +0d5c : d0fe > bne * ;failed not equal (non zero) + > +000e = >test_num = test_num + 1 +0d5e : a90e > lda #test_num ;*** next tests' number +0d60 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ;TSX sets NZ - TXS does not + ; This section also tests for proper stack wrap aroun +0d63 : a201 ldx #1 ;01 + set_stat $ff + > load_flag $ff +0d65 : a9ff > lda #$ff ;allow test to change + > +0d67 : 48 > pha ;use stack to load status +0d68 : 28 > plp + +0d69 : 9a txs +0d6a : 08 php +0d6b : ad0101 lda $101 + cmp_flag $ff +0d6e : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + + trap_ne +0d70 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0d72 : a900 > lda #0 ;allow test to change I + > +0d74 : 48 > pha ;use stack to load status +0d75 : 28 > plp + +0d76 : 9a txs +0d77 : 08 php +0d78 : ad0101 lda $101 + cmp_flag 0 +0d7b : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +0d7d : d0fe > bne * ;failed not equal (non zero) + +0d7f : ca dex ;00 + set_stat $ff + > load_flag $ff +0d80 : a9ff > lda #$ff ;allow test to change + > +0d82 : 48 > pha ;use stack to load status +0d83 : 28 > plp + +0d84 : 9a txs +0d85 : 08 php +0d86 : ad0001 lda $100 + cmp_flag $ff +0d89 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + + trap_ne +0d8b : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0d8d : a900 > lda #0 ;allow test to change I + > +0d8f : 48 > pha ;use stack to load status +0d90 : 28 > plp + +0d91 : 9a txs +0d92 : 08 php +0d93 : ad0001 lda $100 + cmp_flag 0 +0d96 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +0d98 : d0fe > bne * ;failed not equal (non zero) + +0d9a : ca dex ;ff + set_stat $ff + > load_flag $ff +0d9b : a9ff > lda #$ff ;allow test to change + > +0d9d : 48 > pha ;use stack to load status +0d9e : 28 > plp + +0d9f : 9a txs +0da0 : 08 php +0da1 : adff01 lda $1ff + cmp_flag $ff +0da4 : c9ff > cmp #($ff|fao)&m8 ;expected flags + alw + + trap_ne +0da6 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0da8 : a900 > lda #0 ;allow test to change I + > +0daa : 48 > pha ;use stack to load status +0dab : 28 > plp + +0dac : 9a txs +0dad : 08 php +0dae : adff01 lda $1ff + cmp_flag 0 +0db1 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + +0db3 : a201 ldx #1 +0db5 : 9a txs ;sp=01 + set_stat $ff + > load_flag $ff +0db6 : a9ff > lda #$ff ;allow test to change + > +0db8 : 48 > pha ;use stack to load status +0db9 : 28 > plp + +0dba : ba tsx ;clears Z, N +0dbb : 08 php ;sp=00 +0dbc : e001 cpx #1 + trap_ne +0dbe : d0fe > bne * ;failed not equal (non zero) + +0dc0 : ad0101 lda $101 + cmp_flag $ff-minus-zero +0dc3 : c97d > cmp #($ff-minus-zero|fao)&m8 ;expected + + trap_ne +0dc5 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +0dc7 : a9ff > lda #$ff ;allow test to change + > +0dc9 : 48 > pha ;use stack to load status +0dca : 28 > plp + +0dcb : ba tsx ;clears N, sets Z +0dcc : 08 php ;sp=ff +0dcd : e000 cpx #0 + trap_ne +0dcf : d0fe > bne * ;failed not equal (non zero) + +0dd1 : ad0001 lda $100 + cmp_flag $ff-minus +0dd4 : c97f > cmp #($ff-minus|fao)&m8 ;expected flags + + trap_ne +0dd6 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +0dd8 : a9ff > lda #$ff ;allow test to change + > +0dda : 48 > pha ;use stack to load status +0ddb : 28 > plp + +0ddc : ba tsx ;clears N, sets Z +0ddd : 08 php ;sp=fe +0dde : e0ff cpx #$ff + trap_ne +0de0 : d0fe > bne * ;failed not equal (non zero) + +0de2 : adff01 lda $1ff + cmp_flag $ff-zero +0de5 : c9fd > cmp #($ff-zero|fao)&m8 ;expected flags + + trap_ne +0de7 : d0fe > bne * ;failed not equal (non zero) + + +0de9 : a201 ldx #1 +0deb : 9a txs ;sp=01 + set_stat 0 + > load_flag 0 +0dec : a900 > lda #0 ;allow test to change I + > +0dee : 48 > pha ;use stack to load status +0def : 28 > plp + +0df0 : ba tsx ;clears Z, N +0df1 : 08 php ;sp=00 +0df2 : e001 cpx #1 + trap_ne +0df4 : d0fe > bne * ;failed not equal (non zero) + +0df6 : ad0101 lda $101 + cmp_flag 0 +0df9 : c930 > cmp #(0|fao)&m8 ;expected flags + alway + + trap_ne +0dfb : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0dfd : a900 > lda #0 ;allow test to change I + > +0dff : 48 > pha ;use stack to load status +0e00 : 28 > plp + +0e01 : ba tsx ;clears N, sets Z +0e02 : 08 php ;sp=ff +0e03 : e000 cpx #0 + trap_ne +0e05 : d0fe > bne * ;failed not equal (non zero) + +0e07 : ad0001 lda $100 + cmp_flag zero +0e0a : c932 > cmp #(zero|fao)&m8 ;expected flags + al + + trap_ne +0e0c : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +0e0e : a900 > lda #0 ;allow test to change I + > +0e10 : 48 > pha ;use stack to load status +0e11 : 28 > plp + +0e12 : ba tsx ;clears N, sets Z +0e13 : 08 php ;sp=fe +0e14 : e0ff cpx #$ff + trap_ne +0e16 : d0fe > bne * ;failed not equal (non zero) + +0e18 : adff01 lda $1ff + cmp_flag minus +0e1b : c9b0 > cmp #(minus|fao)&m8 ;expected flags + a + + trap_ne +0e1d : d0fe > bne * ;failed not equal (non zero) + +0e1f : 68 pla ;sp=ff + next_test +0e20 : ad0002 > lda test_case ;previous test +0e23 : c90e > cmp #test_num + > trap_ne ;test is out of sequence +0e25 : d0fe > bne * ;failed not equal (non zero) + > +000f = >test_num = test_num + 1 +0e27 : a90f > lda #test_num ;*** next tests' number +0e29 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing index register load & store LDY LDX STY STX + ; LDX / STX - zp,y / abs,y +0e2c : a003 ldy #3 +0e2e : tldx + set_stat 0 + > load_flag 0 +0e2e : a900 > lda #0 ;allow test to change I + > +0e30 : 48 > pha ;use stack to load status +0e31 : 28 > plp + +0e32 : b613 ldx zp1,y +0e34 : 08 php ;test stores do not alter flags +0e35 : 8a txa +0e36 : 49c3 eor #$c3 +0e38 : 28 plp +0e39 : 990302 sta abst,y +0e3c : 08 php ;flags after load/store sequence +0e3d : 49c3 eor #$c3 +0e3f : d91702 cmp abs1,y ;test result + trap_ne +0e42 : d0fe > bne * ;failed not equal (non zero) + +0e44 : 68 pla ;load status + eor_flag 0 +0e45 : 4930 > eor #0|fao ;invert expected flags + +0e47 : d91c02 cmp fLDx,y ;test flags + trap_ne +0e4a : d0fe > bne * ;failed not equal (non zero) + +0e4c : 88 dey +0e4d : 10df bpl tldx + +0e4f : a003 ldy #3 +0e51 : tldx1 + set_stat $ff + > load_flag $ff +0e51 : a9ff > lda #$ff ;allow test to change + > +0e53 : 48 > pha ;use stack to load status +0e54 : 28 > plp + +0e55 : b613 ldx zp1,y +0e57 : 08 php ;test stores do not alter flags +0e58 : 8a txa +0e59 : 49c3 eor #$c3 +0e5b : 28 plp +0e5c : 990302 sta abst,y +0e5f : 08 php ;flags after load/store sequence +0e60 : 49c3 eor #$c3 +0e62 : d91702 cmp abs1,y ;test result + trap_ne +0e65 : d0fe > bne * ;failed not equal (non zero) + +0e67 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0e68 : 497d > eor #lo~fnz |fao ;invert expected + +0e6a : d91c02 cmp fLDx,y ;test flags + trap_ne +0e6d : d0fe > bne * ;failed not equal (non zero) + +0e6f : 88 dey +0e70 : 10df bpl tldx1 + +0e72 : a003 ldy #3 +0e74 : tldx2 + set_stat 0 + > load_flag 0 +0e74 : a900 > lda #0 ;allow test to change I + > +0e76 : 48 > pha ;use stack to load status +0e77 : 28 > plp + +0e78 : be1702 ldx abs1,y +0e7b : 08 php ;test stores do not alter flags +0e7c : 8a txa +0e7d : 49c3 eor #$c3 +0e7f : aa tax +0e80 : 28 plp +0e81 : 960c stx zpt,y +0e83 : 08 php ;flags after load/store sequence +0e84 : 49c3 eor #$c3 +0e86 : d91300 cmp zp1,y ;test result + trap_ne +0e89 : d0fe > bne * ;failed not equal (non zero) + +0e8b : 68 pla ;load status + eor_flag 0 +0e8c : 4930 > eor #0|fao ;invert expected flags + +0e8e : d91c02 cmp fLDx,y ;test flags + trap_ne +0e91 : d0fe > bne * ;failed not equal (non zero) + +0e93 : 88 dey +0e94 : 10de bpl tldx2 + +0e96 : a003 ldy #3 +0e98 : tldx3 + set_stat $ff + > load_flag $ff +0e98 : a9ff > lda #$ff ;allow test to change + > +0e9a : 48 > pha ;use stack to load status +0e9b : 28 > plp + +0e9c : be1702 ldx abs1,y +0e9f : 08 php ;test stores do not alter flags +0ea0 : 8a txa +0ea1 : 49c3 eor #$c3 +0ea3 : aa tax +0ea4 : 28 plp +0ea5 : 960c stx zpt,y +0ea7 : 08 php ;flags after load/store sequence +0ea8 : 49c3 eor #$c3 +0eaa : d91300 cmp zp1,y ;test result + trap_ne +0ead : d0fe > bne * ;failed not equal (non zero) + +0eaf : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0eb0 : 497d > eor #lo~fnz |fao ;invert expected + +0eb2 : d91c02 cmp fLDx,y ;test flags + trap_ne +0eb5 : d0fe > bne * ;failed not equal (non zero) + +0eb7 : 88 dey +0eb8 : 10de bpl tldx3 + +0eba : a003 ldy #3 ;testing store result +0ebc : a200 ldx #0 +0ebe : b90c00 tstx lda zpt,y +0ec1 : 49c3 eor #$c3 +0ec3 : d91300 cmp zp1,y + trap_ne ;store to zp data +0ec6 : d0fe > bne * ;failed not equal (non zero) + +0ec8 : 960c stx zpt,y ;clear +0eca : b90302 lda abst,y +0ecd : 49c3 eor #$c3 +0ecf : d91702 cmp abs1,y + trap_ne ;store to abs data +0ed2 : d0fe > bne * ;failed not equal (non zero) + +0ed4 : 8a txa +0ed5 : 990302 sta abst,y ;clear +0ed8 : 88 dey +0ed9 : 10e3 bpl tstx + next_test +0edb : ad0002 > lda test_case ;previous test +0ede : c90f > cmp #test_num + > trap_ne ;test is out of sequence +0ee0 : d0fe > bne * ;failed not equal (non zero) + > +0010 = >test_num = test_num + 1 +0ee2 : a910 > lda #test_num ;*** next tests' number +0ee4 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; indexed wraparound test (only zp should wrap) +0ee7 : a0fd ldy #3+$fa +0ee9 : b619 tldx4 ldx zp1-$fa&$ff,y ;wrap on indexed zp +0eeb : 8a txa +0eec : 990901 sta abst-$fa,y ;no STX abs,y! +0eef : 88 dey +0ef0 : c0fa cpy #$fa +0ef2 : b0f5 bcs tldx4 +0ef4 : a0fd ldy #3+$fa +0ef6 : be1d01 tldx5 ldx abs1-$fa,y ;no wrap on indexed abs +0ef9 : 9612 stx zpt-$fa&$ff,y +0efb : 88 dey +0efc : c0fa cpy #$fa +0efe : b0f6 bcs tldx5 +0f00 : a003 ldy #3 ;testing wraparound result +0f02 : a200 ldx #0 +0f04 : b90c00 tstx1 lda zpt,y +0f07 : d91300 cmp zp1,y + trap_ne ;store to zp data +0f0a : d0fe > bne * ;failed not equal (non zero) + +0f0c : 960c stx zpt,y ;clear +0f0e : b90302 lda abst,y +0f11 : d91702 cmp abs1,y + trap_ne ;store to abs data +0f14 : d0fe > bne * ;failed not equal (non zero) + +0f16 : 8a txa +0f17 : 990302 sta abst,y ;clear +0f1a : 88 dey +0f1b : 10e7 bpl tstx1 + next_test +0f1d : ad0002 > lda test_case ;previous test +0f20 : c910 > cmp #test_num + > trap_ne ;test is out of sequence +0f22 : d0fe > bne * ;failed not equal (non zero) + > +0011 = >test_num = test_num + 1 +0f24 : a911 > lda #test_num ;*** next tests' number +0f26 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDY / STY - zp,x / abs,x +0f29 : a203 ldx #3 +0f2b : tldy + set_stat 0 + > load_flag 0 +0f2b : a900 > lda #0 ;allow test to change I + > +0f2d : 48 > pha ;use stack to load status +0f2e : 28 > plp + +0f2f : b413 ldy zp1,x +0f31 : 08 php ;test stores do not alter flags +0f32 : 98 tya +0f33 : 49c3 eor #$c3 +0f35 : 28 plp +0f36 : 9d0302 sta abst,x +0f39 : 08 php ;flags after load/store sequence +0f3a : 49c3 eor #$c3 +0f3c : dd1702 cmp abs1,x ;test result + trap_ne +0f3f : d0fe > bne * ;failed not equal (non zero) + +0f41 : 68 pla ;load status + eor_flag 0 +0f42 : 4930 > eor #0|fao ;invert expected flags + +0f44 : dd1c02 cmp fLDx,x ;test flags + trap_ne +0f47 : d0fe > bne * ;failed not equal (non zero) + +0f49 : ca dex +0f4a : 10df bpl tldy + +0f4c : a203 ldx #3 +0f4e : tldy1 + set_stat $ff + > load_flag $ff +0f4e : a9ff > lda #$ff ;allow test to change + > +0f50 : 48 > pha ;use stack to load status +0f51 : 28 > plp + +0f52 : b413 ldy zp1,x +0f54 : 08 php ;test stores do not alter flags +0f55 : 98 tya +0f56 : 49c3 eor #$c3 +0f58 : 28 plp +0f59 : 9d0302 sta abst,x +0f5c : 08 php ;flags after load/store sequence +0f5d : 49c3 eor #$c3 +0f5f : dd1702 cmp abs1,x ;test result + trap_ne +0f62 : d0fe > bne * ;failed not equal (non zero) + +0f64 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0f65 : 497d > eor #lo~fnz |fao ;invert expected + +0f67 : dd1c02 cmp fLDx,x ;test flags + trap_ne +0f6a : d0fe > bne * ;failed not equal (non zero) + +0f6c : ca dex +0f6d : 10df bpl tldy1 + +0f6f : a203 ldx #3 +0f71 : tldy2 + set_stat 0 + > load_flag 0 +0f71 : a900 > lda #0 ;allow test to change I + > +0f73 : 48 > pha ;use stack to load status +0f74 : 28 > plp + +0f75 : bc1702 ldy abs1,x +0f78 : 08 php ;test stores do not alter flags +0f79 : 98 tya +0f7a : 49c3 eor #$c3 +0f7c : a8 tay +0f7d : 28 plp +0f7e : 940c sty zpt,x +0f80 : 08 php ;flags after load/store sequence +0f81 : 49c3 eor #$c3 +0f83 : d513 cmp zp1,x ;test result + trap_ne +0f85 : d0fe > bne * ;failed not equal (non zero) + +0f87 : 68 pla ;load status + eor_flag 0 +0f88 : 4930 > eor #0|fao ;invert expected flags + +0f8a : dd1c02 cmp fLDx,x ;test flags + trap_ne +0f8d : d0fe > bne * ;failed not equal (non zero) + +0f8f : ca dex +0f90 : 10df bpl tldy2 + +0f92 : a203 ldx #3 +0f94 : tldy3 + set_stat $ff + > load_flag $ff +0f94 : a9ff > lda #$ff ;allow test to change + > +0f96 : 48 > pha ;use stack to load status +0f97 : 28 > plp + +0f98 : bc1702 ldy abs1,x +0f9b : 08 php ;test stores do not alter flags +0f9c : 98 tya +0f9d : 49c3 eor #$c3 +0f9f : a8 tay +0fa0 : 28 plp +0fa1 : 940c sty zpt,x +0fa3 : 08 php ;flags after load/store sequence +0fa4 : 49c3 eor #$c3 +0fa6 : d513 cmp zp1,x ;test result + trap_ne +0fa8 : d0fe > bne * ;failed not equal (non zero) + +0faa : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +0fab : 497d > eor #lo~fnz |fao ;invert expected + +0fad : dd1c02 cmp fLDx,x ;test flags + trap_ne +0fb0 : d0fe > bne * ;failed not equal (non zero) + +0fb2 : ca dex +0fb3 : 10df bpl tldy3 + +0fb5 : a203 ldx #3 ;testing store result +0fb7 : a000 ldy #0 +0fb9 : b50c tsty lda zpt,x +0fbb : 49c3 eor #$c3 +0fbd : d513 cmp zp1,x + trap_ne ;store to zp,x data +0fbf : d0fe > bne * ;failed not equal (non zero) + +0fc1 : 940c sty zpt,x ;clear +0fc3 : bd0302 lda abst,x +0fc6 : 49c3 eor #$c3 +0fc8 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +0fcb : d0fe > bne * ;failed not equal (non zero) + +0fcd : 8a txa +0fce : 9d0302 sta abst,x ;clear +0fd1 : ca dex +0fd2 : 10e5 bpl tsty + next_test +0fd4 : ad0002 > lda test_case ;previous test +0fd7 : c911 > cmp #test_num + > trap_ne ;test is out of sequence +0fd9 : d0fe > bne * ;failed not equal (non zero) + > +0012 = >test_num = test_num + 1 +0fdb : a912 > lda #test_num ;*** next tests' number +0fdd : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; indexed wraparound test (only zp should wrap) +0fe0 : a2fd ldx #3+$fa +0fe2 : b419 tldy4 ldy zp1-$fa&$ff,x ;wrap on indexed zp +0fe4 : 98 tya +0fe5 : 9d0901 sta abst-$fa,x ;no STX abs,x! +0fe8 : ca dex +0fe9 : e0fa cpx #$fa +0feb : b0f5 bcs tldy4 +0fed : a2fd ldx #3+$fa +0fef : bc1d01 tldy5 ldy abs1-$fa,x ;no wrap on indexed abs +0ff2 : 9412 sty zpt-$fa&$ff,x +0ff4 : ca dex +0ff5 : e0fa cpx #$fa +0ff7 : b0f6 bcs tldy5 +0ff9 : a203 ldx #3 ;testing wraparound result +0ffb : a000 ldy #0 +0ffd : b50c tsty1 lda zpt,x +0fff : d513 cmp zp1,x + trap_ne ;store to zp,x data +1001 : d0fe > bne * ;failed not equal (non zero) + +1003 : 940c sty zpt,x ;clear +1005 : bd0302 lda abst,x +1008 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +100b : d0fe > bne * ;failed not equal (non zero) + +100d : 8a txa +100e : 9d0302 sta abst,x ;clear +1011 : ca dex +1012 : 10e9 bpl tsty1 + next_test +1014 : ad0002 > lda test_case ;previous test +1017 : c912 > cmp #test_num + > trap_ne ;test is out of sequence +1019 : d0fe > bne * ;failed not equal (non zero) + > +0013 = >test_num = test_num + 1 +101b : a913 > lda #test_num ;*** next tests' number +101d : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDX / STX - zp / abs / # + set_stat 0 + > load_flag 0 +1020 : a900 > lda #0 ;allow test to change + > +1022 : 48 > pha ;use stack to load status +1023 : 28 > plp + +1024 : a613 ldx zp1 +1026 : 08 php ;test stores do not alter flags +1027 : 8a txa +1028 : 49c3 eor #$c3 +102a : aa tax +102b : 28 plp +102c : 8e0302 stx abst +102f : 08 php ;flags after load/store sequence +1030 : 49c3 eor #$c3 +1032 : aa tax +1033 : e0c3 cpx #$c3 ;test result + trap_ne +1035 : d0fe > bne * ;failed not equal (non zero) + +1037 : 68 pla ;load status + eor_flag 0 +1038 : 4930 > eor #0|fao ;invert expected flags + +103a : cd1c02 cmp fLDx ;test flags + trap_ne +103d : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +103f : a900 > lda #0 ;allow test to change I + > +1041 : 48 > pha ;use stack to load status +1042 : 28 > plp + +1043 : a614 ldx zp1+1 +1045 : 08 php ;test stores do not alter flags +1046 : 8a txa +1047 : 49c3 eor #$c3 +1049 : aa tax +104a : 28 plp +104b : 8e0402 stx abst+1 +104e : 08 php ;flags after load/store sequence +104f : 49c3 eor #$c3 +1051 : aa tax +1052 : e082 cpx #$82 ;test result + trap_ne +1054 : d0fe > bne * ;failed not equal (non zero) + +1056 : 68 pla ;load status + eor_flag 0 +1057 : 4930 > eor #0|fao ;invert expected flags + +1059 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +105c : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +105e : a900 > lda #0 ;allow test to change I + > +1060 : 48 > pha ;use stack to load status +1061 : 28 > plp + +1062 : a615 ldx zp1+2 +1064 : 08 php ;test stores do not alter flags +1065 : 8a txa +1066 : 49c3 eor #$c3 +1068 : aa tax +1069 : 28 plp +106a : 8e0502 stx abst+2 +106d : 08 php ;flags after load/store sequence +106e : 49c3 eor #$c3 +1070 : aa tax +1071 : e041 cpx #$41 ;test result + trap_ne +1073 : d0fe > bne * ;failed not equal (non zero) + +1075 : 68 pla ;load status + eor_flag 0 +1076 : 4930 > eor #0|fao ;invert expected flags + +1078 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +107b : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +107d : a900 > lda #0 ;allow test to change I + > +107f : 48 > pha ;use stack to load status +1080 : 28 > plp + +1081 : a616 ldx zp1+3 +1083 : 08 php ;test stores do not alter flags +1084 : 8a txa +1085 : 49c3 eor #$c3 +1087 : aa tax +1088 : 28 plp +1089 : 8e0602 stx abst+3 +108c : 08 php ;flags after load/store sequence +108d : 49c3 eor #$c3 +108f : aa tax +1090 : e000 cpx #0 ;test result + trap_ne +1092 : d0fe > bne * ;failed not equal (non zero) + +1094 : 68 pla ;load status + eor_flag 0 +1095 : 4930 > eor #0|fao ;invert expected flags + +1097 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +109a : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +109c : a9ff > lda #$ff ;allow test to change + > +109e : 48 > pha ;use stack to load status +109f : 28 > plp + +10a0 : a613 ldx zp1 +10a2 : 08 php ;test stores do not alter flags +10a3 : 8a txa +10a4 : 49c3 eor #$c3 +10a6 : aa tax +10a7 : 28 plp +10a8 : 8e0302 stx abst +10ab : 08 php ;flags after load/store sequence +10ac : 49c3 eor #$c3 +10ae : aa tax +10af : e0c3 cpx #$c3 ;test result + trap_ne ; +10b1 : d0fe > bne * ;failed not equal (non zero) + +10b3 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +10b4 : 497d > eor #lo~fnz |fao ;invert expected + +10b6 : cd1c02 cmp fLDx ;test flags + trap_ne +10b9 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +10bb : a9ff > lda #$ff ;allow test to change + > +10bd : 48 > pha ;use stack to load status +10be : 28 > plp + +10bf : a614 ldx zp1+1 +10c1 : 08 php ;test stores do not alter flags +10c2 : 8a txa +10c3 : 49c3 eor #$c3 +10c5 : aa tax +10c6 : 28 plp +10c7 : 8e0402 stx abst+1 +10ca : 08 php ;flags after load/store sequence +10cb : 49c3 eor #$c3 +10cd : aa tax +10ce : e082 cpx #$82 ;test result + trap_ne +10d0 : d0fe > bne * ;failed not equal (non zero) + +10d2 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +10d3 : 497d > eor #lo~fnz |fao ;invert expected + +10d5 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +10d8 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +10da : a9ff > lda #$ff ;allow test to change + > +10dc : 48 > pha ;use stack to load status +10dd : 28 > plp + +10de : a615 ldx zp1+2 +10e0 : 08 php ;test stores do not alter flags +10e1 : 8a txa +10e2 : 49c3 eor #$c3 +10e4 : aa tax +10e5 : 28 plp +10e6 : 8e0502 stx abst+2 +10e9 : 08 php ;flags after load/store sequence +10ea : 49c3 eor #$c3 +10ec : aa tax +10ed : e041 cpx #$41 ;test result + trap_ne ; +10ef : d0fe > bne * ;failed not equal (non zero) + +10f1 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +10f2 : 497d > eor #lo~fnz |fao ;invert expected + +10f4 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +10f7 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +10f9 : a9ff > lda #$ff ;allow test to change + > +10fb : 48 > pha ;use stack to load status +10fc : 28 > plp + +10fd : a616 ldx zp1+3 +10ff : 08 php ;test stores do not alter flags +1100 : 8a txa +1101 : 49c3 eor #$c3 +1103 : aa tax +1104 : 28 plp +1105 : 8e0602 stx abst+3 +1108 : 08 php ;flags after load/store sequence +1109 : 49c3 eor #$c3 +110b : aa tax +110c : e000 cpx #0 ;test result + trap_ne +110e : d0fe > bne * ;failed not equal (non zero) + +1110 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1111 : 497d > eor #lo~fnz |fao ;invert expected + +1113 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1116 : d0fe > bne * ;failed not equal (non zero) + + + set_stat 0 + > load_flag 0 +1118 : a900 > lda #0 ;allow test to change I + > +111a : 48 > pha ;use stack to load status +111b : 28 > plp + +111c : ae1702 ldx abs1 +111f : 08 php ;test stores do not alter flags +1120 : 8a txa +1121 : 49c3 eor #$c3 +1123 : aa tax +1124 : 28 plp +1125 : 860c stx zpt +1127 : 08 php ;flags after load/store sequence +1128 : 49c3 eor #$c3 +112a : c513 cmp zp1 ;test result + trap_ne +112c : d0fe > bne * ;failed not equal (non zero) + +112e : 68 pla ;load status + eor_flag 0 +112f : 4930 > eor #0|fao ;invert expected flags + +1131 : cd1c02 cmp fLDx ;test flags + trap_ne +1134 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1136 : a900 > lda #0 ;allow test to change I + > +1138 : 48 > pha ;use stack to load status +1139 : 28 > plp + +113a : ae1802 ldx abs1+1 +113d : 08 php ;test stores do not alter flags +113e : 8a txa +113f : 49c3 eor #$c3 +1141 : aa tax +1142 : 28 plp +1143 : 860d stx zpt+1 +1145 : 08 php ;flags after load/store sequence +1146 : 49c3 eor #$c3 +1148 : c514 cmp zp1+1 ;test result + trap_ne +114a : d0fe > bne * ;failed not equal (non zero) + +114c : 68 pla ;load status + eor_flag 0 +114d : 4930 > eor #0|fao ;invert expected flags + +114f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1152 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1154 : a900 > lda #0 ;allow test to change I + > +1156 : 48 > pha ;use stack to load status +1157 : 28 > plp + +1158 : ae1902 ldx abs1+2 +115b : 08 php ;test stores do not alter flags +115c : 8a txa +115d : 49c3 eor #$c3 +115f : aa tax +1160 : 28 plp +1161 : 860e stx zpt+2 +1163 : 08 php ;flags after load/store sequence +1164 : 49c3 eor #$c3 +1166 : c515 cmp zp1+2 ;test result + trap_ne +1168 : d0fe > bne * ;failed not equal (non zero) + +116a : 68 pla ;load status + eor_flag 0 +116b : 4930 > eor #0|fao ;invert expected flags + +116d : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1170 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1172 : a900 > lda #0 ;allow test to change I + > +1174 : 48 > pha ;use stack to load status +1175 : 28 > plp + +1176 : ae1a02 ldx abs1+3 +1179 : 08 php ;test stores do not alter flags +117a : 8a txa +117b : 49c3 eor #$c3 +117d : aa tax +117e : 28 plp +117f : 860f stx zpt+3 +1181 : 08 php ;flags after load/store sequence +1182 : 49c3 eor #$c3 +1184 : c516 cmp zp1+3 ;test result + trap_ne +1186 : d0fe > bne * ;failed not equal (non zero) + +1188 : 68 pla ;load status + eor_flag 0 +1189 : 4930 > eor #0|fao ;invert expected flags + +118b : cd1f02 cmp fLDx+3 ;test flags + trap_ne +118e : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1190 : a9ff > lda #$ff ;allow test to change + > +1192 : 48 > pha ;use stack to load status +1193 : 28 > plp + +1194 : ae1702 ldx abs1 +1197 : 08 php ;test stores do not alter flags +1198 : 8a txa +1199 : 49c3 eor #$c3 +119b : aa tax +119c : 28 plp +119d : 860c stx zpt +119f : 08 php ;flags after load/store sequence +11a0 : 49c3 eor #$c3 +11a2 : aa tax +11a3 : e413 cpx zp1 ;test result + trap_ne +11a5 : d0fe > bne * ;failed not equal (non zero) + +11a7 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +11a8 : 497d > eor #lo~fnz |fao ;invert expected + +11aa : cd1c02 cmp fLDx ;test flags + trap_ne +11ad : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +11af : a9ff > lda #$ff ;allow test to change + > +11b1 : 48 > pha ;use stack to load status +11b2 : 28 > plp + +11b3 : ae1802 ldx abs1+1 +11b6 : 08 php ;test stores do not alter flags +11b7 : 8a txa +11b8 : 49c3 eor #$c3 +11ba : aa tax +11bb : 28 plp +11bc : 860d stx zpt+1 +11be : 08 php ;flags after load/store sequence +11bf : 49c3 eor #$c3 +11c1 : aa tax +11c2 : e414 cpx zp1+1 ;test result + trap_ne +11c4 : d0fe > bne * ;failed not equal (non zero) + +11c6 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +11c7 : 497d > eor #lo~fnz |fao ;invert expected + +11c9 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +11cc : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +11ce : a9ff > lda #$ff ;allow test to change + > +11d0 : 48 > pha ;use stack to load status +11d1 : 28 > plp + +11d2 : ae1902 ldx abs1+2 +11d5 : 08 php ;test stores do not alter flags +11d6 : 8a txa +11d7 : 49c3 eor #$c3 +11d9 : aa tax +11da : 28 plp +11db : 860e stx zpt+2 +11dd : 08 php ;flags after load/store sequence +11de : 49c3 eor #$c3 +11e0 : aa tax +11e1 : e415 cpx zp1+2 ;test result + trap_ne +11e3 : d0fe > bne * ;failed not equal (non zero) + +11e5 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +11e6 : 497d > eor #lo~fnz |fao ;invert expected + +11e8 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +11eb : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +11ed : a9ff > lda #$ff ;allow test to change + > +11ef : 48 > pha ;use stack to load status +11f0 : 28 > plp + +11f1 : ae1a02 ldx abs1+3 +11f4 : 08 php ;test stores do not alter flags +11f5 : 8a txa +11f6 : 49c3 eor #$c3 +11f8 : aa tax +11f9 : 28 plp +11fa : 860f stx zpt+3 +11fc : 08 php ;flags after load/store sequence +11fd : 49c3 eor #$c3 +11ff : aa tax +1200 : e416 cpx zp1+3 ;test result + trap_ne +1202 : d0fe > bne * ;failed not equal (non zero) + +1204 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1205 : 497d > eor #lo~fnz |fao ;invert expected + +1207 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +120a : d0fe > bne * ;failed not equal (non zero) + + + set_stat 0 + > load_flag 0 +120c : a900 > lda #0 ;allow test to change + > +120e : 48 > pha ;use stack to load status +120f : 28 > plp + +1210 : a2c3 ldx #$c3 +1212 : 08 php +1213 : ec1702 cpx abs1 ;test result + trap_ne +1216 : d0fe > bne * ;failed not equal (non zero) + +1218 : 68 pla ;load status + eor_flag 0 +1219 : 4930 > eor #0|fao ;invert expected flags + +121b : cd1c02 cmp fLDx ;test flags + trap_ne +121e : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1220 : a900 > lda #0 ;allow test to change I + > +1222 : 48 > pha ;use stack to load status +1223 : 28 > plp + +1224 : a282 ldx #$82 +1226 : 08 php +1227 : ec1802 cpx abs1+1 ;test result + trap_ne +122a : d0fe > bne * ;failed not equal (non zero) + +122c : 68 pla ;load status + eor_flag 0 +122d : 4930 > eor #0|fao ;invert expected flags + +122f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1232 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1234 : a900 > lda #0 ;allow test to change I + > +1236 : 48 > pha ;use stack to load status +1237 : 28 > plp + +1238 : a241 ldx #$41 +123a : 08 php +123b : ec1902 cpx abs1+2 ;test result + trap_ne +123e : d0fe > bne * ;failed not equal (non zero) + +1240 : 68 pla ;load status + eor_flag 0 +1241 : 4930 > eor #0|fao ;invert expected flags + +1243 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1246 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1248 : a900 > lda #0 ;allow test to change I + > +124a : 48 > pha ;use stack to load status +124b : 28 > plp + +124c : a200 ldx #0 +124e : 08 php +124f : ec1a02 cpx abs1+3 ;test result + trap_ne +1252 : d0fe > bne * ;failed not equal (non zero) + +1254 : 68 pla ;load status + eor_flag 0 +1255 : 4930 > eor #0|fao ;invert expected flags + +1257 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +125a : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +125c : a9ff > lda #$ff ;allow test to change + > +125e : 48 > pha ;use stack to load status +125f : 28 > plp + +1260 : a2c3 ldx #$c3 +1262 : 08 php +1263 : ec1702 cpx abs1 ;test result + trap_ne +1266 : d0fe > bne * ;failed not equal (non zero) + +1268 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1269 : 497d > eor #lo~fnz |fao ;invert expected + +126b : cd1c02 cmp fLDx ;test flags + trap_ne +126e : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1270 : a9ff > lda #$ff ;allow test to change + > +1272 : 48 > pha ;use stack to load status +1273 : 28 > plp + +1274 : a282 ldx #$82 +1276 : 08 php +1277 : ec1802 cpx abs1+1 ;test result + trap_ne +127a : d0fe > bne * ;failed not equal (non zero) + +127c : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +127d : 497d > eor #lo~fnz |fao ;invert expected + +127f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1282 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1284 : a9ff > lda #$ff ;allow test to change + > +1286 : 48 > pha ;use stack to load status +1287 : 28 > plp + +1288 : a241 ldx #$41 +128a : 08 php +128b : ec1902 cpx abs1+2 ;test result + trap_ne +128e : d0fe > bne * ;failed not equal (non zero) + +1290 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1291 : 497d > eor #lo~fnz |fao ;invert expected + +1293 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1296 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1298 : a9ff > lda #$ff ;allow test to change + > +129a : 48 > pha ;use stack to load status +129b : 28 > plp + +129c : a200 ldx #0 +129e : 08 php +129f : ec1a02 cpx abs1+3 ;test result + trap_ne +12a2 : d0fe > bne * ;failed not equal (non zero) + +12a4 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +12a5 : 497d > eor #lo~fnz |fao ;invert expected + +12a7 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +12aa : d0fe > bne * ;failed not equal (non zero) + + +12ac : a200 ldx #0 +12ae : a50c lda zpt +12b0 : 49c3 eor #$c3 +12b2 : c513 cmp zp1 + trap_ne ;store to zp data +12b4 : d0fe > bne * ;failed not equal (non zero) + +12b6 : 860c stx zpt ;clear +12b8 : ad0302 lda abst +12bb : 49c3 eor #$c3 +12bd : cd1702 cmp abs1 + trap_ne ;store to abs data +12c0 : d0fe > bne * ;failed not equal (non zero) + +12c2 : 8e0302 stx abst ;clear +12c5 : a50d lda zpt+1 +12c7 : 49c3 eor #$c3 +12c9 : c514 cmp zp1+1 + trap_ne ;store to zp data +12cb : d0fe > bne * ;failed not equal (non zero) + +12cd : 860d stx zpt+1 ;clear +12cf : ad0402 lda abst+1 +12d2 : 49c3 eor #$c3 +12d4 : cd1802 cmp abs1+1 + trap_ne ;store to abs data +12d7 : d0fe > bne * ;failed not equal (non zero) + +12d9 : 8e0402 stx abst+1 ;clear +12dc : a50e lda zpt+2 +12de : 49c3 eor #$c3 +12e0 : c515 cmp zp1+2 + trap_ne ;store to zp data +12e2 : d0fe > bne * ;failed not equal (non zero) + +12e4 : 860e stx zpt+2 ;clear +12e6 : ad0502 lda abst+2 +12e9 : 49c3 eor #$c3 +12eb : cd1902 cmp abs1+2 + trap_ne ;store to abs data +12ee : d0fe > bne * ;failed not equal (non zero) + +12f0 : 8e0502 stx abst+2 ;clear +12f3 : a50f lda zpt+3 +12f5 : 49c3 eor #$c3 +12f7 : c516 cmp zp1+3 + trap_ne ;store to zp data +12f9 : d0fe > bne * ;failed not equal (non zero) + +12fb : 860f stx zpt+3 ;clear +12fd : ad0602 lda abst+3 +1300 : 49c3 eor #$c3 +1302 : cd1a02 cmp abs1+3 + trap_ne ;store to abs data +1305 : d0fe > bne * ;failed not equal (non zero) + +1307 : 8e0602 stx abst+3 ;clear + next_test +130a : ad0002 > lda test_case ;previous test +130d : c913 > cmp #test_num + > trap_ne ;test is out of sequence +130f : d0fe > bne * ;failed not equal (non zero) + > +0014 = >test_num = test_num + 1 +1311 : a914 > lda #test_num ;*** next tests' number +1313 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDY / STY - zp / abs / # + set_stat 0 + > load_flag 0 +1316 : a900 > lda #0 ;allow test to change I + > +1318 : 48 > pha ;use stack to load status +1319 : 28 > plp + +131a : a413 ldy zp1 +131c : 08 php ;test stores do not alter flags +131d : 98 tya +131e : 49c3 eor #$c3 +1320 : a8 tay +1321 : 28 plp +1322 : 8c0302 sty abst +1325 : 08 php ;flags after load/store sequence +1326 : 49c3 eor #$c3 +1328 : a8 tay +1329 : c0c3 cpy #$c3 ;test result + trap_ne +132b : d0fe > bne * ;failed not equal (non zero) + +132d : 68 pla ;load status + eor_flag 0 +132e : 4930 > eor #0|fao ;invert expected flags + +1330 : cd1c02 cmp fLDx ;test flags + trap_ne +1333 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1335 : a900 > lda #0 ;allow test to change I + > +1337 : 48 > pha ;use stack to load status +1338 : 28 > plp + +1339 : a414 ldy zp1+1 +133b : 08 php ;test stores do not alter flags +133c : 98 tya +133d : 49c3 eor #$c3 +133f : a8 tay +1340 : 28 plp +1341 : 8c0402 sty abst+1 +1344 : 08 php ;flags after load/store sequence +1345 : 49c3 eor #$c3 +1347 : a8 tay +1348 : c082 cpy #$82 ;test result + trap_ne +134a : d0fe > bne * ;failed not equal (non zero) + +134c : 68 pla ;load status + eor_flag 0 +134d : 4930 > eor #0|fao ;invert expected flags + +134f : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1352 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1354 : a900 > lda #0 ;allow test to change I + > +1356 : 48 > pha ;use stack to load status +1357 : 28 > plp + +1358 : a415 ldy zp1+2 +135a : 08 php ;test stores do not alter flags +135b : 98 tya +135c : 49c3 eor #$c3 +135e : a8 tay +135f : 28 plp +1360 : 8c0502 sty abst+2 +1363 : 08 php ;flags after load/store sequence +1364 : 49c3 eor #$c3 +1366 : a8 tay +1367 : c041 cpy #$41 ;test result + trap_ne +1369 : d0fe > bne * ;failed not equal (non zero) + +136b : 68 pla ;load status + eor_flag 0 +136c : 4930 > eor #0|fao ;invert expected flags + +136e : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1371 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1373 : a900 > lda #0 ;allow test to change I + > +1375 : 48 > pha ;use stack to load status +1376 : 28 > plp + +1377 : a416 ldy zp1+3 +1379 : 08 php ;test stores do not alter flags +137a : 98 tya +137b : 49c3 eor #$c3 +137d : a8 tay +137e : 28 plp +137f : 8c0602 sty abst+3 +1382 : 08 php ;flags after load/store sequence +1383 : 49c3 eor #$c3 +1385 : a8 tay +1386 : c000 cpy #0 ;test result + trap_ne +1388 : d0fe > bne * ;failed not equal (non zero) + +138a : 68 pla ;load status + eor_flag 0 +138b : 4930 > eor #0|fao ;invert expected flags + +138d : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1390 : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1392 : a9ff > lda #$ff ;allow test to change + > +1394 : 48 > pha ;use stack to load status +1395 : 28 > plp + +1396 : a413 ldy zp1 +1398 : 08 php ;test stores do not alter flags +1399 : 98 tya +139a : 49c3 eor #$c3 +139c : a8 tay +139d : 28 plp +139e : 8c0302 sty abst +13a1 : 08 php ;flags after load/store sequence +13a2 : 49c3 eor #$c3 +13a4 : a8 tay +13a5 : c0c3 cpy #$c3 ;test result + trap_ne +13a7 : d0fe > bne * ;failed not equal (non zero) + +13a9 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +13aa : 497d > eor #lo~fnz |fao ;invert expected + +13ac : cd1c02 cmp fLDx ;test flags + trap_ne +13af : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +13b1 : a9ff > lda #$ff ;allow test to change + > +13b3 : 48 > pha ;use stack to load status +13b4 : 28 > plp + +13b5 : a414 ldy zp1+1 +13b7 : 08 php ;test stores do not alter flags +13b8 : 98 tya +13b9 : 49c3 eor #$c3 +13bb : a8 tay +13bc : 28 plp +13bd : 8c0402 sty abst+1 +13c0 : 08 php ;flags after load/store sequence +13c1 : 49c3 eor #$c3 +13c3 : a8 tay +13c4 : c082 cpy #$82 ;test result + trap_ne +13c6 : d0fe > bne * ;failed not equal (non zero) + +13c8 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +13c9 : 497d > eor #lo~fnz |fao ;invert expected + +13cb : cd1d02 cmp fLDx+1 ;test flags + trap_ne +13ce : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +13d0 : a9ff > lda #$ff ;allow test to change + > +13d2 : 48 > pha ;use stack to load status +13d3 : 28 > plp + +13d4 : a415 ldy zp1+2 +13d6 : 08 php ;test stores do not alter flags +13d7 : 98 tya +13d8 : 49c3 eor #$c3 +13da : a8 tay +13db : 28 plp +13dc : 8c0502 sty abst+2 +13df : 08 php ;flags after load/store sequence +13e0 : 49c3 eor #$c3 +13e2 : a8 tay +13e3 : c041 cpy #$41 ;test result + trap_ne +13e5 : d0fe > bne * ;failed not equal (non zero) + +13e7 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +13e8 : 497d > eor #lo~fnz |fao ;invert expected + +13ea : cd1e02 cmp fLDx+2 ;test flags + trap_ne +13ed : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +13ef : a9ff > lda #$ff ;allow test to change + > +13f1 : 48 > pha ;use stack to load status +13f2 : 28 > plp + +13f3 : a416 ldy zp1+3 +13f5 : 08 php ;test stores do not alter flags +13f6 : 98 tya +13f7 : 49c3 eor #$c3 +13f9 : a8 tay +13fa : 28 plp +13fb : 8c0602 sty abst+3 +13fe : 08 php ;flags after load/store sequence +13ff : 49c3 eor #$c3 +1401 : a8 tay +1402 : c000 cpy #0 ;test result + trap_ne +1404 : d0fe > bne * ;failed not equal (non zero) + +1406 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1407 : 497d > eor #lo~fnz |fao ;invert expected + +1409 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +140c : d0fe > bne * ;failed not equal (non zero) + + + set_stat 0 + > load_flag 0 +140e : a900 > lda #0 ;allow test to change I + > +1410 : 48 > pha ;use stack to load status +1411 : 28 > plp + +1412 : ac1702 ldy abs1 +1415 : 08 php ;test stores do not alter flags +1416 : 98 tya +1417 : 49c3 eor #$c3 +1419 : a8 tay +141a : 28 plp +141b : 840c sty zpt +141d : 08 php ;flags after load/store sequence +141e : 49c3 eor #$c3 +1420 : a8 tay +1421 : c413 cpy zp1 ;test result + trap_ne +1423 : d0fe > bne * ;failed not equal (non zero) + +1425 : 68 pla ;load status + eor_flag 0 +1426 : 4930 > eor #0|fao ;invert expected flags + +1428 : cd1c02 cmp fLDx ;test flags + trap_ne +142b : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +142d : a900 > lda #0 ;allow test to change I + > +142f : 48 > pha ;use stack to load status +1430 : 28 > plp + +1431 : ac1802 ldy abs1+1 +1434 : 08 php ;test stores do not alter flags +1435 : 98 tya +1436 : 49c3 eor #$c3 +1438 : a8 tay +1439 : 28 plp +143a : 840d sty zpt+1 +143c : 08 php ;flags after load/store sequence +143d : 49c3 eor #$c3 +143f : a8 tay +1440 : c414 cpy zp1+1 ;test result + trap_ne +1442 : d0fe > bne * ;failed not equal (non zero) + +1444 : 68 pla ;load status + eor_flag 0 +1445 : 4930 > eor #0|fao ;invert expected flags + +1447 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +144a : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +144c : a900 > lda #0 ;allow test to change I + > +144e : 48 > pha ;use stack to load status +144f : 28 > plp + +1450 : ac1902 ldy abs1+2 +1453 : 08 php ;test stores do not alter flags +1454 : 98 tya +1455 : 49c3 eor #$c3 +1457 : a8 tay +1458 : 28 plp +1459 : 840e sty zpt+2 +145b : 08 php ;flags after load/store sequence +145c : 49c3 eor #$c3 +145e : a8 tay +145f : c415 cpy zp1+2 ;test result + trap_ne +1461 : d0fe > bne * ;failed not equal (non zero) + +1463 : 68 pla ;load status + eor_flag 0 +1464 : 4930 > eor #0|fao ;invert expected flags + +1466 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1469 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +146b : a900 > lda #0 ;allow test to change I + > +146d : 48 > pha ;use stack to load status +146e : 28 > plp + +146f : ac1a02 ldy abs1+3 +1472 : 08 php ;test stores do not alter flags +1473 : 98 tya +1474 : 49c3 eor #$c3 +1476 : a8 tay +1477 : 28 plp +1478 : 840f sty zpt+3 +147a : 08 php ;flags after load/store sequence +147b : 49c3 eor #$c3 +147d : a8 tay +147e : c416 cpy zp1+3 ;test result + trap_ne +1480 : d0fe > bne * ;failed not equal (non zero) + +1482 : 68 pla ;load status + eor_flag 0 +1483 : 4930 > eor #0|fao ;invert expected flags + +1485 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1488 : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +148a : a9ff > lda #$ff ;allow test to change + > +148c : 48 > pha ;use stack to load status +148d : 28 > plp + +148e : ac1702 ldy abs1 +1491 : 08 php ;test stores do not alter flags +1492 : 98 tya +1493 : 49c3 eor #$c3 +1495 : a8 tay +1496 : 28 plp +1497 : 840c sty zpt +1499 : 08 php ;flags after load/store sequence +149a : 49c3 eor #$c3 +149c : a8 tay +149d : c513 cmp zp1 ;test result + trap_ne +149f : d0fe > bne * ;failed not equal (non zero) + +14a1 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14a2 : 497d > eor #lo~fnz |fao ;invert expected + +14a4 : cd1c02 cmp fLDx ;test flags + trap_ne +14a7 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +14a9 : a9ff > lda #$ff ;allow test to change + > +14ab : 48 > pha ;use stack to load status +14ac : 28 > plp + +14ad : ac1802 ldy abs1+1 +14b0 : 08 php ;test stores do not alter flags +14b1 : 98 tya +14b2 : 49c3 eor #$c3 +14b4 : a8 tay +14b5 : 28 plp +14b6 : 840d sty zpt+1 +14b8 : 08 php ;flags after load/store sequence +14b9 : 49c3 eor #$c3 +14bb : a8 tay +14bc : c514 cmp zp1+1 ;test result + trap_ne +14be : d0fe > bne * ;failed not equal (non zero) + +14c0 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14c1 : 497d > eor #lo~fnz |fao ;invert expected + +14c3 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +14c6 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +14c8 : a9ff > lda #$ff ;allow test to change + > +14ca : 48 > pha ;use stack to load status +14cb : 28 > plp + +14cc : ac1902 ldy abs1+2 +14cf : 08 php ;test stores do not alter flags +14d0 : 98 tya +14d1 : 49c3 eor #$c3 +14d3 : a8 tay +14d4 : 28 plp +14d5 : 840e sty zpt+2 +14d7 : 08 php ;flags after load/store sequence +14d8 : 49c3 eor #$c3 +14da : a8 tay +14db : c515 cmp zp1+2 ;test result + trap_ne +14dd : d0fe > bne * ;failed not equal (non zero) + +14df : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14e0 : 497d > eor #lo~fnz |fao ;invert expected + +14e2 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +14e5 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +14e7 : a9ff > lda #$ff ;allow test to change + > +14e9 : 48 > pha ;use stack to load status +14ea : 28 > plp + +14eb : ac1a02 ldy abs1+3 +14ee : 08 php ;test stores do not alter flags +14ef : 98 tya +14f0 : 49c3 eor #$c3 +14f2 : a8 tay +14f3 : 28 plp +14f4 : 840f sty zpt+3 +14f6 : 08 php ;flags after load/store sequence +14f7 : 49c3 eor #$c3 +14f9 : a8 tay +14fa : c516 cmp zp1+3 ;test result + trap_ne +14fc : d0fe > bne * ;failed not equal (non zero) + +14fe : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +14ff : 497d > eor #lo~fnz |fao ;invert expected + +1501 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1504 : d0fe > bne * ;failed not equal (non zero) + + + + set_stat 0 + > load_flag 0 +1506 : a900 > lda #0 ;allow test to change I + > +1508 : 48 > pha ;use stack to load status +1509 : 28 > plp + +150a : a0c3 ldy #$c3 +150c : 08 php +150d : cc1702 cpy abs1 ;test result + trap_ne +1510 : d0fe > bne * ;failed not equal (non zero) + +1512 : 68 pla ;load status + eor_flag 0 +1513 : 4930 > eor #0|fao ;invert expected flags + +1515 : cd1c02 cmp fLDx ;test flags + trap_ne +1518 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +151a : a900 > lda #0 ;allow test to change I + > +151c : 48 > pha ;use stack to load status +151d : 28 > plp + +151e : a082 ldy #$82 +1520 : 08 php +1521 : cc1802 cpy abs1+1 ;test result + trap_ne +1524 : d0fe > bne * ;failed not equal (non zero) + +1526 : 68 pla ;load status + eor_flag 0 +1527 : 4930 > eor #0|fao ;invert expected flags + +1529 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +152c : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +152e : a900 > lda #0 ;allow test to change I + > +1530 : 48 > pha ;use stack to load status +1531 : 28 > plp + +1532 : a041 ldy #$41 +1534 : 08 php +1535 : cc1902 cpy abs1+2 ;test result + trap_ne +1538 : d0fe > bne * ;failed not equal (non zero) + +153a : 68 pla ;load status + eor_flag 0 +153b : 4930 > eor #0|fao ;invert expected flags + +153d : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1540 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1542 : a900 > lda #0 ;allow test to change I + > +1544 : 48 > pha ;use stack to load status +1545 : 28 > plp + +1546 : a000 ldy #0 +1548 : 08 php +1549 : cc1a02 cpy abs1+3 ;test result + trap_ne +154c : d0fe > bne * ;failed not equal (non zero) + +154e : 68 pla ;load status + eor_flag 0 +154f : 4930 > eor #0|fao ;invert expected flags + +1551 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1554 : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1556 : a9ff > lda #$ff ;allow test to change + > +1558 : 48 > pha ;use stack to load status +1559 : 28 > plp + +155a : a0c3 ldy #$c3 +155c : 08 php +155d : cc1702 cpy abs1 ;test result + trap_ne +1560 : d0fe > bne * ;failed not equal (non zero) + +1562 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1563 : 497d > eor #lo~fnz |fao ;invert expected + +1565 : cd1c02 cmp fLDx ;test flags + trap_ne +1568 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +156a : a9ff > lda #$ff ;allow test to change + > +156c : 48 > pha ;use stack to load status +156d : 28 > plp + +156e : a082 ldy #$82 +1570 : 08 php +1571 : cc1802 cpy abs1+1 ;test result + trap_ne +1574 : d0fe > bne * ;failed not equal (non zero) + +1576 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1577 : 497d > eor #lo~fnz |fao ;invert expected + +1579 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +157c : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +157e : a9ff > lda #$ff ;allow test to change + > +1580 : 48 > pha ;use stack to load status +1581 : 28 > plp + +1582 : a041 ldy #$41 +1584 : 08 php +1585 : cc1902 cpy abs1+2 ;test result + trap_ne +1588 : d0fe > bne * ;failed not equal (non zero) + +158a : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +158b : 497d > eor #lo~fnz |fao ;invert expected + +158d : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1590 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1592 : a9ff > lda #$ff ;allow test to change + > +1594 : 48 > pha ;use stack to load status +1595 : 28 > plp + +1596 : a000 ldy #0 +1598 : 08 php +1599 : cc1a02 cpy abs1+3 ;test result + trap_ne +159c : d0fe > bne * ;failed not equal (non zero) + +159e : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +159f : 497d > eor #lo~fnz |fao ;invert expected + +15a1 : cd1f02 cmp fLDx+3 ;test flags + trap_ne +15a4 : d0fe > bne * ;failed not equal (non zero) + + +15a6 : a000 ldy #0 +15a8 : a50c lda zpt +15aa : 49c3 eor #$c3 +15ac : c513 cmp zp1 + trap_ne ;store to zp data +15ae : d0fe > bne * ;failed not equal (non zero) + +15b0 : 840c sty zpt ;clear +15b2 : ad0302 lda abst +15b5 : 49c3 eor #$c3 +15b7 : cd1702 cmp abs1 + trap_ne ;store to abs data +15ba : d0fe > bne * ;failed not equal (non zero) + +15bc : 8c0302 sty abst ;clear +15bf : a50d lda zpt+1 +15c1 : 49c3 eor #$c3 +15c3 : c514 cmp zp1+1 + trap_ne ;store to zp+1 data +15c5 : d0fe > bne * ;failed not equal (non zero) + +15c7 : 840d sty zpt+1 ;clear +15c9 : ad0402 lda abst+1 +15cc : 49c3 eor #$c3 +15ce : cd1802 cmp abs1+1 + trap_ne ;store to abs+1 data +15d1 : d0fe > bne * ;failed not equal (non zero) + +15d3 : 8c0402 sty abst+1 ;clear +15d6 : a50e lda zpt+2 +15d8 : 49c3 eor #$c3 +15da : c515 cmp zp1+2 + trap_ne ;store to zp+2 data +15dc : d0fe > bne * ;failed not equal (non zero) + +15de : 840e sty zpt+2 ;clear +15e0 : ad0502 lda abst+2 +15e3 : 49c3 eor #$c3 +15e5 : cd1902 cmp abs1+2 + trap_ne ;store to abs+2 data +15e8 : d0fe > bne * ;failed not equal (non zero) + +15ea : 8c0502 sty abst+2 ;clear +15ed : a50f lda zpt+3 +15ef : 49c3 eor #$c3 +15f1 : c516 cmp zp1+3 + trap_ne ;store to zp+3 data +15f3 : d0fe > bne * ;failed not equal (non zero) + +15f5 : 840f sty zpt+3 ;clear +15f7 : ad0602 lda abst+3 +15fa : 49c3 eor #$c3 +15fc : cd1a02 cmp abs1+3 + trap_ne ;store to abs+3 data +15ff : d0fe > bne * ;failed not equal (non zero) + +1601 : 8c0602 sty abst+3 ;clear + next_test +1604 : ad0002 > lda test_case ;previous test +1607 : c914 > cmp #test_num + > trap_ne ;test is out of sequence +1609 : d0fe > bne * ;failed not equal (non zero) + > +0015 = >test_num = test_num + 1 +160b : a915 > lda #test_num ;*** next tests' number +160d : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing load / store accumulator LDA / STA all addre + ; LDA / STA - zp,x / abs,x +1610 : a203 ldx #3 +1612 : tldax + set_stat 0 + > load_flag 0 +1612 : a900 > lda #0 ;allow test to change I + > +1614 : 48 > pha ;use stack to load status +1615 : 28 > plp + +1616 : b513 lda zp1,x +1618 : 08 php ;test stores do not alter flags +1619 : 49c3 eor #$c3 +161b : 28 plp +161c : 9d0302 sta abst,x +161f : 08 php ;flags after load/store sequence +1620 : 49c3 eor #$c3 +1622 : dd1702 cmp abs1,x ;test result + trap_ne +1625 : d0fe > bne * ;failed not equal (non zero) + +1627 : 68 pla ;load status + eor_flag 0 +1628 : 4930 > eor #0|fao ;invert expected flags + +162a : dd1c02 cmp fLDx,x ;test flags + trap_ne +162d : d0fe > bne * ;failed not equal (non zero) + +162f : ca dex +1630 : 10e0 bpl tldax + +1632 : a203 ldx #3 +1634 : tldax1 + set_stat $ff + > load_flag $ff +1634 : a9ff > lda #$ff ;allow test to change + > +1636 : 48 > pha ;use stack to load status +1637 : 28 > plp + +1638 : b513 lda zp1,x +163a : 08 php ;test stores do not alter flags +163b : 49c3 eor #$c3 +163d : 28 plp +163e : 9d0302 sta abst,x +1641 : 08 php ;flags after load/store sequence +1642 : 49c3 eor #$c3 +1644 : dd1702 cmp abs1,x ;test result + trap_ne +1647 : d0fe > bne * ;failed not equal (non zero) + +1649 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +164a : 497d > eor #lo~fnz |fao ;invert expected + +164c : dd1c02 cmp fLDx,x ;test flags + trap_ne +164f : d0fe > bne * ;failed not equal (non zero) + +1651 : ca dex +1652 : 10e0 bpl tldax1 + +1654 : a203 ldx #3 +1656 : tldax2 + set_stat 0 + > load_flag 0 +1656 : a900 > lda #0 ;allow test to change I + > +1658 : 48 > pha ;use stack to load status +1659 : 28 > plp + +165a : bd1702 lda abs1,x +165d : 08 php ;test stores do not alter flags +165e : 49c3 eor #$c3 +1660 : 28 plp +1661 : 950c sta zpt,x +1663 : 08 php ;flags after load/store sequence +1664 : 49c3 eor #$c3 +1666 : d513 cmp zp1,x ;test result + trap_ne +1668 : d0fe > bne * ;failed not equal (non zero) + +166a : 68 pla ;load status + eor_flag 0 +166b : 4930 > eor #0|fao ;invert expected flags + +166d : dd1c02 cmp fLDx,x ;test flags + trap_ne +1670 : d0fe > bne * ;failed not equal (non zero) + +1672 : ca dex +1673 : 10e1 bpl tldax2 + +1675 : a203 ldx #3 +1677 : tldax3 + set_stat $ff + > load_flag $ff +1677 : a9ff > lda #$ff ;allow test to change + > +1679 : 48 > pha ;use stack to load status +167a : 28 > plp + +167b : bd1702 lda abs1,x +167e : 08 php ;test stores do not alter flags +167f : 49c3 eor #$c3 +1681 : 28 plp +1682 : 950c sta zpt,x +1684 : 08 php ;flags after load/store sequence +1685 : 49c3 eor #$c3 +1687 : d513 cmp zp1,x ;test result + trap_ne +1689 : d0fe > bne * ;failed not equal (non zero) + +168b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +168c : 497d > eor #lo~fnz |fao ;invert expected + +168e : dd1c02 cmp fLDx,x ;test flags + trap_ne +1691 : d0fe > bne * ;failed not equal (non zero) + +1693 : ca dex +1694 : 10e1 bpl tldax3 + +1696 : a203 ldx #3 ;testing store result +1698 : a000 ldy #0 +169a : b50c tstax lda zpt,x +169c : 49c3 eor #$c3 +169e : d513 cmp zp1,x + trap_ne ;store to zp,x data +16a0 : d0fe > bne * ;failed not equal (non zero) + +16a2 : 940c sty zpt,x ;clear +16a4 : bd0302 lda abst,x +16a7 : 49c3 eor #$c3 +16a9 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +16ac : d0fe > bne * ;failed not equal (non zero) + +16ae : 8a txa +16af : 9d0302 sta abst,x ;clear +16b2 : ca dex +16b3 : 10e5 bpl tstax + next_test +16b5 : ad0002 > lda test_case ;previous test +16b8 : c915 > cmp #test_num + > trap_ne ;test is out of sequence +16ba : d0fe > bne * ;failed not equal (non zero) + > +0016 = >test_num = test_num + 1 +16bc : a916 > lda #test_num ;*** next tests' number +16be : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDA / STA - (zp),y / abs,y / (zp,x) +16c1 : a003 ldy #3 +16c3 : tlday + set_stat 0 + > load_flag 0 +16c3 : a900 > lda #0 ;allow test to change I + > +16c5 : 48 > pha ;use stack to load status +16c6 : 28 > plp + +16c7 : b124 lda (ind1),y +16c9 : 08 php ;test stores do not alter flags +16ca : 49c3 eor #$c3 +16cc : 28 plp +16cd : 990302 sta abst,y +16d0 : 08 php ;flags after load/store sequence +16d1 : 49c3 eor #$c3 +16d3 : d91702 cmp abs1,y ;test result + trap_ne +16d6 : d0fe > bne * ;failed not equal (non zero) + +16d8 : 68 pla ;load status + eor_flag 0 +16d9 : 4930 > eor #0|fao ;invert expected flags + +16db : d91c02 cmp fLDx,y ;test flags + trap_ne +16de : d0fe > bne * ;failed not equal (non zero) + +16e0 : 88 dey +16e1 : 10e0 bpl tlday + +16e3 : a003 ldy #3 +16e5 : tlday1 + set_stat $ff + > load_flag $ff +16e5 : a9ff > lda #$ff ;allow test to change + > +16e7 : 48 > pha ;use stack to load status +16e8 : 28 > plp + +16e9 : b124 lda (ind1),y +16eb : 08 php ;test stores do not alter flags +16ec : 49c3 eor #$c3 +16ee : 28 plp +16ef : 990302 sta abst,y +16f2 : 08 php ;flags after load/store sequence +16f3 : 49c3 eor #$c3 +16f5 : d91702 cmp abs1,y ;test result + trap_ne +16f8 : d0fe > bne * ;failed not equal (non zero) + +16fa : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +16fb : 497d > eor #lo~fnz |fao ;invert expected + +16fd : d91c02 cmp fLDx,y ;test flags + trap_ne +1700 : d0fe > bne * ;failed not equal (non zero) + +1702 : 88 dey +1703 : 10e0 bpl tlday1 + +1705 : a003 ldy #3 ;testing store result +1707 : a200 ldx #0 +1709 : b90302 tstay lda abst,y +170c : 49c3 eor #$c3 +170e : d91702 cmp abs1,y + trap_ne ;store to abs data +1711 : d0fe > bne * ;failed not equal (non zero) + +1713 : 8a txa +1714 : 990302 sta abst,y ;clear +1717 : 88 dey +1718 : 10ef bpl tstay + +171a : a003 ldy #3 +171c : tlday2 + set_stat 0 + > load_flag 0 +171c : a900 > lda #0 ;allow test to change I + > +171e : 48 > pha ;use stack to load status +171f : 28 > plp + +1720 : b91702 lda abs1,y +1723 : 08 php ;test stores do not alter flags +1724 : 49c3 eor #$c3 +1726 : 28 plp +1727 : 9130 sta (indt),y +1729 : 08 php ;flags after load/store sequence +172a : 49c3 eor #$c3 +172c : d124 cmp (ind1),y ;test result + trap_ne +172e : d0fe > bne * ;failed not equal (non zero) + +1730 : 68 pla ;load status + eor_flag 0 +1731 : 4930 > eor #0|fao ;invert expected flags + +1733 : d91c02 cmp fLDx,y ;test flags + trap_ne +1736 : d0fe > bne * ;failed not equal (non zero) + +1738 : 88 dey +1739 : 10e1 bpl tlday2 + +173b : a003 ldy #3 +173d : tlday3 + set_stat $ff + > load_flag $ff +173d : a9ff > lda #$ff ;allow test to change + > +173f : 48 > pha ;use stack to load status +1740 : 28 > plp + +1741 : b91702 lda abs1,y +1744 : 08 php ;test stores do not alter flags +1745 : 49c3 eor #$c3 +1747 : 28 plp +1748 : 9130 sta (indt),y +174a : 08 php ;flags after load/store sequence +174b : 49c3 eor #$c3 +174d : d124 cmp (ind1),y ;test result + trap_ne +174f : d0fe > bne * ;failed not equal (non zero) + +1751 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1752 : 497d > eor #lo~fnz |fao ;invert expected + +1754 : d91c02 cmp fLDx,y ;test flags + trap_ne +1757 : d0fe > bne * ;failed not equal (non zero) + +1759 : 88 dey +175a : 10e1 bpl tlday3 + +175c : a003 ldy #3 ;testing store result +175e : a200 ldx #0 +1760 : b90302 tstay1 lda abst,y +1763 : 49c3 eor #$c3 +1765 : d91702 cmp abs1,y + trap_ne ;store to abs data +1768 : d0fe > bne * ;failed not equal (non zero) + +176a : 8a txa +176b : 990302 sta abst,y ;clear +176e : 88 dey +176f : 10ef bpl tstay1 + +1771 : a206 ldx #6 +1773 : a003 ldy #3 +1775 : tldax4 + set_stat 0 + > load_flag 0 +1775 : a900 > lda #0 ;allow test to change I + > +1777 : 48 > pha ;use stack to load status +1778 : 28 > plp + +1779 : a124 lda (ind1,x) +177b : 08 php ;test stores do not alter flags +177c : 49c3 eor #$c3 +177e : 28 plp +177f : 8130 sta (indt,x) +1781 : 08 php ;flags after load/store sequence +1782 : 49c3 eor #$c3 +1784 : d91702 cmp abs1,y ;test result + trap_ne +1787 : d0fe > bne * ;failed not equal (non zero) + +1789 : 68 pla ;load status + eor_flag 0 +178a : 4930 > eor #0|fao ;invert expected flags + +178c : d91c02 cmp fLDx,y ;test flags + trap_ne +178f : d0fe > bne * ;failed not equal (non zero) + +1791 : ca dex +1792 : ca dex +1793 : 88 dey +1794 : 10df bpl tldax4 + +1796 : a206 ldx #6 +1798 : a003 ldy #3 +179a : tldax5 + set_stat $ff + > load_flag $ff +179a : a9ff > lda #$ff ;allow test to change + > +179c : 48 > pha ;use stack to load status +179d : 28 > plp + +179e : a124 lda (ind1,x) +17a0 : 08 php ;test stores do not alter flags +17a1 : 49c3 eor #$c3 +17a3 : 28 plp +17a4 : 8130 sta (indt,x) +17a6 : 08 php ;flags after load/store sequence +17a7 : 49c3 eor #$c3 +17a9 : d91702 cmp abs1,y ;test result + trap_ne +17ac : d0fe > bne * ;failed not equal (non zero) + +17ae : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +17af : 497d > eor #lo~fnz |fao ;invert expected + +17b1 : d91c02 cmp fLDx,y ;test flags + trap_ne +17b4 : d0fe > bne * ;failed not equal (non zero) + +17b6 : ca dex +17b7 : ca dex +17b8 : 88 dey +17b9 : 10df bpl tldax5 + +17bb : a003 ldy #3 ;testing store result +17bd : a200 ldx #0 +17bf : b90302 tstay2 lda abst,y +17c2 : 49c3 eor #$c3 +17c4 : d91702 cmp abs1,y + trap_ne ;store to abs data +17c7 : d0fe > bne * ;failed not equal (non zero) + +17c9 : 8a txa +17ca : 990302 sta abst,y ;clear +17cd : 88 dey +17ce : 10ef bpl tstay2 + next_test +17d0 : ad0002 > lda test_case ;previous test +17d3 : c916 > cmp #test_num + > trap_ne ;test is out of sequence +17d5 : d0fe > bne * ;failed not equal (non zero) + > +0017 = >test_num = test_num + 1 +17d7 : a917 > lda #test_num ;*** next tests' number +17d9 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; indexed wraparound test (only zp should wrap) +17dc : a2fd ldx #3+$fa +17de : b519 tldax6 lda zp1-$fa&$ff,x ;wrap on indexed zp +17e0 : 9d0901 sta abst-$fa,x ;no STX abs,x! +17e3 : ca dex +17e4 : e0fa cpx #$fa +17e6 : b0f6 bcs tldax6 +17e8 : a2fd ldx #3+$fa +17ea : bd1d01 tldax7 lda abs1-$fa,x ;no wrap on indexed abs +17ed : 9512 sta zpt-$fa&$ff,x +17ef : ca dex +17f0 : e0fa cpx #$fa +17f2 : b0f6 bcs tldax7 + +17f4 : a203 ldx #3 ;testing wraparound result +17f6 : a000 ldy #0 +17f8 : b50c tstax1 lda zpt,x +17fa : d513 cmp zp1,x + trap_ne ;store to zp,x data +17fc : d0fe > bne * ;failed not equal (non zero) + +17fe : 940c sty zpt,x ;clear +1800 : bd0302 lda abst,x +1803 : dd1702 cmp abs1,x + trap_ne ;store to abs,x data +1806 : d0fe > bne * ;failed not equal (non zero) + +1808 : 8a txa +1809 : 9d0302 sta abst,x ;clear +180c : ca dex +180d : 10e9 bpl tstax1 + +180f : a0fb ldy #3+$f8 +1811 : a2fe ldx #6+$f8 +1813 : a12c tlday4 lda (ind1-$f8&$ff,x) ;wrap on indexed zp indir +1815 : 990b01 sta abst-$f8,y +1818 : ca dex +1819 : ca dex +181a : 88 dey +181b : c0f8 cpy #$f8 +181d : b0f4 bcs tlday4 +181f : a003 ldy #3 ;testing wraparound result +1821 : a200 ldx #0 +1823 : b90302 tstay4 lda abst,y +1826 : d91702 cmp abs1,y + trap_ne ;store to abs data +1829 : d0fe > bne * ;failed not equal (non zero) + +182b : 8a txa +182c : 990302 sta abst,y ;clear +182f : 88 dey +1830 : 10f1 bpl tstay4 + +1832 : a0fb ldy #3+$f8 +1834 : b91f01 tlday5 lda abs1-$f8,y ;no wrap on indexed abs +1837 : 9138 sta (inwt),y +1839 : 88 dey +183a : c0f8 cpy #$f8 +183c : b0f6 bcs tlday5 +183e : a003 ldy #3 ;testing wraparound result +1840 : a200 ldx #0 +1842 : b90302 tstay5 lda abst,y +1845 : d91702 cmp abs1,y + trap_ne ;store to abs data +1848 : d0fe > bne * ;failed not equal (non zero) + +184a : 8a txa +184b : 990302 sta abst,y ;clear +184e : 88 dey +184f : 10f1 bpl tstay5 + +1851 : a0fb ldy #3+$f8 +1853 : a2fe ldx #6+$f8 +1855 : b12e tlday6 lda (inw1),y ;no wrap on zp indirect indexe +1857 : 8138 sta (indt-$f8&$ff,x) +1859 : ca dex +185a : ca dex +185b : 88 dey +185c : c0f8 cpy #$f8 +185e : b0f5 bcs tlday6 +1860 : a003 ldy #3 ;testing wraparound result +1862 : a200 ldx #0 +1864 : b90302 tstay6 lda abst,y +1867 : d91702 cmp abs1,y + trap_ne ;store to abs data +186a : d0fe > bne * ;failed not equal (non zero) + +186c : 8a txa +186d : 990302 sta abst,y ;clear +1870 : 88 dey +1871 : 10f1 bpl tstay6 + next_test +1873 : ad0002 > lda test_case ;previous test +1876 : c917 > cmp #test_num + > trap_ne ;test is out of sequence +1878 : d0fe > bne * ;failed not equal (non zero) + > +0018 = >test_num = test_num + 1 +187a : a918 > lda #test_num ;*** next tests' number +187c : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; LDA / STA - zp / abs / # + set_stat 0 + > load_flag 0 +187f : a900 > lda #0 ;allow test to change + > +1881 : 48 > pha ;use stack to load status +1882 : 28 > plp + +1883 : a513 lda zp1 +1885 : 08 php ;test stores do not alter flags +1886 : 49c3 eor #$c3 +1888 : 28 plp +1889 : 8d0302 sta abst +188c : 08 php ;flags after load/store sequence +188d : 49c3 eor #$c3 +188f : c9c3 cmp #$c3 ;test result + trap_ne +1891 : d0fe > bne * ;failed not equal (non zero) + +1893 : 68 pla ;load status + eor_flag 0 +1894 : 4930 > eor #0|fao ;invert expected flags + +1896 : cd1c02 cmp fLDx ;test flags + trap_ne +1899 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +189b : a900 > lda #0 ;allow test to change I + > +189d : 48 > pha ;use stack to load status +189e : 28 > plp + +189f : a514 lda zp1+1 +18a1 : 08 php ;test stores do not alter flags +18a2 : 49c3 eor #$c3 +18a4 : 28 plp +18a5 : 8d0402 sta abst+1 +18a8 : 08 php ;flags after load/store sequence +18a9 : 49c3 eor #$c3 +18ab : c982 cmp #$82 ;test result + trap_ne +18ad : d0fe > bne * ;failed not equal (non zero) + +18af : 68 pla ;load status + eor_flag 0 +18b0 : 4930 > eor #0|fao ;invert expected flags + +18b2 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +18b5 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +18b7 : a900 > lda #0 ;allow test to change I + > +18b9 : 48 > pha ;use stack to load status +18ba : 28 > plp + +18bb : a515 lda zp1+2 +18bd : 08 php ;test stores do not alter flags +18be : 49c3 eor #$c3 +18c0 : 28 plp +18c1 : 8d0502 sta abst+2 +18c4 : 08 php ;flags after load/store sequence +18c5 : 49c3 eor #$c3 +18c7 : c941 cmp #$41 ;test result + trap_ne +18c9 : d0fe > bne * ;failed not equal (non zero) + +18cb : 68 pla ;load status + eor_flag 0 +18cc : 4930 > eor #0|fao ;invert expected flags + +18ce : cd1e02 cmp fLDx+2 ;test flags + trap_ne +18d1 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +18d3 : a900 > lda #0 ;allow test to change I + > +18d5 : 48 > pha ;use stack to load status +18d6 : 28 > plp + +18d7 : a516 lda zp1+3 +18d9 : 08 php ;test stores do not alter flags +18da : 49c3 eor #$c3 +18dc : 28 plp +18dd : 8d0602 sta abst+3 +18e0 : 08 php ;flags after load/store sequence +18e1 : 49c3 eor #$c3 +18e3 : c900 cmp #0 ;test result + trap_ne +18e5 : d0fe > bne * ;failed not equal (non zero) + +18e7 : 68 pla ;load status + eor_flag 0 +18e8 : 4930 > eor #0|fao ;invert expected flags + +18ea : cd1f02 cmp fLDx+3 ;test flags + trap_ne +18ed : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +18ef : a9ff > lda #$ff ;allow test to change + > +18f1 : 48 > pha ;use stack to load status +18f2 : 28 > plp + +18f3 : a513 lda zp1 +18f5 : 08 php ;test stores do not alter flags +18f6 : 49c3 eor #$c3 +18f8 : 28 plp +18f9 : 8d0302 sta abst +18fc : 08 php ;flags after load/store sequence +18fd : 49c3 eor #$c3 +18ff : c9c3 cmp #$c3 ;test result + trap_ne +1901 : d0fe > bne * ;failed not equal (non zero) + +1903 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1904 : 497d > eor #lo~fnz |fao ;invert expected + +1906 : cd1c02 cmp fLDx ;test flags + trap_ne +1909 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +190b : a9ff > lda #$ff ;allow test to change + > +190d : 48 > pha ;use stack to load status +190e : 28 > plp + +190f : a514 lda zp1+1 +1911 : 08 php ;test stores do not alter flags +1912 : 49c3 eor #$c3 +1914 : 28 plp +1915 : 8d0402 sta abst+1 +1918 : 08 php ;flags after load/store sequence +1919 : 49c3 eor #$c3 +191b : c982 cmp #$82 ;test result + trap_ne +191d : d0fe > bne * ;failed not equal (non zero) + +191f : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1920 : 497d > eor #lo~fnz |fao ;invert expected + +1922 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1925 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1927 : a9ff > lda #$ff ;allow test to change + > +1929 : 48 > pha ;use stack to load status +192a : 28 > plp + +192b : a515 lda zp1+2 +192d : 08 php ;test stores do not alter flags +192e : 49c3 eor #$c3 +1930 : 28 plp +1931 : 8d0502 sta abst+2 +1934 : 08 php ;flags after load/store sequence +1935 : 49c3 eor #$c3 +1937 : c941 cmp #$41 ;test result + trap_ne +1939 : d0fe > bne * ;failed not equal (non zero) + +193b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +193c : 497d > eor #lo~fnz |fao ;invert expected + +193e : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1941 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1943 : a9ff > lda #$ff ;allow test to change + > +1945 : 48 > pha ;use stack to load status +1946 : 28 > plp + +1947 : a516 lda zp1+3 +1949 : 08 php ;test stores do not alter flags +194a : 49c3 eor #$c3 +194c : 28 plp +194d : 8d0602 sta abst+3 +1950 : 08 php ;flags after load/store sequence +1951 : 49c3 eor #$c3 +1953 : c900 cmp #0 ;test result + trap_ne +1955 : d0fe > bne * ;failed not equal (non zero) + +1957 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1958 : 497d > eor #lo~fnz |fao ;invert expected + +195a : cd1f02 cmp fLDx+3 ;test flags + trap_ne +195d : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +195f : a900 > lda #0 ;allow test to change I + > +1961 : 48 > pha ;use stack to load status +1962 : 28 > plp + +1963 : ad1702 lda abs1 +1966 : 08 php ;test stores do not alter flags +1967 : 49c3 eor #$c3 +1969 : 28 plp +196a : 850c sta zpt +196c : 08 php ;flags after load/store sequence +196d : 49c3 eor #$c3 +196f : c513 cmp zp1 ;test result + trap_ne +1971 : d0fe > bne * ;failed not equal (non zero) + +1973 : 68 pla ;load status + eor_flag 0 +1974 : 4930 > eor #0|fao ;invert expected flags + +1976 : cd1c02 cmp fLDx ;test flags + trap_ne +1979 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +197b : a900 > lda #0 ;allow test to change I + > +197d : 48 > pha ;use stack to load status +197e : 28 > plp + +197f : ad1802 lda abs1+1 +1982 : 08 php ;test stores do not alter flags +1983 : 49c3 eor #$c3 +1985 : 28 plp +1986 : 850d sta zpt+1 +1988 : 08 php ;flags after load/store sequence +1989 : 49c3 eor #$c3 +198b : c514 cmp zp1+1 ;test result + trap_ne +198d : d0fe > bne * ;failed not equal (non zero) + +198f : 68 pla ;load status + eor_flag 0 +1990 : 4930 > eor #0|fao ;invert expected flags + +1992 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1995 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1997 : a900 > lda #0 ;allow test to change I + > +1999 : 48 > pha ;use stack to load status +199a : 28 > plp + +199b : ad1902 lda abs1+2 +199e : 08 php ;test stores do not alter flags +199f : 49c3 eor #$c3 +19a1 : 28 plp +19a2 : 850e sta zpt+2 +19a4 : 08 php ;flags after load/store sequence +19a5 : 49c3 eor #$c3 +19a7 : c515 cmp zp1+2 ;test result + trap_ne +19a9 : d0fe > bne * ;failed not equal (non zero) + +19ab : 68 pla ;load status + eor_flag 0 +19ac : 4930 > eor #0|fao ;invert expected flags + +19ae : cd1e02 cmp fLDx+2 ;test flags + trap_ne +19b1 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +19b3 : a900 > lda #0 ;allow test to change I + > +19b5 : 48 > pha ;use stack to load status +19b6 : 28 > plp + +19b7 : ad1a02 lda abs1+3 +19ba : 08 php ;test stores do not alter flags +19bb : 49c3 eor #$c3 +19bd : 28 plp +19be : 850f sta zpt+3 +19c0 : 08 php ;flags after load/store sequence +19c1 : 49c3 eor #$c3 +19c3 : c516 cmp zp1+3 ;test result + trap_ne +19c5 : d0fe > bne * ;failed not equal (non zero) + +19c7 : 68 pla ;load status + eor_flag 0 +19c8 : 4930 > eor #0|fao ;invert expected flags + +19ca : cd1f02 cmp fLDx+3 ;test flags + trap_ne +19cd : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +19cf : a9ff > lda #$ff ;allow test to change + > +19d1 : 48 > pha ;use stack to load status +19d2 : 28 > plp + +19d3 : ad1702 lda abs1 +19d6 : 08 php ;test stores do not alter flags +19d7 : 49c3 eor #$c3 +19d9 : 28 plp +19da : 850c sta zpt +19dc : 08 php ;flags after load/store sequence +19dd : 49c3 eor #$c3 +19df : c513 cmp zp1 ;test result + trap_ne +19e1 : d0fe > bne * ;failed not equal (non zero) + +19e3 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +19e4 : 497d > eor #lo~fnz |fao ;invert expected + +19e6 : cd1c02 cmp fLDx ;test flags + trap_ne +19e9 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +19eb : a9ff > lda #$ff ;allow test to change + > +19ed : 48 > pha ;use stack to load status +19ee : 28 > plp + +19ef : ad1802 lda abs1+1 +19f2 : 08 php ;test stores do not alter flags +19f3 : 49c3 eor #$c3 +19f5 : 28 plp +19f6 : 850d sta zpt+1 +19f8 : 08 php ;flags after load/store sequence +19f9 : 49c3 eor #$c3 +19fb : c514 cmp zp1+1 ;test result + trap_ne +19fd : d0fe > bne * ;failed not equal (non zero) + +19ff : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a00 : 497d > eor #lo~fnz |fao ;invert expected + +1a02 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1a05 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1a07 : a9ff > lda #$ff ;allow test to change + > +1a09 : 48 > pha ;use stack to load status +1a0a : 28 > plp + +1a0b : ad1902 lda abs1+2 +1a0e : 08 php ;test stores do not alter flags +1a0f : 49c3 eor #$c3 +1a11 : 28 plp +1a12 : 850e sta zpt+2 +1a14 : 08 php ;flags after load/store sequence +1a15 : 49c3 eor #$c3 +1a17 : c515 cmp zp1+2 ;test result + trap_ne +1a19 : d0fe > bne * ;failed not equal (non zero) + +1a1b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a1c : 497d > eor #lo~fnz |fao ;invert expected + +1a1e : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1a21 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1a23 : a9ff > lda #$ff ;allow test to change + > +1a25 : 48 > pha ;use stack to load status +1a26 : 28 > plp + +1a27 : ad1a02 lda abs1+3 +1a2a : 08 php ;test stores do not alter flags +1a2b : 49c3 eor #$c3 +1a2d : 28 plp +1a2e : 850f sta zpt+3 +1a30 : 08 php ;flags after load/store sequence +1a31 : 49c3 eor #$c3 +1a33 : c516 cmp zp1+3 ;test result + trap_ne +1a35 : d0fe > bne * ;failed not equal (non zero) + +1a37 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a38 : 497d > eor #lo~fnz |fao ;invert expected + +1a3a : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1a3d : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a3f : a900 > lda #0 ;allow test to change + > +1a41 : 48 > pha ;use stack to load status +1a42 : 28 > plp + +1a43 : a9c3 lda #$c3 +1a45 : 08 php +1a46 : cd1702 cmp abs1 ;test result + trap_ne +1a49 : d0fe > bne * ;failed not equal (non zero) + +1a4b : 68 pla ;load status + eor_flag 0 +1a4c : 4930 > eor #0|fao ;invert expected flags + +1a4e : cd1c02 cmp fLDx ;test flags + trap_ne +1a51 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a53 : a900 > lda #0 ;allow test to change I + > +1a55 : 48 > pha ;use stack to load status +1a56 : 28 > plp + +1a57 : a982 lda #$82 +1a59 : 08 php +1a5a : cd1802 cmp abs1+1 ;test result + trap_ne +1a5d : d0fe > bne * ;failed not equal (non zero) + +1a5f : 68 pla ;load status + eor_flag 0 +1a60 : 4930 > eor #0|fao ;invert expected flags + +1a62 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1a65 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a67 : a900 > lda #0 ;allow test to change I + > +1a69 : 48 > pha ;use stack to load status +1a6a : 28 > plp + +1a6b : a941 lda #$41 +1a6d : 08 php +1a6e : cd1902 cmp abs1+2 ;test result + trap_ne +1a71 : d0fe > bne * ;failed not equal (non zero) + +1a73 : 68 pla ;load status + eor_flag 0 +1a74 : 4930 > eor #0|fao ;invert expected flags + +1a76 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1a79 : d0fe > bne * ;failed not equal (non zero) + + set_stat 0 + > load_flag 0 +1a7b : a900 > lda #0 ;allow test to change I + > +1a7d : 48 > pha ;use stack to load status +1a7e : 28 > plp + +1a7f : a900 lda #0 +1a81 : 08 php +1a82 : cd1a02 cmp abs1+3 ;test result + trap_ne +1a85 : d0fe > bne * ;failed not equal (non zero) + +1a87 : 68 pla ;load status + eor_flag 0 +1a88 : 4930 > eor #0|fao ;invert expected flags + +1a8a : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1a8d : d0fe > bne * ;failed not equal (non zero) + + + set_stat $ff + > load_flag $ff +1a8f : a9ff > lda #$ff ;allow test to change + > +1a91 : 48 > pha ;use stack to load status +1a92 : 28 > plp + +1a93 : a9c3 lda #$c3 +1a95 : 08 php +1a96 : cd1702 cmp abs1 ;test result + trap_ne +1a99 : d0fe > bne * ;failed not equal (non zero) + +1a9b : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1a9c : 497d > eor #lo~fnz |fao ;invert expected + +1a9e : cd1c02 cmp fLDx ;test flags + trap_ne +1aa1 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1aa3 : a9ff > lda #$ff ;allow test to change + > +1aa5 : 48 > pha ;use stack to load status +1aa6 : 28 > plp + +1aa7 : a982 lda #$82 +1aa9 : 08 php +1aaa : cd1802 cmp abs1+1 ;test result + trap_ne +1aad : d0fe > bne * ;failed not equal (non zero) + +1aaf : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1ab0 : 497d > eor #lo~fnz |fao ;invert expected + +1ab2 : cd1d02 cmp fLDx+1 ;test flags + trap_ne +1ab5 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1ab7 : a9ff > lda #$ff ;allow test to change + > +1ab9 : 48 > pha ;use stack to load status +1aba : 28 > plp + +1abb : a941 lda #$41 +1abd : 08 php +1abe : cd1902 cmp abs1+2 ;test result + trap_ne +1ac1 : d0fe > bne * ;failed not equal (non zero) + +1ac3 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1ac4 : 497d > eor #lo~fnz |fao ;invert expected + +1ac6 : cd1e02 cmp fLDx+2 ;test flags + trap_ne +1ac9 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +1acb : a9ff > lda #$ff ;allow test to change + > +1acd : 48 > pha ;use stack to load status +1ace : 28 > plp + +1acf : a900 lda #0 +1ad1 : 08 php +1ad2 : cd1a02 cmp abs1+3 ;test result + trap_ne +1ad5 : d0fe > bne * ;failed not equal (non zero) + +1ad7 : 68 pla ;load status + eor_flag lo~fnz ;mask bits not altered +1ad8 : 497d > eor #lo~fnz |fao ;invert expected + +1ada : cd1f02 cmp fLDx+3 ;test flags + trap_ne +1add : d0fe > bne * ;failed not equal (non zero) + + +1adf : a200 ldx #0 +1ae1 : a50c lda zpt +1ae3 : 49c3 eor #$c3 +1ae5 : c513 cmp zp1 + trap_ne ;store to zp data +1ae7 : d0fe > bne * ;failed not equal (non zero) + +1ae9 : 860c stx zpt ;clear +1aeb : ad0302 lda abst +1aee : 49c3 eor #$c3 +1af0 : cd1702 cmp abs1 + trap_ne ;store to abs data +1af3 : d0fe > bne * ;failed not equal (non zero) + +1af5 : 8e0302 stx abst ;clear +1af8 : a50d lda zpt+1 +1afa : 49c3 eor #$c3 +1afc : c514 cmp zp1+1 + trap_ne ;store to zp data +1afe : d0fe > bne * ;failed not equal (non zero) + +1b00 : 860d stx zpt+1 ;clear +1b02 : ad0402 lda abst+1 +1b05 : 49c3 eor #$c3 +1b07 : cd1802 cmp abs1+1 + trap_ne ;store to abs data +1b0a : d0fe > bne * ;failed not equal (non zero) + +1b0c : 8e0402 stx abst+1 ;clear +1b0f : a50e lda zpt+2 +1b11 : 49c3 eor #$c3 +1b13 : c515 cmp zp1+2 + trap_ne ;store to zp data +1b15 : d0fe > bne * ;failed not equal (non zero) + +1b17 : 860e stx zpt+2 ;clear +1b19 : ad0502 lda abst+2 +1b1c : 49c3 eor #$c3 +1b1e : cd1902 cmp abs1+2 + trap_ne ;store to abs data +1b21 : d0fe > bne * ;failed not equal (non zero) + +1b23 : 8e0502 stx abst+2 ;clear +1b26 : a50f lda zpt+3 +1b28 : 49c3 eor #$c3 +1b2a : c516 cmp zp1+3 + trap_ne ;store to zp data +1b2c : d0fe > bne * ;failed not equal (non zero) + +1b2e : 860f stx zpt+3 ;clear +1b30 : ad0602 lda abst+3 +1b33 : 49c3 eor #$c3 +1b35 : cd1a02 cmp abs1+3 + trap_ne ;store to abs data +1b38 : d0fe > bne * ;failed not equal (non zero) + +1b3a : 8e0602 stx abst+3 ;clear + next_test +1b3d : ad0002 > lda test_case ;previous test +1b40 : c918 > cmp #test_num + > trap_ne ;test is out of sequence +1b42 : d0fe > bne * ;failed not equal (non zero) + > +0019 = >test_num = test_num + 1 +1b44 : a919 > lda #test_num ;*** next tests' number +1b46 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing bit test & compares BIT CPX CPY CMP all addr + ; BIT - zp / abs + set_a $ff,0 + > load_flag 0 +1b49 : a900 > lda #0 ;allow test to change I + > +1b4b : 48 > pha ;use stack to load status +1b4c : a9ff > lda #$ff ;precharge accu +1b4e : 28 > plp + +1b4f : 2416 bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,fz +1b51 : 08 > php ;save flags +1b52 : c9ff > cmp #$ff ;test result + > trap_ne +1b54 : d0fe > bne * ;failed not equal (non zero) + > +1b56 : 68 > pla ;load status +1b57 : 48 > pha + > cmp_flag fz +1b58 : c932 > cmp #(fz |fao)&m8 ;expected flags + alw + > + > trap_ne +1b5a : d0fe > bne * ;failed not equal (non zero) + > +1b5c : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1b5d : a900 > lda #0 ;allow test to change I + > +1b5f : 48 > pha ;use stack to load status +1b60 : a901 > lda #1 ;precharge accu +1b62 : 28 > plp + +1b63 : 2415 bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv +1b65 : 08 > php ;save flags +1b66 : c901 > cmp #1 ;test result + > trap_ne +1b68 : d0fe > bne * ;failed not equal (non zero) + > +1b6a : 68 > pla ;load status +1b6b : 48 > pha + > cmp_flag fv +1b6c : c970 > cmp #(fv|fao)&m8 ;expected flags + alwa + > + > trap_ne +1b6e : d0fe > bne * ;failed not equal (non zero) + > +1b70 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1b71 : a900 > lda #0 ;allow test to change I + > +1b73 : 48 > pha ;use stack to load status +1b74 : a901 > lda #1 ;precharge accu +1b76 : 28 > plp + +1b77 : 2414 bit zp1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,fnz +1b79 : 08 > php ;save flags +1b7a : c901 > cmp #1 ;test result + > trap_ne +1b7c : d0fe > bne * ;failed not equal (non zero) + > +1b7e : 68 > pla ;load status +1b7f : 48 > pha + > cmp_flag fnz +1b80 : c9b2 > cmp #(fnz|fao)&m8 ;expected flags + alw + > + > trap_ne +1b82 : d0fe > bne * ;failed not equal (non zero) + > +1b84 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1b85 : a900 > lda #0 ;allow test to change I + > +1b87 : 48 > pha ;use stack to load status +1b88 : a901 > lda #1 ;precharge accu +1b8a : 28 > plp + +1b8b : 2413 bit zp1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,fnv +1b8d : 08 > php ;save flags +1b8e : c901 > cmp #1 ;test result + > trap_ne +1b90 : d0fe > bne * ;failed not equal (non zero) + > +1b92 : 68 > pla ;load status +1b93 : 48 > pha + > cmp_flag fnv +1b94 : c9f0 > cmp #(fnv|fao)&m8 ;expected flags + alw + > + > trap_ne +1b96 : d0fe > bne * ;failed not equal (non zero) + > +1b98 : 28 > plp ;restore status + + + set_a $ff,$ff + > load_flag $ff +1b99 : a9ff > lda #$ff ;allow test to change + > +1b9b : 48 > pha ;use stack to load status +1b9c : a9ff > lda #$ff ;precharge accu +1b9e : 28 > plp + +1b9f : 2416 bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv +1ba1 : 08 > php ;save flags +1ba2 : c9ff > cmp #$ff ;test result + > trap_ne +1ba4 : d0fe > bne * ;failed not equal (non zero) + > +1ba6 : 68 > pla ;load status +1ba7 : 48 > pha + > cmp_flag ~fnv +1ba8 : c93f > cmp #(~fnv |fao)&m8 ;expected flags + a + > + > trap_ne +1baa : d0fe > bne * ;failed not equal (non zero) + > +1bac : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1bad : a9ff > lda #$ff ;allow test to change + > +1baf : 48 > pha ;use stack to load status +1bb0 : a901 > lda #1 ;precharge accu +1bb2 : 28 > plp + +1bb3 : 2415 bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz +1bb5 : 08 > php ;save flags +1bb6 : c901 > cmp #1 ;test result + > trap_ne +1bb8 : d0fe > bne * ;failed not equal (non zero) + > +1bba : 68 > pla ;load status +1bbb : 48 > pha + > cmp_flag ~fnz +1bbc : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1bbe : d0fe > bne * ;failed not equal (non zero) + > +1bc0 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1bc1 : a9ff > lda #$ff ;allow test to change + > +1bc3 : 48 > pha ;use stack to load status +1bc4 : a901 > lda #1 ;precharge accu +1bc6 : 28 > plp + +1bc7 : 2414 bit zp1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,~fv +1bc9 : 08 > php ;save flags +1bca : c901 > cmp #1 ;test result + > trap_ne +1bcc : d0fe > bne * ;failed not equal (non zero) + > +1bce : 68 > pla ;load status +1bcf : 48 > pha + > cmp_flag ~fv +1bd0 : c9bf > cmp #(~fv|fao)&m8 ;expected flags + alw + > + > trap_ne +1bd2 : d0fe > bne * ;failed not equal (non zero) + > +1bd4 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1bd5 : a9ff > lda #$ff ;allow test to change + > +1bd7 : 48 > pha ;use stack to load status +1bd8 : a901 > lda #1 ;precharge accu +1bda : 28 > plp + +1bdb : 2413 bit zp1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,~fz +1bdd : 08 > php ;save flags +1bde : c901 > cmp #1 ;test result + > trap_ne +1be0 : d0fe > bne * ;failed not equal (non zero) + > +1be2 : 68 > pla ;load status +1be3 : 48 > pha + > cmp_flag ~fz +1be4 : c9fd > cmp #(~fz|fao)&m8 ;expected flags + alw + > + > trap_ne +1be6 : d0fe > bne * ;failed not equal (non zero) + > +1be8 : 28 > plp ;restore status + + + set_a $ff,0 + > load_flag 0 +1be9 : a900 > lda #0 ;allow test to change I + > +1beb : 48 > pha ;use stack to load status +1bec : a9ff > lda #$ff ;precharge accu +1bee : 28 > plp + +1bef : 2c1a02 bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,fz +1bf2 : 08 > php ;save flags +1bf3 : c9ff > cmp #$ff ;test result + > trap_ne +1bf5 : d0fe > bne * ;failed not equal (non zero) + > +1bf7 : 68 > pla ;load status +1bf8 : 48 > pha + > cmp_flag fz +1bf9 : c932 > cmp #(fz |fao)&m8 ;expected flags + alw + > + > trap_ne +1bfb : d0fe > bne * ;failed not equal (non zero) + > +1bfd : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1bfe : a900 > lda #0 ;allow test to change I + > +1c00 : 48 > pha ;use stack to load status +1c01 : a901 > lda #1 ;precharge accu +1c03 : 28 > plp + +1c04 : 2c1902 bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv +1c07 : 08 > php ;save flags +1c08 : c901 > cmp #1 ;test result + > trap_ne +1c0a : d0fe > bne * ;failed not equal (non zero) + > +1c0c : 68 > pla ;load status +1c0d : 48 > pha + > cmp_flag fv +1c0e : c970 > cmp #(fv|fao)&m8 ;expected flags + alwa + > + > trap_ne +1c10 : d0fe > bne * ;failed not equal (non zero) + > +1c12 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1c13 : a900 > lda #0 ;allow test to change I + > +1c15 : 48 > pha ;use stack to load status +1c16 : a901 > lda #1 ;precharge accu +1c18 : 28 > plp + +1c19 : 2c1802 bit abs1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,fnz +1c1c : 08 > php ;save flags +1c1d : c901 > cmp #1 ;test result + > trap_ne +1c1f : d0fe > bne * ;failed not equal (non zero) + > +1c21 : 68 > pla ;load status +1c22 : 48 > pha + > cmp_flag fnz +1c23 : c9b2 > cmp #(fnz|fao)&m8 ;expected flags + alw + > + > trap_ne +1c25 : d0fe > bne * ;failed not equal (non zero) + > +1c27 : 28 > plp ;restore status + + set_a 1,0 + > load_flag 0 +1c28 : a900 > lda #0 ;allow test to change I + > +1c2a : 48 > pha ;use stack to load status +1c2b : a901 > lda #1 ;precharge accu +1c2d : 28 > plp + +1c2e : 2c1702 bit abs1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,fnv +1c31 : 08 > php ;save flags +1c32 : c901 > cmp #1 ;test result + > trap_ne +1c34 : d0fe > bne * ;failed not equal (non zero) + > +1c36 : 68 > pla ;load status +1c37 : 48 > pha + > cmp_flag fnv +1c38 : c9f0 > cmp #(fnv|fao)&m8 ;expected flags + alw + > + > trap_ne +1c3a : d0fe > bne * ;failed not equal (non zero) + > +1c3c : 28 > plp ;restore status + + + set_a $ff,$ff + > load_flag $ff +1c3d : a9ff > lda #$ff ;allow test to change + > +1c3f : 48 > pha ;use stack to load status +1c40 : a9ff > lda #$ff ;precharge accu +1c42 : 28 > plp + +1c43 : 2c1a02 bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv +1c46 : 08 > php ;save flags +1c47 : c9ff > cmp #$ff ;test result + > trap_ne +1c49 : d0fe > bne * ;failed not equal (non zero) + > +1c4b : 68 > pla ;load status +1c4c : 48 > pha + > cmp_flag ~fnv +1c4d : c93f > cmp #(~fnv |fao)&m8 ;expected flags + a + > + > trap_ne +1c4f : d0fe > bne * ;failed not equal (non zero) + > +1c51 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1c52 : a9ff > lda #$ff ;allow test to change + > +1c54 : 48 > pha ;use stack to load status +1c55 : a901 > lda #1 ;precharge accu +1c57 : 28 > plp + +1c58 : 2c1902 bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz +1c5b : 08 > php ;save flags +1c5c : c901 > cmp #1 ;test result + > trap_ne +1c5e : d0fe > bne * ;failed not equal (non zero) + > +1c60 : 68 > pla ;load status +1c61 : 48 > pha + > cmp_flag ~fnz +1c62 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1c64 : d0fe > bne * ;failed not equal (non zero) + > +1c66 : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1c67 : a9ff > lda #$ff ;allow test to change + > +1c69 : 48 > pha ;use stack to load status +1c6a : a901 > lda #1 ;precharge accu +1c6c : 28 > plp + +1c6d : 2c1802 bit abs1+1 ;82 - should set N (M7) & Z / clea + tst_a 1,~fv +1c70 : 08 > php ;save flags +1c71 : c901 > cmp #1 ;test result + > trap_ne +1c73 : d0fe > bne * ;failed not equal (non zero) + > +1c75 : 68 > pla ;load status +1c76 : 48 > pha + > cmp_flag ~fv +1c77 : c9bf > cmp #(~fv|fao)&m8 ;expected flags + alw + > + > trap_ne +1c79 : d0fe > bne * ;failed not equal (non zero) + > +1c7b : 28 > plp ;restore status + + set_a 1,$ff + > load_flag $ff +1c7c : a9ff > lda #$ff ;allow test to change + > +1c7e : 48 > pha ;use stack to load status +1c7f : a901 > lda #1 ;precharge accu +1c81 : 28 > plp + +1c82 : 2c1702 bit abs1 ;c3 - should set N (M7) & V (M6) / + tst_a 1,~fz +1c85 : 08 > php ;save flags +1c86 : c901 > cmp #1 ;test result + > trap_ne +1c88 : d0fe > bne * ;failed not equal (non zero) + > +1c8a : 68 > pla ;load status +1c8b : 48 > pha + > cmp_flag ~fz +1c8c : c9fd > cmp #(~fz|fao)&m8 ;expected flags + alw + > + > trap_ne +1c8e : d0fe > bne * ;failed not equal (non zero) + > +1c90 : 28 > plp ;restore status + + next_test +1c91 : ad0002 > lda test_case ;previous test +1c94 : c919 > cmp #test_num + > trap_ne ;test is out of sequence +1c96 : d0fe > bne * ;failed not equal (non zero) + > +001a = >test_num = test_num + 1 +1c98 : a91a > lda #test_num ;*** next tests' number +1c9a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; CPX - zp / abs / # + set_x $80,0 + > load_flag 0 +1c9d : a900 > lda #0 ;allow test to change I + > +1c9f : 48 > pha ;use stack to load status +1ca0 : a280 > ldx #$80 ;precharge index x +1ca2 : 28 > plp + +1ca3 : e417 cpx zp7f + tst_stat fc +1ca5 : 08 > php ;save status +1ca6 : 68 > pla ;use stack to retrieve status +1ca7 : 48 > pha + > cmp_flag fc +1ca8 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1caa : d0fe > bne * ;failed not equal (non zero) + > +1cac : 28 > plp ;restore status + +1cad : ca dex +1cae : e417 cpx zp7f + tst_stat fzc +1cb0 : 08 > php ;save status +1cb1 : 68 > pla ;use stack to retrieve status +1cb2 : 48 > pha + > cmp_flag fzc +1cb3 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1cb5 : d0fe > bne * ;failed not equal (non zero) + > +1cb7 : 28 > plp ;restore status + +1cb8 : ca dex +1cb9 : e417 cpx zp7f + tst_x $7e,fn +1cbb : 08 > php ;save flags +1cbc : e07e > cpx #$7e ;test result + > trap_ne +1cbe : d0fe > bne * ;failed not equal (non zero) + > +1cc0 : 68 > pla ;load status +1cc1 : 48 > pha + > cmp_flag fn +1cc2 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1cc4 : d0fe > bne * ;failed not equal (non zero) + > +1cc6 : 28 > plp ;restore status + + set_x $80,$ff + > load_flag $ff +1cc7 : a9ff > lda #$ff ;allow test to change + > +1cc9 : 48 > pha ;use stack to load status +1cca : a280 > ldx #$80 ;precharge index x +1ccc : 28 > plp + +1ccd : e417 cpx zp7f + tst_stat ~fnz +1ccf : 08 > php ;save status +1cd0 : 68 > pla ;use stack to retrieve status +1cd1 : 48 > pha + > cmp_flag ~fnz +1cd2 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1cd4 : d0fe > bne * ;failed not equal (non zero) + > +1cd6 : 28 > plp ;restore status + +1cd7 : ca dex +1cd8 : e417 cpx zp7f + tst_stat ~fn +1cda : 08 > php ;save status +1cdb : 68 > pla ;use stack to retrieve status +1cdc : 48 > pha + > cmp_flag ~fn +1cdd : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1cdf : d0fe > bne * ;failed not equal (non zero) + > +1ce1 : 28 > plp ;restore status + +1ce2 : ca dex +1ce3 : e417 cpx zp7f + tst_x $7e,~fzc +1ce5 : 08 > php ;save flags +1ce6 : e07e > cpx #$7e ;test result + > trap_ne +1ce8 : d0fe > bne * ;failed not equal (non zero) + > +1cea : 68 > pla ;load status +1ceb : 48 > pha + > cmp_flag ~fzc +1cec : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1cee : d0fe > bne * ;failed not equal (non zero) + > +1cf0 : 28 > plp ;restore status + + + set_x $80,0 + > load_flag 0 +1cf1 : a900 > lda #0 ;allow test to change I + > +1cf3 : 48 > pha ;use stack to load status +1cf4 : a280 > ldx #$80 ;precharge index x +1cf6 : 28 > plp + +1cf7 : ec1b02 cpx abs7f + tst_stat fc +1cfa : 08 > php ;save status +1cfb : 68 > pla ;use stack to retrieve status +1cfc : 48 > pha + > cmp_flag fc +1cfd : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1cff : d0fe > bne * ;failed not equal (non zero) + > +1d01 : 28 > plp ;restore status + +1d02 : ca dex +1d03 : ec1b02 cpx abs7f + tst_stat fzc +1d06 : 08 > php ;save status +1d07 : 68 > pla ;use stack to retrieve status +1d08 : 48 > pha + > cmp_flag fzc +1d09 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1d0b : d0fe > bne * ;failed not equal (non zero) + > +1d0d : 28 > plp ;restore status + +1d0e : ca dex +1d0f : ec1b02 cpx abs7f + tst_x $7e,fn +1d12 : 08 > php ;save flags +1d13 : e07e > cpx #$7e ;test result + > trap_ne +1d15 : d0fe > bne * ;failed not equal (non zero) + > +1d17 : 68 > pla ;load status +1d18 : 48 > pha + > cmp_flag fn +1d19 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1d1b : d0fe > bne * ;failed not equal (non zero) + > +1d1d : 28 > plp ;restore status + + set_x $80,$ff + > load_flag $ff +1d1e : a9ff > lda #$ff ;allow test to change + > +1d20 : 48 > pha ;use stack to load status +1d21 : a280 > ldx #$80 ;precharge index x +1d23 : 28 > plp + +1d24 : ec1b02 cpx abs7f + tst_stat ~fnz +1d27 : 08 > php ;save status +1d28 : 68 > pla ;use stack to retrieve status +1d29 : 48 > pha + > cmp_flag ~fnz +1d2a : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1d2c : d0fe > bne * ;failed not equal (non zero) + > +1d2e : 28 > plp ;restore status + +1d2f : ca dex +1d30 : ec1b02 cpx abs7f + tst_stat ~fn +1d33 : 08 > php ;save status +1d34 : 68 > pla ;use stack to retrieve status +1d35 : 48 > pha + > cmp_flag ~fn +1d36 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1d38 : d0fe > bne * ;failed not equal (non zero) + > +1d3a : 28 > plp ;restore status + +1d3b : ca dex +1d3c : ec1b02 cpx abs7f + tst_x $7e,~fzc +1d3f : 08 > php ;save flags +1d40 : e07e > cpx #$7e ;test result + > trap_ne +1d42 : d0fe > bne * ;failed not equal (non zero) + > +1d44 : 68 > pla ;load status +1d45 : 48 > pha + > cmp_flag ~fzc +1d46 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1d48 : d0fe > bne * ;failed not equal (non zero) + > +1d4a : 28 > plp ;restore status + + + set_x $80,0 + > load_flag 0 +1d4b : a900 > lda #0 ;allow test to change I + > +1d4d : 48 > pha ;use stack to load status +1d4e : a280 > ldx #$80 ;precharge index x +1d50 : 28 > plp + +1d51 : e07f cpx #$7f + tst_stat fc +1d53 : 08 > php ;save status +1d54 : 68 > pla ;use stack to retrieve status +1d55 : 48 > pha + > cmp_flag fc +1d56 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1d58 : d0fe > bne * ;failed not equal (non zero) + > +1d5a : 28 > plp ;restore status + +1d5b : ca dex +1d5c : e07f cpx #$7f + tst_stat fzc +1d5e : 08 > php ;save status +1d5f : 68 > pla ;use stack to retrieve status +1d60 : 48 > pha + > cmp_flag fzc +1d61 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1d63 : d0fe > bne * ;failed not equal (non zero) + > +1d65 : 28 > plp ;restore status + +1d66 : ca dex +1d67 : e07f cpx #$7f + tst_x $7e,fn +1d69 : 08 > php ;save flags +1d6a : e07e > cpx #$7e ;test result + > trap_ne +1d6c : d0fe > bne * ;failed not equal (non zero) + > +1d6e : 68 > pla ;load status +1d6f : 48 > pha + > cmp_flag fn +1d70 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1d72 : d0fe > bne * ;failed not equal (non zero) + > +1d74 : 28 > plp ;restore status + + set_x $80,$ff + > load_flag $ff +1d75 : a9ff > lda #$ff ;allow test to change + > +1d77 : 48 > pha ;use stack to load status +1d78 : a280 > ldx #$80 ;precharge index x +1d7a : 28 > plp + +1d7b : e07f cpx #$7f + tst_stat ~fnz +1d7d : 08 > php ;save status +1d7e : 68 > pla ;use stack to retrieve status +1d7f : 48 > pha + > cmp_flag ~fnz +1d80 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1d82 : d0fe > bne * ;failed not equal (non zero) + > +1d84 : 28 > plp ;restore status + +1d85 : ca dex +1d86 : e07f cpx #$7f + tst_stat ~fn +1d88 : 08 > php ;save status +1d89 : 68 > pla ;use stack to retrieve status +1d8a : 48 > pha + > cmp_flag ~fn +1d8b : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1d8d : d0fe > bne * ;failed not equal (non zero) + > +1d8f : 28 > plp ;restore status + +1d90 : ca dex +1d91 : e07f cpx #$7f + tst_x $7e,~fzc +1d93 : 08 > php ;save flags +1d94 : e07e > cpx #$7e ;test result + > trap_ne +1d96 : d0fe > bne * ;failed not equal (non zero) + > +1d98 : 68 > pla ;load status +1d99 : 48 > pha + > cmp_flag ~fzc +1d9a : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1d9c : d0fe > bne * ;failed not equal (non zero) + > +1d9e : 28 > plp ;restore status + + next_test +1d9f : ad0002 > lda test_case ;previous test +1da2 : c91a > cmp #test_num + > trap_ne ;test is out of sequence +1da4 : d0fe > bne * ;failed not equal (non zero) + > +001b = >test_num = test_num + 1 +1da6 : a91b > lda #test_num ;*** next tests' number +1da8 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; CPY - zp / abs / # + set_y $80,0 + > load_flag 0 +1dab : a900 > lda #0 ;allow test to change I + > +1dad : 48 > pha ;use stack to load status +1dae : a080 > ldy #$80 ;precharge index y +1db0 : 28 > plp + +1db1 : c417 cpy zp7f + tst_stat fc +1db3 : 08 > php ;save status +1db4 : 68 > pla ;use stack to retrieve status +1db5 : 48 > pha + > cmp_flag fc +1db6 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1db8 : d0fe > bne * ;failed not equal (non zero) + > +1dba : 28 > plp ;restore status + +1dbb : 88 dey +1dbc : c417 cpy zp7f + tst_stat fzc +1dbe : 08 > php ;save status +1dbf : 68 > pla ;use stack to retrieve status +1dc0 : 48 > pha + > cmp_flag fzc +1dc1 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1dc3 : d0fe > bne * ;failed not equal (non zero) + > +1dc5 : 28 > plp ;restore status + +1dc6 : 88 dey +1dc7 : c417 cpy zp7f + tst_y $7e,fn +1dc9 : 08 > php ;save flags +1dca : c07e > cpy #$7e ;test result + > trap_ne +1dcc : d0fe > bne * ;failed not equal (non zero) + > +1dce : 68 > pla ;load status +1dcf : 48 > pha + > cmp_flag fn +1dd0 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1dd2 : d0fe > bne * ;failed not equal (non zero) + > +1dd4 : 28 > plp ;restore status + + set_y $80,$ff + > load_flag $ff +1dd5 : a9ff > lda #$ff ;allow test to change + > +1dd7 : 48 > pha ;use stack to load status +1dd8 : a080 > ldy #$80 ;precharge index y +1dda : 28 > plp + +1ddb : c417 cpy zp7f + tst_stat ~fnz +1ddd : 08 > php ;save status +1dde : 68 > pla ;use stack to retrieve status +1ddf : 48 > pha + > cmp_flag ~fnz +1de0 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1de2 : d0fe > bne * ;failed not equal (non zero) + > +1de4 : 28 > plp ;restore status + +1de5 : 88 dey +1de6 : c417 cpy zp7f + tst_stat ~fn +1de8 : 08 > php ;save status +1de9 : 68 > pla ;use stack to retrieve status +1dea : 48 > pha + > cmp_flag ~fn +1deb : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1ded : d0fe > bne * ;failed not equal (non zero) + > +1def : 28 > plp ;restore status + +1df0 : 88 dey +1df1 : c417 cpy zp7f + tst_y $7e,~fzc +1df3 : 08 > php ;save flags +1df4 : c07e > cpy #$7e ;test result + > trap_ne +1df6 : d0fe > bne * ;failed not equal (non zero) + > +1df8 : 68 > pla ;load status +1df9 : 48 > pha + > cmp_flag ~fzc +1dfa : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1dfc : d0fe > bne * ;failed not equal (non zero) + > +1dfe : 28 > plp ;restore status + + + set_y $80,0 + > load_flag 0 +1dff : a900 > lda #0 ;allow test to change I + > +1e01 : 48 > pha ;use stack to load status +1e02 : a080 > ldy #$80 ;precharge index y +1e04 : 28 > plp + +1e05 : cc1b02 cpy abs7f + tst_stat fc +1e08 : 08 > php ;save status +1e09 : 68 > pla ;use stack to retrieve status +1e0a : 48 > pha + > cmp_flag fc +1e0b : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e0d : d0fe > bne * ;failed not equal (non zero) + > +1e0f : 28 > plp ;restore status + +1e10 : 88 dey +1e11 : cc1b02 cpy abs7f + tst_stat fzc +1e14 : 08 > php ;save status +1e15 : 68 > pla ;use stack to retrieve status +1e16 : 48 > pha + > cmp_flag fzc +1e17 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1e19 : d0fe > bne * ;failed not equal (non zero) + > +1e1b : 28 > plp ;restore status + +1e1c : 88 dey +1e1d : cc1b02 cpy abs7f + tst_y $7e,fn +1e20 : 08 > php ;save flags +1e21 : c07e > cpy #$7e ;test result + > trap_ne +1e23 : d0fe > bne * ;failed not equal (non zero) + > +1e25 : 68 > pla ;load status +1e26 : 48 > pha + > cmp_flag fn +1e27 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e29 : d0fe > bne * ;failed not equal (non zero) + > +1e2b : 28 > plp ;restore status + + set_y $80,$ff + > load_flag $ff +1e2c : a9ff > lda #$ff ;allow test to change + > +1e2e : 48 > pha ;use stack to load status +1e2f : a080 > ldy #$80 ;precharge index y +1e31 : 28 > plp + +1e32 : cc1b02 cpy abs7f + tst_stat ~fnz +1e35 : 08 > php ;save status +1e36 : 68 > pla ;use stack to retrieve status +1e37 : 48 > pha + > cmp_flag ~fnz +1e38 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1e3a : d0fe > bne * ;failed not equal (non zero) + > +1e3c : 28 > plp ;restore status + +1e3d : 88 dey +1e3e : cc1b02 cpy abs7f + tst_stat ~fn +1e41 : 08 > php ;save status +1e42 : 68 > pla ;use stack to retrieve status +1e43 : 48 > pha + > cmp_flag ~fn +1e44 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1e46 : d0fe > bne * ;failed not equal (non zero) + > +1e48 : 28 > plp ;restore status + +1e49 : 88 dey +1e4a : cc1b02 cpy abs7f + tst_y $7e,~fzc +1e4d : 08 > php ;save flags +1e4e : c07e > cpy #$7e ;test result + > trap_ne +1e50 : d0fe > bne * ;failed not equal (non zero) + > +1e52 : 68 > pla ;load status +1e53 : 48 > pha + > cmp_flag ~fzc +1e54 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1e56 : d0fe > bne * ;failed not equal (non zero) + > +1e58 : 28 > plp ;restore status + + + set_y $80,0 + > load_flag 0 +1e59 : a900 > lda #0 ;allow test to change I + > +1e5b : 48 > pha ;use stack to load status +1e5c : a080 > ldy #$80 ;precharge index y +1e5e : 28 > plp + +1e5f : c07f cpy #$7f + tst_stat fc +1e61 : 08 > php ;save status +1e62 : 68 > pla ;use stack to retrieve status +1e63 : 48 > pha + > cmp_flag fc +1e64 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e66 : d0fe > bne * ;failed not equal (non zero) + > +1e68 : 28 > plp ;restore status + +1e69 : 88 dey +1e6a : c07f cpy #$7f + tst_stat fzc +1e6c : 08 > php ;save status +1e6d : 68 > pla ;use stack to retrieve status +1e6e : 48 > pha + > cmp_flag fzc +1e6f : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1e71 : d0fe > bne * ;failed not equal (non zero) + > +1e73 : 28 > plp ;restore status + +1e74 : 88 dey +1e75 : c07f cpy #$7f + tst_y $7e,fn +1e77 : 08 > php ;save flags +1e78 : c07e > cpy #$7e ;test result + > trap_ne +1e7a : d0fe > bne * ;failed not equal (non zero) + > +1e7c : 68 > pla ;load status +1e7d : 48 > pha + > cmp_flag fn +1e7e : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1e80 : d0fe > bne * ;failed not equal (non zero) + > +1e82 : 28 > plp ;restore status + + set_y $80,$ff + > load_flag $ff +1e83 : a9ff > lda #$ff ;allow test to change + > +1e85 : 48 > pha ;use stack to load status +1e86 : a080 > ldy #$80 ;precharge index y +1e88 : 28 > plp + +1e89 : c07f cpy #$7f + tst_stat ~fnz +1e8b : 08 > php ;save status +1e8c : 68 > pla ;use stack to retrieve status +1e8d : 48 > pha + > cmp_flag ~fnz +1e8e : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1e90 : d0fe > bne * ;failed not equal (non zero) + > +1e92 : 28 > plp ;restore status + +1e93 : 88 dey +1e94 : c07f cpy #$7f + tst_stat ~fn +1e96 : 08 > php ;save status +1e97 : 68 > pla ;use stack to retrieve status +1e98 : 48 > pha + > cmp_flag ~fn +1e99 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1e9b : d0fe > bne * ;failed not equal (non zero) + > +1e9d : 28 > plp ;restore status + +1e9e : 88 dey +1e9f : c07f cpy #$7f + tst_y $7e,~fzc +1ea1 : 08 > php ;save flags +1ea2 : c07e > cpy #$7e ;test result + > trap_ne +1ea4 : d0fe > bne * ;failed not equal (non zero) + > +1ea6 : 68 > pla ;load status +1ea7 : 48 > pha + > cmp_flag ~fzc +1ea8 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1eaa : d0fe > bne * ;failed not equal (non zero) + > +1eac : 28 > plp ;restore status + + next_test +1ead : ad0002 > lda test_case ;previous test +1eb0 : c91b > cmp #test_num + > trap_ne ;test is out of sequence +1eb2 : d0fe > bne * ;failed not equal (non zero) + > +001c = >test_num = test_num + 1 +1eb4 : a91c > lda #test_num ;*** next tests' number +1eb6 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; CMP - zp / abs / # + set_a $80,0 + > load_flag 0 +1eb9 : a900 > lda #0 ;allow test to change I + > +1ebb : 48 > pha ;use stack to load status +1ebc : a980 > lda #$80 ;precharge accu +1ebe : 28 > plp + +1ebf : c517 cmp zp7f + tst_a $80,fc +1ec1 : 08 > php ;save flags +1ec2 : c980 > cmp #$80 ;test result + > trap_ne +1ec4 : d0fe > bne * ;failed not equal (non zero) + > +1ec6 : 68 > pla ;load status +1ec7 : 48 > pha + > cmp_flag fc +1ec8 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1eca : d0fe > bne * ;failed not equal (non zero) + > +1ecc : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +1ecd : a900 > lda #0 ;allow test to change I + > +1ecf : 48 > pha ;use stack to load status +1ed0 : a97f > lda #$7f ;precharge accu +1ed2 : 28 > plp + +1ed3 : c517 cmp zp7f + tst_a $7f,fzc +1ed5 : 08 > php ;save flags +1ed6 : c97f > cmp #$7f ;test result + > trap_ne +1ed8 : d0fe > bne * ;failed not equal (non zero) + > +1eda : 68 > pla ;load status +1edb : 48 > pha + > cmp_flag fzc +1edc : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1ede : d0fe > bne * ;failed not equal (non zero) + > +1ee0 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +1ee1 : a900 > lda #0 ;allow test to change I + > +1ee3 : 48 > pha ;use stack to load status +1ee4 : a97e > lda #$7e ;precharge accu +1ee6 : 28 > plp + +1ee7 : c517 cmp zp7f + tst_a $7e,fn +1ee9 : 08 > php ;save flags +1eea : c97e > cmp #$7e ;test result + > trap_ne +1eec : d0fe > bne * ;failed not equal (non zero) + > +1eee : 68 > pla ;load status +1eef : 48 > pha + > cmp_flag fn +1ef0 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1ef2 : d0fe > bne * ;failed not equal (non zero) + > +1ef4 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +1ef5 : a9ff > lda #$ff ;allow test to change + > +1ef7 : 48 > pha ;use stack to load status +1ef8 : a980 > lda #$80 ;precharge accu +1efa : 28 > plp + +1efb : c517 cmp zp7f + tst_a $80,~fnz +1efd : 08 > php ;save flags +1efe : c980 > cmp #$80 ;test result + > trap_ne +1f00 : d0fe > bne * ;failed not equal (non zero) + > +1f02 : 68 > pla ;load status +1f03 : 48 > pha + > cmp_flag ~fnz +1f04 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1f06 : d0fe > bne * ;failed not equal (non zero) + > +1f08 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +1f09 : a9ff > lda #$ff ;allow test to change + > +1f0b : 48 > pha ;use stack to load status +1f0c : a97f > lda #$7f ;precharge accu +1f0e : 28 > plp + +1f0f : c517 cmp zp7f + tst_a $7f,~fn +1f11 : 08 > php ;save flags +1f12 : c97f > cmp #$7f ;test result + > trap_ne +1f14 : d0fe > bne * ;failed not equal (non zero) + > +1f16 : 68 > pla ;load status +1f17 : 48 > pha + > cmp_flag ~fn +1f18 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1f1a : d0fe > bne * ;failed not equal (non zero) + > +1f1c : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +1f1d : a9ff > lda #$ff ;allow test to change + > +1f1f : 48 > pha ;use stack to load status +1f20 : a97e > lda #$7e ;precharge accu +1f22 : 28 > plp + +1f23 : c517 cmp zp7f + tst_a $7e,~fzc +1f25 : 08 > php ;save flags +1f26 : c97e > cmp #$7e ;test result + > trap_ne +1f28 : d0fe > bne * ;failed not equal (non zero) + > +1f2a : 68 > pla ;load status +1f2b : 48 > pha + > cmp_flag ~fzc +1f2c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1f2e : d0fe > bne * ;failed not equal (non zero) + > +1f30 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +1f31 : a900 > lda #0 ;allow test to change I + > +1f33 : 48 > pha ;use stack to load status +1f34 : a980 > lda #$80 ;precharge accu +1f36 : 28 > plp + +1f37 : cd1b02 cmp abs7f + tst_a $80,fc +1f3a : 08 > php ;save flags +1f3b : c980 > cmp #$80 ;test result + > trap_ne +1f3d : d0fe > bne * ;failed not equal (non zero) + > +1f3f : 68 > pla ;load status +1f40 : 48 > pha + > cmp_flag fc +1f41 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1f43 : d0fe > bne * ;failed not equal (non zero) + > +1f45 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +1f46 : a900 > lda #0 ;allow test to change I + > +1f48 : 48 > pha ;use stack to load status +1f49 : a97f > lda #$7f ;precharge accu +1f4b : 28 > plp + +1f4c : cd1b02 cmp abs7f + tst_a $7f,fzc +1f4f : 08 > php ;save flags +1f50 : c97f > cmp #$7f ;test result + > trap_ne +1f52 : d0fe > bne * ;failed not equal (non zero) + > +1f54 : 68 > pla ;load status +1f55 : 48 > pha + > cmp_flag fzc +1f56 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1f58 : d0fe > bne * ;failed not equal (non zero) + > +1f5a : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +1f5b : a900 > lda #0 ;allow test to change I + > +1f5d : 48 > pha ;use stack to load status +1f5e : a97e > lda #$7e ;precharge accu +1f60 : 28 > plp + +1f61 : cd1b02 cmp abs7f + tst_a $7e,fn +1f64 : 08 > php ;save flags +1f65 : c97e > cmp #$7e ;test result + > trap_ne +1f67 : d0fe > bne * ;failed not equal (non zero) + > +1f69 : 68 > pla ;load status +1f6a : 48 > pha + > cmp_flag fn +1f6b : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1f6d : d0fe > bne * ;failed not equal (non zero) + > +1f6f : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +1f70 : a9ff > lda #$ff ;allow test to change + > +1f72 : 48 > pha ;use stack to load status +1f73 : a980 > lda #$80 ;precharge accu +1f75 : 28 > plp + +1f76 : cd1b02 cmp abs7f + tst_a $80,~fnz +1f79 : 08 > php ;save flags +1f7a : c980 > cmp #$80 ;test result + > trap_ne +1f7c : d0fe > bne * ;failed not equal (non zero) + > +1f7e : 68 > pla ;load status +1f7f : 48 > pha + > cmp_flag ~fnz +1f80 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1f82 : d0fe > bne * ;failed not equal (non zero) + > +1f84 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +1f85 : a9ff > lda #$ff ;allow test to change + > +1f87 : 48 > pha ;use stack to load status +1f88 : a97f > lda #$7f ;precharge accu +1f8a : 28 > plp + +1f8b : cd1b02 cmp abs7f + tst_a $7f,~fn +1f8e : 08 > php ;save flags +1f8f : c97f > cmp #$7f ;test result + > trap_ne +1f91 : d0fe > bne * ;failed not equal (non zero) + > +1f93 : 68 > pla ;load status +1f94 : 48 > pha + > cmp_flag ~fn +1f95 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +1f97 : d0fe > bne * ;failed not equal (non zero) + > +1f99 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +1f9a : a9ff > lda #$ff ;allow test to change + > +1f9c : 48 > pha ;use stack to load status +1f9d : a97e > lda #$7e ;precharge accu +1f9f : 28 > plp + +1fa0 : cd1b02 cmp abs7f + tst_a $7e,~fzc +1fa3 : 08 > php ;save flags +1fa4 : c97e > cmp #$7e ;test result + > trap_ne +1fa6 : d0fe > bne * ;failed not equal (non zero) + > +1fa8 : 68 > pla ;load status +1fa9 : 48 > pha + > cmp_flag ~fzc +1faa : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +1fac : d0fe > bne * ;failed not equal (non zero) + > +1fae : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +1faf : a900 > lda #0 ;allow test to change I + > +1fb1 : 48 > pha ;use stack to load status +1fb2 : a980 > lda #$80 ;precharge accu +1fb4 : 28 > plp + +1fb5 : c97f cmp #$7f + tst_a $80,fc +1fb7 : 08 > php ;save flags +1fb8 : c980 > cmp #$80 ;test result + > trap_ne +1fba : d0fe > bne * ;failed not equal (non zero) + > +1fbc : 68 > pla ;load status +1fbd : 48 > pha + > cmp_flag fc +1fbe : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +1fc0 : d0fe > bne * ;failed not equal (non zero) + > +1fc2 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +1fc3 : a900 > lda #0 ;allow test to change I + > +1fc5 : 48 > pha ;use stack to load status +1fc6 : a97f > lda #$7f ;precharge accu +1fc8 : 28 > plp + +1fc9 : c97f cmp #$7f + tst_a $7f,fzc +1fcb : 08 > php ;save flags +1fcc : c97f > cmp #$7f ;test result + > trap_ne +1fce : d0fe > bne * ;failed not equal (non zero) + > +1fd0 : 68 > pla ;load status +1fd1 : 48 > pha + > cmp_flag fzc +1fd2 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +1fd4 : d0fe > bne * ;failed not equal (non zero) + > +1fd6 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +1fd7 : a900 > lda #0 ;allow test to change I + > +1fd9 : 48 > pha ;use stack to load status +1fda : a97e > lda #$7e ;precharge accu +1fdc : 28 > plp + +1fdd : c97f cmp #$7f + tst_a $7e,fn +1fdf : 08 > php ;save flags +1fe0 : c97e > cmp #$7e ;test result + > trap_ne +1fe2 : d0fe > bne * ;failed not equal (non zero) + > +1fe4 : 68 > pla ;load status +1fe5 : 48 > pha + > cmp_flag fn +1fe6 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +1fe8 : d0fe > bne * ;failed not equal (non zero) + > +1fea : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +1feb : a9ff > lda #$ff ;allow test to change + > +1fed : 48 > pha ;use stack to load status +1fee : a980 > lda #$80 ;precharge accu +1ff0 : 28 > plp + +1ff1 : c97f cmp #$7f + tst_a $80,~fnz +1ff3 : 08 > php ;save flags +1ff4 : c980 > cmp #$80 ;test result + > trap_ne +1ff6 : d0fe > bne * ;failed not equal (non zero) + > +1ff8 : 68 > pla ;load status +1ff9 : 48 > pha + > cmp_flag ~fnz +1ffa : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +1ffc : d0fe > bne * ;failed not equal (non zero) + > +1ffe : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +1fff : a9ff > lda #$ff ;allow test to change + > +2001 : 48 > pha ;use stack to load status +2002 : a97f > lda #$7f ;precharge accu +2004 : 28 > plp + +2005 : c97f cmp #$7f + tst_a $7f,~fn +2007 : 08 > php ;save flags +2008 : c97f > cmp #$7f ;test result + > trap_ne +200a : d0fe > bne * ;failed not equal (non zero) + > +200c : 68 > pla ;load status +200d : 48 > pha + > cmp_flag ~fn +200e : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2010 : d0fe > bne * ;failed not equal (non zero) + > +2012 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +2013 : a9ff > lda #$ff ;allow test to change + > +2015 : 48 > pha ;use stack to load status +2016 : a97e > lda #$7e ;precharge accu +2018 : 28 > plp + +2019 : c97f cmp #$7f + tst_a $7e,~fzc +201b : 08 > php ;save flags +201c : c97e > cmp #$7e ;test result + > trap_ne +201e : d0fe > bne * ;failed not equal (non zero) + > +2020 : 68 > pla ;load status +2021 : 48 > pha + > cmp_flag ~fzc +2022 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +2024 : d0fe > bne * ;failed not equal (non zero) + > +2026 : 28 > plp ;restore status + + +2027 : a204 ldx #4 ;with indexing by X + set_a $80,0 + > load_flag 0 +2029 : a900 > lda #0 ;allow test to change I + > +202b : 48 > pha ;use stack to load status +202c : a980 > lda #$80 ;precharge accu +202e : 28 > plp + +202f : d513 cmp zp1,x + tst_a $80,fc +2031 : 08 > php ;save flags +2032 : c980 > cmp #$80 ;test result + > trap_ne +2034 : d0fe > bne * ;failed not equal (non zero) + > +2036 : 68 > pla ;load status +2037 : 48 > pha + > cmp_flag fc +2038 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +203a : d0fe > bne * ;failed not equal (non zero) + > +203c : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +203d : a900 > lda #0 ;allow test to change I + > +203f : 48 > pha ;use stack to load status +2040 : a97f > lda #$7f ;precharge accu +2042 : 28 > plp + +2043 : d513 cmp zp1,x + tst_a $7f,fzc +2045 : 08 > php ;save flags +2046 : c97f > cmp #$7f ;test result + > trap_ne +2048 : d0fe > bne * ;failed not equal (non zero) + > +204a : 68 > pla ;load status +204b : 48 > pha + > cmp_flag fzc +204c : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +204e : d0fe > bne * ;failed not equal (non zero) + > +2050 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +2051 : a900 > lda #0 ;allow test to change I + > +2053 : 48 > pha ;use stack to load status +2054 : a97e > lda #$7e ;precharge accu +2056 : 28 > plp + +2057 : d513 cmp zp1,x + tst_a $7e,fn +2059 : 08 > php ;save flags +205a : c97e > cmp #$7e ;test result + > trap_ne +205c : d0fe > bne * ;failed not equal (non zero) + > +205e : 68 > pla ;load status +205f : 48 > pha + > cmp_flag fn +2060 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +2062 : d0fe > bne * ;failed not equal (non zero) + > +2064 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +2065 : a9ff > lda #$ff ;allow test to change + > +2067 : 48 > pha ;use stack to load status +2068 : a980 > lda #$80 ;precharge accu +206a : 28 > plp + +206b : d513 cmp zp1,x + tst_a $80,~fnz +206d : 08 > php ;save flags +206e : c980 > cmp #$80 ;test result + > trap_ne +2070 : d0fe > bne * ;failed not equal (non zero) + > +2072 : 68 > pla ;load status +2073 : 48 > pha + > cmp_flag ~fnz +2074 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +2076 : d0fe > bne * ;failed not equal (non zero) + > +2078 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +2079 : a9ff > lda #$ff ;allow test to change + > +207b : 48 > pha ;use stack to load status +207c : a97f > lda #$7f ;precharge accu +207e : 28 > plp + +207f : d513 cmp zp1,x + tst_a $7f,~fn +2081 : 08 > php ;save flags +2082 : c97f > cmp #$7f ;test result + > trap_ne +2084 : d0fe > bne * ;failed not equal (non zero) + > +2086 : 68 > pla ;load status +2087 : 48 > pha + > cmp_flag ~fn +2088 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +208a : d0fe > bne * ;failed not equal (non zero) + > +208c : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +208d : a9ff > lda #$ff ;allow test to change + > +208f : 48 > pha ;use stack to load status +2090 : a97e > lda #$7e ;precharge accu +2092 : 28 > plp + +2093 : d513 cmp zp1,x + tst_a $7e,~fzc +2095 : 08 > php ;save flags +2096 : c97e > cmp #$7e ;test result + > trap_ne +2098 : d0fe > bne * ;failed not equal (non zero) + > +209a : 68 > pla ;load status +209b : 48 > pha + > cmp_flag ~fzc +209c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +209e : d0fe > bne * ;failed not equal (non zero) + > +20a0 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +20a1 : a900 > lda #0 ;allow test to change I + > +20a3 : 48 > pha ;use stack to load status +20a4 : a980 > lda #$80 ;precharge accu +20a6 : 28 > plp + +20a7 : dd1702 cmp abs1,x + tst_a $80,fc +20aa : 08 > php ;save flags +20ab : c980 > cmp #$80 ;test result + > trap_ne +20ad : d0fe > bne * ;failed not equal (non zero) + > +20af : 68 > pla ;load status +20b0 : 48 > pha + > cmp_flag fc +20b1 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +20b3 : d0fe > bne * ;failed not equal (non zero) + > +20b5 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +20b6 : a900 > lda #0 ;allow test to change I + > +20b8 : 48 > pha ;use stack to load status +20b9 : a97f > lda #$7f ;precharge accu +20bb : 28 > plp + +20bc : dd1702 cmp abs1,x + tst_a $7f,fzc +20bf : 08 > php ;save flags +20c0 : c97f > cmp #$7f ;test result + > trap_ne +20c2 : d0fe > bne * ;failed not equal (non zero) + > +20c4 : 68 > pla ;load status +20c5 : 48 > pha + > cmp_flag fzc +20c6 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +20c8 : d0fe > bne * ;failed not equal (non zero) + > +20ca : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +20cb : a900 > lda #0 ;allow test to change I + > +20cd : 48 > pha ;use stack to load status +20ce : a97e > lda #$7e ;precharge accu +20d0 : 28 > plp + +20d1 : dd1702 cmp abs1,x + tst_a $7e,fn +20d4 : 08 > php ;save flags +20d5 : c97e > cmp #$7e ;test result + > trap_ne +20d7 : d0fe > bne * ;failed not equal (non zero) + > +20d9 : 68 > pla ;load status +20da : 48 > pha + > cmp_flag fn +20db : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +20dd : d0fe > bne * ;failed not equal (non zero) + > +20df : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +20e0 : a9ff > lda #$ff ;allow test to change + > +20e2 : 48 > pha ;use stack to load status +20e3 : a980 > lda #$80 ;precharge accu +20e5 : 28 > plp + +20e6 : dd1702 cmp abs1,x + tst_a $80,~fnz +20e9 : 08 > php ;save flags +20ea : c980 > cmp #$80 ;test result + > trap_ne +20ec : d0fe > bne * ;failed not equal (non zero) + > +20ee : 68 > pla ;load status +20ef : 48 > pha + > cmp_flag ~fnz +20f0 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +20f2 : d0fe > bne * ;failed not equal (non zero) + > +20f4 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +20f5 : a9ff > lda #$ff ;allow test to change + > +20f7 : 48 > pha ;use stack to load status +20f8 : a97f > lda #$7f ;precharge accu +20fa : 28 > plp + +20fb : dd1702 cmp abs1,x + tst_a $7f,~fn +20fe : 08 > php ;save flags +20ff : c97f > cmp #$7f ;test result + > trap_ne +2101 : d0fe > bne * ;failed not equal (non zero) + > +2103 : 68 > pla ;load status +2104 : 48 > pha + > cmp_flag ~fn +2105 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2107 : d0fe > bne * ;failed not equal (non zero) + > +2109 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +210a : a9ff > lda #$ff ;allow test to change + > +210c : 48 > pha ;use stack to load status +210d : a97e > lda #$7e ;precharge accu +210f : 28 > plp + +2110 : dd1702 cmp abs1,x + tst_a $7e,~fzc +2113 : 08 > php ;save flags +2114 : c97e > cmp #$7e ;test result + > trap_ne +2116 : d0fe > bne * ;failed not equal (non zero) + > +2118 : 68 > pla ;load status +2119 : 48 > pha + > cmp_flag ~fzc +211a : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +211c : d0fe > bne * ;failed not equal (non zero) + > +211e : 28 > plp ;restore status + + +211f : a004 ldy #4 ;with indexing by Y +2121 : a208 ldx #8 ;with indexed indirect + set_a $80,0 + > load_flag 0 +2123 : a900 > lda #0 ;allow test to change I + > +2125 : 48 > pha ;use stack to load status +2126 : a980 > lda #$80 ;precharge accu +2128 : 28 > plp + +2129 : d91702 cmp abs1,y + tst_a $80,fc +212c : 08 > php ;save flags +212d : c980 > cmp #$80 ;test result + > trap_ne +212f : d0fe > bne * ;failed not equal (non zero) + > +2131 : 68 > pla ;load status +2132 : 48 > pha + > cmp_flag fc +2133 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +2135 : d0fe > bne * ;failed not equal (non zero) + > +2137 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +2138 : a900 > lda #0 ;allow test to change I + > +213a : 48 > pha ;use stack to load status +213b : a97f > lda #$7f ;precharge accu +213d : 28 > plp + +213e : d91702 cmp abs1,y + tst_a $7f,fzc +2141 : 08 > php ;save flags +2142 : c97f > cmp #$7f ;test result + > trap_ne +2144 : d0fe > bne * ;failed not equal (non zero) + > +2146 : 68 > pla ;load status +2147 : 48 > pha + > cmp_flag fzc +2148 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +214a : d0fe > bne * ;failed not equal (non zero) + > +214c : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +214d : a900 > lda #0 ;allow test to change I + > +214f : 48 > pha ;use stack to load status +2150 : a97e > lda #$7e ;precharge accu +2152 : 28 > plp + +2153 : d91702 cmp abs1,y + tst_a $7e,fn +2156 : 08 > php ;save flags +2157 : c97e > cmp #$7e ;test result + > trap_ne +2159 : d0fe > bne * ;failed not equal (non zero) + > +215b : 68 > pla ;load status +215c : 48 > pha + > cmp_flag fn +215d : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +215f : d0fe > bne * ;failed not equal (non zero) + > +2161 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +2162 : a9ff > lda #$ff ;allow test to change + > +2164 : 48 > pha ;use stack to load status +2165 : a980 > lda #$80 ;precharge accu +2167 : 28 > plp + +2168 : d91702 cmp abs1,y + tst_a $80,~fnz +216b : 08 > php ;save flags +216c : c980 > cmp #$80 ;test result + > trap_ne +216e : d0fe > bne * ;failed not equal (non zero) + > +2170 : 68 > pla ;load status +2171 : 48 > pha + > cmp_flag ~fnz +2172 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +2174 : d0fe > bne * ;failed not equal (non zero) + > +2176 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +2177 : a9ff > lda #$ff ;allow test to change + > +2179 : 48 > pha ;use stack to load status +217a : a97f > lda #$7f ;precharge accu +217c : 28 > plp + +217d : d91702 cmp abs1,y + tst_a $7f,~fn +2180 : 08 > php ;save flags +2181 : c97f > cmp #$7f ;test result + > trap_ne +2183 : d0fe > bne * ;failed not equal (non zero) + > +2185 : 68 > pla ;load status +2186 : 48 > pha + > cmp_flag ~fn +2187 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2189 : d0fe > bne * ;failed not equal (non zero) + > +218b : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +218c : a9ff > lda #$ff ;allow test to change + > +218e : 48 > pha ;use stack to load status +218f : a97e > lda #$7e ;precharge accu +2191 : 28 > plp + +2192 : d91702 cmp abs1,y + tst_a $7e,~fzc +2195 : 08 > php ;save flags +2196 : c97e > cmp #$7e ;test result + > trap_ne +2198 : d0fe > bne * ;failed not equal (non zero) + > +219a : 68 > pla ;load status +219b : 48 > pha + > cmp_flag ~fzc +219c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +219e : d0fe > bne * ;failed not equal (non zero) + > +21a0 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +21a1 : a900 > lda #0 ;allow test to change I + > +21a3 : 48 > pha ;use stack to load status +21a4 : a980 > lda #$80 ;precharge accu +21a6 : 28 > plp + +21a7 : c124 cmp (ind1,x) + tst_a $80,fc +21a9 : 08 > php ;save flags +21aa : c980 > cmp #$80 ;test result + > trap_ne +21ac : d0fe > bne * ;failed not equal (non zero) + > +21ae : 68 > pla ;load status +21af : 48 > pha + > cmp_flag fc +21b0 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +21b2 : d0fe > bne * ;failed not equal (non zero) + > +21b4 : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +21b5 : a900 > lda #0 ;allow test to change I + > +21b7 : 48 > pha ;use stack to load status +21b8 : a97f > lda #$7f ;precharge accu +21ba : 28 > plp + +21bb : c124 cmp (ind1,x) + tst_a $7f,fzc +21bd : 08 > php ;save flags +21be : c97f > cmp #$7f ;test result + > trap_ne +21c0 : d0fe > bne * ;failed not equal (non zero) + > +21c2 : 68 > pla ;load status +21c3 : 48 > pha + > cmp_flag fzc +21c4 : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +21c6 : d0fe > bne * ;failed not equal (non zero) + > +21c8 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +21c9 : a900 > lda #0 ;allow test to change I + > +21cb : 48 > pha ;use stack to load status +21cc : a97e > lda #$7e ;precharge accu +21ce : 28 > plp + +21cf : c124 cmp (ind1,x) + tst_a $7e,fn +21d1 : 08 > php ;save flags +21d2 : c97e > cmp #$7e ;test result + > trap_ne +21d4 : d0fe > bne * ;failed not equal (non zero) + > +21d6 : 68 > pla ;load status +21d7 : 48 > pha + > cmp_flag fn +21d8 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +21da : d0fe > bne * ;failed not equal (non zero) + > +21dc : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +21dd : a9ff > lda #$ff ;allow test to change + > +21df : 48 > pha ;use stack to load status +21e0 : a980 > lda #$80 ;precharge accu +21e2 : 28 > plp + +21e3 : c124 cmp (ind1,x) + tst_a $80,~fnz +21e5 : 08 > php ;save flags +21e6 : c980 > cmp #$80 ;test result + > trap_ne +21e8 : d0fe > bne * ;failed not equal (non zero) + > +21ea : 68 > pla ;load status +21eb : 48 > pha + > cmp_flag ~fnz +21ec : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +21ee : d0fe > bne * ;failed not equal (non zero) + > +21f0 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +21f1 : a9ff > lda #$ff ;allow test to change + > +21f3 : 48 > pha ;use stack to load status +21f4 : a97f > lda #$7f ;precharge accu +21f6 : 28 > plp + +21f7 : c124 cmp (ind1,x) + tst_a $7f,~fn +21f9 : 08 > php ;save flags +21fa : c97f > cmp #$7f ;test result + > trap_ne +21fc : d0fe > bne * ;failed not equal (non zero) + > +21fe : 68 > pla ;load status +21ff : 48 > pha + > cmp_flag ~fn +2200 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +2202 : d0fe > bne * ;failed not equal (non zero) + > +2204 : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +2205 : a9ff > lda #$ff ;allow test to change + > +2207 : 48 > pha ;use stack to load status +2208 : a97e > lda #$7e ;precharge accu +220a : 28 > plp + +220b : c124 cmp (ind1,x) + tst_a $7e,~fzc +220d : 08 > php ;save flags +220e : c97e > cmp #$7e ;test result + > trap_ne +2210 : d0fe > bne * ;failed not equal (non zero) + > +2212 : 68 > pla ;load status +2213 : 48 > pha + > cmp_flag ~fzc +2214 : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +2216 : d0fe > bne * ;failed not equal (non zero) + > +2218 : 28 > plp ;restore status + + + set_a $80,0 + > load_flag 0 +2219 : a900 > lda #0 ;allow test to change I + > +221b : 48 > pha ;use stack to load status +221c : a980 > lda #$80 ;precharge accu +221e : 28 > plp + +221f : d124 cmp (ind1),y + tst_a $80,fc +2221 : 08 > php ;save flags +2222 : c980 > cmp #$80 ;test result + > trap_ne +2224 : d0fe > bne * ;failed not equal (non zero) + > +2226 : 68 > pla ;load status +2227 : 48 > pha + > cmp_flag fc +2228 : c931 > cmp #(fc|fao)&m8 ;expected flags + alwa + > + > trap_ne +222a : d0fe > bne * ;failed not equal (non zero) + > +222c : 28 > plp ;restore status + + set_a $7f,0 + > load_flag 0 +222d : a900 > lda #0 ;allow test to change I + > +222f : 48 > pha ;use stack to load status +2230 : a97f > lda #$7f ;precharge accu +2232 : 28 > plp + +2233 : d124 cmp (ind1),y + tst_a $7f,fzc +2235 : 08 > php ;save flags +2236 : c97f > cmp #$7f ;test result + > trap_ne +2238 : d0fe > bne * ;failed not equal (non zero) + > +223a : 68 > pla ;load status +223b : 48 > pha + > cmp_flag fzc +223c : c933 > cmp #(fzc|fao)&m8 ;expected flags + alw + > + > trap_ne +223e : d0fe > bne * ;failed not equal (non zero) + > +2240 : 28 > plp ;restore status + + set_a $7e,0 + > load_flag 0 +2241 : a900 > lda #0 ;allow test to change I + > +2243 : 48 > pha ;use stack to load status +2244 : a97e > lda #$7e ;precharge accu +2246 : 28 > plp + +2247 : d124 cmp (ind1),y + tst_a $7e,fn +2249 : 08 > php ;save flags +224a : c97e > cmp #$7e ;test result + > trap_ne +224c : d0fe > bne * ;failed not equal (non zero) + > +224e : 68 > pla ;load status +224f : 48 > pha + > cmp_flag fn +2250 : c9b0 > cmp #(fn|fao)&m8 ;expected flags + alwa + > + > trap_ne +2252 : d0fe > bne * ;failed not equal (non zero) + > +2254 : 28 > plp ;restore status + + set_a $80,$ff + > load_flag $ff +2255 : a9ff > lda #$ff ;allow test to change + > +2257 : 48 > pha ;use stack to load status +2258 : a980 > lda #$80 ;precharge accu +225a : 28 > plp + +225b : d124 cmp (ind1),y + tst_a $80,~fnz +225d : 08 > php ;save flags +225e : c980 > cmp #$80 ;test result + > trap_ne +2260 : d0fe > bne * ;failed not equal (non zero) + > +2262 : 68 > pla ;load status +2263 : 48 > pha + > cmp_flag ~fnz +2264 : c97d > cmp #(~fnz|fao)&m8 ;expected flags + al + > + > trap_ne +2266 : d0fe > bne * ;failed not equal (non zero) + > +2268 : 28 > plp ;restore status + + set_a $7f,$ff + > load_flag $ff +2269 : a9ff > lda #$ff ;allow test to change + > +226b : 48 > pha ;use stack to load status +226c : a97f > lda #$7f ;precharge accu +226e : 28 > plp + +226f : d124 cmp (ind1),y + tst_a $7f,~fn +2271 : 08 > php ;save flags +2272 : c97f > cmp #$7f ;test result + > trap_ne +2274 : d0fe > bne * ;failed not equal (non zero) + > +2276 : 68 > pla ;load status +2277 : 48 > pha + > cmp_flag ~fn +2278 : c97f > cmp #(~fn|fao)&m8 ;expected flags + alw + > + > trap_ne +227a : d0fe > bne * ;failed not equal (non zero) + > +227c : 28 > plp ;restore status + + set_a $7e,$ff + > load_flag $ff +227d : a9ff > lda #$ff ;allow test to change + > +227f : 48 > pha ;use stack to load status +2280 : a97e > lda #$7e ;precharge accu +2282 : 28 > plp + +2283 : d124 cmp (ind1),y + tst_a $7e,~fzc +2285 : 08 > php ;save flags +2286 : c97e > cmp #$7e ;test result + > trap_ne +2288 : d0fe > bne * ;failed not equal (non zero) + > +228a : 68 > pla ;load status +228b : 48 > pha + > cmp_flag ~fzc +228c : c9fc > cmp #(~fzc|fao)&m8 ;expected flags + al + > + > trap_ne +228e : d0fe > bne * ;failed not equal (non zero) + > +2290 : 28 > plp ;restore status + + next_test +2291 : ad0002 > lda test_case ;previous test +2294 : c91c > cmp #test_num + > trap_ne ;test is out of sequence +2296 : d0fe > bne * ;failed not equal (non zero) + > +001d = >test_num = test_num + 1 +2298 : a91d > lda #test_num ;*** next tests' number +229a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing shifts - ASL LSR ROL ROR all addressing mode + ; shifts - accumulator +229d : a203 ldx #3 +229f : tasl + set_ax zp1,0 + > load_flag 0 +229f : a900 > lda #0 ;allow test to change I + > +22a1 : 48 > pha ;use stack to load status +22a2 : b513 > lda zp1,x ;precharge accu +22a4 : 28 > plp + +22a5 : 0a asl a + tst_ax rASL,fASL,0 +22a6 : 08 > php ;save flags +22a7 : dd2002 > cmp rASL,x ;test result + > trap_ne +22aa : d0fe > bne * ;failed not equal (non zero) + > +22ac : 68 > pla ;load status + > eor_flag 0 +22ad : 4930 > eor #0|fao ;invert expected flags + > +22af : dd3002 > cmp fASL,x ;test flags + > trap_ne ; +22b2 : d0fe > bne * ;failed not equal (non zero) + > + +22b4 : ca dex +22b5 : 10e8 bpl tasl +22b7 : a203 ldx #3 +22b9 : tasl1 + set_ax zp1,$ff + > load_flag $ff +22b9 : a9ff > lda #$ff ;allow test to change + > +22bb : 48 > pha ;use stack to load status +22bc : b513 > lda zp1,x ;precharge accu +22be : 28 > plp + +22bf : 0a asl a + tst_ax rASL,fASL,$ff-fnzc +22c0 : 08 > php ;save flags +22c1 : dd2002 > cmp rASL,x ;test result + > trap_ne +22c4 : d0fe > bne * ;failed not equal (non zero) + > +22c6 : 68 > pla ;load status + > eor_flag $ff-fnzc +22c7 : 497c > eor #$ff-fnzc|fao ;invert expected + > +22c9 : dd3002 > cmp fASL,x ;test flags + > trap_ne ; +22cc : d0fe > bne * ;failed not equal (non zero) + > + +22ce : ca dex +22cf : 10e8 bpl tasl1 + +22d1 : a203 ldx #3 +22d3 : tlsr + set_ax zp1,0 + > load_flag 0 +22d3 : a900 > lda #0 ;allow test to change I + > +22d5 : 48 > pha ;use stack to load status +22d6 : b513 > lda zp1,x ;precharge accu +22d8 : 28 > plp + +22d9 : 4a lsr a + tst_ax rLSR,fLSR,0 +22da : 08 > php ;save flags +22db : dd2802 > cmp rLSR,x ;test result + > trap_ne +22de : d0fe > bne * ;failed not equal (non zero) + > +22e0 : 68 > pla ;load status + > eor_flag 0 +22e1 : 4930 > eor #0|fao ;invert expected flags + > +22e3 : dd3802 > cmp fLSR,x ;test flags + > trap_ne ; +22e6 : d0fe > bne * ;failed not equal (non zero) + > + +22e8 : ca dex +22e9 : 10e8 bpl tlsr +22eb : a203 ldx #3 +22ed : tlsr1 + set_ax zp1,$ff + > load_flag $ff +22ed : a9ff > lda #$ff ;allow test to change + > +22ef : 48 > pha ;use stack to load status +22f0 : b513 > lda zp1,x ;precharge accu +22f2 : 28 > plp + +22f3 : 4a lsr a + tst_ax rLSR,fLSR,$ff-fnzc +22f4 : 08 > php ;save flags +22f5 : dd2802 > cmp rLSR,x ;test result + > trap_ne +22f8 : d0fe > bne * ;failed not equal (non zero) + > +22fa : 68 > pla ;load status + > eor_flag $ff-fnzc +22fb : 497c > eor #$ff-fnzc|fao ;invert expected + > +22fd : dd3802 > cmp fLSR,x ;test flags + > trap_ne ; +2300 : d0fe > bne * ;failed not equal (non zero) + > + +2302 : ca dex +2303 : 10e8 bpl tlsr1 + +2305 : a203 ldx #3 +2307 : trol + set_ax zp1,0 + > load_flag 0 +2307 : a900 > lda #0 ;allow test to change I + > +2309 : 48 > pha ;use stack to load status +230a : b513 > lda zp1,x ;precharge accu +230c : 28 > plp + +230d : 2a rol a + tst_ax rROL,fROL,0 +230e : 08 > php ;save flags +230f : dd2002 > cmp rROL,x ;test result + > trap_ne +2312 : d0fe > bne * ;failed not equal (non zero) + > +2314 : 68 > pla ;load status + > eor_flag 0 +2315 : 4930 > eor #0|fao ;invert expected flags + > +2317 : dd3002 > cmp fROL,x ;test flags + > trap_ne ; +231a : d0fe > bne * ;failed not equal (non zero) + > + +231c : ca dex +231d : 10e8 bpl trol +231f : a203 ldx #3 +2321 : trol1 + set_ax zp1,$ff-fc + > load_flag $ff-fc +2321 : a9fe > lda #$ff-fc ;allow test to cha + > +2323 : 48 > pha ;use stack to load status +2324 : b513 > lda zp1,x ;precharge accu +2326 : 28 > plp + +2327 : 2a rol a + tst_ax rROL,fROL,$ff-fnzc +2328 : 08 > php ;save flags +2329 : dd2002 > cmp rROL,x ;test result + > trap_ne +232c : d0fe > bne * ;failed not equal (non zero) + > +232e : 68 > pla ;load status + > eor_flag $ff-fnzc +232f : 497c > eor #$ff-fnzc|fao ;invert expected + > +2331 : dd3002 > cmp fROL,x ;test flags + > trap_ne ; +2334 : d0fe > bne * ;failed not equal (non zero) + > + +2336 : ca dex +2337 : 10e8 bpl trol1 + +2339 : a203 ldx #3 +233b : trolc + set_ax zp1,fc + > load_flag fc +233b : a901 > lda #fc ;allow test to change + > +233d : 48 > pha ;use stack to load status +233e : b513 > lda zp1,x ;precharge accu +2340 : 28 > plp + +2341 : 2a rol a + tst_ax rROLc,fROLc,0 +2342 : 08 > php ;save flags +2343 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2346 : d0fe > bne * ;failed not equal (non zero) + > +2348 : 68 > pla ;load status + > eor_flag 0 +2349 : 4930 > eor #0|fao ;invert expected flags + > +234b : dd3402 > cmp fROLc,x ;test flags + > trap_ne ; +234e : d0fe > bne * ;failed not equal (non zero) + > + +2350 : ca dex +2351 : 10e8 bpl trolc +2353 : a203 ldx #3 +2355 : trolc1 + set_ax zp1,$ff + > load_flag $ff +2355 : a9ff > lda #$ff ;allow test to change + > +2357 : 48 > pha ;use stack to load status +2358 : b513 > lda zp1,x ;precharge accu +235a : 28 > plp + +235b : 2a rol a + tst_ax rROLc,fROLc,$ff-fnzc +235c : 08 > php ;save flags +235d : dd2402 > cmp rROLc,x ;test result + > trap_ne +2360 : d0fe > bne * ;failed not equal (non zero) + > +2362 : 68 > pla ;load status + > eor_flag $ff-fnzc +2363 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2365 : dd3402 > cmp fROLc,x ;test flags + > trap_ne ; +2368 : d0fe > bne * ;failed not equal (non zero) + > + +236a : ca dex +236b : 10e8 bpl trolc1 + +236d : a203 ldx #3 +236f : tror + set_ax zp1,0 + > load_flag 0 +236f : a900 > lda #0 ;allow test to change I + > +2371 : 48 > pha ;use stack to load status +2372 : b513 > lda zp1,x ;precharge accu +2374 : 28 > plp + +2375 : 6a ror a + tst_ax rROR,fROR,0 +2376 : 08 > php ;save flags +2377 : dd2802 > cmp rROR,x ;test result + > trap_ne +237a : d0fe > bne * ;failed not equal (non zero) + > +237c : 68 > pla ;load status + > eor_flag 0 +237d : 4930 > eor #0|fao ;invert expected flags + > +237f : dd3802 > cmp fROR,x ;test flags + > trap_ne ; +2382 : d0fe > bne * ;failed not equal (non zero) + > + +2384 : ca dex +2385 : 10e8 bpl tror +2387 : a203 ldx #3 +2389 : tror1 + set_ax zp1,$ff-fc + > load_flag $ff-fc +2389 : a9fe > lda #$ff-fc ;allow test to cha + > +238b : 48 > pha ;use stack to load status +238c : b513 > lda zp1,x ;precharge accu +238e : 28 > plp + +238f : 6a ror a + tst_ax rROR,fROR,$ff-fnzc +2390 : 08 > php ;save flags +2391 : dd2802 > cmp rROR,x ;test result + > trap_ne +2394 : d0fe > bne * ;failed not equal (non zero) + > +2396 : 68 > pla ;load status + > eor_flag $ff-fnzc +2397 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2399 : dd3802 > cmp fROR,x ;test flags + > trap_ne ; +239c : d0fe > bne * ;failed not equal (non zero) + > + +239e : ca dex +239f : 10e8 bpl tror1 + +23a1 : a203 ldx #3 +23a3 : trorc + set_ax zp1,fc + > load_flag fc +23a3 : a901 > lda #fc ;allow test to change + > +23a5 : 48 > pha ;use stack to load status +23a6 : b513 > lda zp1,x ;precharge accu +23a8 : 28 > plp + +23a9 : 6a ror a + tst_ax rRORc,fRORc,0 +23aa : 08 > php ;save flags +23ab : dd2c02 > cmp rRORc,x ;test result + > trap_ne +23ae : d0fe > bne * ;failed not equal (non zero) + > +23b0 : 68 > pla ;load status + > eor_flag 0 +23b1 : 4930 > eor #0|fao ;invert expected flags + > +23b3 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne ; +23b6 : d0fe > bne * ;failed not equal (non zero) + > + +23b8 : ca dex +23b9 : 10e8 bpl trorc +23bb : a203 ldx #3 +23bd : trorc1 + set_ax zp1,$ff + > load_flag $ff +23bd : a9ff > lda #$ff ;allow test to change + > +23bf : 48 > pha ;use stack to load status +23c0 : b513 > lda zp1,x ;precharge accu +23c2 : 28 > plp + +23c3 : 6a ror a + tst_ax rRORc,fRORc,$ff-fnzc +23c4 : 08 > php ;save flags +23c5 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +23c8 : d0fe > bne * ;failed not equal (non zero) + > +23ca : 68 > pla ;load status + > eor_flag $ff-fnzc +23cb : 497c > eor #$ff-fnzc|fao ;invert expected + > +23cd : dd3c02 > cmp fRORc,x ;test flags + > trap_ne ; +23d0 : d0fe > bne * ;failed not equal (non zero) + > + +23d2 : ca dex +23d3 : 10e8 bpl trorc1 + next_test +23d5 : ad0002 > lda test_case ;previous test +23d8 : c91d > cmp #test_num + > trap_ne ;test is out of sequence +23da : d0fe > bne * ;failed not equal (non zero) + > +001e = >test_num = test_num + 1 +23dc : a91e > lda #test_num ;*** next tests' number +23de : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - zeropage +23e1 : a203 ldx #3 +23e3 : tasl2 + set_z zp1,0 + > load_flag 0 +23e3 : a900 > lda #0 ;allow test to change I + > +23e5 : 48 > pha ;use stack to load status +23e6 : b513 > lda zp1,x ;load to zeropage +23e8 : 850c > sta zpt +23ea : 28 > plp + +23eb : 060c asl zpt + tst_z rASL,fASL,0 +23ed : 08 > php ;save flags +23ee : a50c > lda zpt +23f0 : dd2002 > cmp rASL,x ;test result + > trap_ne +23f3 : d0fe > bne * ;failed not equal (non zero) + > +23f5 : 68 > pla ;load status + > eor_flag 0 +23f6 : 4930 > eor #0|fao ;invert expected flags + > +23f8 : dd3002 > cmp fASL,x ;test flags + > trap_ne +23fb : d0fe > bne * ;failed not equal (non zero) + > + +23fd : ca dex +23fe : 10e3 bpl tasl2 +2400 : a203 ldx #3 +2402 : tasl3 + set_z zp1,$ff + > load_flag $ff +2402 : a9ff > lda #$ff ;allow test to change + > +2404 : 48 > pha ;use stack to load status +2405 : b513 > lda zp1,x ;load to zeropage +2407 : 850c > sta zpt +2409 : 28 > plp + +240a : 060c asl zpt + tst_z rASL,fASL,$ff-fnzc +240c : 08 > php ;save flags +240d : a50c > lda zpt +240f : dd2002 > cmp rASL,x ;test result + > trap_ne +2412 : d0fe > bne * ;failed not equal (non zero) + > +2414 : 68 > pla ;load status + > eor_flag $ff-fnzc +2415 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2417 : dd3002 > cmp fASL,x ;test flags + > trap_ne +241a : d0fe > bne * ;failed not equal (non zero) + > + +241c : ca dex +241d : 10e3 bpl tasl3 + +241f : a203 ldx #3 +2421 : tlsr2 + set_z zp1,0 + > load_flag 0 +2421 : a900 > lda #0 ;allow test to change I + > +2423 : 48 > pha ;use stack to load status +2424 : b513 > lda zp1,x ;load to zeropage +2426 : 850c > sta zpt +2428 : 28 > plp + +2429 : 460c lsr zpt + tst_z rLSR,fLSR,0 +242b : 08 > php ;save flags +242c : a50c > lda zpt +242e : dd2802 > cmp rLSR,x ;test result + > trap_ne +2431 : d0fe > bne * ;failed not equal (non zero) + > +2433 : 68 > pla ;load status + > eor_flag 0 +2434 : 4930 > eor #0|fao ;invert expected flags + > +2436 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +2439 : d0fe > bne * ;failed not equal (non zero) + > + +243b : ca dex +243c : 10e3 bpl tlsr2 +243e : a203 ldx #3 +2440 : tlsr3 + set_z zp1,$ff + > load_flag $ff +2440 : a9ff > lda #$ff ;allow test to change + > +2442 : 48 > pha ;use stack to load status +2443 : b513 > lda zp1,x ;load to zeropage +2445 : 850c > sta zpt +2447 : 28 > plp + +2448 : 460c lsr zpt + tst_z rLSR,fLSR,$ff-fnzc +244a : 08 > php ;save flags +244b : a50c > lda zpt +244d : dd2802 > cmp rLSR,x ;test result + > trap_ne +2450 : d0fe > bne * ;failed not equal (non zero) + > +2452 : 68 > pla ;load status + > eor_flag $ff-fnzc +2453 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2455 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +2458 : d0fe > bne * ;failed not equal (non zero) + > + +245a : ca dex +245b : 10e3 bpl tlsr3 + +245d : a203 ldx #3 +245f : trol2 + set_z zp1,0 + > load_flag 0 +245f : a900 > lda #0 ;allow test to change I + > +2461 : 48 > pha ;use stack to load status +2462 : b513 > lda zp1,x ;load to zeropage +2464 : 850c > sta zpt +2466 : 28 > plp + +2467 : 260c rol zpt + tst_z rROL,fROL,0 +2469 : 08 > php ;save flags +246a : a50c > lda zpt +246c : dd2002 > cmp rROL,x ;test result + > trap_ne +246f : d0fe > bne * ;failed not equal (non zero) + > +2471 : 68 > pla ;load status + > eor_flag 0 +2472 : 4930 > eor #0|fao ;invert expected flags + > +2474 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2477 : d0fe > bne * ;failed not equal (non zero) + > + +2479 : ca dex +247a : 10e3 bpl trol2 +247c : a203 ldx #3 +247e : trol3 + set_z zp1,$ff-fc + > load_flag $ff-fc +247e : a9fe > lda #$ff-fc ;allow test to cha + > +2480 : 48 > pha ;use stack to load status +2481 : b513 > lda zp1,x ;load to zeropage +2483 : 850c > sta zpt +2485 : 28 > plp + +2486 : 260c rol zpt + tst_z rROL,fROL,$ff-fnzc +2488 : 08 > php ;save flags +2489 : a50c > lda zpt +248b : dd2002 > cmp rROL,x ;test result + > trap_ne +248e : d0fe > bne * ;failed not equal (non zero) + > +2490 : 68 > pla ;load status + > eor_flag $ff-fnzc +2491 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2493 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2496 : d0fe > bne * ;failed not equal (non zero) + > + +2498 : ca dex +2499 : 10e3 bpl trol3 + +249b : a203 ldx #3 +249d : trolc2 + set_z zp1,fc + > load_flag fc +249d : a901 > lda #fc ;allow test to change + > +249f : 48 > pha ;use stack to load status +24a0 : b513 > lda zp1,x ;load to zeropage +24a2 : 850c > sta zpt +24a4 : 28 > plp + +24a5 : 260c rol zpt + tst_z rROLc,fROLc,0 +24a7 : 08 > php ;save flags +24a8 : a50c > lda zpt +24aa : dd2402 > cmp rROLc,x ;test result + > trap_ne +24ad : d0fe > bne * ;failed not equal (non zero) + > +24af : 68 > pla ;load status + > eor_flag 0 +24b0 : 4930 > eor #0|fao ;invert expected flags + > +24b2 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +24b5 : d0fe > bne * ;failed not equal (non zero) + > + +24b7 : ca dex +24b8 : 10e3 bpl trolc2 +24ba : a203 ldx #3 +24bc : trolc3 + set_z zp1,$ff + > load_flag $ff +24bc : a9ff > lda #$ff ;allow test to change + > +24be : 48 > pha ;use stack to load status +24bf : b513 > lda zp1,x ;load to zeropage +24c1 : 850c > sta zpt +24c3 : 28 > plp + +24c4 : 260c rol zpt + tst_z rROLc,fROLc,$ff-fnzc +24c6 : 08 > php ;save flags +24c7 : a50c > lda zpt +24c9 : dd2402 > cmp rROLc,x ;test result + > trap_ne +24cc : d0fe > bne * ;failed not equal (non zero) + > +24ce : 68 > pla ;load status + > eor_flag $ff-fnzc +24cf : 497c > eor #$ff-fnzc|fao ;invert expected + > +24d1 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +24d4 : d0fe > bne * ;failed not equal (non zero) + > + +24d6 : ca dex +24d7 : 10e3 bpl trolc3 + +24d9 : a203 ldx #3 +24db : tror2 + set_z zp1,0 + > load_flag 0 +24db : a900 > lda #0 ;allow test to change I + > +24dd : 48 > pha ;use stack to load status +24de : b513 > lda zp1,x ;load to zeropage +24e0 : 850c > sta zpt +24e2 : 28 > plp + +24e3 : 660c ror zpt + tst_z rROR,fROR,0 +24e5 : 08 > php ;save flags +24e6 : a50c > lda zpt +24e8 : dd2802 > cmp rROR,x ;test result + > trap_ne +24eb : d0fe > bne * ;failed not equal (non zero) + > +24ed : 68 > pla ;load status + > eor_flag 0 +24ee : 4930 > eor #0|fao ;invert expected flags + > +24f0 : dd3802 > cmp fROR,x ;test flags + > trap_ne +24f3 : d0fe > bne * ;failed not equal (non zero) + > + +24f5 : ca dex +24f6 : 10e3 bpl tror2 +24f8 : a203 ldx #3 +24fa : tror3 + set_z zp1,$ff-fc + > load_flag $ff-fc +24fa : a9fe > lda #$ff-fc ;allow test to cha + > +24fc : 48 > pha ;use stack to load status +24fd : b513 > lda zp1,x ;load to zeropage +24ff : 850c > sta zpt +2501 : 28 > plp + +2502 : 660c ror zpt + tst_z rROR,fROR,$ff-fnzc +2504 : 08 > php ;save flags +2505 : a50c > lda zpt +2507 : dd2802 > cmp rROR,x ;test result + > trap_ne +250a : d0fe > bne * ;failed not equal (non zero) + > +250c : 68 > pla ;load status + > eor_flag $ff-fnzc +250d : 497c > eor #$ff-fnzc|fao ;invert expected + > +250f : dd3802 > cmp fROR,x ;test flags + > trap_ne +2512 : d0fe > bne * ;failed not equal (non zero) + > + +2514 : ca dex +2515 : 10e3 bpl tror3 + +2517 : a203 ldx #3 +2519 : trorc2 + set_z zp1,fc + > load_flag fc +2519 : a901 > lda #fc ;allow test to change + > +251b : 48 > pha ;use stack to load status +251c : b513 > lda zp1,x ;load to zeropage +251e : 850c > sta zpt +2520 : 28 > plp + +2521 : 660c ror zpt + tst_z rRORc,fRORc,0 +2523 : 08 > php ;save flags +2524 : a50c > lda zpt +2526 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +2529 : d0fe > bne * ;failed not equal (non zero) + > +252b : 68 > pla ;load status + > eor_flag 0 +252c : 4930 > eor #0|fao ;invert expected flags + > +252e : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2531 : d0fe > bne * ;failed not equal (non zero) + > + +2533 : ca dex +2534 : 10e3 bpl trorc2 +2536 : a203 ldx #3 +2538 : trorc3 + set_z zp1,$ff + > load_flag $ff +2538 : a9ff > lda #$ff ;allow test to change + > +253a : 48 > pha ;use stack to load status +253b : b513 > lda zp1,x ;load to zeropage +253d : 850c > sta zpt +253f : 28 > plp + +2540 : 660c ror zpt + tst_z rRORc,fRORc,$ff-fnzc +2542 : 08 > php ;save flags +2543 : a50c > lda zpt +2545 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +2548 : d0fe > bne * ;failed not equal (non zero) + > +254a : 68 > pla ;load status + > eor_flag $ff-fnzc +254b : 497c > eor #$ff-fnzc|fao ;invert expected + > +254d : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2550 : d0fe > bne * ;failed not equal (non zero) + > + +2552 : ca dex +2553 : 10e3 bpl trorc3 + next_test +2555 : ad0002 > lda test_case ;previous test +2558 : c91e > cmp #test_num + > trap_ne ;test is out of sequence +255a : d0fe > bne * ;failed not equal (non zero) + > +001f = >test_num = test_num + 1 +255c : a91f > lda #test_num ;*** next tests' number +255e : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - absolute +2561 : a203 ldx #3 +2563 : tasl4 + set_abs zp1,0 + > load_flag 0 +2563 : a900 > lda #0 ;allow test to change I + > +2565 : 48 > pha ;use stack to load status +2566 : b513 > lda zp1,x ;load to memory +2568 : 8d0302 > sta abst +256b : 28 > plp + +256c : 0e0302 asl abst + tst_abs rASL,fASL,0 +256f : 08 > php ;save flags +2570 : ad0302 > lda abst +2573 : dd2002 > cmp rASL,x ;test result + > trap_ne +2576 : d0fe > bne * ;failed not equal (non zero) + > +2578 : 68 > pla ;load status + > eor_flag 0 +2579 : 4930 > eor #0|fao ;invert expected flags + > +257b : dd3002 > cmp fASL,x ;test flags + > trap_ne +257e : d0fe > bne * ;failed not equal (non zero) + > + +2580 : ca dex +2581 : 10e0 bpl tasl4 +2583 : a203 ldx #3 +2585 : tasl5 + set_abs zp1,$ff + > load_flag $ff +2585 : a9ff > lda #$ff ;allow test to change + > +2587 : 48 > pha ;use stack to load status +2588 : b513 > lda zp1,x ;load to memory +258a : 8d0302 > sta abst +258d : 28 > plp + +258e : 0e0302 asl abst + tst_abs rASL,fASL,$ff-fnzc +2591 : 08 > php ;save flags +2592 : ad0302 > lda abst +2595 : dd2002 > cmp rASL,x ;test result + > trap_ne +2598 : d0fe > bne * ;failed not equal (non zero) + > +259a : 68 > pla ;load status + > eor_flag $ff-fnzc +259b : 497c > eor #$ff-fnzc|fao ;invert expected + > +259d : dd3002 > cmp fASL,x ;test flags + > trap_ne +25a0 : d0fe > bne * ;failed not equal (non zero) + > + +25a2 : ca dex +25a3 : 10e0 bpl tasl5 + +25a5 : a203 ldx #3 +25a7 : tlsr4 + set_abs zp1,0 + > load_flag 0 +25a7 : a900 > lda #0 ;allow test to change I + > +25a9 : 48 > pha ;use stack to load status +25aa : b513 > lda zp1,x ;load to memory +25ac : 8d0302 > sta abst +25af : 28 > plp + +25b0 : 4e0302 lsr abst + tst_abs rLSR,fLSR,0 +25b3 : 08 > php ;save flags +25b4 : ad0302 > lda abst +25b7 : dd2802 > cmp rLSR,x ;test result + > trap_ne +25ba : d0fe > bne * ;failed not equal (non zero) + > +25bc : 68 > pla ;load status + > eor_flag 0 +25bd : 4930 > eor #0|fao ;invert expected flags + > +25bf : dd3802 > cmp fLSR,x ;test flags + > trap_ne +25c2 : d0fe > bne * ;failed not equal (non zero) + > + +25c4 : ca dex +25c5 : 10e0 bpl tlsr4 +25c7 : a203 ldx #3 +25c9 : tlsr5 + set_abs zp1,$ff + > load_flag $ff +25c9 : a9ff > lda #$ff ;allow test to change + > +25cb : 48 > pha ;use stack to load status +25cc : b513 > lda zp1,x ;load to memory +25ce : 8d0302 > sta abst +25d1 : 28 > plp + +25d2 : 4e0302 lsr abst + tst_abs rLSR,fLSR,$ff-fnzc +25d5 : 08 > php ;save flags +25d6 : ad0302 > lda abst +25d9 : dd2802 > cmp rLSR,x ;test result + > trap_ne +25dc : d0fe > bne * ;failed not equal (non zero) + > +25de : 68 > pla ;load status + > eor_flag $ff-fnzc +25df : 497c > eor #$ff-fnzc|fao ;invert expected + > +25e1 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +25e4 : d0fe > bne * ;failed not equal (non zero) + > + +25e6 : ca dex +25e7 : 10e0 bpl tlsr5 + +25e9 : a203 ldx #3 +25eb : trol4 + set_abs zp1,0 + > load_flag 0 +25eb : a900 > lda #0 ;allow test to change I + > +25ed : 48 > pha ;use stack to load status +25ee : b513 > lda zp1,x ;load to memory +25f0 : 8d0302 > sta abst +25f3 : 28 > plp + +25f4 : 2e0302 rol abst + tst_abs rROL,fROL,0 +25f7 : 08 > php ;save flags +25f8 : ad0302 > lda abst +25fb : dd2002 > cmp rROL,x ;test result + > trap_ne +25fe : d0fe > bne * ;failed not equal (non zero) + > +2600 : 68 > pla ;load status + > eor_flag 0 +2601 : 4930 > eor #0|fao ;invert expected flags + > +2603 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2606 : d0fe > bne * ;failed not equal (non zero) + > + +2608 : ca dex +2609 : 10e0 bpl trol4 +260b : a203 ldx #3 +260d : trol5 + set_abs zp1,$ff-fc + > load_flag $ff-fc +260d : a9fe > lda #$ff-fc ;allow test to cha + > +260f : 48 > pha ;use stack to load status +2610 : b513 > lda zp1,x ;load to memory +2612 : 8d0302 > sta abst +2615 : 28 > plp + +2616 : 2e0302 rol abst + tst_abs rROL,fROL,$ff-fnzc +2619 : 08 > php ;save flags +261a : ad0302 > lda abst +261d : dd2002 > cmp rROL,x ;test result + > trap_ne +2620 : d0fe > bne * ;failed not equal (non zero) + > +2622 : 68 > pla ;load status + > eor_flag $ff-fnzc +2623 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2625 : dd3002 > cmp fROL,x ;test flags + > trap_ne +2628 : d0fe > bne * ;failed not equal (non zero) + > + +262a : ca dex +262b : 10e0 bpl trol5 + +262d : a203 ldx #3 +262f : trolc4 + set_abs zp1,fc + > load_flag fc +262f : a901 > lda #fc ;allow test to change + > +2631 : 48 > pha ;use stack to load status +2632 : b513 > lda zp1,x ;load to memory +2634 : 8d0302 > sta abst +2637 : 28 > plp + +2638 : 2e0302 rol abst + tst_abs rROLc,fROLc,0 +263b : 08 > php ;save flags +263c : ad0302 > lda abst +263f : dd2402 > cmp rROLc,x ;test result + > trap_ne +2642 : d0fe > bne * ;failed not equal (non zero) + > +2644 : 68 > pla ;load status + > eor_flag 0 +2645 : 4930 > eor #0|fao ;invert expected flags + > +2647 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +264a : d0fe > bne * ;failed not equal (non zero) + > + +264c : ca dex +264d : 10e0 bpl trolc4 +264f : a203 ldx #3 +2651 : trolc5 + set_abs zp1,$ff + > load_flag $ff +2651 : a9ff > lda #$ff ;allow test to change + > +2653 : 48 > pha ;use stack to load status +2654 : b513 > lda zp1,x ;load to memory +2656 : 8d0302 > sta abst +2659 : 28 > plp + +265a : 2e0302 rol abst + tst_abs rROLc,fROLc,$ff-fnzc +265d : 08 > php ;save flags +265e : ad0302 > lda abst +2661 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2664 : d0fe > bne * ;failed not equal (non zero) + > +2666 : 68 > pla ;load status + > eor_flag $ff-fnzc +2667 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2669 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +266c : d0fe > bne * ;failed not equal (non zero) + > + +266e : ca dex +266f : 10e0 bpl trolc5 + +2671 : a203 ldx #3 +2673 : tror4 + set_abs zp1,0 + > load_flag 0 +2673 : a900 > lda #0 ;allow test to change I + > +2675 : 48 > pha ;use stack to load status +2676 : b513 > lda zp1,x ;load to memory +2678 : 8d0302 > sta abst +267b : 28 > plp + +267c : 6e0302 ror abst + tst_abs rROR,fROR,0 +267f : 08 > php ;save flags +2680 : ad0302 > lda abst +2683 : dd2802 > cmp rROR,x ;test result + > trap_ne +2686 : d0fe > bne * ;failed not equal (non zero) + > +2688 : 68 > pla ;load status + > eor_flag 0 +2689 : 4930 > eor #0|fao ;invert expected flags + > +268b : dd3802 > cmp fROR,x ;test flags + > trap_ne +268e : d0fe > bne * ;failed not equal (non zero) + > + +2690 : ca dex +2691 : 10e0 bpl tror4 +2693 : a203 ldx #3 +2695 : tror5 + set_abs zp1,$ff-fc + > load_flag $ff-fc +2695 : a9fe > lda #$ff-fc ;allow test to cha + > +2697 : 48 > pha ;use stack to load status +2698 : b513 > lda zp1,x ;load to memory +269a : 8d0302 > sta abst +269d : 28 > plp + +269e : 6e0302 ror abst + tst_abs rROR,fROR,$ff-fnzc +26a1 : 08 > php ;save flags +26a2 : ad0302 > lda abst +26a5 : dd2802 > cmp rROR,x ;test result + > trap_ne +26a8 : d0fe > bne * ;failed not equal (non zero) + > +26aa : 68 > pla ;load status + > eor_flag $ff-fnzc +26ab : 497c > eor #$ff-fnzc|fao ;invert expected + > +26ad : dd3802 > cmp fROR,x ;test flags + > trap_ne +26b0 : d0fe > bne * ;failed not equal (non zero) + > + +26b2 : ca dex +26b3 : 10e0 bpl tror5 + +26b5 : a203 ldx #3 +26b7 : trorc4 + set_abs zp1,fc + > load_flag fc +26b7 : a901 > lda #fc ;allow test to change + > +26b9 : 48 > pha ;use stack to load status +26ba : b513 > lda zp1,x ;load to memory +26bc : 8d0302 > sta abst +26bf : 28 > plp + +26c0 : 6e0302 ror abst + tst_abs rRORc,fRORc,0 +26c3 : 08 > php ;save flags +26c4 : ad0302 > lda abst +26c7 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +26ca : d0fe > bne * ;failed not equal (non zero) + > +26cc : 68 > pla ;load status + > eor_flag 0 +26cd : 4930 > eor #0|fao ;invert expected flags + > +26cf : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +26d2 : d0fe > bne * ;failed not equal (non zero) + > + +26d4 : ca dex +26d5 : 10e0 bpl trorc4 +26d7 : a203 ldx #3 +26d9 : trorc5 + set_abs zp1,$ff + > load_flag $ff +26d9 : a9ff > lda #$ff ;allow test to change + > +26db : 48 > pha ;use stack to load status +26dc : b513 > lda zp1,x ;load to memory +26de : 8d0302 > sta abst +26e1 : 28 > plp + +26e2 : 6e0302 ror abst + tst_abs rRORc,fRORc,$ff-fnzc +26e5 : 08 > php ;save flags +26e6 : ad0302 > lda abst +26e9 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +26ec : d0fe > bne * ;failed not equal (non zero) + > +26ee : 68 > pla ;load status + > eor_flag $ff-fnzc +26ef : 497c > eor #$ff-fnzc|fao ;invert expected + > +26f1 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +26f4 : d0fe > bne * ;failed not equal (non zero) + > + +26f6 : ca dex +26f7 : 10e0 bpl trorc5 + next_test +26f9 : ad0002 > lda test_case ;previous test +26fc : c91f > cmp #test_num + > trap_ne ;test is out of sequence +26fe : d0fe > bne * ;failed not equal (non zero) + > +0020 = >test_num = test_num + 1 +2700 : a920 > lda #test_num ;*** next tests' number +2702 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - zp indexed +2705 : a203 ldx #3 +2707 : tasl6 + set_zx zp1,0 + > load_flag 0 +2707 : a900 > lda #0 ;allow test to change I + > +2709 : 48 > pha ;use stack to load status +270a : b513 > lda zp1,x ;load to indexed zeropage +270c : 950c > sta zpt,x +270e : 28 > plp + +270f : 160c asl zpt,x + tst_zx rASL,fASL,0 +2711 : 08 > php ;save flags +2712 : b50c > lda zpt,x +2714 : dd2002 > cmp rASL,x ;test result + > trap_ne +2717 : d0fe > bne * ;failed not equal (non zero) + > +2719 : 68 > pla ;load status + > eor_flag 0 +271a : 4930 > eor #0|fao ;invert expected flags + > +271c : dd3002 > cmp fASL,x ;test flags + > trap_ne +271f : d0fe > bne * ;failed not equal (non zero) + > + +2721 : ca dex +2722 : 10e3 bpl tasl6 +2724 : a203 ldx #3 +2726 : tasl7 + set_zx zp1,$ff + > load_flag $ff +2726 : a9ff > lda #$ff ;allow test to change + > +2728 : 48 > pha ;use stack to load status +2729 : b513 > lda zp1,x ;load to indexed zeropage +272b : 950c > sta zpt,x +272d : 28 > plp + +272e : 160c asl zpt,x + tst_zx rASL,fASL,$ff-fnzc +2730 : 08 > php ;save flags +2731 : b50c > lda zpt,x +2733 : dd2002 > cmp rASL,x ;test result + > trap_ne +2736 : d0fe > bne * ;failed not equal (non zero) + > +2738 : 68 > pla ;load status + > eor_flag $ff-fnzc +2739 : 497c > eor #$ff-fnzc|fao ;invert expected + > +273b : dd3002 > cmp fASL,x ;test flags + > trap_ne +273e : d0fe > bne * ;failed not equal (non zero) + > + +2740 : ca dex +2741 : 10e3 bpl tasl7 + +2743 : a203 ldx #3 +2745 : tlsr6 + set_zx zp1,0 + > load_flag 0 +2745 : a900 > lda #0 ;allow test to change I + > +2747 : 48 > pha ;use stack to load status +2748 : b513 > lda zp1,x ;load to indexed zeropage +274a : 950c > sta zpt,x +274c : 28 > plp + +274d : 560c lsr zpt,x + tst_zx rLSR,fLSR,0 +274f : 08 > php ;save flags +2750 : b50c > lda zpt,x +2752 : dd2802 > cmp rLSR,x ;test result + > trap_ne +2755 : d0fe > bne * ;failed not equal (non zero) + > +2757 : 68 > pla ;load status + > eor_flag 0 +2758 : 4930 > eor #0|fao ;invert expected flags + > +275a : dd3802 > cmp fLSR,x ;test flags + > trap_ne +275d : d0fe > bne * ;failed not equal (non zero) + > + +275f : ca dex +2760 : 10e3 bpl tlsr6 +2762 : a203 ldx #3 +2764 : tlsr7 + set_zx zp1,$ff + > load_flag $ff +2764 : a9ff > lda #$ff ;allow test to change + > +2766 : 48 > pha ;use stack to load status +2767 : b513 > lda zp1,x ;load to indexed zeropage +2769 : 950c > sta zpt,x +276b : 28 > plp + +276c : 560c lsr zpt,x + tst_zx rLSR,fLSR,$ff-fnzc +276e : 08 > php ;save flags +276f : b50c > lda zpt,x +2771 : dd2802 > cmp rLSR,x ;test result + > trap_ne +2774 : d0fe > bne * ;failed not equal (non zero) + > +2776 : 68 > pla ;load status + > eor_flag $ff-fnzc +2777 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2779 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +277c : d0fe > bne * ;failed not equal (non zero) + > + +277e : ca dex +277f : 10e3 bpl tlsr7 + +2781 : a203 ldx #3 +2783 : trol6 + set_zx zp1,0 + > load_flag 0 +2783 : a900 > lda #0 ;allow test to change I + > +2785 : 48 > pha ;use stack to load status +2786 : b513 > lda zp1,x ;load to indexed zeropage +2788 : 950c > sta zpt,x +278a : 28 > plp + +278b : 360c rol zpt,x + tst_zx rROL,fROL,0 +278d : 08 > php ;save flags +278e : b50c > lda zpt,x +2790 : dd2002 > cmp rROL,x ;test result + > trap_ne +2793 : d0fe > bne * ;failed not equal (non zero) + > +2795 : 68 > pla ;load status + > eor_flag 0 +2796 : 4930 > eor #0|fao ;invert expected flags + > +2798 : dd3002 > cmp fROL,x ;test flags + > trap_ne +279b : d0fe > bne * ;failed not equal (non zero) + > + +279d : ca dex +279e : 10e3 bpl trol6 +27a0 : a203 ldx #3 +27a2 : trol7 + set_zx zp1,$ff-fc + > load_flag $ff-fc +27a2 : a9fe > lda #$ff-fc ;allow test to cha + > +27a4 : 48 > pha ;use stack to load status +27a5 : b513 > lda zp1,x ;load to indexed zeropage +27a7 : 950c > sta zpt,x +27a9 : 28 > plp + +27aa : 360c rol zpt,x + tst_zx rROL,fROL,$ff-fnzc +27ac : 08 > php ;save flags +27ad : b50c > lda zpt,x +27af : dd2002 > cmp rROL,x ;test result + > trap_ne +27b2 : d0fe > bne * ;failed not equal (non zero) + > +27b4 : 68 > pla ;load status + > eor_flag $ff-fnzc +27b5 : 497c > eor #$ff-fnzc|fao ;invert expected + > +27b7 : dd3002 > cmp fROL,x ;test flags + > trap_ne +27ba : d0fe > bne * ;failed not equal (non zero) + > + +27bc : ca dex +27bd : 10e3 bpl trol7 + +27bf : a203 ldx #3 +27c1 : trolc6 + set_zx zp1,fc + > load_flag fc +27c1 : a901 > lda #fc ;allow test to change + > +27c3 : 48 > pha ;use stack to load status +27c4 : b513 > lda zp1,x ;load to indexed zeropage +27c6 : 950c > sta zpt,x +27c8 : 28 > plp + +27c9 : 360c rol zpt,x + tst_zx rROLc,fROLc,0 +27cb : 08 > php ;save flags +27cc : b50c > lda zpt,x +27ce : dd2402 > cmp rROLc,x ;test result + > trap_ne +27d1 : d0fe > bne * ;failed not equal (non zero) + > +27d3 : 68 > pla ;load status + > eor_flag 0 +27d4 : 4930 > eor #0|fao ;invert expected flags + > +27d6 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +27d9 : d0fe > bne * ;failed not equal (non zero) + > + +27db : ca dex +27dc : 10e3 bpl trolc6 +27de : a203 ldx #3 +27e0 : trolc7 + set_zx zp1,$ff + > load_flag $ff +27e0 : a9ff > lda #$ff ;allow test to change + > +27e2 : 48 > pha ;use stack to load status +27e3 : b513 > lda zp1,x ;load to indexed zeropage +27e5 : 950c > sta zpt,x +27e7 : 28 > plp + +27e8 : 360c rol zpt,x + tst_zx rROLc,fROLc,$ff-fnzc +27ea : 08 > php ;save flags +27eb : b50c > lda zpt,x +27ed : dd2402 > cmp rROLc,x ;test result + > trap_ne +27f0 : d0fe > bne * ;failed not equal (non zero) + > +27f2 : 68 > pla ;load status + > eor_flag $ff-fnzc +27f3 : 497c > eor #$ff-fnzc|fao ;invert expected + > +27f5 : dd3402 > cmp fROLc,x ;test flags + > trap_ne +27f8 : d0fe > bne * ;failed not equal (non zero) + > + +27fa : ca dex +27fb : 10e3 bpl trolc7 + +27fd : a203 ldx #3 +27ff : tror6 + set_zx zp1,0 + > load_flag 0 +27ff : a900 > lda #0 ;allow test to change I + > +2801 : 48 > pha ;use stack to load status +2802 : b513 > lda zp1,x ;load to indexed zeropage +2804 : 950c > sta zpt,x +2806 : 28 > plp + +2807 : 760c ror zpt,x + tst_zx rROR,fROR,0 +2809 : 08 > php ;save flags +280a : b50c > lda zpt,x +280c : dd2802 > cmp rROR,x ;test result + > trap_ne +280f : d0fe > bne * ;failed not equal (non zero) + > +2811 : 68 > pla ;load status + > eor_flag 0 +2812 : 4930 > eor #0|fao ;invert expected flags + > +2814 : dd3802 > cmp fROR,x ;test flags + > trap_ne +2817 : d0fe > bne * ;failed not equal (non zero) + > + +2819 : ca dex +281a : 10e3 bpl tror6 +281c : a203 ldx #3 +281e : tror7 + set_zx zp1,$ff-fc + > load_flag $ff-fc +281e : a9fe > lda #$ff-fc ;allow test to cha + > +2820 : 48 > pha ;use stack to load status +2821 : b513 > lda zp1,x ;load to indexed zeropage +2823 : 950c > sta zpt,x +2825 : 28 > plp + +2826 : 760c ror zpt,x + tst_zx rROR,fROR,$ff-fnzc +2828 : 08 > php ;save flags +2829 : b50c > lda zpt,x +282b : dd2802 > cmp rROR,x ;test result + > trap_ne +282e : d0fe > bne * ;failed not equal (non zero) + > +2830 : 68 > pla ;load status + > eor_flag $ff-fnzc +2831 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2833 : dd3802 > cmp fROR,x ;test flags + > trap_ne +2836 : d0fe > bne * ;failed not equal (non zero) + > + +2838 : ca dex +2839 : 10e3 bpl tror7 + +283b : a203 ldx #3 +283d : trorc6 + set_zx zp1,fc + > load_flag fc +283d : a901 > lda #fc ;allow test to change + > +283f : 48 > pha ;use stack to load status +2840 : b513 > lda zp1,x ;load to indexed zeropage +2842 : 950c > sta zpt,x +2844 : 28 > plp + +2845 : 760c ror zpt,x + tst_zx rRORc,fRORc,0 +2847 : 08 > php ;save flags +2848 : b50c > lda zpt,x +284a : dd2c02 > cmp rRORc,x ;test result + > trap_ne +284d : d0fe > bne * ;failed not equal (non zero) + > +284f : 68 > pla ;load status + > eor_flag 0 +2850 : 4930 > eor #0|fao ;invert expected flags + > +2852 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2855 : d0fe > bne * ;failed not equal (non zero) + > + +2857 : ca dex +2858 : 10e3 bpl trorc6 +285a : a203 ldx #3 +285c : trorc7 + set_zx zp1,$ff + > load_flag $ff +285c : a9ff > lda #$ff ;allow test to change + > +285e : 48 > pha ;use stack to load status +285f : b513 > lda zp1,x ;load to indexed zeropage +2861 : 950c > sta zpt,x +2863 : 28 > plp + +2864 : 760c ror zpt,x + tst_zx rRORc,fRORc,$ff-fnzc +2866 : 08 > php ;save flags +2867 : b50c > lda zpt,x +2869 : dd2c02 > cmp rRORc,x ;test result + > trap_ne +286c : d0fe > bne * ;failed not equal (non zero) + > +286e : 68 > pla ;load status + > eor_flag $ff-fnzc +286f : 497c > eor #$ff-fnzc|fao ;invert expected + > +2871 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2874 : d0fe > bne * ;failed not equal (non zero) + > + +2876 : ca dex +2877 : 10e3 bpl trorc7 + next_test +2879 : ad0002 > lda test_case ;previous test +287c : c920 > cmp #test_num + > trap_ne ;test is out of sequence +287e : d0fe > bne * ;failed not equal (non zero) + > +0021 = >test_num = test_num + 1 +2880 : a921 > lda #test_num ;*** next tests' number +2882 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; shifts - abs indexed +2885 : a203 ldx #3 +2887 : tasl8 + set_absx zp1,0 + > load_flag 0 +2887 : a900 > lda #0 ;allow test to change I + > +2889 : 48 > pha ;use stack to load status +288a : b513 > lda zp1,x ;load to indexed memory +288c : 9d0302 > sta abst,x +288f : 28 > plp + +2890 : 1e0302 asl abst,x + tst_absx rASL,fASL,0 +2893 : 08 > php ;save flags +2894 : bd0302 > lda abst,x +2897 : dd2002 > cmp rASL,x ;test result + > trap_ne +289a : d0fe > bne * ;failed not equal (non zero) + > +289c : 68 > pla ;load status + > eor_flag 0 +289d : 4930 > eor #0|fao ;invert expected flags + > +289f : dd3002 > cmp fASL,x ;test flags + > trap_ne +28a2 : d0fe > bne * ;failed not equal (non zero) + > + +28a4 : ca dex +28a5 : 10e0 bpl tasl8 +28a7 : a203 ldx #3 +28a9 : tasl9 + set_absx zp1,$ff + > load_flag $ff +28a9 : a9ff > lda #$ff ;allow test to change + > +28ab : 48 > pha ;use stack to load status +28ac : b513 > lda zp1,x ;load to indexed memory +28ae : 9d0302 > sta abst,x +28b1 : 28 > plp + +28b2 : 1e0302 asl abst,x + tst_absx rASL,fASL,$ff-fnzc +28b5 : 08 > php ;save flags +28b6 : bd0302 > lda abst,x +28b9 : dd2002 > cmp rASL,x ;test result + > trap_ne +28bc : d0fe > bne * ;failed not equal (non zero) + > +28be : 68 > pla ;load status + > eor_flag $ff-fnzc +28bf : 497c > eor #$ff-fnzc|fao ;invert expected + > +28c1 : dd3002 > cmp fASL,x ;test flags + > trap_ne +28c4 : d0fe > bne * ;failed not equal (non zero) + > + +28c6 : ca dex +28c7 : 10e0 bpl tasl9 + +28c9 : a203 ldx #3 +28cb : tlsr8 + set_absx zp1,0 + > load_flag 0 +28cb : a900 > lda #0 ;allow test to change I + > +28cd : 48 > pha ;use stack to load status +28ce : b513 > lda zp1,x ;load to indexed memory +28d0 : 9d0302 > sta abst,x +28d3 : 28 > plp + +28d4 : 5e0302 lsr abst,x + tst_absx rLSR,fLSR,0 +28d7 : 08 > php ;save flags +28d8 : bd0302 > lda abst,x +28db : dd2802 > cmp rLSR,x ;test result + > trap_ne +28de : d0fe > bne * ;failed not equal (non zero) + > +28e0 : 68 > pla ;load status + > eor_flag 0 +28e1 : 4930 > eor #0|fao ;invert expected flags + > +28e3 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +28e6 : d0fe > bne * ;failed not equal (non zero) + > + +28e8 : ca dex +28e9 : 10e0 bpl tlsr8 +28eb : a203 ldx #3 +28ed : tlsr9 + set_absx zp1,$ff + > load_flag $ff +28ed : a9ff > lda #$ff ;allow test to change + > +28ef : 48 > pha ;use stack to load status +28f0 : b513 > lda zp1,x ;load to indexed memory +28f2 : 9d0302 > sta abst,x +28f5 : 28 > plp + +28f6 : 5e0302 lsr abst,x + tst_absx rLSR,fLSR,$ff-fnzc +28f9 : 08 > php ;save flags +28fa : bd0302 > lda abst,x +28fd : dd2802 > cmp rLSR,x ;test result + > trap_ne +2900 : d0fe > bne * ;failed not equal (non zero) + > +2902 : 68 > pla ;load status + > eor_flag $ff-fnzc +2903 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2905 : dd3802 > cmp fLSR,x ;test flags + > trap_ne +2908 : d0fe > bne * ;failed not equal (non zero) + > + +290a : ca dex +290b : 10e0 bpl tlsr9 + +290d : a203 ldx #3 +290f : trol8 + set_absx zp1,0 + > load_flag 0 +290f : a900 > lda #0 ;allow test to change I + > +2911 : 48 > pha ;use stack to load status +2912 : b513 > lda zp1,x ;load to indexed memory +2914 : 9d0302 > sta abst,x +2917 : 28 > plp + +2918 : 3e0302 rol abst,x + tst_absx rROL,fROL,0 +291b : 08 > php ;save flags +291c : bd0302 > lda abst,x +291f : dd2002 > cmp rROL,x ;test result + > trap_ne +2922 : d0fe > bne * ;failed not equal (non zero) + > +2924 : 68 > pla ;load status + > eor_flag 0 +2925 : 4930 > eor #0|fao ;invert expected flags + > +2927 : dd3002 > cmp fROL,x ;test flags + > trap_ne +292a : d0fe > bne * ;failed not equal (non zero) + > + +292c : ca dex +292d : 10e0 bpl trol8 +292f : a203 ldx #3 +2931 : trol9 + set_absx zp1,$ff-fc + > load_flag $ff-fc +2931 : a9fe > lda #$ff-fc ;allow test to cha + > +2933 : 48 > pha ;use stack to load status +2934 : b513 > lda zp1,x ;load to indexed memory +2936 : 9d0302 > sta abst,x +2939 : 28 > plp + +293a : 3e0302 rol abst,x + tst_absx rROL,fROL,$ff-fnzc +293d : 08 > php ;save flags +293e : bd0302 > lda abst,x +2941 : dd2002 > cmp rROL,x ;test result + > trap_ne +2944 : d0fe > bne * ;failed not equal (non zero) + > +2946 : 68 > pla ;load status + > eor_flag $ff-fnzc +2947 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2949 : dd3002 > cmp fROL,x ;test flags + > trap_ne +294c : d0fe > bne * ;failed not equal (non zero) + > + +294e : ca dex +294f : 10e0 bpl trol9 + +2951 : a203 ldx #3 +2953 : trolc8 + set_absx zp1,fc + > load_flag fc +2953 : a901 > lda #fc ;allow test to change + > +2955 : 48 > pha ;use stack to load status +2956 : b513 > lda zp1,x ;load to indexed memory +2958 : 9d0302 > sta abst,x +295b : 28 > plp + +295c : 3e0302 rol abst,x + tst_absx rROLc,fROLc,0 +295f : 08 > php ;save flags +2960 : bd0302 > lda abst,x +2963 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2966 : d0fe > bne * ;failed not equal (non zero) + > +2968 : 68 > pla ;load status + > eor_flag 0 +2969 : 4930 > eor #0|fao ;invert expected flags + > +296b : dd3402 > cmp fROLc,x ;test flags + > trap_ne +296e : d0fe > bne * ;failed not equal (non zero) + > + +2970 : ca dex +2971 : 10e0 bpl trolc8 +2973 : a203 ldx #3 +2975 : trolc9 + set_absx zp1,$ff + > load_flag $ff +2975 : a9ff > lda #$ff ;allow test to change + > +2977 : 48 > pha ;use stack to load status +2978 : b513 > lda zp1,x ;load to indexed memory +297a : 9d0302 > sta abst,x +297d : 28 > plp + +297e : 3e0302 rol abst,x + tst_absx rROLc,fROLc,$ff-fnzc +2981 : 08 > php ;save flags +2982 : bd0302 > lda abst,x +2985 : dd2402 > cmp rROLc,x ;test result + > trap_ne +2988 : d0fe > bne * ;failed not equal (non zero) + > +298a : 68 > pla ;load status + > eor_flag $ff-fnzc +298b : 497c > eor #$ff-fnzc|fao ;invert expected + > +298d : dd3402 > cmp fROLc,x ;test flags + > trap_ne +2990 : d0fe > bne * ;failed not equal (non zero) + > + +2992 : ca dex +2993 : 10e0 bpl trolc9 + +2995 : a203 ldx #3 +2997 : tror8 + set_absx zp1,0 + > load_flag 0 +2997 : a900 > lda #0 ;allow test to change I + > +2999 : 48 > pha ;use stack to load status +299a : b513 > lda zp1,x ;load to indexed memory +299c : 9d0302 > sta abst,x +299f : 28 > plp + +29a0 : 7e0302 ror abst,x + tst_absx rROR,fROR,0 +29a3 : 08 > php ;save flags +29a4 : bd0302 > lda abst,x +29a7 : dd2802 > cmp rROR,x ;test result + > trap_ne +29aa : d0fe > bne * ;failed not equal (non zero) + > +29ac : 68 > pla ;load status + > eor_flag 0 +29ad : 4930 > eor #0|fao ;invert expected flags + > +29af : dd3802 > cmp fROR,x ;test flags + > trap_ne +29b2 : d0fe > bne * ;failed not equal (non zero) + > + +29b4 : ca dex +29b5 : 10e0 bpl tror8 +29b7 : a203 ldx #3 +29b9 : tror9 + set_absx zp1,$ff-fc + > load_flag $ff-fc +29b9 : a9fe > lda #$ff-fc ;allow test to cha + > +29bb : 48 > pha ;use stack to load status +29bc : b513 > lda zp1,x ;load to indexed memory +29be : 9d0302 > sta abst,x +29c1 : 28 > plp + +29c2 : 7e0302 ror abst,x + tst_absx rROR,fROR,$ff-fnzc +29c5 : 08 > php ;save flags +29c6 : bd0302 > lda abst,x +29c9 : dd2802 > cmp rROR,x ;test result + > trap_ne +29cc : d0fe > bne * ;failed not equal (non zero) + > +29ce : 68 > pla ;load status + > eor_flag $ff-fnzc +29cf : 497c > eor #$ff-fnzc|fao ;invert expected + > +29d1 : dd3802 > cmp fROR,x ;test flags + > trap_ne +29d4 : d0fe > bne * ;failed not equal (non zero) + > + +29d6 : ca dex +29d7 : 10e0 bpl tror9 + +29d9 : a203 ldx #3 +29db : trorc8 + set_absx zp1,fc + > load_flag fc +29db : a901 > lda #fc ;allow test to change + > +29dd : 48 > pha ;use stack to load status +29de : b513 > lda zp1,x ;load to indexed memory +29e0 : 9d0302 > sta abst,x +29e3 : 28 > plp + +29e4 : 7e0302 ror abst,x + tst_absx rRORc,fRORc,0 +29e7 : 08 > php ;save flags +29e8 : bd0302 > lda abst,x +29eb : dd2c02 > cmp rRORc,x ;test result + > trap_ne +29ee : d0fe > bne * ;failed not equal (non zero) + > +29f0 : 68 > pla ;load status + > eor_flag 0 +29f1 : 4930 > eor #0|fao ;invert expected flags + > +29f3 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +29f6 : d0fe > bne * ;failed not equal (non zero) + > + +29f8 : ca dex +29f9 : 10e0 bpl trorc8 +29fb : a203 ldx #3 +29fd : trorc9 + set_absx zp1,$ff + > load_flag $ff +29fd : a9ff > lda #$ff ;allow test to change + > +29ff : 48 > pha ;use stack to load status +2a00 : b513 > lda zp1,x ;load to indexed memory +2a02 : 9d0302 > sta abst,x +2a05 : 28 > plp + +2a06 : 7e0302 ror abst,x + tst_absx rRORc,fRORc,$ff-fnzc +2a09 : 08 > php ;save flags +2a0a : bd0302 > lda abst,x +2a0d : dd2c02 > cmp rRORc,x ;test result + > trap_ne +2a10 : d0fe > bne * ;failed not equal (non zero) + > +2a12 : 68 > pla ;load status + > eor_flag $ff-fnzc +2a13 : 497c > eor #$ff-fnzc|fao ;invert expected + > +2a15 : dd3c02 > cmp fRORc,x ;test flags + > trap_ne +2a18 : d0fe > bne * ;failed not equal (non zero) + > + +2a1a : ca dex +2a1b : 10e0 bpl trorc9 + next_test +2a1d : ad0002 > lda test_case ;previous test +2a20 : c921 > cmp #test_num + > trap_ne ;test is out of sequence +2a22 : d0fe > bne * ;failed not equal (non zero) + > +0022 = >test_num = test_num + 1 +2a24 : a922 > lda #test_num ;*** next tests' number +2a26 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing memory increment/decrement - INC DEC all add + ; zeropage +2a29 : a200 ldx #0 +2a2b : a97e lda #$7e +2a2d : 850c sta zpt +2a2f : tinc + set_stat 0 + > load_flag 0 +2a2f : a900 > lda #0 ;allow test to change I + > +2a31 : 48 > pha ;use stack to load status +2a32 : 28 > plp + +2a33 : e60c inc zpt + tst_z rINC,fINC,0 +2a35 : 08 > php ;save flags +2a36 : a50c > lda zpt +2a38 : dd4002 > cmp rINC,x ;test result + > trap_ne +2a3b : d0fe > bne * ;failed not equal (non zero) + > +2a3d : 68 > pla ;load status + > eor_flag 0 +2a3e : 4930 > eor #0|fao ;invert expected flags + > +2a40 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2a43 : d0fe > bne * ;failed not equal (non zero) + > + +2a45 : e8 inx +2a46 : e002 cpx #2 +2a48 : d004 bne tinc1 +2a4a : a9fe lda #$fe +2a4c : 850c sta zpt +2a4e : e005 tinc1 cpx #5 +2a50 : d0dd bne tinc +2a52 : ca dex +2a53 : e60c inc zpt +2a55 : tdec + set_stat 0 + > load_flag 0 +2a55 : a900 > lda #0 ;allow test to change I + > +2a57 : 48 > pha ;use stack to load status +2a58 : 28 > plp + +2a59 : c60c dec zpt + tst_z rINC,fINC,0 +2a5b : 08 > php ;save flags +2a5c : a50c > lda zpt +2a5e : dd4002 > cmp rINC,x ;test result + > trap_ne +2a61 : d0fe > bne * ;failed not equal (non zero) + > +2a63 : 68 > pla ;load status + > eor_flag 0 +2a64 : 4930 > eor #0|fao ;invert expected flags + > +2a66 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2a69 : d0fe > bne * ;failed not equal (non zero) + > + +2a6b : ca dex +2a6c : 300a bmi tdec1 +2a6e : e001 cpx #1 +2a70 : d0e3 bne tdec +2a72 : a981 lda #$81 +2a74 : 850c sta zpt +2a76 : d0dd bne tdec +2a78 : tdec1 +2a78 : a200 ldx #0 +2a7a : a97e lda #$7e +2a7c : 850c sta zpt +2a7e : tinc10 + set_stat $ff + > load_flag $ff +2a7e : a9ff > lda #$ff ;allow test to change + > +2a80 : 48 > pha ;use stack to load status +2a81 : 28 > plp + +2a82 : e60c inc zpt + tst_z rINC,fINC,$ff-fnz +2a84 : 08 > php ;save flags +2a85 : a50c > lda zpt +2a87 : dd4002 > cmp rINC,x ;test result + > trap_ne +2a8a : d0fe > bne * ;failed not equal (non zero) + > +2a8c : 68 > pla ;load status + > eor_flag $ff-fnz +2a8d : 497d > eor #$ff-fnz|fao ;invert expected + > +2a8f : dd4502 > cmp fINC,x ;test flags + > trap_ne +2a92 : d0fe > bne * ;failed not equal (non zero) + > + +2a94 : e8 inx +2a95 : e002 cpx #2 +2a97 : d004 bne tinc11 +2a99 : a9fe lda #$fe +2a9b : 850c sta zpt +2a9d : e005 tinc11 cpx #5 +2a9f : d0dd bne tinc10 +2aa1 : ca dex +2aa2 : e60c inc zpt +2aa4 : tdec10 + set_stat $ff + > load_flag $ff +2aa4 : a9ff > lda #$ff ;allow test to change + > +2aa6 : 48 > pha ;use stack to load status +2aa7 : 28 > plp + +2aa8 : c60c dec zpt + tst_z rINC,fINC,$ff-fnz +2aaa : 08 > php ;save flags +2aab : a50c > lda zpt +2aad : dd4002 > cmp rINC,x ;test result + > trap_ne +2ab0 : d0fe > bne * ;failed not equal (non zero) + > +2ab2 : 68 > pla ;load status + > eor_flag $ff-fnz +2ab3 : 497d > eor #$ff-fnz|fao ;invert expected + > +2ab5 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2ab8 : d0fe > bne * ;failed not equal (non zero) + > + +2aba : ca dex +2abb : 300a bmi tdec11 +2abd : e001 cpx #1 +2abf : d0e3 bne tdec10 +2ac1 : a981 lda #$81 +2ac3 : 850c sta zpt +2ac5 : d0dd bne tdec10 +2ac7 : tdec11 + next_test +2ac7 : ad0002 > lda test_case ;previous test +2aca : c922 > cmp #test_num + > trap_ne ;test is out of sequence +2acc : d0fe > bne * ;failed not equal (non zero) + > +0023 = >test_num = test_num + 1 +2ace : a923 > lda #test_num ;*** next tests' number +2ad0 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; absolute memory +2ad3 : a200 ldx #0 +2ad5 : a97e lda #$7e +2ad7 : 8d0302 sta abst +2ada : tinc2 + set_stat 0 + > load_flag 0 +2ada : a900 > lda #0 ;allow test to change I + > +2adc : 48 > pha ;use stack to load status +2add : 28 > plp + +2ade : ee0302 inc abst + tst_abs rINC,fINC,0 +2ae1 : 08 > php ;save flags +2ae2 : ad0302 > lda abst +2ae5 : dd4002 > cmp rINC,x ;test result + > trap_ne +2ae8 : d0fe > bne * ;failed not equal (non zero) + > +2aea : 68 > pla ;load status + > eor_flag 0 +2aeb : 4930 > eor #0|fao ;invert expected flags + > +2aed : dd4502 > cmp fINC,x ;test flags + > trap_ne +2af0 : d0fe > bne * ;failed not equal (non zero) + > + +2af2 : e8 inx +2af3 : e002 cpx #2 +2af5 : d005 bne tinc3 +2af7 : a9fe lda #$fe +2af9 : 8d0302 sta abst +2afc : e005 tinc3 cpx #5 +2afe : d0da bne tinc2 +2b00 : ca dex +2b01 : ee0302 inc abst +2b04 : tdec2 + set_stat 0 + > load_flag 0 +2b04 : a900 > lda #0 ;allow test to change I + > +2b06 : 48 > pha ;use stack to load status +2b07 : 28 > plp + +2b08 : ce0302 dec abst + tst_abs rINC,fINC,0 +2b0b : 08 > php ;save flags +2b0c : ad0302 > lda abst +2b0f : dd4002 > cmp rINC,x ;test result + > trap_ne +2b12 : d0fe > bne * ;failed not equal (non zero) + > +2b14 : 68 > pla ;load status + > eor_flag 0 +2b15 : 4930 > eor #0|fao ;invert expected flags + > +2b17 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2b1a : d0fe > bne * ;failed not equal (non zero) + > + +2b1c : ca dex +2b1d : 300b bmi tdec3 +2b1f : e001 cpx #1 +2b21 : d0e1 bne tdec2 +2b23 : a981 lda #$81 +2b25 : 8d0302 sta abst +2b28 : d0da bne tdec2 +2b2a : tdec3 +2b2a : a200 ldx #0 +2b2c : a97e lda #$7e +2b2e : 8d0302 sta abst +2b31 : tinc12 + set_stat $ff + > load_flag $ff +2b31 : a9ff > lda #$ff ;allow test to change + > +2b33 : 48 > pha ;use stack to load status +2b34 : 28 > plp + +2b35 : ee0302 inc abst + tst_abs rINC,fINC,$ff-fnz +2b38 : 08 > php ;save flags +2b39 : ad0302 > lda abst +2b3c : dd4002 > cmp rINC,x ;test result + > trap_ne +2b3f : d0fe > bne * ;failed not equal (non zero) + > +2b41 : 68 > pla ;load status + > eor_flag $ff-fnz +2b42 : 497d > eor #$ff-fnz|fao ;invert expected + > +2b44 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2b47 : d0fe > bne * ;failed not equal (non zero) + > + +2b49 : e8 inx +2b4a : e002 cpx #2 +2b4c : d005 bne tinc13 +2b4e : a9fe lda #$fe +2b50 : 8d0302 sta abst +2b53 : e005 tinc13 cpx #5 +2b55 : d0da bne tinc12 +2b57 : ca dex +2b58 : ee0302 inc abst +2b5b : tdec12 + set_stat $ff + > load_flag $ff +2b5b : a9ff > lda #$ff ;allow test to change + > +2b5d : 48 > pha ;use stack to load status +2b5e : 28 > plp + +2b5f : ce0302 dec abst + tst_abs rINC,fINC,$ff-fnz +2b62 : 08 > php ;save flags +2b63 : ad0302 > lda abst +2b66 : dd4002 > cmp rINC,x ;test result + > trap_ne +2b69 : d0fe > bne * ;failed not equal (non zero) + > +2b6b : 68 > pla ;load status + > eor_flag $ff-fnz +2b6c : 497d > eor #$ff-fnz|fao ;invert expected + > +2b6e : dd4502 > cmp fINC,x ;test flags + > trap_ne +2b71 : d0fe > bne * ;failed not equal (non zero) + > + +2b73 : ca dex +2b74 : 300b bmi tdec13 +2b76 : e001 cpx #1 +2b78 : d0e1 bne tdec12 +2b7a : a981 lda #$81 +2b7c : 8d0302 sta abst +2b7f : d0da bne tdec12 +2b81 : tdec13 + next_test +2b81 : ad0002 > lda test_case ;previous test +2b84 : c923 > cmp #test_num + > trap_ne ;test is out of sequence +2b86 : d0fe > bne * ;failed not equal (non zero) + > +0024 = >test_num = test_num + 1 +2b88 : a924 > lda #test_num ;*** next tests' number +2b8a : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; zeropage indexed +2b8d : a200 ldx #0 +2b8f : a97e lda #$7e +2b91 : 950c tinc4 sta zpt,x + set_stat 0 + > load_flag 0 +2b93 : a900 > lda #0 ;allow test to change I + > +2b95 : 48 > pha ;use stack to load status +2b96 : 28 > plp + +2b97 : f60c inc zpt,x + tst_zx rINC,fINC,0 +2b99 : 08 > php ;save flags +2b9a : b50c > lda zpt,x +2b9c : dd4002 > cmp rINC,x ;test result + > trap_ne +2b9f : d0fe > bne * ;failed not equal (non zero) + > +2ba1 : 68 > pla ;load status + > eor_flag 0 +2ba2 : 4930 > eor #0|fao ;invert expected flags + > +2ba4 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2ba7 : d0fe > bne * ;failed not equal (non zero) + > + +2ba9 : b50c lda zpt,x +2bab : e8 inx +2bac : e002 cpx #2 +2bae : d002 bne tinc5 +2bb0 : a9fe lda #$fe +2bb2 : e005 tinc5 cpx #5 +2bb4 : d0db bne tinc4 +2bb6 : ca dex +2bb7 : a902 lda #2 +2bb9 : 950c tdec4 sta zpt,x + set_stat 0 + > load_flag 0 +2bbb : a900 > lda #0 ;allow test to change I + > +2bbd : 48 > pha ;use stack to load status +2bbe : 28 > plp + +2bbf : d60c dec zpt,x + tst_zx rINC,fINC,0 +2bc1 : 08 > php ;save flags +2bc2 : b50c > lda zpt,x +2bc4 : dd4002 > cmp rINC,x ;test result + > trap_ne +2bc7 : d0fe > bne * ;failed not equal (non zero) + > +2bc9 : 68 > pla ;load status + > eor_flag 0 +2bca : 4930 > eor #0|fao ;invert expected flags + > +2bcc : dd4502 > cmp fINC,x ;test flags + > trap_ne +2bcf : d0fe > bne * ;failed not equal (non zero) + > + +2bd1 : b50c lda zpt,x +2bd3 : ca dex +2bd4 : 3008 bmi tdec5 +2bd6 : e001 cpx #1 +2bd8 : d0df bne tdec4 +2bda : a981 lda #$81 +2bdc : d0db bne tdec4 +2bde : tdec5 +2bde : a200 ldx #0 +2be0 : a97e lda #$7e +2be2 : 950c tinc14 sta zpt,x + set_stat $ff + > load_flag $ff +2be4 : a9ff > lda #$ff ;allow test to change + > +2be6 : 48 > pha ;use stack to load status +2be7 : 28 > plp + +2be8 : f60c inc zpt,x + tst_zx rINC,fINC,$ff-fnz +2bea : 08 > php ;save flags +2beb : b50c > lda zpt,x +2bed : dd4002 > cmp rINC,x ;test result + > trap_ne +2bf0 : d0fe > bne * ;failed not equal (non zero) + > +2bf2 : 68 > pla ;load status + > eor_flag $ff-fnz +2bf3 : 497d > eor #$ff-fnz|fao ;invert expected + > +2bf5 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2bf8 : d0fe > bne * ;failed not equal (non zero) + > + +2bfa : b50c lda zpt,x +2bfc : e8 inx +2bfd : e002 cpx #2 +2bff : d002 bne tinc15 +2c01 : a9fe lda #$fe +2c03 : e005 tinc15 cpx #5 +2c05 : d0db bne tinc14 +2c07 : ca dex +2c08 : a902 lda #2 +2c0a : 950c tdec14 sta zpt,x + set_stat $ff + > load_flag $ff +2c0c : a9ff > lda #$ff ;allow test to change + > +2c0e : 48 > pha ;use stack to load status +2c0f : 28 > plp + +2c10 : d60c dec zpt,x + tst_zx rINC,fINC,$ff-fnz +2c12 : 08 > php ;save flags +2c13 : b50c > lda zpt,x +2c15 : dd4002 > cmp rINC,x ;test result + > trap_ne +2c18 : d0fe > bne * ;failed not equal (non zero) + > +2c1a : 68 > pla ;load status + > eor_flag $ff-fnz +2c1b : 497d > eor #$ff-fnz|fao ;invert expected + > +2c1d : dd4502 > cmp fINC,x ;test flags + > trap_ne +2c20 : d0fe > bne * ;failed not equal (non zero) + > + +2c22 : b50c lda zpt,x +2c24 : ca dex +2c25 : 3008 bmi tdec15 +2c27 : e001 cpx #1 +2c29 : d0df bne tdec14 +2c2b : a981 lda #$81 +2c2d : d0db bne tdec14 +2c2f : tdec15 + next_test +2c2f : ad0002 > lda test_case ;previous test +2c32 : c924 > cmp #test_num + > trap_ne ;test is out of sequence +2c34 : d0fe > bne * ;failed not equal (non zero) + > +0025 = >test_num = test_num + 1 +2c36 : a925 > lda #test_num ;*** next tests' number +2c38 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; memory indexed +2c3b : a200 ldx #0 +2c3d : a97e lda #$7e +2c3f : 9d0302 tinc6 sta abst,x + set_stat 0 + > load_flag 0 +2c42 : a900 > lda #0 ;allow test to change I + > +2c44 : 48 > pha ;use stack to load status +2c45 : 28 > plp + +2c46 : fe0302 inc abst,x + tst_absx rINC,fINC,0 +2c49 : 08 > php ;save flags +2c4a : bd0302 > lda abst,x +2c4d : dd4002 > cmp rINC,x ;test result + > trap_ne +2c50 : d0fe > bne * ;failed not equal (non zero) + > +2c52 : 68 > pla ;load status + > eor_flag 0 +2c53 : 4930 > eor #0|fao ;invert expected flags + > +2c55 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2c58 : d0fe > bne * ;failed not equal (non zero) + > + +2c5a : bd0302 lda abst,x +2c5d : e8 inx +2c5e : e002 cpx #2 +2c60 : d002 bne tinc7 +2c62 : a9fe lda #$fe +2c64 : e005 tinc7 cpx #5 +2c66 : d0d7 bne tinc6 +2c68 : ca dex +2c69 : a902 lda #2 +2c6b : 9d0302 tdec6 sta abst,x + set_stat 0 + > load_flag 0 +2c6e : a900 > lda #0 ;allow test to change I + > +2c70 : 48 > pha ;use stack to load status +2c71 : 28 > plp + +2c72 : de0302 dec abst,x + tst_absx rINC,fINC,0 +2c75 : 08 > php ;save flags +2c76 : bd0302 > lda abst,x +2c79 : dd4002 > cmp rINC,x ;test result + > trap_ne +2c7c : d0fe > bne * ;failed not equal (non zero) + > +2c7e : 68 > pla ;load status + > eor_flag 0 +2c7f : 4930 > eor #0|fao ;invert expected flags + > +2c81 : dd4502 > cmp fINC,x ;test flags + > trap_ne +2c84 : d0fe > bne * ;failed not equal (non zero) + > + +2c86 : bd0302 lda abst,x +2c89 : ca dex +2c8a : 3008 bmi tdec7 +2c8c : e001 cpx #1 +2c8e : d0db bne tdec6 +2c90 : a981 lda #$81 +2c92 : d0d7 bne tdec6 +2c94 : tdec7 +2c94 : a200 ldx #0 +2c96 : a97e lda #$7e +2c98 : 9d0302 tinc16 sta abst,x + set_stat $ff + > load_flag $ff +2c9b : a9ff > lda #$ff ;allow test to change + > +2c9d : 48 > pha ;use stack to load status +2c9e : 28 > plp + +2c9f : fe0302 inc abst,x + tst_absx rINC,fINC,$ff-fnz +2ca2 : 08 > php ;save flags +2ca3 : bd0302 > lda abst,x +2ca6 : dd4002 > cmp rINC,x ;test result + > trap_ne +2ca9 : d0fe > bne * ;failed not equal (non zero) + > +2cab : 68 > pla ;load status + > eor_flag $ff-fnz +2cac : 497d > eor #$ff-fnz|fao ;invert expected + > +2cae : dd4502 > cmp fINC,x ;test flags + > trap_ne +2cb1 : d0fe > bne * ;failed not equal (non zero) + > + +2cb3 : bd0302 lda abst,x +2cb6 : e8 inx +2cb7 : e002 cpx #2 +2cb9 : d002 bne tinc17 +2cbb : a9fe lda #$fe +2cbd : e005 tinc17 cpx #5 +2cbf : d0d7 bne tinc16 +2cc1 : ca dex +2cc2 : a902 lda #2 +2cc4 : 9d0302 tdec16 sta abst,x + set_stat $ff + > load_flag $ff +2cc7 : a9ff > lda #$ff ;allow test to change + > +2cc9 : 48 > pha ;use stack to load status +2cca : 28 > plp + +2ccb : de0302 dec abst,x + tst_absx rINC,fINC,$ff-fnz +2cce : 08 > php ;save flags +2ccf : bd0302 > lda abst,x +2cd2 : dd4002 > cmp rINC,x ;test result + > trap_ne +2cd5 : d0fe > bne * ;failed not equal (non zero) + > +2cd7 : 68 > pla ;load status + > eor_flag $ff-fnz +2cd8 : 497d > eor #$ff-fnz|fao ;invert expected + > +2cda : dd4502 > cmp fINC,x ;test flags + > trap_ne +2cdd : d0fe > bne * ;failed not equal (non zero) + > + +2cdf : bd0302 lda abst,x +2ce2 : ca dex +2ce3 : 3008 bmi tdec17 +2ce5 : e001 cpx #1 +2ce7 : d0db bne tdec16 +2ce9 : a981 lda #$81 +2ceb : d0d7 bne tdec16 +2ced : tdec17 + next_test +2ced : ad0002 > lda test_case ;previous test +2cf0 : c925 > cmp #test_num + > trap_ne ;test is out of sequence +2cf2 : d0fe > bne * ;failed not equal (non zero) + > +0026 = >test_num = test_num + 1 +2cf4 : a926 > lda #test_num ;*** next tests' number +2cf6 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; testing logical instructions - AND EOR ORA all addre + ; AND +2cf9 : a203 ldx #3 ;immediate +2cfb : b51c tand lda zpAN,x +2cfd : 8d0902 sta ex_andi+1 ;set AND # operand + set_ax absANa,0 + > load_flag 0 +2d00 : a900 > lda #0 ;allow test to change I + > +2d02 : 48 > pha ;use stack to load status +2d03 : bd5a02 > lda absANa,x ;precharge accu +2d06 : 28 > plp + +2d07 : 200802 jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,0 +2d0a : 08 > php ;save flags +2d0b : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d0e : d0fe > bne * ;failed not equal (non zero) + > +2d10 : 68 > pla ;load status + > eor_flag 0 +2d11 : 4930 > eor #0|fao ;invert expected flags + > +2d13 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d16 : d0fe > bne * ;failed not equal (non zero) + > + +2d18 : ca dex +2d19 : 10e0 bpl tand +2d1b : a203 ldx #3 +2d1d : b51c tand1 lda zpAN,x +2d1f : 8d0902 sta ex_andi+1 ;set AND # operand + set_ax absANa,$ff + > load_flag $ff +2d22 : a9ff > lda #$ff ;allow test to change + > +2d24 : 48 > pha ;use stack to load status +2d25 : bd5a02 > lda absANa,x ;precharge accu +2d28 : 28 > plp + +2d29 : 200802 jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,$ff-fnz +2d2c : 08 > php ;save flags +2d2d : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d30 : d0fe > bne * ;failed not equal (non zero) + > +2d32 : 68 > pla ;load status + > eor_flag $ff-fnz +2d33 : 497d > eor #$ff-fnz|fao ;invert expected + > +2d35 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d38 : d0fe > bne * ;failed not equal (non zero) + > + +2d3a : ca dex +2d3b : 10e0 bpl tand1 + +2d3d : a203 ldx #3 ;zp +2d3f : b51c tand2 lda zpAN,x +2d41 : 850c sta zpt + set_ax absANa,0 + > load_flag 0 +2d43 : a900 > lda #0 ;allow test to change I + > +2d45 : 48 > pha ;use stack to load status +2d46 : bd5a02 > lda absANa,x ;precharge accu +2d49 : 28 > plp + +2d4a : 250c and zpt + tst_ax absrlo,absflo,0 +2d4c : 08 > php ;save flags +2d4d : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d50 : d0fe > bne * ;failed not equal (non zero) + > +2d52 : 68 > pla ;load status + > eor_flag 0 +2d53 : 4930 > eor #0|fao ;invert expected flags + > +2d55 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d58 : d0fe > bne * ;failed not equal (non zero) + > + +2d5a : ca dex +2d5b : 10e2 bpl tand2 +2d5d : a203 ldx #3 +2d5f : b51c tand3 lda zpAN,x +2d61 : 850c sta zpt + set_ax absANa,$ff + > load_flag $ff +2d63 : a9ff > lda #$ff ;allow test to change + > +2d65 : 48 > pha ;use stack to load status +2d66 : bd5a02 > lda absANa,x ;precharge accu +2d69 : 28 > plp + +2d6a : 250c and zpt + tst_ax absrlo,absflo,$ff-fnz +2d6c : 08 > php ;save flags +2d6d : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d70 : d0fe > bne * ;failed not equal (non zero) + > +2d72 : 68 > pla ;load status + > eor_flag $ff-fnz +2d73 : 497d > eor #$ff-fnz|fao ;invert expected + > +2d75 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d78 : d0fe > bne * ;failed not equal (non zero) + > + +2d7a : ca dex +2d7b : 10e2 bpl tand3 + +2d7d : a203 ldx #3 ;abs +2d7f : b51c tand4 lda zpAN,x +2d81 : 8d0302 sta abst + set_ax absANa,0 + > load_flag 0 +2d84 : a900 > lda #0 ;allow test to change I + > +2d86 : 48 > pha ;use stack to load status +2d87 : bd5a02 > lda absANa,x ;precharge accu +2d8a : 28 > plp + +2d8b : 2d0302 and abst + tst_ax absrlo,absflo,0 +2d8e : 08 > php ;save flags +2d8f : dd6202 > cmp absrlo,x ;test result + > trap_ne +2d92 : d0fe > bne * ;failed not equal (non zero) + > +2d94 : 68 > pla ;load status + > eor_flag 0 +2d95 : 4930 > eor #0|fao ;invert expected flags + > +2d97 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2d9a : d0fe > bne * ;failed not equal (non zero) + > + +2d9c : ca dex +2d9d : 10e0 bpl tand4 +2d9f : a203 ldx #3 +2da1 : b51c tand5 lda zpAN,x +2da3 : 8d0302 sta abst + set_ax absANa,$ff + > load_flag $ff +2da6 : a9ff > lda #$ff ;allow test to change + > +2da8 : 48 > pha ;use stack to load status +2da9 : bd5a02 > lda absANa,x ;precharge accu +2dac : 28 > plp + +2dad : 2d0302 and abst + tst_ax absrlo,absflo,$ff-fnz +2db0 : 08 > php ;save flags +2db1 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2db4 : d0fe > bne * ;failed not equal (non zero) + > +2db6 : 68 > pla ;load status + > eor_flag $ff-fnz +2db7 : 497d > eor #$ff-fnz|fao ;invert expected + > +2db9 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2dbc : d0fe > bne * ;failed not equal (non zero) + > + +2dbe : ca dex +2dbf : 1002 bpl tand6 + +2dc1 : a203 ldx #3 ;zp,x +2dc3 : tand6 + set_ax absANa,0 + > load_flag 0 +2dc3 : a900 > lda #0 ;allow test to change I + > +2dc5 : 48 > pha ;use stack to load status +2dc6 : bd5a02 > lda absANa,x ;precharge accu +2dc9 : 28 > plp + +2dca : 351c and zpAN,x + tst_ax absrlo,absflo,0 +2dcc : 08 > php ;save flags +2dcd : dd6202 > cmp absrlo,x ;test result + > trap_ne +2dd0 : d0fe > bne * ;failed not equal (non zero) + > +2dd2 : 68 > pla ;load status + > eor_flag 0 +2dd3 : 4930 > eor #0|fao ;invert expected flags + > +2dd5 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2dd8 : d0fe > bne * ;failed not equal (non zero) + > + +2dda : ca dex +2ddb : 10e6 bpl tand6 +2ddd : a203 ldx #3 +2ddf : tand7 + set_ax absANa,$ff + > load_flag $ff +2ddf : a9ff > lda #$ff ;allow test to change + > +2de1 : 48 > pha ;use stack to load status +2de2 : bd5a02 > lda absANa,x ;precharge accu +2de5 : 28 > plp + +2de6 : 351c and zpAN,x + tst_ax absrlo,absflo,$ff-fnz +2de8 : 08 > php ;save flags +2de9 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2dec : d0fe > bne * ;failed not equal (non zero) + > +2dee : 68 > pla ;load status + > eor_flag $ff-fnz +2def : 497d > eor #$ff-fnz|fao ;invert expected + > +2df1 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2df4 : d0fe > bne * ;failed not equal (non zero) + > + +2df6 : ca dex +2df7 : 10e6 bpl tand7 + +2df9 : a203 ldx #3 ;abs,x +2dfb : tand8 + set_ax absANa,0 + > load_flag 0 +2dfb : a900 > lda #0 ;allow test to change I + > +2dfd : 48 > pha ;use stack to load status +2dfe : bd5a02 > lda absANa,x ;precharge accu +2e01 : 28 > plp + +2e02 : 3d4e02 and absAN,x + tst_ax absrlo,absflo,0 +2e05 : 08 > php ;save flags +2e06 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2e09 : d0fe > bne * ;failed not equal (non zero) + > +2e0b : 68 > pla ;load status + > eor_flag 0 +2e0c : 4930 > eor #0|fao ;invert expected flags + > +2e0e : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2e11 : d0fe > bne * ;failed not equal (non zero) + > + +2e13 : ca dex +2e14 : 10e5 bpl tand8 +2e16 : a203 ldx #3 +2e18 : tand9 + set_ax absANa,$ff + > load_flag $ff +2e18 : a9ff > lda #$ff ;allow test to change + > +2e1a : 48 > pha ;use stack to load status +2e1b : bd5a02 > lda absANa,x ;precharge accu +2e1e : 28 > plp + +2e1f : 3d4e02 and absAN,x + tst_ax absrlo,absflo,$ff-fnz +2e22 : 08 > php ;save flags +2e23 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2e26 : d0fe > bne * ;failed not equal (non zero) + > +2e28 : 68 > pla ;load status + > eor_flag $ff-fnz +2e29 : 497d > eor #$ff-fnz|fao ;invert expected + > +2e2b : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2e2e : d0fe > bne * ;failed not equal (non zero) + > + +2e30 : ca dex +2e31 : 10e5 bpl tand9 + +2e33 : a003 ldy #3 ;abs,y +2e35 : tand10 + set_ay absANa,0 + > load_flag 0 +2e35 : a900 > lda #0 ;allow test to change I + > +2e37 : 48 > pha ;use stack to load status +2e38 : b95a02 > lda absANa,y ;precharge accu +2e3b : 28 > plp + +2e3c : 394e02 and absAN,y + tst_ay absrlo,absflo,0 +2e3f : 08 > php ;save flags +2e40 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e43 : d0fe > bne * ;failed not equal (non zero) + > +2e45 : 68 > pla ;load status + > eor_flag 0 +2e46 : 4930 > eor #0|fao ;invert expected flags + > +2e48 : d96602 > cmp absflo,y ;test flags + > trap_ne +2e4b : d0fe > bne * ;failed not equal (non zero) + > + +2e4d : 88 dey +2e4e : 10e5 bpl tand10 +2e50 : a003 ldy #3 +2e52 : tand11 + set_ay absANa,$ff + > load_flag $ff +2e52 : a9ff > lda #$ff ;allow test to change + > +2e54 : 48 > pha ;use stack to load status +2e55 : b95a02 > lda absANa,y ;precharge accu +2e58 : 28 > plp + +2e59 : 394e02 and absAN,y + tst_ay absrlo,absflo,$ff-fnz +2e5c : 08 > php ;save flags +2e5d : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e60 : d0fe > bne * ;failed not equal (non zero) + > +2e62 : 68 > pla ;load status + > eor_flag $ff-fnz +2e63 : 497d > eor #$ff-fnz|fao ;invert expected + > +2e65 : d96602 > cmp absflo,y ;test flags + > trap_ne +2e68 : d0fe > bne * ;failed not equal (non zero) + > + +2e6a : 88 dey +2e6b : 10e5 bpl tand11 + +2e6d : a206 ldx #6 ;(zp,x) +2e6f : a003 ldy #3 +2e71 : tand12 + set_ay absANa,0 + > load_flag 0 +2e71 : a900 > lda #0 ;allow test to change I + > +2e73 : 48 > pha ;use stack to load status +2e74 : b95a02 > lda absANa,y ;precharge accu +2e77 : 28 > plp + +2e78 : 213a and (indAN,x) + tst_ay absrlo,absflo,0 +2e7a : 08 > php ;save flags +2e7b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e7e : d0fe > bne * ;failed not equal (non zero) + > +2e80 : 68 > pla ;load status + > eor_flag 0 +2e81 : 4930 > eor #0|fao ;invert expected flags + > +2e83 : d96602 > cmp absflo,y ;test flags + > trap_ne +2e86 : d0fe > bne * ;failed not equal (non zero) + > + +2e88 : ca dex +2e89 : ca dex +2e8a : 88 dey +2e8b : 10e4 bpl tand12 +2e8d : a206 ldx #6 +2e8f : a003 ldy #3 +2e91 : tand13 + set_ay absANa,$ff + > load_flag $ff +2e91 : a9ff > lda #$ff ;allow test to change + > +2e93 : 48 > pha ;use stack to load status +2e94 : b95a02 > lda absANa,y ;precharge accu +2e97 : 28 > plp + +2e98 : 213a and (indAN,x) + tst_ay absrlo,absflo,$ff-fnz +2e9a : 08 > php ;save flags +2e9b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2e9e : d0fe > bne * ;failed not equal (non zero) + > +2ea0 : 68 > pla ;load status + > eor_flag $ff-fnz +2ea1 : 497d > eor #$ff-fnz|fao ;invert expected + > +2ea3 : d96602 > cmp absflo,y ;test flags + > trap_ne +2ea6 : d0fe > bne * ;failed not equal (non zero) + > + +2ea8 : ca dex +2ea9 : ca dex +2eaa : 88 dey +2eab : 10e4 bpl tand13 + +2ead : a003 ldy #3 ;(zp),y +2eaf : tand14 + set_ay absANa,0 + > load_flag 0 +2eaf : a900 > lda #0 ;allow test to change I + > +2eb1 : 48 > pha ;use stack to load status +2eb2 : b95a02 > lda absANa,y ;precharge accu +2eb5 : 28 > plp + +2eb6 : 313a and (indAN),y + tst_ay absrlo,absflo,0 +2eb8 : 08 > php ;save flags +2eb9 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2ebc : d0fe > bne * ;failed not equal (non zero) + > +2ebe : 68 > pla ;load status + > eor_flag 0 +2ebf : 4930 > eor #0|fao ;invert expected flags + > +2ec1 : d96602 > cmp absflo,y ;test flags + > trap_ne +2ec4 : d0fe > bne * ;failed not equal (non zero) + > + +2ec6 : 88 dey +2ec7 : 10e6 bpl tand14 +2ec9 : a003 ldy #3 +2ecb : tand15 + set_ay absANa,$ff + > load_flag $ff +2ecb : a9ff > lda #$ff ;allow test to change + > +2ecd : 48 > pha ;use stack to load status +2ece : b95a02 > lda absANa,y ;precharge accu +2ed1 : 28 > plp + +2ed2 : 313a and (indAN),y + tst_ay absrlo,absflo,$ff-fnz +2ed4 : 08 > php ;save flags +2ed5 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +2ed8 : d0fe > bne * ;failed not equal (non zero) + > +2eda : 68 > pla ;load status + > eor_flag $ff-fnz +2edb : 497d > eor #$ff-fnz|fao ;invert expected + > +2edd : d96602 > cmp absflo,y ;test flags + > trap_ne +2ee0 : d0fe > bne * ;failed not equal (non zero) + > + +2ee2 : 88 dey +2ee3 : 10e6 bpl tand15 + next_test +2ee5 : ad0002 > lda test_case ;previous test +2ee8 : c926 > cmp #test_num + > trap_ne ;test is out of sequence +2eea : d0fe > bne * ;failed not equal (non zero) + > +0027 = >test_num = test_num + 1 +2eec : a927 > lda #test_num ;*** next tests' number +2eee : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; EOR +2ef1 : a203 ldx #3 ;immediate - self modifying co +2ef3 : b520 teor lda zpEO,x +2ef5 : 8d0c02 sta ex_eori+1 ;set EOR # operand + set_ax absEOa,0 + > load_flag 0 +2ef8 : a900 > lda #0 ;allow test to change I + > +2efa : 48 > pha ;use stack to load status +2efb : bd5e02 > lda absEOa,x ;precharge accu +2efe : 28 > plp + +2eff : 200b02 jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,0 +2f02 : 08 > php ;save flags +2f03 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f06 : d0fe > bne * ;failed not equal (non zero) + > +2f08 : 68 > pla ;load status + > eor_flag 0 +2f09 : 4930 > eor #0|fao ;invert expected flags + > +2f0b : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f0e : d0fe > bne * ;failed not equal (non zero) + > + +2f10 : ca dex +2f11 : 10e0 bpl teor +2f13 : a203 ldx #3 +2f15 : b520 teor1 lda zpEO,x +2f17 : 8d0c02 sta ex_eori+1 ;set EOR # operand + set_ax absEOa,$ff + > load_flag $ff +2f1a : a9ff > lda #$ff ;allow test to change + > +2f1c : 48 > pha ;use stack to load status +2f1d : bd5e02 > lda absEOa,x ;precharge accu +2f20 : 28 > plp + +2f21 : 200b02 jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,$ff-fnz +2f24 : 08 > php ;save flags +2f25 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f28 : d0fe > bne * ;failed not equal (non zero) + > +2f2a : 68 > pla ;load status + > eor_flag $ff-fnz +2f2b : 497d > eor #$ff-fnz|fao ;invert expected + > +2f2d : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f30 : d0fe > bne * ;failed not equal (non zero) + > + +2f32 : ca dex +2f33 : 10e0 bpl teor1 + +2f35 : a203 ldx #3 ;zp +2f37 : b520 teor2 lda zpEO,x +2f39 : 850c sta zpt + set_ax absEOa,0 + > load_flag 0 +2f3b : a900 > lda #0 ;allow test to change I + > +2f3d : 48 > pha ;use stack to load status +2f3e : bd5e02 > lda absEOa,x ;precharge accu +2f41 : 28 > plp + +2f42 : 450c eor zpt + tst_ax absrlo,absflo,0 +2f44 : 08 > php ;save flags +2f45 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f48 : d0fe > bne * ;failed not equal (non zero) + > +2f4a : 68 > pla ;load status + > eor_flag 0 +2f4b : 4930 > eor #0|fao ;invert expected flags + > +2f4d : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f50 : d0fe > bne * ;failed not equal (non zero) + > + +2f52 : ca dex +2f53 : 10e2 bpl teor2 +2f55 : a203 ldx #3 +2f57 : b520 teor3 lda zpEO,x +2f59 : 850c sta zpt + set_ax absEOa,$ff + > load_flag $ff +2f5b : a9ff > lda #$ff ;allow test to change + > +2f5d : 48 > pha ;use stack to load status +2f5e : bd5e02 > lda absEOa,x ;precharge accu +2f61 : 28 > plp + +2f62 : 450c eor zpt + tst_ax absrlo,absflo,$ff-fnz +2f64 : 08 > php ;save flags +2f65 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f68 : d0fe > bne * ;failed not equal (non zero) + > +2f6a : 68 > pla ;load status + > eor_flag $ff-fnz +2f6b : 497d > eor #$ff-fnz|fao ;invert expected + > +2f6d : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f70 : d0fe > bne * ;failed not equal (non zero) + > + +2f72 : ca dex +2f73 : 10e2 bpl teor3 + +2f75 : a203 ldx #3 ;abs +2f77 : b520 teor4 lda zpEO,x +2f79 : 8d0302 sta abst + set_ax absEOa,0 + > load_flag 0 +2f7c : a900 > lda #0 ;allow test to change I + > +2f7e : 48 > pha ;use stack to load status +2f7f : bd5e02 > lda absEOa,x ;precharge accu +2f82 : 28 > plp + +2f83 : 4d0302 eor abst + tst_ax absrlo,absflo,0 +2f86 : 08 > php ;save flags +2f87 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2f8a : d0fe > bne * ;failed not equal (non zero) + > +2f8c : 68 > pla ;load status + > eor_flag 0 +2f8d : 4930 > eor #0|fao ;invert expected flags + > +2f8f : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2f92 : d0fe > bne * ;failed not equal (non zero) + > + +2f94 : ca dex +2f95 : 10e0 bpl teor4 +2f97 : a203 ldx #3 +2f99 : b520 teor5 lda zpEO,x +2f9b : 8d0302 sta abst + set_ax absEOa,$ff + > load_flag $ff +2f9e : a9ff > lda #$ff ;allow test to change + > +2fa0 : 48 > pha ;use stack to load status +2fa1 : bd5e02 > lda absEOa,x ;precharge accu +2fa4 : 28 > plp + +2fa5 : 4d0302 eor abst + tst_ax absrlo,absflo,$ff-fnz +2fa8 : 08 > php ;save flags +2fa9 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2fac : d0fe > bne * ;failed not equal (non zero) + > +2fae : 68 > pla ;load status + > eor_flag $ff-fnz +2faf : 497d > eor #$ff-fnz|fao ;invert expected + > +2fb1 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2fb4 : d0fe > bne * ;failed not equal (non zero) + > + +2fb6 : ca dex +2fb7 : 1002 bpl teor6 + +2fb9 : a203 ldx #3 ;zp,x +2fbb : teor6 + set_ax absEOa,0 + > load_flag 0 +2fbb : a900 > lda #0 ;allow test to change I + > +2fbd : 48 > pha ;use stack to load status +2fbe : bd5e02 > lda absEOa,x ;precharge accu +2fc1 : 28 > plp + +2fc2 : 5520 eor zpEO,x + tst_ax absrlo,absflo,0 +2fc4 : 08 > php ;save flags +2fc5 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2fc8 : d0fe > bne * ;failed not equal (non zero) + > +2fca : 68 > pla ;load status + > eor_flag 0 +2fcb : 4930 > eor #0|fao ;invert expected flags + > +2fcd : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2fd0 : d0fe > bne * ;failed not equal (non zero) + > + +2fd2 : ca dex +2fd3 : 10e6 bpl teor6 +2fd5 : a203 ldx #3 +2fd7 : teor7 + set_ax absEOa,$ff + > load_flag $ff +2fd7 : a9ff > lda #$ff ;allow test to change + > +2fd9 : 48 > pha ;use stack to load status +2fda : bd5e02 > lda absEOa,x ;precharge accu +2fdd : 28 > plp + +2fde : 5520 eor zpEO,x + tst_ax absrlo,absflo,$ff-fnz +2fe0 : 08 > php ;save flags +2fe1 : dd6202 > cmp absrlo,x ;test result + > trap_ne +2fe4 : d0fe > bne * ;failed not equal (non zero) + > +2fe6 : 68 > pla ;load status + > eor_flag $ff-fnz +2fe7 : 497d > eor #$ff-fnz|fao ;invert expected + > +2fe9 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +2fec : d0fe > bne * ;failed not equal (non zero) + > + +2fee : ca dex +2fef : 10e6 bpl teor7 + +2ff1 : a203 ldx #3 ;abs,x +2ff3 : teor8 + set_ax absEOa,0 + > load_flag 0 +2ff3 : a900 > lda #0 ;allow test to change I + > +2ff5 : 48 > pha ;use stack to load status +2ff6 : bd5e02 > lda absEOa,x ;precharge accu +2ff9 : 28 > plp + +2ffa : 5d5202 eor absEO,x + tst_ax absrlo,absflo,0 +2ffd : 08 > php ;save flags +2ffe : dd6202 > cmp absrlo,x ;test result + > trap_ne +3001 : d0fe > bne * ;failed not equal (non zero) + > +3003 : 68 > pla ;load status + > eor_flag 0 +3004 : 4930 > eor #0|fao ;invert expected flags + > +3006 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3009 : d0fe > bne * ;failed not equal (non zero) + > + +300b : ca dex +300c : 10e5 bpl teor8 +300e : a203 ldx #3 +3010 : teor9 + set_ax absEOa,$ff + > load_flag $ff +3010 : a9ff > lda #$ff ;allow test to change + > +3012 : 48 > pha ;use stack to load status +3013 : bd5e02 > lda absEOa,x ;precharge accu +3016 : 28 > plp + +3017 : 5d5202 eor absEO,x + tst_ax absrlo,absflo,$ff-fnz +301a : 08 > php ;save flags +301b : dd6202 > cmp absrlo,x ;test result + > trap_ne +301e : d0fe > bne * ;failed not equal (non zero) + > +3020 : 68 > pla ;load status + > eor_flag $ff-fnz +3021 : 497d > eor #$ff-fnz|fao ;invert expected + > +3023 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3026 : d0fe > bne * ;failed not equal (non zero) + > + +3028 : ca dex +3029 : 10e5 bpl teor9 + +302b : a003 ldy #3 ;abs,y +302d : teor10 + set_ay absEOa,0 + > load_flag 0 +302d : a900 > lda #0 ;allow test to change I + > +302f : 48 > pha ;use stack to load status +3030 : b95e02 > lda absEOa,y ;precharge accu +3033 : 28 > plp + +3034 : 595202 eor absEO,y + tst_ay absrlo,absflo,0 +3037 : 08 > php ;save flags +3038 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +303b : d0fe > bne * ;failed not equal (non zero) + > +303d : 68 > pla ;load status + > eor_flag 0 +303e : 4930 > eor #0|fao ;invert expected flags + > +3040 : d96602 > cmp absflo,y ;test flags + > trap_ne +3043 : d0fe > bne * ;failed not equal (non zero) + > + +3045 : 88 dey +3046 : 10e5 bpl teor10 +3048 : a003 ldy #3 +304a : teor11 + set_ay absEOa,$ff + > load_flag $ff +304a : a9ff > lda #$ff ;allow test to change + > +304c : 48 > pha ;use stack to load status +304d : b95e02 > lda absEOa,y ;precharge accu +3050 : 28 > plp + +3051 : 595202 eor absEO,y + tst_ay absrlo,absflo,$ff-fnz +3054 : 08 > php ;save flags +3055 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3058 : d0fe > bne * ;failed not equal (non zero) + > +305a : 68 > pla ;load status + > eor_flag $ff-fnz +305b : 497d > eor #$ff-fnz|fao ;invert expected + > +305d : d96602 > cmp absflo,y ;test flags + > trap_ne +3060 : d0fe > bne * ;failed not equal (non zero) + > + +3062 : 88 dey +3063 : 10e5 bpl teor11 + +3065 : a206 ldx #6 ;(zp,x) +3067 : a003 ldy #3 +3069 : teor12 + set_ay absEOa,0 + > load_flag 0 +3069 : a900 > lda #0 ;allow test to change I + > +306b : 48 > pha ;use stack to load status +306c : b95e02 > lda absEOa,y ;precharge accu +306f : 28 > plp + +3070 : 4142 eor (indEO,x) + tst_ay absrlo,absflo,0 +3072 : 08 > php ;save flags +3073 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3076 : d0fe > bne * ;failed not equal (non zero) + > +3078 : 68 > pla ;load status + > eor_flag 0 +3079 : 4930 > eor #0|fao ;invert expected flags + > +307b : d96602 > cmp absflo,y ;test flags + > trap_ne +307e : d0fe > bne * ;failed not equal (non zero) + > + +3080 : ca dex +3081 : ca dex +3082 : 88 dey +3083 : 10e4 bpl teor12 +3085 : a206 ldx #6 +3087 : a003 ldy #3 +3089 : teor13 + set_ay absEOa,$ff + > load_flag $ff +3089 : a9ff > lda #$ff ;allow test to change + > +308b : 48 > pha ;use stack to load status +308c : b95e02 > lda absEOa,y ;precharge accu +308f : 28 > plp + +3090 : 4142 eor (indEO,x) + tst_ay absrlo,absflo,$ff-fnz +3092 : 08 > php ;save flags +3093 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3096 : d0fe > bne * ;failed not equal (non zero) + > +3098 : 68 > pla ;load status + > eor_flag $ff-fnz +3099 : 497d > eor #$ff-fnz|fao ;invert expected + > +309b : d96602 > cmp absflo,y ;test flags + > trap_ne +309e : d0fe > bne * ;failed not equal (non zero) + > + +30a0 : ca dex +30a1 : ca dex +30a2 : 88 dey +30a3 : 10e4 bpl teor13 + +30a5 : a003 ldy #3 ;(zp),y +30a7 : teor14 + set_ay absEOa,0 + > load_flag 0 +30a7 : a900 > lda #0 ;allow test to change I + > +30a9 : 48 > pha ;use stack to load status +30aa : b95e02 > lda absEOa,y ;precharge accu +30ad : 28 > plp + +30ae : 5142 eor (indEO),y + tst_ay absrlo,absflo,0 +30b0 : 08 > php ;save flags +30b1 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +30b4 : d0fe > bne * ;failed not equal (non zero) + > +30b6 : 68 > pla ;load status + > eor_flag 0 +30b7 : 4930 > eor #0|fao ;invert expected flags + > +30b9 : d96602 > cmp absflo,y ;test flags + > trap_ne +30bc : d0fe > bne * ;failed not equal (non zero) + > + +30be : 88 dey +30bf : 10e6 bpl teor14 +30c1 : a003 ldy #3 +30c3 : teor15 + set_ay absEOa,$ff + > load_flag $ff +30c3 : a9ff > lda #$ff ;allow test to change + > +30c5 : 48 > pha ;use stack to load status +30c6 : b95e02 > lda absEOa,y ;precharge accu +30c9 : 28 > plp + +30ca : 5142 eor (indEO),y + tst_ay absrlo,absflo,$ff-fnz +30cc : 08 > php ;save flags +30cd : d96202 > cmp absrlo,y ;test result + > trap_ne ; +30d0 : d0fe > bne * ;failed not equal (non zero) + > +30d2 : 68 > pla ;load status + > eor_flag $ff-fnz +30d3 : 497d > eor #$ff-fnz|fao ;invert expected + > +30d5 : d96602 > cmp absflo,y ;test flags + > trap_ne +30d8 : d0fe > bne * ;failed not equal (non zero) + > + +30da : 88 dey +30db : 10e6 bpl teor15 + next_test +30dd : ad0002 > lda test_case ;previous test +30e0 : c927 > cmp #test_num + > trap_ne ;test is out of sequence +30e2 : d0fe > bne * ;failed not equal (non zero) + > +0028 = >test_num = test_num + 1 +30e4 : a928 > lda #test_num ;*** next tests' number +30e6 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; OR +30e9 : a203 ldx #3 ;immediate - self modifying co +30eb : b518 tora lda zpOR,x +30ed : 8d0f02 sta ex_orai+1 ;set ORA # operand + set_ax absORa,0 + > load_flag 0 +30f0 : a900 > lda #0 ;allow test to change I + > +30f2 : 48 > pha ;use stack to load status +30f3 : bd5602 > lda absORa,x ;precharge accu +30f6 : 28 > plp + +30f7 : 200e02 jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,0 +30fa : 08 > php ;save flags +30fb : dd6202 > cmp absrlo,x ;test result + > trap_ne +30fe : d0fe > bne * ;failed not equal (non zero) + > +3100 : 68 > pla ;load status + > eor_flag 0 +3101 : 4930 > eor #0|fao ;invert expected flags + > +3103 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3106 : d0fe > bne * ;failed not equal (non zero) + > + +3108 : ca dex +3109 : 10e0 bpl tora +310b : a203 ldx #3 +310d : b518 tora1 lda zpOR,x +310f : 8d0f02 sta ex_orai+1 ;set ORA # operand + set_ax absORa,$ff + > load_flag $ff +3112 : a9ff > lda #$ff ;allow test to change + > +3114 : 48 > pha ;use stack to load status +3115 : bd5602 > lda absORa,x ;precharge accu +3118 : 28 > plp + +3119 : 200e02 jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,$ff-fnz +311c : 08 > php ;save flags +311d : dd6202 > cmp absrlo,x ;test result + > trap_ne +3120 : d0fe > bne * ;failed not equal (non zero) + > +3122 : 68 > pla ;load status + > eor_flag $ff-fnz +3123 : 497d > eor #$ff-fnz|fao ;invert expected + > +3125 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3128 : d0fe > bne * ;failed not equal (non zero) + > + +312a : ca dex +312b : 10e0 bpl tora1 + +312d : a203 ldx #3 ;zp +312f : b518 tora2 lda zpOR,x +3131 : 850c sta zpt + set_ax absORa,0 + > load_flag 0 +3133 : a900 > lda #0 ;allow test to change I + > +3135 : 48 > pha ;use stack to load status +3136 : bd5602 > lda absORa,x ;precharge accu +3139 : 28 > plp + +313a : 050c ora zpt + tst_ax absrlo,absflo,0 +313c : 08 > php ;save flags +313d : dd6202 > cmp absrlo,x ;test result + > trap_ne +3140 : d0fe > bne * ;failed not equal (non zero) + > +3142 : 68 > pla ;load status + > eor_flag 0 +3143 : 4930 > eor #0|fao ;invert expected flags + > +3145 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3148 : d0fe > bne * ;failed not equal (non zero) + > + +314a : ca dex +314b : 10e2 bpl tora2 +314d : a203 ldx #3 +314f : b518 tora3 lda zpOR,x +3151 : 850c sta zpt + set_ax absORa,$ff + > load_flag $ff +3153 : a9ff > lda #$ff ;allow test to change + > +3155 : 48 > pha ;use stack to load status +3156 : bd5602 > lda absORa,x ;precharge accu +3159 : 28 > plp + +315a : 050c ora zpt + tst_ax absrlo,absflo,$ff-fnz +315c : 08 > php ;save flags +315d : dd6202 > cmp absrlo,x ;test result + > trap_ne +3160 : d0fe > bne * ;failed not equal (non zero) + > +3162 : 68 > pla ;load status + > eor_flag $ff-fnz +3163 : 497d > eor #$ff-fnz|fao ;invert expected + > +3165 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3168 : d0fe > bne * ;failed not equal (non zero) + > + +316a : ca dex +316b : 10e2 bpl tora3 + +316d : a203 ldx #3 ;abs +316f : b518 tora4 lda zpOR,x +3171 : 8d0302 sta abst + set_ax absORa,0 + > load_flag 0 +3174 : a900 > lda #0 ;allow test to change I + > +3176 : 48 > pha ;use stack to load status +3177 : bd5602 > lda absORa,x ;precharge accu +317a : 28 > plp + +317b : 0d0302 ora abst + tst_ax absrlo,absflo,0 +317e : 08 > php ;save flags +317f : dd6202 > cmp absrlo,x ;test result + > trap_ne +3182 : d0fe > bne * ;failed not equal (non zero) + > +3184 : 68 > pla ;load status + > eor_flag 0 +3185 : 4930 > eor #0|fao ;invert expected flags + > +3187 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +318a : d0fe > bne * ;failed not equal (non zero) + > + +318c : ca dex +318d : 10e0 bpl tora4 +318f : a203 ldx #3 +3191 : b518 tora5 lda zpOR,x +3193 : 8d0302 sta abst + set_ax absORa,$ff + > load_flag $ff +3196 : a9ff > lda #$ff ;allow test to change + > +3198 : 48 > pha ;use stack to load status +3199 : bd5602 > lda absORa,x ;precharge accu +319c : 28 > plp + +319d : 0d0302 ora abst + tst_ax absrlo,absflo,$ff-fnz +31a0 : 08 > php ;save flags +31a1 : dd6202 > cmp absrlo,x ;test result + > trap_ne +31a4 : d0fe > bne * ;failed not equal (non zero) + > +31a6 : 68 > pla ;load status + > eor_flag $ff-fnz +31a7 : 497d > eor #$ff-fnz|fao ;invert expected + > +31a9 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +31ac : d0fe > bne * ;failed not equal (non zero) + > + +31ae : ca dex +31af : 1002 bpl tora6 + +31b1 : a203 ldx #3 ;zp,x +31b3 : tora6 + set_ax absORa,0 + > load_flag 0 +31b3 : a900 > lda #0 ;allow test to change I + > +31b5 : 48 > pha ;use stack to load status +31b6 : bd5602 > lda absORa,x ;precharge accu +31b9 : 28 > plp + +31ba : 1518 ora zpOR,x + tst_ax absrlo,absflo,0 +31bc : 08 > php ;save flags +31bd : dd6202 > cmp absrlo,x ;test result + > trap_ne +31c0 : d0fe > bne * ;failed not equal (non zero) + > +31c2 : 68 > pla ;load status + > eor_flag 0 +31c3 : 4930 > eor #0|fao ;invert expected flags + > +31c5 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +31c8 : d0fe > bne * ;failed not equal (non zero) + > + +31ca : ca dex +31cb : 10e6 bpl tora6 +31cd : a203 ldx #3 +31cf : tora7 + set_ax absORa,$ff + > load_flag $ff +31cf : a9ff > lda #$ff ;allow test to change + > +31d1 : 48 > pha ;use stack to load status +31d2 : bd5602 > lda absORa,x ;precharge accu +31d5 : 28 > plp + +31d6 : 1518 ora zpOR,x + tst_ax absrlo,absflo,$ff-fnz +31d8 : 08 > php ;save flags +31d9 : dd6202 > cmp absrlo,x ;test result + > trap_ne +31dc : d0fe > bne * ;failed not equal (non zero) + > +31de : 68 > pla ;load status + > eor_flag $ff-fnz +31df : 497d > eor #$ff-fnz|fao ;invert expected + > +31e1 : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +31e4 : d0fe > bne * ;failed not equal (non zero) + > + +31e6 : ca dex +31e7 : 10e6 bpl tora7 + +31e9 : a203 ldx #3 ;abs,x +31eb : tora8 + set_ax absORa,0 + > load_flag 0 +31eb : a900 > lda #0 ;allow test to change I + > +31ed : 48 > pha ;use stack to load status +31ee : bd5602 > lda absORa,x ;precharge accu +31f1 : 28 > plp + +31f2 : 1d4a02 ora absOR,x + tst_ax absrlo,absflo,0 +31f5 : 08 > php ;save flags +31f6 : dd6202 > cmp absrlo,x ;test result + > trap_ne +31f9 : d0fe > bne * ;failed not equal (non zero) + > +31fb : 68 > pla ;load status + > eor_flag 0 +31fc : 4930 > eor #0|fao ;invert expected flags + > +31fe : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +3201 : d0fe > bne * ;failed not equal (non zero) + > + +3203 : ca dex +3204 : 10e5 bpl tora8 +3206 : a203 ldx #3 +3208 : tora9 + set_ax absORa,$ff + > load_flag $ff +3208 : a9ff > lda #$ff ;allow test to change + > +320a : 48 > pha ;use stack to load status +320b : bd5602 > lda absORa,x ;precharge accu +320e : 28 > plp + +320f : 1d4a02 ora absOR,x + tst_ax absrlo,absflo,$ff-fnz +3212 : 08 > php ;save flags +3213 : dd6202 > cmp absrlo,x ;test result + > trap_ne +3216 : d0fe > bne * ;failed not equal (non zero) + > +3218 : 68 > pla ;load status + > eor_flag $ff-fnz +3219 : 497d > eor #$ff-fnz|fao ;invert expected + > +321b : dd6602 > cmp absflo,x ;test flags + > trap_ne ; +321e : d0fe > bne * ;failed not equal (non zero) + > + +3220 : ca dex +3221 : 10e5 bpl tora9 + +3223 : a003 ldy #3 ;abs,y +3225 : tora10 + set_ay absORa,0 + > load_flag 0 +3225 : a900 > lda #0 ;allow test to change I + > +3227 : 48 > pha ;use stack to load status +3228 : b95602 > lda absORa,y ;precharge accu +322b : 28 > plp + +322c : 194a02 ora absOR,y + tst_ay absrlo,absflo,0 +322f : 08 > php ;save flags +3230 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3233 : d0fe > bne * ;failed not equal (non zero) + > +3235 : 68 > pla ;load status + > eor_flag 0 +3236 : 4930 > eor #0|fao ;invert expected flags + > +3238 : d96602 > cmp absflo,y ;test flags + > trap_ne +323b : d0fe > bne * ;failed not equal (non zero) + > + +323d : 88 dey +323e : 10e5 bpl tora10 +3240 : a003 ldy #3 +3242 : tora11 + set_ay absORa,$ff + > load_flag $ff +3242 : a9ff > lda #$ff ;allow test to change + > +3244 : 48 > pha ;use stack to load status +3245 : b95602 > lda absORa,y ;precharge accu +3248 : 28 > plp + +3249 : 194a02 ora absOR,y + tst_ay absrlo,absflo,$ff-fnz +324c : 08 > php ;save flags +324d : d96202 > cmp absrlo,y ;test result + > trap_ne ; +3250 : d0fe > bne * ;failed not equal (non zero) + > +3252 : 68 > pla ;load status + > eor_flag $ff-fnz +3253 : 497d > eor #$ff-fnz|fao ;invert expected + > +3255 : d96602 > cmp absflo,y ;test flags + > trap_ne +3258 : d0fe > bne * ;failed not equal (non zero) + > + +325a : 88 dey +325b : 10e5 bpl tora11 + +325d : a206 ldx #6 ;(zp,x) +325f : a003 ldy #3 +3261 : tora12 + set_ay absORa,0 + > load_flag 0 +3261 : a900 > lda #0 ;allow test to change I + > +3263 : 48 > pha ;use stack to load status +3264 : b95602 > lda absORa,y ;precharge accu +3267 : 28 > plp + +3268 : 014a ora (indOR,x) + tst_ay absrlo,absflo,0 +326a : 08 > php ;save flags +326b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +326e : d0fe > bne * ;failed not equal (non zero) + > +3270 : 68 > pla ;load status + > eor_flag 0 +3271 : 4930 > eor #0|fao ;invert expected flags + > +3273 : d96602 > cmp absflo,y ;test flags + > trap_ne +3276 : d0fe > bne * ;failed not equal (non zero) + > + +3278 : ca dex +3279 : ca dex +327a : 88 dey +327b : 10e4 bpl tora12 +327d : a206 ldx #6 +327f : a003 ldy #3 +3281 : tora13 + set_ay absORa,$ff + > load_flag $ff +3281 : a9ff > lda #$ff ;allow test to change + > +3283 : 48 > pha ;use stack to load status +3284 : b95602 > lda absORa,y ;precharge accu +3287 : 28 > plp + +3288 : 014a ora (indOR,x) + tst_ay absrlo,absflo,$ff-fnz +328a : 08 > php ;save flags +328b : d96202 > cmp absrlo,y ;test result + > trap_ne ; +328e : d0fe > bne * ;failed not equal (non zero) + > +3290 : 68 > pla ;load status + > eor_flag $ff-fnz +3291 : 497d > eor #$ff-fnz|fao ;invert expected + > +3293 : d96602 > cmp absflo,y ;test flags + > trap_ne +3296 : d0fe > bne * ;failed not equal (non zero) + > + +3298 : ca dex +3299 : ca dex +329a : 88 dey +329b : 10e4 bpl tora13 + +329d : a003 ldy #3 ;(zp),y +329f : tora14 + set_ay absORa,0 + > load_flag 0 +329f : a900 > lda #0 ;allow test to change I + > +32a1 : 48 > pha ;use stack to load status +32a2 : b95602 > lda absORa,y ;precharge accu +32a5 : 28 > plp + +32a6 : 114a ora (indOR),y + tst_ay absrlo,absflo,0 +32a8 : 08 > php ;save flags +32a9 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +32ac : d0fe > bne * ;failed not equal (non zero) + > +32ae : 68 > pla ;load status + > eor_flag 0 +32af : 4930 > eor #0|fao ;invert expected flags + > +32b1 : d96602 > cmp absflo,y ;test flags + > trap_ne +32b4 : d0fe > bne * ;failed not equal (non zero) + > + +32b6 : 88 dey +32b7 : 10e6 bpl tora14 +32b9 : a003 ldy #3 +32bb : tora15 + set_ay absORa,$ff + > load_flag $ff +32bb : a9ff > lda #$ff ;allow test to change + > +32bd : 48 > pha ;use stack to load status +32be : b95602 > lda absORa,y ;precharge accu +32c1 : 28 > plp + +32c2 : 114a ora (indOR),y + tst_ay absrlo,absflo,$ff-fnz +32c4 : 08 > php ;save flags +32c5 : d96202 > cmp absrlo,y ;test result + > trap_ne ; +32c8 : d0fe > bne * ;failed not equal (non zero) + > +32ca : 68 > pla ;load status + > eor_flag $ff-fnz +32cb : 497d > eor #$ff-fnz|fao ;invert expected + > +32cd : d96602 > cmp absflo,y ;test flags + > trap_ne +32d0 : d0fe > bne * ;failed not equal (non zero) + > + +32d2 : 88 dey +32d3 : 10e6 bpl tora15 + if I_flag = 3 +32d5 : 58 cli + endif + next_test +32d6 : ad0002 > lda test_case ;previous test +32d9 : c928 > cmp #test_num + > trap_ne ;test is out of sequence +32db : d0fe > bne * ;failed not equal (non zero) + > +0029 = >test_num = test_num + 1 +32dd : a929 > lda #test_num ;*** next tests' number +32df : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; full binary add/subtract test + ; iterates through all combinations of operands and ca + ; uses increments/decrements to predict result & resul +32e2 : d8 cld +32e3 : a20e ldx #ad2 ;for indexed test +32e5 : a0ff ldy #$ff ;max range +32e7 : a900 lda #0 ;start with adding zeroes & no +32e9 : 850c sta adfc ;carry in - for diag +32eb : 850d sta ad1 ;operand 1 - accumulator +32ed : 850e sta ad2 ;operand 2 - memory or immedia +32ef : 8d0302 sta ada2 ;non zp +32f2 : 850f sta adrl ;expected result bits 0-7 +32f4 : 8510 sta adrh ;expected result bit 8 (carry +32f6 : a9ff lda #$ff ;complemented operand 2 for su +32f8 : 8512 sta sb2 +32fa : 8d0402 sta sba2 ;non zp +32fd : a902 lda #2 ;expected Z-flag +32ff : 8511 sta adrf +3301 : 18 tadd clc ;test with carry clear +3302 : 207c35 jsr chkadd +3305 : e60c inc adfc ;now with carry +3307 : e60f inc adrl ;result +1 +3309 : 08 php ;save N & Z from low result +330a : 08 php +330b : 68 pla ;accu holds expected flags +330c : 2982 and #$82 ;mask N & Z +330e : 28 plp +330f : d002 bne tadd1 +3311 : e610 inc adrh ;result bit 8 - carry +3313 : 0510 tadd1 ora adrh ;merge C to expected flags +3315 : 8511 sta adrf ;save expected flags except ov +3317 : 38 sec ;test with carry set +3318 : 207c35 jsr chkadd +331b : c60c dec adfc ;same for operand +1 but no ca +331d : e60d inc ad1 +331f : d0e0 bne tadd ;iterate op1 +3321 : a900 lda #0 ;preset result to op2 when op1 +3323 : 8510 sta adrh +3325 : ee0302 inc ada2 +3328 : e60e inc ad2 +332a : 08 php ;save NZ as operand 2 becomes +332b : 68 pla +332c : 2982 and #$82 ;mask N00000Z0 +332e : 8511 sta adrf ;no need to check carry as we +3330 : c612 dec sb2 ;complement subtract operand 2 +3332 : ce0402 dec sba2 +3335 : a50e lda ad2 +3337 : 850f sta adrl +3339 : d0c6 bne tadd ;iterate op2 + if disable_decimal < 1 + next_test +333b : ad0002 > lda test_case ;previous test +333e : c929 > cmp #test_num + > trap_ne ;test is out of sequence +3340 : d0fe > bne * ;failed not equal (non zero) + > +002a = >test_num = test_num + 1 +3342 : a92a > lda #test_num ;*** next tests' number +3344 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; decimal add/subtract test + ; *** WARNING - tests documented behavior only! *** + ; only valid BCD operands are tested, N V Z flags ar + ; iterates through all valid combinations of operands + ; uses increments/decrements to predict result & carry +3347 : f8 sed +3348 : a20e ldx #ad2 ;for indexed test +334a : a0ff ldy #$ff ;max range +334c : a999 lda #$99 ;start with adding 99 to 99 wi +334e : 850d sta ad1 ;operand 1 - accumulator +3350 : 850e sta ad2 ;operand 2 - memory or immedia +3352 : 8d0302 sta ada2 ;non zp +3355 : 850f sta adrl ;expected result bits 0-7 +3357 : a901 lda #1 ;set carry in & out +3359 : 850c sta adfc ;carry in - for diag +335b : 8510 sta adrh ;expected result bit 8 (carry +335d : a900 lda #0 ;complemented operand 2 for su +335f : 8512 sta sb2 +3361 : 8d0402 sta sba2 ;non zp +3364 : 38 tdad sec ;test with carry set +3365 : 204934 jsr chkdad +3368 : c60c dec adfc ;now with carry clear +336a : a50f lda adrl ;decimal adjust result +336c : d008 bne tdad1 ;skip clear carry & preset res +336e : c610 dec adrh +3370 : a999 lda #$99 +3372 : 850f sta adrl +3374 : d012 bne tdad3 +3376 : 290f tdad1 and #$f ;lower nibble mask +3378 : d00c bne tdad2 ;no decimal adjust needed +337a : c60f dec adrl ;decimal adjust (?0-6) +337c : c60f dec adrl +337e : c60f dec adrl +3380 : c60f dec adrl +3382 : c60f dec adrl +3384 : c60f dec adrl +3386 : c60f tdad2 dec adrl ;result -1 +3388 : 18 tdad3 clc ;test with carry clear +3389 : 204934 jsr chkdad +338c : e60c inc adfc ;same for operand -1 but with +338e : a50d lda ad1 ;decimal adjust operand 1 +3390 : f015 beq tdad5 ;iterate operand 2 +3392 : 290f and #$f ;lower nibble mask +3394 : d00c bne tdad4 ;skip decimal adjust +3396 : c60d dec ad1 ;decimal adjust (?0-6) +3398 : c60d dec ad1 +339a : c60d dec ad1 +339c : c60d dec ad1 +339e : c60d dec ad1 +33a0 : c60d dec ad1 +33a2 : c60d tdad4 dec ad1 ;operand 1 -1 +33a4 : 4c6433 jmp tdad ;iterate op1 + +33a7 : a999 tdad5 lda #$99 ;precharge op1 max +33a9 : 850d sta ad1 +33ab : a50e lda ad2 ;decimal adjust operand 2 +33ad : f030 beq tdad7 ;end of iteration +33af : 290f and #$f ;lower nibble mask +33b1 : d018 bne tdad6 ;skip decimal adjust +33b3 : c60e dec ad2 ;decimal adjust (?0-6) +33b5 : c60e dec ad2 +33b7 : c60e dec ad2 +33b9 : c60e dec ad2 +33bb : c60e dec ad2 +33bd : c60e dec ad2 +33bf : e612 inc sb2 ;complemented decimal adjust f +33c1 : e612 inc sb2 +33c3 : e612 inc sb2 +33c5 : e612 inc sb2 +33c7 : e612 inc sb2 +33c9 : e612 inc sb2 +33cb : c60e tdad6 dec ad2 ;operand 2 -1 +33cd : e612 inc sb2 ;complemented operand for subt +33cf : a512 lda sb2 +33d1 : 8d0402 sta sba2 ;copy as non zp operand +33d4 : a50e lda ad2 +33d6 : 8d0302 sta ada2 ;copy as non zp operand +33d9 : 850f sta adrl ;new result since op1+carry=00 +33db : e610 inc adrh ;result carry +33dd : d085 bne tdad ;iterate op2 +33df : tdad7 + next_test +33df : ad0002 > lda test_case ;previous test +33e2 : c92a > cmp #test_num + > trap_ne ;test is out of sequence +33e4 : d0fe > bne * ;failed not equal (non zero) + > +002b = >test_num = test_num + 1 +33e6 : a92b > lda #test_num ;*** next tests' number +33e8 : 8d0002 > sta test_case + > ;check_ram ;uncomment to find altere + + + ; decimal/binary switch test + ; tests CLD, SED, PLP, RTI to properly switch between + ; tables +33eb : 18 clc +33ec : d8 cld +33ed : 08 php +33ee : a955 lda #$55 +33f0 : 6955 adc #$55 +33f2 : c9aa cmp #$aa + trap_ne ;expected binary result after +33f4 : d0fe > bne * ;failed not equal (non zero) + +33f6 : 18 clc +33f7 : f8 sed +33f8 : 08 php +33f9 : a955 lda #$55 +33fb : 6955 adc #$55 +33fd : c910 cmp #$10 + trap_ne ;expected decimal result after +33ff : d0fe > bne * ;failed not equal (non zero) + +3401 : d8 cld +3402 : 28 plp +3403 : a955 lda #$55 +3405 : 6955 adc #$55 +3407 : c910 cmp #$10 + trap_ne ;expected decimal result after +3409 : d0fe > bne * ;failed not equal (non zero) + +340b : 28 plp +340c : a955 lda #$55 +340e : 6955 adc #$55 +3410 : c9aa cmp #$aa + trap_ne ;expected binary result after +3412 : d0fe > bne * ;failed not equal (non zero) + +3414 : 18 clc +3415 : a934 lda #hi bin_rti_ret ;emulated interrupt for rt +3417 : 48 pha +3418 : a92f lda #lo bin_rti_ret +341a : 48 pha +341b : 08 php +341c : f8 sed +341d : a934 lda #hi dec_rti_ret ;emulated interrupt for rt +341f : 48 pha +3420 : a926 lda #lo dec_rti_ret +3422 : 48 pha +3423 : 08 php +3424 : d8 cld +3425 : 40 rti +3426 : dec_rti_ret +3426 : a955 lda #$55 +3428 : 6955 adc #$55 +342a : c910 cmp #$10 + trap_ne ;expected decimal result after +342c : d0fe > bne * ;failed not equal (non zero) + +342e : 40 rti +342f : bin_rti_ret +342f : a955 lda #$55 +3431 : 6955 adc #$55 +3433 : c9aa cmp #$aa + trap_ne ;expected binary result after +3435 : d0fe > bne * ;failed not equal (non zero) + + endif + +3437 : ad0002 lda test_case +343a : c92b cmp #test_num + trap_ne ;previous test is out of seque +343c : d0fe > bne * ;failed not equal (non zero) + +343e : a9f0 lda #$f0 ;mark opcode testing complete +3440 : 8d0002 sta test_case + + ; final RAM integrity test + ; verifies that none of the previous tests has alter + ; designated write areas. + check_ram + > ;RAM check disabled - RAM size not set + + ; *** DEBUG INFO *** + ; to debug checksum errors uncomment check_ram in the + ; narrow down the responsible opcode. + ; may give false errors when monitor, OS or other back + ; allowed during previous tests. + + + ; S U C C E S S ************************************** + ; ------------- + success ;if you get here everything we +3443 : 4c4334 > jmp * ;test passed, no errors + + ; ------------- + ; S U C C E S S ************************************** +3446 : 4c0004 jmp start ;run again + + if disable_decimal < 1 + ; core subroutine of the decimal add/subtract test + ; *** WARNING - tests documented behavior only! *** + ; only valid BCD operands are tested, N V Z flags ar + ; iterates through all valid combinations of operands + ; uses increments/decrements to predict result & carry +3449 : chkdad + ; decimal ADC / SBC zp +3449 : 08 php ;save carry for subtract +344a : a50d lda ad1 +344c : 650e adc ad2 ;perform add +344e : 08 php +344f : c50f cmp adrl ;check result + trap_ne ;bad result +3451 : d0fe > bne * ;failed not equal (non zero) + +3453 : 68 pla ;check flags +3454 : 2901 and #1 ;mask carry +3456 : c510 cmp adrh + trap_ne ;bad carry +3458 : d0fe > bne * ;failed not equal (non zero) + +345a : 28 plp +345b : 08 php ;save carry for next add +345c : a50d lda ad1 +345e : e512 sbc sb2 ;perform subtract +3460 : 08 php +3461 : c50f cmp adrl ;check result + trap_ne ;bad result +3463 : d0fe > bne * ;failed not equal (non zero) + +3465 : 68 pla ;check flags +3466 : 2901 and #1 ;mask carry +3468 : c510 cmp adrh + trap_ne ;bad flags +346a : d0fe > bne * ;failed not equal (non zero) + +346c : 28 plp + ; decimal ADC / SBC abs +346d : 08 php ;save carry for subtract +346e : a50d lda ad1 +3470 : 6d0302 adc ada2 ;perform add +3473 : 08 php +3474 : c50f cmp adrl ;check result + trap_ne ;bad result +3476 : d0fe > bne * ;failed not equal (non zero) + +3478 : 68 pla ;check flags +3479 : 2901 and #1 ;mask carry +347b : c510 cmp adrh + trap_ne ;bad carry +347d : d0fe > bne * ;failed not equal (non zero) + +347f : 28 plp +3480 : 08 php ;save carry for next add +3481 : a50d lda ad1 +3483 : ed0402 sbc sba2 ;perform subtract +3486 : 08 php +3487 : c50f cmp adrl ;check result + trap_ne ;bad result +3489 : d0fe > bne * ;failed not equal (non zero) + +348b : 68 pla ;check flags +348c : 2901 and #1 ;mask carry +348e : c510 cmp adrh + trap_ne ;bad carry +3490 : d0fe > bne * ;failed not equal (non zero) + +3492 : 28 plp + ; decimal ADC / SBC # +3493 : 08 php ;save carry for subtract +3494 : a50e lda ad2 +3496 : 8d1202 sta ex_adci+1 ;set ADC # operand +3499 : a50d lda ad1 +349b : 201102 jsr ex_adci ;execute ADC # in RAM +349e : 08 php +349f : c50f cmp adrl ;check result + trap_ne ;bad result +34a1 : d0fe > bne * ;failed not equal (non zero) + +34a3 : 68 pla ;check flags +34a4 : 2901 and #1 ;mask carry +34a6 : c510 cmp adrh + trap_ne ;bad carry +34a8 : d0fe > bne * ;failed not equal (non zero) + +34aa : 28 plp +34ab : 08 php ;save carry for next add +34ac : a512 lda sb2 +34ae : 8d1502 sta ex_sbci+1 ;set SBC # operand +34b1 : a50d lda ad1 +34b3 : 201402 jsr ex_sbci ;execute SBC # in RAM +34b6 : 08 php +34b7 : c50f cmp adrl ;check result + trap_ne ;bad result +34b9 : d0fe > bne * ;failed not equal (non zero) + +34bb : 68 pla ;check flags +34bc : 2901 and #1 ;mask carry +34be : c510 cmp adrh + trap_ne ;bad carry +34c0 : d0fe > bne * ;failed not equal (non zero) + +34c2 : 28 plp + ; decimal ADC / SBC zp,x +34c3 : 08 php ;save carry for subtract +34c4 : a50d lda ad1 +34c6 : 7500 adc 0,x ;perform add +34c8 : 08 php +34c9 : c50f cmp adrl ;check result + trap_ne ;bad result +34cb : d0fe > bne * ;failed not equal (non zero) + +34cd : 68 pla ;check flags +34ce : 2901 and #1 ;mask carry +34d0 : c510 cmp adrh + trap_ne ;bad carry +34d2 : d0fe > bne * ;failed not equal (non zero) + +34d4 : 28 plp +34d5 : 08 php ;save carry for next add +34d6 : a50d lda ad1 +34d8 : f504 sbc sb2-ad2,x ;perform subtract +34da : 08 php +34db : c50f cmp adrl ;check result + trap_ne ;bad result +34dd : d0fe > bne * ;failed not equal (non zero) + +34df : 68 pla ;check flags +34e0 : 2901 and #1 ;mask carry +34e2 : c510 cmp adrh + trap_ne ;bad carry +34e4 : d0fe > bne * ;failed not equal (non zero) + +34e6 : 28 plp + ; decimal ADC / SBC abs,x +34e7 : 08 php ;save carry for subtract +34e8 : a50d lda ad1 +34ea : 7df501 adc ada2-ad2,x ;perform add +34ed : 08 php +34ee : c50f cmp adrl ;check result + trap_ne ;bad result +34f0 : d0fe > bne * ;failed not equal (non zero) + +34f2 : 68 pla ;check flags +34f3 : 2901 and #1 ;mask carry +34f5 : c510 cmp adrh + trap_ne ;bad carry +34f7 : d0fe > bne * ;failed not equal (non zero) + +34f9 : 28 plp +34fa : 08 php ;save carry for next add +34fb : a50d lda ad1 +34fd : fdf601 sbc sba2-ad2,x ;perform subtract +3500 : 08 php +3501 : c50f cmp adrl ;check result + trap_ne ;bad result +3503 : d0fe > bne * ;failed not equal (non zero) + +3505 : 68 pla ;check flags +3506 : 2901 and #1 ;mask carry +3508 : c510 cmp adrh + trap_ne ;bad carry +350a : d0fe > bne * ;failed not equal (non zero) + +350c : 28 plp + ; decimal ADC / SBC abs,y +350d : 08 php ;save carry for subtract +350e : a50d lda ad1 +3510 : 790401 adc ada2-$ff,y ;perform add +3513 : 08 php +3514 : c50f cmp adrl ;check result + trap_ne ;bad result +3516 : d0fe > bne * ;failed not equal (non zero) + +3518 : 68 pla ;check flags +3519 : 2901 and #1 ;mask carry +351b : c510 cmp adrh + trap_ne ;bad carry +351d : d0fe > bne * ;failed not equal (non zero) + +351f : 28 plp +3520 : 08 php ;save carry for next add +3521 : a50d lda ad1 +3523 : f90501 sbc sba2-$ff,y ;perform subtract +3526 : 08 php +3527 : c50f cmp adrl ;check result + trap_ne ;bad result +3529 : d0fe > bne * ;failed not equal (non zero) + +352b : 68 pla ;check flags +352c : 2901 and #1 ;mask carry +352e : c510 cmp adrh + trap_ne ;bad carry +3530 : d0fe > bne * ;failed not equal (non zero) + +3532 : 28 plp + ; decimal ADC / SBC (zp,x) +3533 : 08 php ;save carry for subtract +3534 : a50d lda ad1 +3536 : 6144 adc (lo adi2-ad2,x) ;perform add +3538 : 08 php +3539 : c50f cmp adrl ;check result + trap_ne ;bad result +353b : d0fe > bne * ;failed not equal (non zero) + +353d : 68 pla ;check flags +353e : 2901 and #1 ;mask carry +3540 : c510 cmp adrh + trap_ne ;bad carry +3542 : d0fe > bne * ;failed not equal (non zero) + +3544 : 28 plp +3545 : 08 php ;save carry for next add +3546 : a50d lda ad1 +3548 : e146 sbc (lo sbi2-ad2,x) ;perform subtract +354a : 08 php +354b : c50f cmp adrl ;check result + trap_ne ;bad result +354d : d0fe > bne * ;failed not equal (non zero) + +354f : 68 pla ;check flags +3550 : 2901 and #1 ;mask carry +3552 : c510 cmp adrh + trap_ne ;bad carry +3554 : d0fe > bne * ;failed not equal (non zero) + +3556 : 28 plp + ; decimal ADC / SBC (abs),y +3557 : 08 php ;save carry for subtract +3558 : a50d lda ad1 +355a : 7156 adc (adiy2),y ;perform add +355c : 08 php +355d : c50f cmp adrl ;check result + trap_ne ;bad result +355f : d0fe > bne * ;failed not equal (non zero) + +3561 : 68 pla ;check flags +3562 : 2901 and #1 ;mask carry +3564 : c510 cmp adrh + trap_ne ;bad carry +3566 : d0fe > bne * ;failed not equal (non zero) + +3568 : 28 plp +3569 : 08 php ;save carry for next add +356a : a50d lda ad1 +356c : f158 sbc (sbiy2),y ;perform subtract +356e : 08 php +356f : c50f cmp adrl ;check result + trap_ne ;bad result +3571 : d0fe > bne * ;failed not equal (non zero) + +3573 : 68 pla ;check flags +3574 : 2901 and #1 ;mask carry +3576 : c510 cmp adrh + trap_ne ;bad carry +3578 : d0fe > bne * ;failed not equal (non zero) + +357a : 28 plp +357b : 60 rts + endif + + ; core subroutine of the full binary add/subtract test + ; iterates through all combinations of operands and ca + ; uses increments/decrements to predict result & resul +357c : a511 chkadd lda adrf ;add V-flag if overflow +357e : 2983 and #$83 ;keep N-----ZC / clear V +3580 : 48 pha +3581 : a50d lda ad1 ;test sign unequal between ope +3583 : 450e eor ad2 +3585 : 300a bmi ckad1 ;no overflow possible - operan +3587 : a50d lda ad1 ;test sign equal between opera +3589 : 450f eor adrl +358b : 1004 bpl ckad1 ;no overflow occured - operand +358d : 68 pla +358e : 0940 ora #$40 ;set V +3590 : 48 pha +3591 : 68 ckad1 pla +3592 : 8511 sta adrf ;save expected flags + ; binary ADC / SBC zp +3594 : 08 php ;save carry for subtract +3595 : a50d lda ad1 +3597 : 650e adc ad2 ;perform add +3599 : 08 php +359a : c50f cmp adrl ;check result + trap_ne ;bad result +359c : d0fe > bne * ;failed not equal (non zero) + +359e : 68 pla ;check flags +359f : 29c3 and #$c3 ;mask NV----ZC +35a1 : c511 cmp adrf + trap_ne ;bad flags +35a3 : d0fe > bne * ;failed not equal (non zero) + +35a5 : 28 plp +35a6 : 08 php ;save carry for next add +35a7 : a50d lda ad1 +35a9 : e512 sbc sb2 ;perform subtract +35ab : 08 php +35ac : c50f cmp adrl ;check result + trap_ne ;bad result +35ae : d0fe > bne * ;failed not equal (non zero) + +35b0 : 68 pla ;check flags +35b1 : 29c3 and #$c3 ;mask NV----ZC +35b3 : c511 cmp adrf + trap_ne ;bad flags +35b5 : d0fe > bne * ;failed not equal (non zero) + +35b7 : 28 plp + ; binary ADC / SBC abs +35b8 : 08 php ;save carry for subtract +35b9 : a50d lda ad1 +35bb : 6d0302 adc ada2 ;perform add +35be : 08 php +35bf : c50f cmp adrl ;check result + trap_ne ;bad result +35c1 : d0fe > bne * ;failed not equal (non zero) + +35c3 : 68 pla ;check flags +35c4 : 29c3 and #$c3 ;mask NV----ZC +35c6 : c511 cmp adrf + trap_ne ;bad flags +35c8 : d0fe > bne * ;failed not equal (non zero) + +35ca : 28 plp +35cb : 08 php ;save carry for next add +35cc : a50d lda ad1 +35ce : ed0402 sbc sba2 ;perform subtract +35d1 : 08 php +35d2 : c50f cmp adrl ;check result + trap_ne ;bad result +35d4 : d0fe > bne * ;failed not equal (non zero) + +35d6 : 68 pla ;check flags +35d7 : 29c3 and #$c3 ;mask NV----ZC +35d9 : c511 cmp adrf + trap_ne ;bad flags +35db : d0fe > bne * ;failed not equal (non zero) + +35dd : 28 plp + ; binary ADC / SBC # +35de : 08 php ;save carry for subtract +35df : a50e lda ad2 +35e1 : 8d1202 sta ex_adci+1 ;set ADC # operand +35e4 : a50d lda ad1 +35e6 : 201102 jsr ex_adci ;execute ADC # in RAM +35e9 : 08 php +35ea : c50f cmp adrl ;check result + trap_ne ;bad result +35ec : d0fe > bne * ;failed not equal (non zero) + +35ee : 68 pla ;check flags +35ef : 29c3 and #$c3 ;mask NV----ZC +35f1 : c511 cmp adrf + trap_ne ;bad flags +35f3 : d0fe > bne * ;failed not equal (non zero) + +35f5 : 28 plp +35f6 : 08 php ;save carry for next add +35f7 : a512 lda sb2 +35f9 : 8d1502 sta ex_sbci+1 ;set SBC # operand +35fc : a50d lda ad1 +35fe : 201402 jsr ex_sbci ;execute SBC # in RAM +3601 : 08 php +3602 : c50f cmp adrl ;check result + trap_ne ;bad result +3604 : d0fe > bne * ;failed not equal (non zero) + +3606 : 68 pla ;check flags +3607 : 29c3 and #$c3 ;mask NV----ZC +3609 : c511 cmp adrf + trap_ne ;bad flags +360b : d0fe > bne * ;failed not equal (non zero) + +360d : 28 plp + ; binary ADC / SBC zp,x +360e : 08 php ;save carry for subtract +360f : a50d lda ad1 +3611 : 7500 adc 0,x ;perform add +3613 : 08 php +3614 : c50f cmp adrl ;check result + trap_ne ;bad result +3616 : d0fe > bne * ;failed not equal (non zero) + +3618 : 68 pla ;check flags +3619 : 29c3 and #$c3 ;mask NV----ZC +361b : c511 cmp adrf + trap_ne ;bad flags +361d : d0fe > bne * ;failed not equal (non zero) + +361f : 28 plp +3620 : 08 php ;save carry for next add +3621 : a50d lda ad1 +3623 : f504 sbc sb2-ad2,x ;perform subtract +3625 : 08 php +3626 : c50f cmp adrl ;check result + trap_ne ;bad result +3628 : d0fe > bne * ;failed not equal (non zero) + +362a : 68 pla ;check flags +362b : 29c3 and #$c3 ;mask NV----ZC +362d : c511 cmp adrf + trap_ne ;bad flags +362f : d0fe > bne * ;failed not equal (non zero) + +3631 : 28 plp + ; binary ADC / SBC abs,x +3632 : 08 php ;save carry for subtract +3633 : a50d lda ad1 +3635 : 7df501 adc ada2-ad2,x ;perform add +3638 : 08 php +3639 : c50f cmp adrl ;check result + trap_ne ;bad result +363b : d0fe > bne * ;failed not equal (non zero) + +363d : 68 pla ;check flags +363e : 29c3 and #$c3 ;mask NV----ZC +3640 : c511 cmp adrf + trap_ne ;bad flags +3642 : d0fe > bne * ;failed not equal (non zero) + +3644 : 28 plp +3645 : 08 php ;save carry for next add +3646 : a50d lda ad1 +3648 : fdf601 sbc sba2-ad2,x ;perform subtract +364b : 08 php +364c : c50f cmp adrl ;check result + trap_ne ;bad result +364e : d0fe > bne * ;failed not equal (non zero) + +3650 : 68 pla ;check flags +3651 : 29c3 and #$c3 ;mask NV----ZC +3653 : c511 cmp adrf + trap_ne ;bad flags +3655 : d0fe > bne * ;failed not equal (non zero) + +3657 : 28 plp + ; binary ADC / SBC abs,y +3658 : 08 php ;save carry for subtract +3659 : a50d lda ad1 +365b : 790401 adc ada2-$ff,y ;perform add +365e : 08 php +365f : c50f cmp adrl ;check result + trap_ne ;bad result +3661 : d0fe > bne * ;failed not equal (non zero) + +3663 : 68 pla ;check flags +3664 : 29c3 and #$c3 ;mask NV----ZC +3666 : c511 cmp adrf + trap_ne ;bad flags +3668 : d0fe > bne * ;failed not equal (non zero) + +366a : 28 plp +366b : 08 php ;save carry for next add +366c : a50d lda ad1 +366e : f90501 sbc sba2-$ff,y ;perform subtract +3671 : 08 php +3672 : c50f cmp adrl ;check result + trap_ne ;bad result +3674 : d0fe > bne * ;failed not equal (non zero) + +3676 : 68 pla ;check flags +3677 : 29c3 and #$c3 ;mask NV----ZC +3679 : c511 cmp adrf + trap_ne ;bad flags +367b : d0fe > bne * ;failed not equal (non zero) + +367d : 28 plp + ; binary ADC / SBC (zp,x) +367e : 08 php ;save carry for subtract +367f : a50d lda ad1 +3681 : 6144 adc (lo adi2-ad2,x) ;perform add +3683 : 08 php +3684 : c50f cmp adrl ;check result + trap_ne ;bad result +3686 : d0fe > bne * ;failed not equal (non zero) + +3688 : 68 pla ;check flags +3689 : 29c3 and #$c3 ;mask NV----ZC +368b : c511 cmp adrf + trap_ne ;bad flags +368d : d0fe > bne * ;failed not equal (non zero) + +368f : 28 plp +3690 : 08 php ;save carry for next add +3691 : a50d lda ad1 +3693 : e146 sbc (lo sbi2-ad2,x) ;perform subtract +3695 : 08 php +3696 : c50f cmp adrl ;check result + trap_ne ;bad result +3698 : d0fe > bne * ;failed not equal (non zero) + +369a : 68 pla ;check flags +369b : 29c3 and #$c3 ;mask NV----ZC +369d : c511 cmp adrf + trap_ne ;bad flags +369f : d0fe > bne * ;failed not equal (non zero) + +36a1 : 28 plp + ; binary ADC / SBC (abs),y +36a2 : 08 php ;save carry for subtract +36a3 : a50d lda ad1 +36a5 : 7156 adc (adiy2),y ;perform add +36a7 : 08 php +36a8 : c50f cmp adrl ;check result + trap_ne ;bad result +36aa : d0fe > bne * ;failed not equal (non zero) + +36ac : 68 pla ;check flags +36ad : 29c3 and #$c3 ;mask NV----ZC +36af : c511 cmp adrf + trap_ne ;bad flags +36b1 : d0fe > bne * ;failed not equal (non zero) + +36b3 : 28 plp +36b4 : 08 php ;save carry for next add +36b5 : a50d lda ad1 +36b7 : f158 sbc (sbiy2),y ;perform subtract +36b9 : 08 php +36ba : c50f cmp adrl ;check result + trap_ne ;bad result +36bc : d0fe > bne * ;failed not equal (non zero) + +36be : 68 pla ;check flags +36bf : 29c3 and #$c3 ;mask NV----ZC +36c1 : c511 cmp adrf + trap_ne ;bad flags +36c3 : d0fe > bne * ;failed not equal (non zero) + +36c5 : 28 plp +36c6 : 60 rts + + ; target for the jump absolute test +36c7 : 88 dey +36c8 : 88 dey +36c9 : test_far +36c9 : 08 php ;either SP or Y count will fai +36ca : 88 dey +36cb : 88 dey +36cc : 88 dey +36cd : 28 plp + trap_cs ;flags loaded? +36ce : b0fe > bcs * ;failed carry set + + trap_vs +36d0 : 70fe > bvs * ;failed overflow set + + trap_mi +36d2 : 30fe > bmi * ;failed minus (bit 7 set) + + trap_eq +36d4 : f0fe > beq * ;failed equal (zero) + +36d6 : c946 cmp #'F' ;registers loaded? + trap_ne +36d8 : d0fe > bne * ;failed not equal (non zero) + +36da : e041 cpx #'A' + trap_ne +36dc : d0fe > bne * ;failed not equal (non zero) + +36de : c04f cpy #('R'-3) + trap_ne +36e0 : d0fe > bne * ;failed not equal (non zero) + +36e2 : 48 pha ;save a,x +36e3 : 8a txa +36e4 : 48 pha +36e5 : ba tsx +36e6 : e0fd cpx #$fd ;check SP + trap_ne +36e8 : d0fe > bne * ;failed not equal (non zero) + +36ea : 68 pla ;restore x +36eb : aa tax + set_stat $ff + > load_flag $ff +36ec : a9ff > lda #$ff ;allow test to change + > +36ee : 48 > pha ;use stack to load status +36ef : 28 > plp + +36f0 : 68 pla ;restore a +36f1 : e8 inx ;return registers with modific +36f2 : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 +36f4 : 4c0f09 jmp far_ret + + ; target for the jump indirect test +36f7 : 00 align +36f8 : 0137 ptr_tst_ind dw test_ind +36fa : 6409 ptr_ind_ret dw ind_ret + trap ;runover protection +36fc : 4cfc36 > jmp * ;failed anyway + +36ff : 88 dey +3700 : 88 dey +3701 : test_ind +3701 : 08 php ;either SP or Y count will fai +3702 : 88 dey +3703 : 88 dey +3704 : 88 dey +3705 : 28 plp + trap_cs ;flags loaded? +3706 : b0fe > bcs * ;failed carry set + + trap_vs +3708 : 70fe > bvs * ;failed overflow set + + trap_mi +370a : 30fe > bmi * ;failed minus (bit 7 set) + + trap_eq +370c : f0fe > beq * ;failed equal (zero) + +370e : c949 cmp #'I' ;registers loaded? + trap_ne +3710 : d0fe > bne * ;failed not equal (non zero) + +3712 : e04e cpx #'N' + trap_ne +3714 : d0fe > bne * ;failed not equal (non zero) + +3716 : c041 cpy #('D'-3) + trap_ne +3718 : d0fe > bne * ;failed not equal (non zero) + +371a : 48 pha ;save a,x +371b : 8a txa +371c : 48 pha +371d : ba tsx +371e : e0fd cpx #$fd ;check SP + trap_ne +3720 : d0fe > bne * ;failed not equal (non zero) + +3722 : 68 pla ;restore x +3723 : aa tax + set_stat $ff + > load_flag $ff +3724 : a9ff > lda #$ff ;allow test to change + > +3726 : 48 > pha ;use stack to load status +3727 : 28 > plp + +3728 : 68 pla ;restore a +3729 : e8 inx ;return registers with modific +372a : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 +372c : 6cfa36 jmp (ptr_ind_ret) + trap ;runover protection +372f : 4c2f37 > jmp * ;failed anyway + + + ; target for the jump subroutine test +3732 : 88 dey +3733 : 88 dey +3734 : test_jsr +3734 : 08 php ;either SP or Y count will fai +3735 : 88 dey +3736 : 88 dey +3737 : 88 dey +3738 : 28 plp + trap_cs ;flags loaded? +3739 : b0fe > bcs * ;failed carry set + + trap_vs +373b : 70fe > bvs * ;failed overflow set + + trap_mi +373d : 30fe > bmi * ;failed minus (bit 7 set) + + trap_eq +373f : f0fe > beq * ;failed equal (zero) + +3741 : c94a cmp #'J' ;registers loaded? + trap_ne +3743 : d0fe > bne * ;failed not equal (non zero) + +3745 : e053 cpx #'S' + trap_ne +3747 : d0fe > bne * ;failed not equal (non zero) + +3749 : c04f cpy #('R'-3) + trap_ne +374b : d0fe > bne * ;failed not equal (non zero) + +374d : 48 pha ;save a,x +374e : 8a txa +374f : 48 pha +3750 : ba tsx ;sp -4? (return addr,a,x) +3751 : e0fb cpx #$fb + trap_ne +3753 : d0fe > bne * ;failed not equal (non zero) + +3755 : adff01 lda $1ff ;propper return on stack +3758 : c909 cmp #hi(jsr_ret) + trap_ne +375a : d0fe > bne * ;failed not equal (non zero) + +375c : adfe01 lda $1fe +375f : c99a cmp #lo(jsr_ret) + trap_ne +3761 : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +3763 : a9ff > lda #$ff ;allow test to change + > +3765 : 48 > pha ;use stack to load status +3766 : 28 > plp + +3767 : 68 pla ;pull x,a +3768 : aa tax +3769 : 68 pla +376a : e8 inx ;return registers with modific +376b : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 +376d : 60 rts + trap ;runover protection +376e : 4c6e37 > jmp * ;failed anyway + + + ;trap in case of unexpected IRQ, NMI, BRK, RESET - BRK +3771 : nmi_trap + trap ;check stack for conditions at +3771 : 4c7137 > jmp * ;failed anyway + +3774 : res_trap + trap ;unexpected RESET +3774 : 4c7437 > jmp * ;failed anyway + + +3777 : 88 dey +3778 : 88 dey +3779 : irq_trap ;BRK test or unextpected BRK o +3779 : 08 php ;either SP or Y count will fai +377a : 88 dey +377b : 88 dey +377c : 88 dey + ;next 4 traps could be caused by unexpected BR + ;check stack for BREAK and originating locatio + ;possible jump/branch into weeds (uninitialize +377d : c942 cmp #'B' ;registers loaded? + trap_ne +377f : d0fe > bne * ;failed not equal (non zero) + +3781 : e052 cpx #'R' + trap_ne +3783 : d0fe > bne * ;failed not equal (non zero) + +3785 : c048 cpy #('K'-3) + trap_ne +3787 : d0fe > bne * ;failed not equal (non zero) + +3789 : 850a sta irq_a ;save registers during break t +378b : 860b stx irq_x +378d : ba tsx ;test break on stack +378e : bd0201 lda $102,x + cmp_flag 0 ;break test should have B=1 +3791 : c930 > cmp #(0 |fao)&m8 ;expected flags + + + trap_ne ; - no break flag on stack +3793 : d0fe > bne * ;failed not equal (non zero) + +3795 : 68 pla +3796 : c934 cmp #fai ;should have added interrupt d + trap_ne +3798 : d0fe > bne * ;failed not equal (non zero) + +379a : ba tsx +379b : e0fc cpx #$fc ;sp -3? (return addr, flags) + trap_ne +379d : d0fe > bne * ;failed not equal (non zero) + +379f : adff01 lda $1ff ;propper return on stack +37a2 : c909 cmp #hi(brk_ret) + trap_ne +37a4 : d0fe > bne * ;failed not equal (non zero) + +37a6 : adfe01 lda $1fe +37a9 : c9d1 cmp #lo(brk_ret) + trap_ne +37ab : d0fe > bne * ;failed not equal (non zero) + + set_stat $ff + > load_flag $ff +37ad : a9ff > lda #$ff ;allow test to change + > +37af : 48 > pha ;use stack to load status +37b0 : 28 > plp + +37b1 : a60b ldx irq_x +37b3 : e8 inx ;return registers with modific +37b4 : a50a lda irq_a +37b6 : 49aa eor #$aa ;N=1, V=1, Z=0, C=1 but origin +37b8 : 40 rti + trap ;runover protection +37b9 : 4cb937 > jmp * ;failed anyway + + + if report = 1 + include "report.i65" + endif + + ;copy of data to initialize BSS segment + if load_data_direct != 1 + zp_init + zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT + zp7f_ db $7f ;test pattern for compare + ;logical zeropage operands + zpOR_ db 0,$1f,$71,$80 ;test pattern for OR + zpAN_ db $0f,$ff,$7f,$80 ;test pattern for AND + zpEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR + ;indirect addressing pointers + ind1_ dw abs1 ;indirect pointer to patte + dw abs1+1 + dw abs1+2 + dw abs1+3 + dw abs7f + inw1_ dw abs1-$f8 ;indirect pointer for wrap + indt_ dw abst ;indirect pointer to store + dw abst+1 + dw abst+2 + dw abst+3 + inwt_ dw abst-$f8 ;indirect pointer for wrap + indAN_ dw absAN ;indirect pointer to AND p + dw absAN+1 + dw absAN+2 + dw absAN+3 + indEO_ dw absEO ;indirect pointer to EOR p + dw absEO+1 + dw absEO+2 + dw absEO+3 + indOR_ dw absOR ;indirect pointer to OR pa + dw absOR+1 + dw absOR+2 + dw absOR+3 + ;add/subtract indirect pointers + adi2_ dw ada2 ;indirect pointer to opera + sbi2_ dw sba2 ;indirect pointer to compl + adiy2_ dw ada2-$ff ;with offset for indirect + sbiy2_ dw sba2-$ff + zp_end + if (zp_end - zp_init) != (zp_bss_end - zp_bss) + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and + endif + data_init + ex_and_ and #0 ;execute immediate opcodes + rts + ex_eor_ eor #0 ;execute immediate opcodes + rts + ex_ora_ ora #0 ;execute immediate opcodes + rts + ex_adc_ adc #0 ;execute immediate opcodes + rts + ex_sbc_ sbc #0 ;execute immediate opcodes + rts + abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT + abs7f_ db $7f ;test pattern for compare + ;loads + fLDx_ db fn,fn,0,fz ;expected flags for load + ;shifts + rASL_ ;expected result ASL & ROL + rROL_ db $86,$04,$82,0 ; " + rROLc_ db $87,$05,$83,1 ;expected result ROL +carr + rLSR_ ;expected result LSR & ROR + rROR_ db $61,$41,$20,0 ; " + rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carr + fASL_ ;expected flags for shifts + fROL_ db fnc,fc,fn,fz ;no carry in + fROLc_ db fnc,fc,fn,0 ;carry in + fLSR_ + fROR_ db fc,0,fc,fz ;no carry in + fRORc_ db fnc,fn,fnc,fn ;carry in + ;increments (decrements) + rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/D + fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DE + ;logical memory operand + absOR_ db 0,$1f,$71,$80 ;test pattern for OR + absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND + absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR + ;logical accu operand + absORa_ db 0,$f1,$1f,0 ;test pattern for OR + absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND + absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR + ;logical results + absrlo_ db 0,$ff,$7f,$80 + absflo_ db fz,fn,0,fn + data_end + if (data_end - data_init) != (data_bss_end - data_ + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and + endif + + vec_init + dw nmi_trap + dw res_trap + dw irq_trap + vec_bss equ $fffa + endif ;end of RAM init data + + if (load_data_direct = 1) & (ROM_vectors = 1) +fffa = org $fffa ;vectors +fffa : 7137 dw nmi_trap +fffc : 7437 dw res_trap +fffe : 7937 dw irq_trap + endif + +fffa = end start + +No errors in pass 2. +Wrote binary from address $0000 through $ffff. +Total size 65536 bytes. +Program start address is at $0400 (1024). + \ No newline at end of file diff --git a/6502_functional_test.asm b/6502_functional_test.asm new file mode 100644 index 0000000..17b68c1 --- /dev/null +++ b/6502_functional_test.asm @@ -0,0 +1,6011 @@ +; +; 6 5 0 2 F U N C T I O N A L T E S T +; +; Copyright (C) 2012-2015 Klaus Dormann +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . + + +; This program is designed to test all opcodes of a 6502 emulator using all +; addressing modes with focus on propper setting of the processor status +; register bits. +; +; version 21-oct-2015 +; contact info at http://2m5.de or email K@2m5.de +; +; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/ +; command line switches: -l -m -s2 -w -h0 +; | | | | no page headers in listing +; | | | wide listing (133 char/col) +; | | write intel hex file instead of binary +; | expand macros in listing +; generate pass2 listing +; +; No IO - should be run from a monitor with access to registers. +; To run load intel hex image with a load command, than alter PC to 400 hex +; (code_segment) and enter a go command. +; Loop on program counter determines error or successful completion of test. +; Check listing for relevant traps (jump/branch *). +; Please note that in early tests some instructions will have to be used before +; they are actually tested! +; +; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled. +; Tests documented behavior of the original NMOS 6502 only! No unofficial +; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will +; not be tested. Decimal ops will only be tested with valid BCD operands and +; N V Z flags will be ignored. +; +; Debugging hints: +; Most of the code is written sequentially. if you hit a trap, check the +; immediately preceeding code for the instruction to be tested. Results are +; tested first, flags are checked second by pushing them onto the stack and +; pulling them to the accumulator after the result was checked. The "real" +; flags are no longer valid for the tested instruction at this time! +; If the tested instruction was indexed, the relevant index (X or Y) must +; also be checked. Opposed to the flags, X and Y registers are still valid. +; +; versions: +; 28-jul-2012 1st version distributed for testing +; 29-jul-2012 fixed references to location 0, now #0 +; added license - GPLv3 +; 30-jul-2012 added configuration options +; 01-aug-2012 added trap macro to allow user to change error handling +; 01-dec-2012 fixed trap in branch field must be a branch +; 02-mar-2013 fixed PLA flags not tested +; 19-jul-2013 allowed ROM vectors to be loaded when load_data_direct = 0 +; added test sequence check to detect if tests jump their fence +; 23-jul-2013 added RAM integrity check option +; 16-aug-2013 added error report to standard output option +; 13-dec-2014 added binary/decimal opcode table switch test +; 14-dec-2014 improved relative address test +; 23-aug-2015 added option to disable self modifying tests +; 24-aug-2015 all self modifying immediate opcodes now execute in data RAM +; added small branch offset pretest +; 21-oct-2015 added option to disable decimal mode ADC & SBC tests + + +; C O N F I G U R A T I O N + +;ROM_vectors writable (0=no, 1=yes) +;if ROM vectors can not be used interrupts will not be trapped +;as a consequence BRK can not be tested but will be emulated to test RTI +ROM_vectors = 1 + +;load_data_direct (0=move from code segment, 1=load directly) +;loading directly is preferred but may not be supported by your platform +;0 produces only consecutive object code, 1 is not suitable for a binary image +load_data_direct = 1 + +;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow +;change) 2 requires extra code and is not recommended. SEI & CLI can only be +;tested if you allow changing the interrupt status (I_flag = 3) +I_flag = 3 + +;configure memory - try to stay away from memory used by the system +;zero_page memory start address, $50 (80) consecutive Bytes required +; add 2 if I_flag = 2 +zero_page = $a + +;data_segment memory start address, $6A (106) consecutive Bytes required +data_segment = $200 + if (data_segment & $ff) != 0 + ERROR ERROR ERROR low byte of data_segment MUST be $00 !! + endif + +;code_segment memory start address, 13kB of consecutive space required +; add 2.5 kB if I_flag = 2 +code_segment = $400 + +;self modifying code may be disabled to allow running in ROM +;0=part of the code is self modifying and must reside in RAM +;1=tests disabled: branch range +disable_selfmod = 0 + +;report errors through I/O channel (0=use standard self trap loops, 1=include +;report.i65 as I/O channel, add 3.5 kB) +report = 0 + +;RAM integrity test option. Checks for undesired RAM writes. +;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k) +;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM +ram_top = -1 + +;disable test decimal mode ADC & SBC, 0=enable, 1=disable, +;2=disable including decimal flag in processor status +disable_decimal = 0 + + noopt ;do not take shortcuts + +;macros for error & success traps to allow user modification +;example: +;trap macro +; jsr my_error_handler +; endm +;trap_eq macro +; bne skip\? +; trap ;failed equal (zero) +;skip\? +; endm +; +; my_error_handler should pop the calling address from the stack and report it. +; putting larger portions of code (more than 3 bytes) inside the trap macro +; may lead to branch range problems for some tests. + if report = 0 +trap macro + jmp * ;failed anyway + endm +trap_eq macro + beq * ;failed equal (zero) + endm +trap_ne macro + bne * ;failed not equal (non zero) + endm +trap_cs macro + bcs * ;failed carry set + endm +trap_cc macro + bcc * ;failed carry clear + endm +trap_mi macro + bmi * ;failed minus (bit 7 set) + endm +trap_pl macro + bpl * ;failed plus (bit 7 clear) + endm +trap_vs macro + bvs * ;failed overflow set + endm +trap_vc macro + bvc * ;failed overflow clear + endm +; please observe that during the test the stack gets invalidated +; therefore a RTS inside the success macro is not possible +success macro + jmp * ;test passed, no errors + endm + endif + if report = 1 +trap macro + jsr report_error + endm +trap_eq macro + bne skip\? + trap ;failed equal (zero) +skip\? + endm +trap_ne macro + beq skip\? + trap ;failed not equal (non zero) +skip\? + endm +trap_cs macro + bcc skip\? + trap ;failed carry set +skip\? + endm +trap_cc macro + bcs skip\? + trap ;failed carry clear +skip\? + endm +trap_mi macro + bpl skip\? + trap ;failed minus (bit 7 set) +skip\? + endm +trap_pl macro + bmi skip\? + trap ;failed plus (bit 7 clear) +skip\? + endm +trap_vs macro + bvc skip\? + trap ;failed overflow set +skip\? + endm +trap_vc macro + bvs skip\? + trap ;failed overflow clear +skip\? + endm +; please observe that during the test the stack gets invalidated +; therefore a RTS inside the success macro is not possible +success macro + jsr report_success + endm + endif + + +carry equ %00000001 ;flag bits in status +zero equ %00000010 +intdis equ %00000100 +decmode equ %00001000 +break equ %00010000 +reserv equ %00100000 +overfl equ %01000000 +minus equ %10000000 + +fc equ carry +fz equ zero +fzc equ carry+zero +fv equ overfl +fvz equ overfl+zero +fn equ minus +fnc equ minus+carry +fnz equ minus+zero +fnzc equ minus+zero+carry +fnv equ minus+overfl + +fao equ break+reserv ;bits always on after PHP, BRK +fai equ fao+intdis ;+ forced interrupt disable +faod equ fao+decmode ;+ ignore decimal +faid equ fai+decmode ;+ ignore decimal +m8 equ $ff ;8 bit mask +m8i equ $ff&~intdis ;8 bit mask - interrupt disable + +;macros to allow masking of status bits. +;masking test of decimal bit +;masking of interrupt enable/disable on load and compare +;masking of always on bits after PHP or BRK (unused & break) on compare + if disable_decimal < 2 + if I_flag = 0 +load_flag macro + lda #\1&m8i ;force enable interrupts (mask I) + endm +cmp_flag macro + cmp #(\1|fao)&m8i ;I_flag is always enabled + always on bits + endm +eor_flag macro + eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 1 +load_flag macro + lda #\1|intdis ;force disable interrupts + endm +cmp_flag macro + cmp #(\1|fai)&m8 ;I_flag is always disabled + always on bits + endm +eor_flag macro + eor #(\1|fai) ;invert expected flags + always on bits + I + endm + endif + if I_flag = 2 +load_flag macro + lda #\1 + ora flag_I_on ;restore I-flag + and flag_I_off + endm +cmp_flag macro + eor flag_I_on ;I_flag is never changed + cmp #(\1|fao)&m8i ;expected flags + always on bits, mask I + endm +eor_flag macro + eor flag_I_on ;I_flag is never changed + eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 3 +load_flag macro + lda #\1 ;allow test to change I-flag (no mask) + endm +cmp_flag macro + cmp #(\1|fao)&m8 ;expected flags + always on bits + endm +eor_flag macro + eor #\1|fao ;invert expected flags + always on bits + endm + endif + else + if I_flag = 0 +load_flag macro + lda #\1&m8i ;force enable interrupts (mask I) + endm +cmp_flag macro + ora #decmode ;ignore decimal mode bit + cmp #(\1|faod)&m8i ;I_flag is always enabled + always on bits + endm +eor_flag macro + ora #decmode ;ignore decimal mode bit + eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 1 +load_flag macro + lda #\1|intdis ;force disable interrupts + endm +cmp_flag macro + ora #decmode ;ignore decimal mode bit + cmp #(\1|faid)&m8 ;I_flag is always disabled + always on bits + endm +eor_flag macro + ora #decmode ;ignore decimal mode bit + eor #(\1|faid) ;invert expected flags + always on bits + I + endm + endif + if I_flag = 2 +load_flag macro + lda #\1 + ora flag_I_on ;restore I-flag + and flag_I_off + endm +cmp_flag macro + eor flag_I_on ;I_flag is never changed + ora #decmode ;ignore decimal mode bit + cmp #(\1|faod)&m8i ;expected flags + always on bits, mask I + endm +eor_flag macro + eor flag_I_on ;I_flag is never changed + ora #decmode ;ignore decimal mode bit + eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits + endm + endif + if I_flag = 3 +load_flag macro + lda #\1 ;allow test to change I-flag (no mask) + endm +cmp_flag macro + ora #decmode ;ignore decimal mode bit + cmp #(\1|faod)&m8 ;expected flags + always on bits + endm +eor_flag macro + ora #decmode ;ignore decimal mode bit + eor #\1|faod ;invert expected flags + always on bits + endm + endif + endif + +;macros to set (register|memory|zeropage) & status +set_stat macro ;setting flags in the processor status register + load_flag \1 + pha ;use stack to load status + plp + endm + +set_a macro ;precharging accu & status + load_flag \2 + pha ;use stack to load status + lda #\1 ;precharge accu + plp + endm + +set_x macro ;precharging index & status + load_flag \2 + pha ;use stack to load status + ldx #\1 ;precharge index x + plp + endm + +set_y macro ;precharging index & status + load_flag \2 + pha ;use stack to load status + ldy #\1 ;precharge index y + plp + endm + +set_ax macro ;precharging indexed accu & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;precharge accu + plp + endm + +set_ay macro ;precharging indexed accu & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,y ;precharge accu + plp + endm + +set_z macro ;precharging indexed zp & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to zeropage + sta zpt + plp + endm + +set_zx macro ;precharging zp,x & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to indexed zeropage + sta zpt,x + plp + endm + +set_abs macro ;precharging indexed memory & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to memory + sta abst + plp + endm + +set_absx macro ;precharging abs,x & immediate status + load_flag \2 + pha ;use stack to load status + lda \1,x ;load to indexed memory + sta abst,x + plp + endm + +;macros to test (register|memory|zeropage) & status & (mask) +tst_stat macro ;testing flags in the processor status register + php ;save status + pla ;use stack to retrieve status + pha + cmp_flag \1 + trap_ne + plp ;restore status + endm + +tst_a macro ;testing result in accu & flags + php ;save flags + cmp #\1 ;test result + trap_ne + pla ;load status + pha + cmp_flag \2 + trap_ne + plp ;restore status + endm + +tst_x macro ;testing result in x index & flags + php ;save flags + cpx #\1 ;test result + trap_ne + pla ;load status + pha + cmp_flag \2 + trap_ne + plp ;restore status + endm + +tst_y macro ;testing result in y index & flags + php ;save flags + cpy #\1 ;test result + trap_ne + pla ;load status + pha + cmp_flag \2 + trap_ne + plp ;restore status + endm + +tst_ax macro ;indexed testing result in accu & flags + php ;save flags + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne ; + endm + +tst_ay macro ;indexed testing result in accu & flags + php ;save flags + cmp \1,y ;test result + trap_ne ; + pla ;load status + eor_flag \3 + cmp \2,y ;test flags + trap_ne + endm + +tst_z macro ;indexed testing result in zp & flags + php ;save flags + lda zpt + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +tst_zx macro ;testing result in zp,x & flags + php ;save flags + lda zpt,x + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +tst_abs macro ;indexed testing result in memory & flags + php ;save flags + lda abst + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +tst_absx macro ;testing result in abs,x & flags + php ;save flags + lda abst,x + cmp \1,x ;test result + trap_ne + pla ;load status + eor_flag \3 + cmp \2,x ;test flags + trap_ne + endm + +; RAM integrity test +; verifies that none of the previous tests has altered RAM outside of the +; designated write areas. +; uses zpt word as indirect pointer, zpt+2 word as checksum + if ram_top > -1 +check_ram macro + cld + lda #0 + sta zpt ;set low byte of indirect pointer + sta zpt+3 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write test area +ccs3\? adc zero_page,x + bcc ccs2\? + inc zpt+3 ;carry to high byte + clc +ccs2\? inx + bne ccs3\? + ldx #hi(abs1) ;set high byte of indirect pointer + stx zpt+1 + ldy #lo(abs1) ;data after write & execute test area +ccs5\? adc (zpt),y + bcc ccs4\? + inc zpt+3 ;carry to high byte + clc +ccs4\? iny + bne ccs5\? + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne ccs5\? + sta zpt+2 ;checksum low is + cmp ram_chksm ;checksum low expected + trap_ne ;checksum mismatch + lda zpt+3 ;checksum high is + cmp ram_chksm+1 ;checksum high expected + trap_ne ;checksum mismatch + endm + else +check_ram macro + ;RAM check disabled - RAM size not set + endm + endif + +next_test macro ;make sure, tests don't jump the fence + lda test_case ;previous test + cmp #test_num + trap_ne ;test is out of sequence +test_num = test_num + 1 + lda #test_num ;*** next tests' number + sta test_case + ;check_ram ;uncomment to find altered RAM after each test + endm + + if load_data_direct = 1 + data + else + bss ;uninitialized segment, copy of data at end of code! + endif + org 0 ;edited to load from 0x0000 (was: org zero_page) + ds zero_page ;see above (this line added) +;break test interrupt save +irq_a ds 1 ;a register +irq_x ds 1 ;x register + if I_flag = 2 +;masking for I bit in status +flag_I_on ds 1 ;or mask to load flags +flag_I_off ds 1 ;and mask to load flags + endif +zpt ;5 bytes store/modify test area +;add/subtract operand generation and result/flag prediction +adfc ds 1 ;carry flag before op +ad1 ds 1 ;operand 1 - accumulator +ad2 ds 1 ;operand 2 - memory / immediate +adrl ds 1 ;expected result bits 0-7 +adrh ds 1 ;expected result bit 8 (carry) +adrf ds 1 ;expected flags NV0000ZC (only binary mode) +sb2 ds 1 ;operand 2 complemented for subtract +zp_bss +zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +zp7f db $7f ;test pattern for compare +;logical zeropage operands +zpOR db 0,$1f,$71,$80 ;test pattern for OR +zpAN db $0f,$ff,$7f,$80 ;test pattern for AND +zpEO db $ff,$0f,$8f,$8f ;test pattern for EOR +;indirect addressing pointers +ind1 dw abs1 ;indirect pointer to pattern in absolute memory + dw abs1+1 + dw abs1+2 + dw abs1+3 + dw abs7f +inw1 dw abs1-$f8 ;indirect pointer for wrap-test pattern +indt dw abst ;indirect pointer to store area in absolute memory + dw abst+1 + dw abst+2 + dw abst+3 +inwt dw abst-$f8 ;indirect pointer for wrap-test store +indAN dw absAN ;indirect pointer to AND pattern in absolute memory + dw absAN+1 + dw absAN+2 + dw absAN+3 +indEO dw absEO ;indirect pointer to EOR pattern in absolute memory + dw absEO+1 + dw absEO+2 + dw absEO+3 +indOR dw absOR ;indirect pointer to OR pattern in absolute memory + dw absOR+1 + dw absOR+2 + dw absOR+3 +;add/subtract indirect pointers +adi2 dw ada2 ;indirect pointer to operand 2 in absolute memory +sbi2 dw sba2 ;indirect pointer to complemented operand 2 (SBC) +adiy2 dw ada2-$ff ;with offset for indirect indexed +sbiy2 dw sba2-$ff +zp_bss_end + + org data_segment +test_case ds 1 ;current test number +ram_chksm ds 2 ;checksum for RAM integrity test +;add/subtract operand copy - abs tests write area +abst ;5 bytes store/modify test area +ada2 ds 1 ;operand 2 +sba2 ds 1 ;operand 2 complemented for subtract + ds 3 ;fill remaining bytes +data_bss + if load_data_direct = 1 +ex_andi and #0 ;execute immediate opcodes + rts +ex_eori eor #0 ;execute immediate opcodes + rts +ex_orai ora #0 ;execute immediate opcodes + rts +ex_adci adc #0 ;execute immediate opcodes + rts +ex_sbci sbc #0 ;execute immediate opcodes + rts + else +ex_andi ds 3 +ex_eori ds 3 +ex_orai ds 3 +ex_adci ds 3 +ex_sbci ds 3 + endif +abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +abs7f db $7f ;test pattern for compare +;loads +fLDx db fn,fn,0,fz ;expected flags for load +;shifts +rASL ;expected result ASL & ROL -carry +rROL db $86,$04,$82,0 ; " +rROLc db $87,$05,$83,1 ;expected result ROL +carry +rLSR ;expected result LSR & ROR -carry +rROR db $61,$41,$20,0 ; " +rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carry +fASL ;expected flags for shifts +fROL db fnc,fc,fn,fz ;no carry in +fROLc db fnc,fc,fn,0 ;carry in +fLSR +fROR db fc,0,fc,fz ;no carry in +fRORc db fnc,fn,fnc,fn ;carry in +;increments (decrements) +rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC +fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC +;logical memory operand +absOR db 0,$1f,$71,$80 ;test pattern for OR +absAN db $0f,$ff,$7f,$80 ;test pattern for AND +absEO db $ff,$0f,$8f,$8f ;test pattern for EOR +;logical accu operand +absORa db 0,$f1,$1f,0 ;test pattern for OR +absANa db $f0,$ff,$ff,$ff ;test pattern for AND +absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR +;logical results +absrlo db 0,$ff,$7f,$80 +absflo db fz,fn,0,fn +data_bss_end + + + code + org code_segment +start cld + ldx #$ff + txs + lda #0 ;*** test 0 = initialize + sta test_case +test_num = 0 + +;stop interrupts before initializing BSS + if I_flag = 1 + sei + endif + +;initialize I/O for report channel + if report = 1 + jsr report_init + endif + +;pretest small branch offset + ldx #5 + jmp psb_test +psb_bwok + ldy #5 + bne psb_forw + trap ;branch should be taken + dey ;forward landing zone + dey + dey + dey + dey +psb_forw + dey + dey + dey + dey + dey + beq psb_fwok + trap ;forward offset + + dex ;backward landing zone + dex + dex + dex + dex +psb_back + dex + dex + dex + dex + dex + beq psb_bwok + trap ;backward offset +psb_test + bne psb_back + trap ;branch should be taken +psb_fwok + +;initialize BSS segment + if load_data_direct != 1 + ldx #zp_end-zp_init-1 +ld_zp lda zp_init,x + sta zp_bss,x + dex + bpl ld_zp + ldx #data_end-data_init-1 +ld_data lda data_init,x + sta data_bss,x + dex + bpl ld_data + if ROM_vectors = 1 + ldx #5 +ld_vect lda vec_init,x + sta vec_bss,x + dex + bpl ld_vect + endif + endif + +;retain status of interrupt flag + if I_flag = 2 + php + pla + and #4 ;isolate flag + sta flag_I_on ;or mask + eor #lo(~4) ;reverse + sta flag_I_off ;and mask + endif + +;generate checksum for RAM integrity test + if ram_top > -1 + lda #0 + sta zpt ;set low byte of indirect pointer + sta ram_chksm+1 ;checksum high byte + if disable_selfmod = 0 + sta range_adr ;reset self modifying code + endif + clc + ldx #zp_bss-zero_page ;zeropage - write test area +gcs3 adc zero_page,x + bcc gcs2 + inc ram_chksm+1 ;carry to high byte + clc +gcs2 inx + bne gcs3 + ldx #hi(abs1) ;set high byte of indirect pointer + stx zpt+1 + ldy #lo(abs1) ;data after write & execute test area +gcs5 adc (zpt),y + bcc gcs4 + inc ram_chksm+1 ;carry to high byte + clc +gcs4 iny + bne gcs5 + inx ;advance RAM high address + stx zpt+1 + cpx #ram_top + bne gcs5 + sta ram_chksm ;checksum complete + endif + next_test + + if disable_selfmod = 0 +;testing relative addressing with BEQ + ldy #$fe ;testing maximum range, not -1/-2 (invalid/self adr) +range_loop + dey ;next relative address + tya + tax ;precharge count to end of loop + bpl range_fw ;calculate relative address + clc ;avoid branch self or to relative address of branch + adc #2 + nop ;offset landing zone - tolerate +/-5 offset to branch + nop + nop + nop + nop +range_fw + nop + nop + nop + nop + nop + eor #$7f ;complement except sign + sta range_adr ;load into test target + lda #0 ;should set zero flag in status register + jmp range_op + + dex ; offset landing zone - backward branch too far + dex + dex + dex + dex + ;relative address target field with branch under test in the middle + dex ;-128 - max backward + dex + dex + dex + dex + dex + dex + dex + dex ;-120 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-110 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-100 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-90 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-80 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-70 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-60 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-50 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-40 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-30 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-20 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;-10 + dex + dex + dex + dex + dex + dex + dex ;-3 +range_op ;test target with zero flag=0, z=1 if previous dex +range_adr = *+1 ;modifiable relative address + beq *+64 ;+64 if called without modification + dex ;+0 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+10 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+20 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+30 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+40 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+50 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+60 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+70 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+80 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+90 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+100 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+110 + dex + dex + dex + dex + dex + dex + dex + dex + dex + dex ;+120 + dex + dex + dex + dex + dex + dex + nop ;offset landing zone - forward branch too far + nop + nop + nop + nop + beq range_ok ;+127 - max forward + trap ; bad range + nop ;offset landing zone - tolerate +/-5 offset to branch + nop + nop + nop + nop +range_ok + nop + nop + nop + nop + nop + cpy #0 + beq range_end + jmp range_loop +range_end ;range test successful + endif + next_test + +;partial test BNE & CMP, CPX, CPY immediate + cpy #1 ;testing BNE true + bne test_bne + trap +test_bne + lda #0 + cmp #0 ;test compare immediate + trap_ne + trap_cc + trap_mi + cmp #1 + trap_eq + trap_cs + trap_pl + tax + cpx #0 ;test compare x immediate + trap_ne + trap_cc + trap_mi + cpx #1 + trap_eq + trap_cs + trap_pl + tay + cpy #0 ;test compare y immediate + trap_ne + trap_cc + trap_mi + cpy #1 + trap_eq + trap_cs + trap_pl + next_test +;testing stack operations PHA PHP PLA PLP + + ldx #$ff ;initialize stack + txs + lda #$55 + pha + lda #$aa + pha + cmp $1fe ;on stack ? + trap_ne + tsx + txa ;overwrite accu + cmp #$fd ;sp decremented? + trap_ne + pla + cmp #$aa ;successful retreived from stack? + trap_ne + pla + cmp #$55 + trap_ne + cmp $1ff ;remains on stack? + trap_ne + tsx + cpx #$ff ;sp incremented? + trap_ne + next_test + +;testing branch decisions BPL BMI BVC BVS BCC BCS BNE BEQ + set_stat $ff ;all on + bpl nbr1 ;branches should not be taken + bvc nbr2 + bcc nbr3 + bne nbr4 + bmi br1 ;branches should be taken + trap +br1 bvs br2 + trap +br2 bcs br3 + trap +br3 beq br4 + trap +nbr1 + trap ;previous bpl taken +nbr2 + trap ;previous bvc taken +nbr3 + trap ;previous bcc taken +nbr4 + trap ;previous bne taken +br4 php + tsx + cpx #$fe ;sp after php? + trap_ne + pla + cmp_flag $ff ;returned all flags on? + trap_ne + tsx + cpx #$ff ;sp after php? + trap_ne + set_stat 0 ;all off + bmi nbr11 ;branches should not be taken + bvs nbr12 + bcs nbr13 + beq nbr14 + bpl br11 ;branches should be taken + trap +br11 bvc br12 + trap +br12 bcc br13 + trap +br13 bne br14 + trap +nbr11 + trap ;previous bmi taken +nbr12 + trap ;previous bvs taken +nbr13 + trap ;previous bcs taken +nbr14 + trap ;previous beq taken +br14 php + pla + cmp_flag 0 ;flags off except break (pushed by sw) + reserved? + trap_ne + ;crosscheck flags + set_stat zero + bne brzs1 + beq brzs2 +brzs1 + trap ;branch zero/non zero +brzs2 bcs brzs3 + bcc brzs4 +brzs3 + trap ;branch carry/no carry +brzs4 bmi brzs5 + bpl brzs6 +brzs5 + trap ;branch minus/plus +brzs6 bvs brzs7 + bvc brzs8 +brzs7 + trap ;branch overflow/no overflow +brzs8 + set_stat carry + beq brcs1 + bne brcs2 +brcs1 + trap ;branch zero/non zero +brcs2 bcc brcs3 + bcs brcs4 +brcs3 + trap ;branch carry/no carry +brcs4 bmi brcs5 + bpl brcs6 +brcs5 + trap ;branch minus/plus +brcs6 bvs brcs7 + bvc brcs8 +brcs7 + trap ;branch overflow/no overflow + +brcs8 + set_stat minus + beq brmi1 + bne brmi2 +brmi1 + trap ;branch zero/non zero +brmi2 bcs brmi3 + bcc brmi4 +brmi3 + trap ;branch carry/no carry +brmi4 bpl brmi5 + bmi brmi6 +brmi5 + trap ;branch minus/plus +brmi6 bvs brmi7 + bvc brmi8 +brmi7 + trap ;branch overflow/no overflow +brmi8 + set_stat overfl + beq brvs1 + bne brvs2 +brvs1 + trap ;branch zero/non zero +brvs2 bcs brvs3 + bcc brvs4 +brvs3 + trap ;branch carry/no carry +brvs4 bmi brvs5 + bpl brvs6 +brvs5 + trap ;branch minus/plus +brvs6 bvc brvs7 + bvs brvs8 +brvs7 + trap ;branch overflow/no overflow +brvs8 + set_stat $ff-zero + beq brzc1 + bne brzc2 +brzc1 + trap ;branch zero/non zero +brzc2 bcc brzc3 + bcs brzc4 +brzc3 + trap ;branch carry/no carry +brzc4 bpl brzc5 + bmi brzc6 +brzc5 + trap ;branch minus/plus +brzc6 bvc brzc7 + bvs brzc8 +brzc7 + trap ;branch overflow/no overflow +brzc8 + set_stat $ff-carry + bne brcc1 + beq brcc2 +brcc1 + trap ;branch zero/non zero +brcc2 bcs brcc3 + bcc brcc4 +brcc3 + trap ;branch carry/no carry +brcc4 bpl brcc5 + bmi brcc6 +brcc5 + trap ;branch minus/plus +brcc6 bvc brcc7 + bvs brcc8 +brcc7 + trap ;branch overflow/no overflow +brcc8 + set_stat $ff-minus + bne brpl1 + beq brpl2 +brpl1 + trap ;branch zero/non zero +brpl2 bcc brpl3 + bcs brpl4 +brpl3 + trap ;branch carry/no carry +brpl4 bmi brpl5 + bpl brpl6 +brpl5 + trap ;branch minus/plus +brpl6 bvc brpl7 + bvs brpl8 +brpl7 + trap ;branch overflow/no overflow +brpl8 + set_stat $ff-overfl + bne brvc1 + beq brvc2 +brvc1 + trap ;branch zero/non zero +brvc2 bcc brvc3 + bcs brvc4 +brvc3 + trap ;branch carry/no carry +brvc4 bpl brvc5 + bmi brvc6 +brvc5 + trap ;branch minus/plus +brvc6 bvs brvc7 + bvc brvc8 +brvc7 + trap ;branch overflow/no overflow +brvc8 + next_test + +; test PHA does not alter flags or accumulator but PLA does + ldx #$55 ;x & y protected + ldy #$aa + set_a 1,$ff ;push + pha + tst_a 1,$ff + set_a 0,0 + pha + tst_a 0,0 + set_a $ff,$ff + pha + tst_a $ff,$ff + set_a 1,0 + pha + tst_a 1,0 + set_a 0,$ff + pha + tst_a 0,$ff + set_a $ff,0 + pha + tst_a $ff,0 + set_a 0,$ff ;pull + pla + tst_a $ff,$ff-zero + set_a $ff,0 + pla + tst_a 0,zero + set_a $fe,$ff + pla + tst_a 1,$ff-zero-minus + set_a 0,0 + pla + tst_a $ff,minus + set_a $ff,$ff + pla + tst_a 0,$ff-minus + set_a $fe,0 + pla + tst_a 1,0 + cpx #$55 ;x & y unchanged? + trap_ne + cpy #$aa + trap_ne + next_test + +; partial pretest EOR # + set_a $3c,0 + eor #$c3 + tst_a $ff,fn + set_a $c3,0 + eor #$c3 + tst_a 0,fz + next_test + +; PC modifying instructions except branches (NOP, JMP, JSR, RTS, BRK, RTI) +; testing NOP + ldx #$24 + ldy #$42 + set_a $18,0 + nop + tst_a $18,0 + cpx #$24 + trap_ne + cpy #$42 + trap_ne + ldx #$db + ldy #$bd + set_a $e7,$ff + nop + tst_a $e7,$ff + cpx #$db + trap_ne + cpy #$bd + trap_ne + next_test + +; jump absolute + set_stat $0 + lda #'F' + ldx #'A' + ldy #'R' ;N=0, V=0, Z=0, C=0 + jmp test_far + nop + nop + trap_ne ;runover protection + inx + inx +far_ret + trap_eq ;returned flags OK? + trap_pl + trap_cc + trap_vc + cmp #('F'^$aa) ;returned registers OK? + trap_ne + cpx #('A'+1) + trap_ne + cpy #('R'-3) + trap_ne + dex + iny + iny + iny + eor #$aa ;N=0, V=1, Z=0, C=1 + jmp test_near + nop + nop + trap_ne ;runover protection + inx + inx +test_near + trap_eq ;passed flags OK? + trap_mi + trap_cc + trap_vc + cmp #'F' ;passed registers OK? + trap_ne + cpx #'A' + trap_ne + cpy #'R' + trap_ne + next_test + +; jump indirect + set_stat 0 + lda #'I' + ldx #'N' + ldy #'D' ;N=0, V=0, Z=0, C=0 + jmp (ptr_tst_ind) + nop + trap_ne ;runover protection + dey + dey +ind_ret + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_eq ;returned flags OK? + trap_pl + trap_cc + trap_vc + cmp #('I'^$aa) ;returned registers OK? + trap_ne + cpx #('N'+1) + trap_ne + cpy #('D'-6) + trap_ne + tsx ;SP check + cpx #$ff + trap_ne + next_test + +; jump subroutine & return from subroutine + set_stat 0 + lda #'J' + ldx #'S' + ldy #'R' ;N=0, V=0, Z=0, C=0 + jsr test_jsr +jsr_ret = *-1 ;last address of jsr = return address + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_eq ;returned flags OK? + trap_pl + trap_cc + trap_vc + cmp #('J'^$aa) ;returned registers OK? + trap_ne + cpx #('S'+1) + trap_ne + cpy #('R'-6) + trap_ne + tsx ;sp? + cpx #$ff + trap_ne + next_test + +; break & return from interrupt + if ROM_vectors = 1 + set_stat 0 + lda #'B' + ldx #'R' + ldy #'K' ;N=0, V=0, Z=0, C=0 + brk + else + lda #hi brk_ret ;emulated break + pha + lda #lo brk_ret + pha + lda #fao ;set break & unused on stack + pha + set_stat intdis + lda #'B' + ldx #'R' + ldy #'K' ;N=0, V=0, Z=0, C=0 + jmp irq_trap + endif + dey ;should not be executed +brk_ret ;address of break return + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + cmp #('B'^$aa) ;returned registers OK? + trap_ne + cpx #('R'+1) + trap_ne + cpy #('K'-6) + trap_ne + pla ;returned flags OK (unchanged)? + cmp_flag 0 + trap_ne + tsx ;sp? + cpx #$ff + trap_ne + next_test + +; test set and clear flags CLC CLI CLD CLV SEC SEI SED + set_stat $ff + clc + tst_stat $ff-carry + sec + tst_stat $ff + if I_flag = 3 + cli + tst_stat $ff-intdis + sei + tst_stat $ff + endif + cld + tst_stat $ff-decmode + sed + tst_stat $ff + clv + tst_stat $ff-overfl + set_stat 0 + tst_stat 0 + sec + tst_stat carry + clc + tst_stat 0 + if I_flag = 3 + sei + tst_stat intdis + cli + tst_stat 0 + endif + sed + tst_stat decmode + cld + tst_stat 0 + set_stat overfl + tst_stat overfl + clv + tst_stat 0 + next_test +; testing index register increment/decrement and transfer +; INX INY DEX DEY TAX TXA TAY TYA + ldx #$fe + set_stat $ff + inx ;ff + tst_x $ff,$ff-zero + inx ;00 + tst_x 0,$ff-minus + inx ;01 + tst_x 1,$ff-minus-zero + dex ;00 + tst_x 0,$ff-minus + dex ;ff + tst_x $ff,$ff-zero + dex ;fe + set_stat 0 + inx ;ff + tst_x $ff,minus + inx ;00 + tst_x 0,zero + inx ;01 + tst_x 1,0 + dex ;00 + tst_x 0,zero + dex ;ff + tst_x $ff,minus + + ldy #$fe + set_stat $ff + iny ;ff + tst_y $ff,$ff-zero + iny ;00 + tst_y 0,$ff-minus + iny ;01 + tst_y 1,$ff-minus-zero + dey ;00 + tst_y 0,$ff-minus + dey ;ff + tst_y $ff,$ff-zero + dey ;fe + set_stat 0 + iny ;ff + tst_y $ff,0+minus + iny ;00 + tst_y 0,zero + iny ;01 + tst_y 1,0 + dey ;00 + tst_y 0,zero + dey ;ff + tst_y $ff,minus + + ldx #$ff + set_stat $ff + txa + tst_a $ff,$ff-zero + php + inx ;00 + plp + txa + tst_a 0,$ff-minus + php + inx ;01 + plp + txa + tst_a 1,$ff-minus-zero + set_stat 0 + txa + tst_a 1,0 + php + dex ;00 + plp + txa + tst_a 0,zero + php + dex ;ff + plp + txa + tst_a $ff,minus + + ldy #$ff + set_stat $ff + tya + tst_a $ff,$ff-zero + php + iny ;00 + plp + tya + tst_a 0,$ff-minus + php + iny ;01 + plp + tya + tst_a 1,$ff-minus-zero + set_stat 0 + tya + tst_a 1,0 + php + dey ;00 + plp + tya + tst_a 0,zero + php + dey ;ff + plp + tya + tst_a $ff,minus + + load_flag $ff + pha + ldx #$ff ;ff + txa + plp + tay + tst_y $ff,$ff-zero + php + inx ;00 + txa + plp + tay + tst_y 0,$ff-minus + php + inx ;01 + txa + plp + tay + tst_y 1,$ff-minus-zero + load_flag 0 + pha + lda #0 + txa + plp + tay + tst_y 1,0 + php + dex ;00 + txa + plp + tay + tst_y 0,zero + php + dex ;ff + txa + plp + tay + tst_y $ff,minus + + + load_flag $ff + pha + ldy #$ff ;ff + tya + plp + tax + tst_x $ff,$ff-zero + php + iny ;00 + tya + plp + tax + tst_x 0,$ff-minus + php + iny ;01 + tya + plp + tax + tst_x 1,$ff-minus-zero + load_flag 0 + pha + lda #0 ;preset status + tya + plp + tax + tst_x 1,0 + php + dey ;00 + tya + plp + tax + tst_x 0,zero + php + dey ;ff + tya + plp + tax + tst_x $ff,minus + next_test + +;TSX sets NZ - TXS does not +; This section also tests for proper stack wrap around. + ldx #1 ;01 + set_stat $ff + txs + php + lda $101 + cmp_flag $ff + trap_ne + set_stat 0 + txs + php + lda $101 + cmp_flag 0 + trap_ne + dex ;00 + set_stat $ff + txs + php + lda $100 + cmp_flag $ff + trap_ne + set_stat 0 + txs + php + lda $100 + cmp_flag 0 + trap_ne + dex ;ff + set_stat $ff + txs + php + lda $1ff + cmp_flag $ff + trap_ne + set_stat 0 + txs + php + lda $1ff + cmp_flag 0 + + ldx #1 + txs ;sp=01 + set_stat $ff + tsx ;clears Z, N + php ;sp=00 + cpx #1 + trap_ne + lda $101 + cmp_flag $ff-minus-zero + trap_ne + set_stat $ff + tsx ;clears N, sets Z + php ;sp=ff + cpx #0 + trap_ne + lda $100 + cmp_flag $ff-minus + trap_ne + set_stat $ff + tsx ;clears N, sets Z + php ;sp=fe + cpx #$ff + trap_ne + lda $1ff + cmp_flag $ff-zero + trap_ne + + ldx #1 + txs ;sp=01 + set_stat 0 + tsx ;clears Z, N + php ;sp=00 + cpx #1 + trap_ne + lda $101 + cmp_flag 0 + trap_ne + set_stat 0 + tsx ;clears N, sets Z + php ;sp=ff + cpx #0 + trap_ne + lda $100 + cmp_flag zero + trap_ne + set_stat 0 + tsx ;clears N, sets Z + php ;sp=fe + cpx #$ff + trap_ne + lda $1ff + cmp_flag minus + trap_ne + pla ;sp=ff + next_test + +; testing index register load & store LDY LDX STY STX all addressing modes +; LDX / STX - zp,y / abs,y + ldy #3 +tldx + set_stat 0 + ldx zp1,y + php ;test stores do not alter flags + txa + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx + + ldy #3 +tldx1 + set_stat $ff + ldx zp1,y + php ;test stores do not alter flags + txa + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx1 + + ldy #3 +tldx2 + set_stat 0 + ldx abs1,y + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt,y + php ;flags after load/store sequence + eor #$c3 + cmp zp1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx2 + + ldy #3 +tldx3 + set_stat $ff + ldx abs1,y + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt,y + php ;flags after load/store sequence + eor #$c3 + cmp zp1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tldx3 + + ldy #3 ;testing store result + ldx #0 +tstx lda zpt,y + eor #$c3 + cmp zp1,y + trap_ne ;store to zp data + stx zpt,y ;clear + lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstx + next_test + +; indexed wraparound test (only zp should wrap) + ldy #3+$fa +tldx4 ldx zp1-$fa&$ff,y ;wrap on indexed zp + txa + sta abst-$fa,y ;no STX abs,y! + dey + cpy #$fa + bcs tldx4 + ldy #3+$fa +tldx5 ldx abs1-$fa,y ;no wrap on indexed abs + stx zpt-$fa&$ff,y + dey + cpy #$fa + bcs tldx5 + ldy #3 ;testing wraparound result + ldx #0 +tstx1 lda zpt,y + cmp zp1,y + trap_ne ;store to zp data + stx zpt,y ;clear + lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstx1 + next_test + +; LDY / STY - zp,x / abs,x + ldx #3 +tldy + set_stat 0 + ldy zp1,x + php ;test stores do not alter flags + tya + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy + + ldx #3 +tldy1 + set_stat $ff + ldy zp1,x + php ;test stores do not alter flags + tya + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy1 + + ldx #3 +tldy2 + set_stat 0 + ldy abs1,x + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy2 + + ldx #3 +tldy3 + set_stat $ff + ldy abs1,x + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldy3 + + ldx #3 ;testing store result + ldy #0 +tsty lda zpt,x + eor #$c3 + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + eor #$c3 + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tsty + next_test + +; indexed wraparound test (only zp should wrap) + ldx #3+$fa +tldy4 ldy zp1-$fa&$ff,x ;wrap on indexed zp + tya + sta abst-$fa,x ;no STX abs,x! + dex + cpx #$fa + bcs tldy4 + ldx #3+$fa +tldy5 ldy abs1-$fa,x ;no wrap on indexed abs + sty zpt-$fa&$ff,x + dex + cpx #$fa + bcs tldy5 + ldx #3 ;testing wraparound result + ldy #0 +tsty1 lda zpt,x + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tsty1 + next_test + +; LDX / STX - zp / abs / # + set_stat 0 + ldx zp1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$c3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldx zp1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+1 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$82 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldx zp1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+2 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$41 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldx zp1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+3 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #0 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldx zp1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$c3 ;test result + trap_ne ; + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldx zp1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+1 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$82 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldx zp1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+2 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #$41 ;test result + trap_ne ; + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldx zp1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx abst+3 + php ;flags after load/store sequence + eor #$c3 + tax + cpx #0 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + set_stat 0 + ldx abs1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt + php ;flags after load/store sequence + eor #$c3 + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldx abs1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+1 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldx abs1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+2 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldx abs1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+3 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldx abs1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldx abs1+1 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+1 + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldx abs1+2 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+2 + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldx abs1+3 + php ;test stores do not alter flags + txa + eor #$c3 + tax + plp + stx zpt+3 + php ;flags after load/store sequence + eor #$c3 + tax + cpx zp1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + set_stat 0 + ldx #$c3 + php + cpx abs1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldx #$82 + php + cpx abs1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldx #$41 + php + cpx abs1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldx #0 + php + cpx abs1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldx #$c3 + php + cpx abs1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldx #$82 + php + cpx abs1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldx #$41 + php + cpx abs1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldx #0 + php + cpx abs1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + ldx #0 + lda zpt + eor #$c3 + cmp zp1 + trap_ne ;store to zp data + stx zpt ;clear + lda abst + eor #$c3 + cmp abs1 + trap_ne ;store to abs data + stx abst ;clear + lda zpt+1 + eor #$c3 + cmp zp1+1 + trap_ne ;store to zp data + stx zpt+1 ;clear + lda abst+1 + eor #$c3 + cmp abs1+1 + trap_ne ;store to abs data + stx abst+1 ;clear + lda zpt+2 + eor #$c3 + cmp zp1+2 + trap_ne ;store to zp data + stx zpt+2 ;clear + lda abst+2 + eor #$c3 + cmp abs1+2 + trap_ne ;store to abs data + stx abst+2 ;clear + lda zpt+3 + eor #$c3 + cmp zp1+3 + trap_ne ;store to zp data + stx zpt+3 ;clear + lda abst+3 + eor #$c3 + cmp abs1+3 + trap_ne ;store to abs data + stx abst+3 ;clear + next_test + +; LDY / STY - zp / abs / # + set_stat 0 + ldy zp1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$c3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldy zp1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+1 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$82 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldy zp1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+2 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$41 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldy zp1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+3 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #0 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldy zp1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$c3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldy zp1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+1 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$82 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldy zp1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+2 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #$41 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldy zp1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty abst+3 + php ;flags after load/store sequence + eor #$c3 + tay + cpy #0 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + set_stat 0 + ldy abs1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldy abs1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+1 + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldy abs1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+2 + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldy abs1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+3 + php ;flags after load/store sequence + eor #$c3 + tay + cpy zp1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldy abs1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldy abs1+1 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+1 + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldy abs1+2 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+2 + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldy abs1+3 + php ;test stores do not alter flags + tya + eor #$c3 + tay + plp + sty zpt+3 + php ;flags after load/store sequence + eor #$c3 + tay + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + + set_stat 0 + ldy #$c3 + php + cpy abs1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + ldy #$82 + php + cpy abs1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + ldy #$41 + php + cpy abs1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + ldy #0 + php + cpy abs1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + ldy #$c3 + php + cpy abs1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + ldy #$82 + php + cpy abs1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + ldy #$41 + php + cpy abs1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + ldy #0 + php + cpy abs1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + ldy #0 + lda zpt + eor #$c3 + cmp zp1 + trap_ne ;store to zp data + sty zpt ;clear + lda abst + eor #$c3 + cmp abs1 + trap_ne ;store to abs data + sty abst ;clear + lda zpt+1 + eor #$c3 + cmp zp1+1 + trap_ne ;store to zp+1 data + sty zpt+1 ;clear + lda abst+1 + eor #$c3 + cmp abs1+1 + trap_ne ;store to abs+1 data + sty abst+1 ;clear + lda zpt+2 + eor #$c3 + cmp zp1+2 + trap_ne ;store to zp+2 data + sty zpt+2 ;clear + lda abst+2 + eor #$c3 + cmp abs1+2 + trap_ne ;store to abs+2 data + sty abst+2 ;clear + lda zpt+3 + eor #$c3 + cmp zp1+3 + trap_ne ;store to zp+3 data + sty zpt+3 ;clear + lda abst+3 + eor #$c3 + cmp abs1+3 + trap_ne ;store to abs+3 data + sty abst+3 ;clear + next_test + +; testing load / store accumulator LDA / STA all addressing modes +; LDA / STA - zp,x / abs,x + ldx #3 +tldax + set_stat 0 + lda zp1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax + + ldx #3 +tldax1 + set_stat $ff + lda zp1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,x + php ;flags after load/store sequence + eor #$c3 + cmp abs1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax1 + + ldx #3 +tldax2 + set_stat 0 + lda abs1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax2 + + ldx #3 +tldax3 + set_stat $ff + lda abs1,x + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt,x + php ;flags after load/store sequence + eor #$c3 + cmp zp1,x ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,x ;test flags + trap_ne + dex + bpl tldax3 + + ldx #3 ;testing store result + ldy #0 +tstax lda zpt,x + eor #$c3 + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + eor #$c3 + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tstax + next_test + +; LDA / STA - (zp),y / abs,y / (zp,x) + ldy #3 +tlday + set_stat 0 + lda (ind1),y + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday + + ldy #3 +tlday1 + set_stat $ff + lda (ind1),y + php ;test stores do not alter flags + eor #$c3 + plp + sta abst,y + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday1 + + ldy #3 ;testing store result + ldx #0 +tstay lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay + + ldy #3 +tlday2 + set_stat 0 + lda abs1,y + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt),y + php ;flags after load/store sequence + eor #$c3 + cmp (ind1),y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday2 + + ldy #3 +tlday3 + set_stat $ff + lda abs1,y + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt),y + php ;flags after load/store sequence + eor #$c3 + cmp (ind1),y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dey + bpl tlday3 + + ldy #3 ;testing store result + ldx #0 +tstay1 lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay1 + + ldx #6 + ldy #3 +tldax4 + set_stat 0 + lda (ind1,x) + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt,x) + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx,y ;test flags + trap_ne + dex + dex + dey + bpl tldax4 + + ldx #6 + ldy #3 +tldax5 + set_stat $ff + lda (ind1,x) + php ;test stores do not alter flags + eor #$c3 + plp + sta (indt,x) + php ;flags after load/store sequence + eor #$c3 + cmp abs1,y ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx,y ;test flags + trap_ne + dex + dex + dey + bpl tldax5 + + ldy #3 ;testing store result + ldx #0 +tstay2 lda abst,y + eor #$c3 + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay2 + next_test + +; indexed wraparound test (only zp should wrap) + ldx #3+$fa +tldax6 lda zp1-$fa&$ff,x ;wrap on indexed zp + sta abst-$fa,x ;no STX abs,x! + dex + cpx #$fa + bcs tldax6 + ldx #3+$fa +tldax7 lda abs1-$fa,x ;no wrap on indexed abs + sta zpt-$fa&$ff,x + dex + cpx #$fa + bcs tldax7 + + ldx #3 ;testing wraparound result + ldy #0 +tstax1 lda zpt,x + cmp zp1,x + trap_ne ;store to zp,x data + sty zpt,x ;clear + lda abst,x + cmp abs1,x + trap_ne ;store to abs,x data + txa + sta abst,x ;clear + dex + bpl tstax1 + + ldy #3+$f8 + ldx #6+$f8 +tlday4 lda (ind1-$f8&$ff,x) ;wrap on indexed zp indirect + sta abst-$f8,y + dex + dex + dey + cpy #$f8 + bcs tlday4 + ldy #3 ;testing wraparound result + ldx #0 +tstay4 lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay4 + + ldy #3+$f8 +tlday5 lda abs1-$f8,y ;no wrap on indexed abs + sta (inwt),y + dey + cpy #$f8 + bcs tlday5 + ldy #3 ;testing wraparound result + ldx #0 +tstay5 lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay5 + + ldy #3+$f8 + ldx #6+$f8 +tlday6 lda (inw1),y ;no wrap on zp indirect indexed + sta (indt-$f8&$ff,x) + dex + dex + dey + cpy #$f8 + bcs tlday6 + ldy #3 ;testing wraparound result + ldx #0 +tstay6 lda abst,y + cmp abs1,y + trap_ne ;store to abs data + txa + sta abst,y ;clear + dey + bpl tstay6 + next_test + +; LDA / STA - zp / abs / # + set_stat 0 + lda zp1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst + php ;flags after load/store sequence + eor #$c3 + cmp #$c3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + lda zp1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+1 + php ;flags after load/store sequence + eor #$c3 + cmp #$82 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + lda zp1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+2 + php ;flags after load/store sequence + eor #$c3 + cmp #$41 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + lda zp1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+3 + php ;flags after load/store sequence + eor #$c3 + cmp #0 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + set_stat $ff + lda zp1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst + php ;flags after load/store sequence + eor #$c3 + cmp #$c3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + lda zp1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+1 + php ;flags after load/store sequence + eor #$c3 + cmp #$82 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + lda zp1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+2 + php ;flags after load/store sequence + eor #$c3 + cmp #$41 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + lda zp1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta abst+3 + php ;flags after load/store sequence + eor #$c3 + cmp #0 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + set_stat 0 + lda abs1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt + php ;flags after load/store sequence + eor #$c3 + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + lda abs1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+1 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + lda abs1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+2 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + lda abs1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+3 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + set_stat $ff + lda abs1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt + php ;flags after load/store sequence + eor #$c3 + cmp zp1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + lda abs1+1 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+1 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + lda abs1+2 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+2 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + lda abs1+3 + php ;test stores do not alter flags + eor #$c3 + plp + sta zpt+3 + php ;flags after load/store sequence + eor #$c3 + cmp zp1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + set_stat 0 + lda #$c3 + php + cmp abs1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx ;test flags + trap_ne + set_stat 0 + lda #$82 + php + cmp abs1+1 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+1 ;test flags + trap_ne + set_stat 0 + lda #$41 + php + cmp abs1+2 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+2 ;test flags + trap_ne + set_stat 0 + lda #0 + php + cmp abs1+3 ;test result + trap_ne + pla ;load status + eor_flag 0 + cmp fLDx+3 ;test flags + trap_ne + + set_stat $ff + lda #$c3 + php + cmp abs1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx ;test flags + trap_ne + set_stat $ff + lda #$82 + php + cmp abs1+1 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+1 ;test flags + trap_ne + set_stat $ff + lda #$41 + php + cmp abs1+2 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+2 ;test flags + trap_ne + set_stat $ff + lda #0 + php + cmp abs1+3 ;test result + trap_ne + pla ;load status + eor_flag lo~fnz ;mask bits not altered + cmp fLDx+3 ;test flags + trap_ne + + ldx #0 + lda zpt + eor #$c3 + cmp zp1 + trap_ne ;store to zp data + stx zpt ;clear + lda abst + eor #$c3 + cmp abs1 + trap_ne ;store to abs data + stx abst ;clear + lda zpt+1 + eor #$c3 + cmp zp1+1 + trap_ne ;store to zp data + stx zpt+1 ;clear + lda abst+1 + eor #$c3 + cmp abs1+1 + trap_ne ;store to abs data + stx abst+1 ;clear + lda zpt+2 + eor #$c3 + cmp zp1+2 + trap_ne ;store to zp data + stx zpt+2 ;clear + lda abst+2 + eor #$c3 + cmp abs1+2 + trap_ne ;store to abs data + stx abst+2 ;clear + lda zpt+3 + eor #$c3 + cmp zp1+3 + trap_ne ;store to zp data + stx zpt+3 ;clear + lda abst+3 + eor #$c3 + cmp abs1+3 + trap_ne ;store to abs data + stx abst+3 ;clear + next_test + +; testing bit test & compares BIT CPX CPY CMP all addressing modes +; BIT - zp / abs + set_a $ff,0 + bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,fz + set_a 1,0 + bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv + set_a 1,0 + bit zp1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,fnz + set_a 1,0 + bit zp1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,fnv + + set_a $ff,$ff + bit zp1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv + set_a 1,$ff + bit zp1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz + set_a 1,$ff + bit zp1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,~fv + set_a 1,$ff + bit zp1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,~fz + + set_a $ff,0 + bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,fz + set_a 1,0 + bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,fv + set_a 1,0 + bit abs1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,fnz + set_a 1,0 + bit abs1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,fnv + + set_a $ff,$ff + bit abs1+3 ;00 - should set Z / clear NV + tst_a $ff,~fnv + set_a 1,$ff + bit abs1+2 ;41 - should set V (M6) / clear NZ + tst_a 1,~fnz + set_a 1,$ff + bit abs1+1 ;82 - should set N (M7) & Z / clear V + tst_a 1,~fv + set_a 1,$ff + bit abs1 ;c3 - should set N (M7) & V (M6) / clear Z + tst_a 1,~fz + next_test + +; CPX - zp / abs / # + set_x $80,0 + cpx zp7f + tst_stat fc + dex + cpx zp7f + tst_stat fzc + dex + cpx zp7f + tst_x $7e,fn + set_x $80,$ff + cpx zp7f + tst_stat ~fnz + dex + cpx zp7f + tst_stat ~fn + dex + cpx zp7f + tst_x $7e,~fzc + + set_x $80,0 + cpx abs7f + tst_stat fc + dex + cpx abs7f + tst_stat fzc + dex + cpx abs7f + tst_x $7e,fn + set_x $80,$ff + cpx abs7f + tst_stat ~fnz + dex + cpx abs7f + tst_stat ~fn + dex + cpx abs7f + tst_x $7e,~fzc + + set_x $80,0 + cpx #$7f + tst_stat fc + dex + cpx #$7f + tst_stat fzc + dex + cpx #$7f + tst_x $7e,fn + set_x $80,$ff + cpx #$7f + tst_stat ~fnz + dex + cpx #$7f + tst_stat ~fn + dex + cpx #$7f + tst_x $7e,~fzc + next_test + +; CPY - zp / abs / # + set_y $80,0 + cpy zp7f + tst_stat fc + dey + cpy zp7f + tst_stat fzc + dey + cpy zp7f + tst_y $7e,fn + set_y $80,$ff + cpy zp7f + tst_stat ~fnz + dey + cpy zp7f + tst_stat ~fn + dey + cpy zp7f + tst_y $7e,~fzc + + set_y $80,0 + cpy abs7f + tst_stat fc + dey + cpy abs7f + tst_stat fzc + dey + cpy abs7f + tst_y $7e,fn + set_y $80,$ff + cpy abs7f + tst_stat ~fnz + dey + cpy abs7f + tst_stat ~fn + dey + cpy abs7f + tst_y $7e,~fzc + + set_y $80,0 + cpy #$7f + tst_stat fc + dey + cpy #$7f + tst_stat fzc + dey + cpy #$7f + tst_y $7e,fn + set_y $80,$ff + cpy #$7f + tst_stat ~fnz + dey + cpy #$7f + tst_stat ~fn + dey + cpy #$7f + tst_y $7e,~fzc + next_test + +; CMP - zp / abs / # + set_a $80,0 + cmp zp7f + tst_a $80,fc + set_a $7f,0 + cmp zp7f + tst_a $7f,fzc + set_a $7e,0 + cmp zp7f + tst_a $7e,fn + set_a $80,$ff + cmp zp7f + tst_a $80,~fnz + set_a $7f,$ff + cmp zp7f + tst_a $7f,~fn + set_a $7e,$ff + cmp zp7f + tst_a $7e,~fzc + + set_a $80,0 + cmp abs7f + tst_a $80,fc + set_a $7f,0 + cmp abs7f + tst_a $7f,fzc + set_a $7e,0 + cmp abs7f + tst_a $7e,fn + set_a $80,$ff + cmp abs7f + tst_a $80,~fnz + set_a $7f,$ff + cmp abs7f + tst_a $7f,~fn + set_a $7e,$ff + cmp abs7f + tst_a $7e,~fzc + + set_a $80,0 + cmp #$7f + tst_a $80,fc + set_a $7f,0 + cmp #$7f + tst_a $7f,fzc + set_a $7e,0 + cmp #$7f + tst_a $7e,fn + set_a $80,$ff + cmp #$7f + tst_a $80,~fnz + set_a $7f,$ff + cmp #$7f + tst_a $7f,~fn + set_a $7e,$ff + cmp #$7f + tst_a $7e,~fzc + + ldx #4 ;with indexing by X + set_a $80,0 + cmp zp1,x + tst_a $80,fc + set_a $7f,0 + cmp zp1,x + tst_a $7f,fzc + set_a $7e,0 + cmp zp1,x + tst_a $7e,fn + set_a $80,$ff + cmp zp1,x + tst_a $80,~fnz + set_a $7f,$ff + cmp zp1,x + tst_a $7f,~fn + set_a $7e,$ff + cmp zp1,x + tst_a $7e,~fzc + + set_a $80,0 + cmp abs1,x + tst_a $80,fc + set_a $7f,0 + cmp abs1,x + tst_a $7f,fzc + set_a $7e,0 + cmp abs1,x + tst_a $7e,fn + set_a $80,$ff + cmp abs1,x + tst_a $80,~fnz + set_a $7f,$ff + cmp abs1,x + tst_a $7f,~fn + set_a $7e,$ff + cmp abs1,x + tst_a $7e,~fzc + + ldy #4 ;with indexing by Y + ldx #8 ;with indexed indirect + set_a $80,0 + cmp abs1,y + tst_a $80,fc + set_a $7f,0 + cmp abs1,y + tst_a $7f,fzc + set_a $7e,0 + cmp abs1,y + tst_a $7e,fn + set_a $80,$ff + cmp abs1,y + tst_a $80,~fnz + set_a $7f,$ff + cmp abs1,y + tst_a $7f,~fn + set_a $7e,$ff + cmp abs1,y + tst_a $7e,~fzc + + set_a $80,0 + cmp (ind1,x) + tst_a $80,fc + set_a $7f,0 + cmp (ind1,x) + tst_a $7f,fzc + set_a $7e,0 + cmp (ind1,x) + tst_a $7e,fn + set_a $80,$ff + cmp (ind1,x) + tst_a $80,~fnz + set_a $7f,$ff + cmp (ind1,x) + tst_a $7f,~fn + set_a $7e,$ff + cmp (ind1,x) + tst_a $7e,~fzc + + set_a $80,0 + cmp (ind1),y + tst_a $80,fc + set_a $7f,0 + cmp (ind1),y + tst_a $7f,fzc + set_a $7e,0 + cmp (ind1),y + tst_a $7e,fn + set_a $80,$ff + cmp (ind1),y + tst_a $80,~fnz + set_a $7f,$ff + cmp (ind1),y + tst_a $7f,~fn + set_a $7e,$ff + cmp (ind1),y + tst_a $7e,~fzc + next_test + +; testing shifts - ASL LSR ROL ROR all addressing modes +; shifts - accumulator + ldx #3 +tasl + set_ax zp1,0 + asl a + tst_ax rASL,fASL,0 + dex + bpl tasl + ldx #3 +tasl1 + set_ax zp1,$ff + asl a + tst_ax rASL,fASL,$ff-fnzc + dex + bpl tasl1 + + ldx #3 +tlsr + set_ax zp1,0 + lsr a + tst_ax rLSR,fLSR,0 + dex + bpl tlsr + ldx #3 +tlsr1 + set_ax zp1,$ff + lsr a + tst_ax rLSR,fLSR,$ff-fnzc + dex + bpl tlsr1 + + ldx #3 +trol + set_ax zp1,0 + rol a + tst_ax rROL,fROL,0 + dex + bpl trol + ldx #3 +trol1 + set_ax zp1,$ff-fc + rol a + tst_ax rROL,fROL,$ff-fnzc + dex + bpl trol1 + + ldx #3 +trolc + set_ax zp1,fc + rol a + tst_ax rROLc,fROLc,0 + dex + bpl trolc + ldx #3 +trolc1 + set_ax zp1,$ff + rol a + tst_ax rROLc,fROLc,$ff-fnzc + dex + bpl trolc1 + + ldx #3 +tror + set_ax zp1,0 + ror a + tst_ax rROR,fROR,0 + dex + bpl tror + ldx #3 +tror1 + set_ax zp1,$ff-fc + ror a + tst_ax rROR,fROR,$ff-fnzc + dex + bpl tror1 + + ldx #3 +trorc + set_ax zp1,fc + ror a + tst_ax rRORc,fRORc,0 + dex + bpl trorc + ldx #3 +trorc1 + set_ax zp1,$ff + ror a + tst_ax rRORc,fRORc,$ff-fnzc + dex + bpl trorc1 + next_test + +; shifts - zeropage + ldx #3 +tasl2 + set_z zp1,0 + asl zpt + tst_z rASL,fASL,0 + dex + bpl tasl2 + ldx #3 +tasl3 + set_z zp1,$ff + asl zpt + tst_z rASL,fASL,$ff-fnzc + dex + bpl tasl3 + + ldx #3 +tlsr2 + set_z zp1,0 + lsr zpt + tst_z rLSR,fLSR,0 + dex + bpl tlsr2 + ldx #3 +tlsr3 + set_z zp1,$ff + lsr zpt + tst_z rLSR,fLSR,$ff-fnzc + dex + bpl tlsr3 + + ldx #3 +trol2 + set_z zp1,0 + rol zpt + tst_z rROL,fROL,0 + dex + bpl trol2 + ldx #3 +trol3 + set_z zp1,$ff-fc + rol zpt + tst_z rROL,fROL,$ff-fnzc + dex + bpl trol3 + + ldx #3 +trolc2 + set_z zp1,fc + rol zpt + tst_z rROLc,fROLc,0 + dex + bpl trolc2 + ldx #3 +trolc3 + set_z zp1,$ff + rol zpt + tst_z rROLc,fROLc,$ff-fnzc + dex + bpl trolc3 + + ldx #3 +tror2 + set_z zp1,0 + ror zpt + tst_z rROR,fROR,0 + dex + bpl tror2 + ldx #3 +tror3 + set_z zp1,$ff-fc + ror zpt + tst_z rROR,fROR,$ff-fnzc + dex + bpl tror3 + + ldx #3 +trorc2 + set_z zp1,fc + ror zpt + tst_z rRORc,fRORc,0 + dex + bpl trorc2 + ldx #3 +trorc3 + set_z zp1,$ff + ror zpt + tst_z rRORc,fRORc,$ff-fnzc + dex + bpl trorc3 + next_test + +; shifts - absolute + ldx #3 +tasl4 + set_abs zp1,0 + asl abst + tst_abs rASL,fASL,0 + dex + bpl tasl4 + ldx #3 +tasl5 + set_abs zp1,$ff + asl abst + tst_abs rASL,fASL,$ff-fnzc + dex + bpl tasl5 + + ldx #3 +tlsr4 + set_abs zp1,0 + lsr abst + tst_abs rLSR,fLSR,0 + dex + bpl tlsr4 + ldx #3 +tlsr5 + set_abs zp1,$ff + lsr abst + tst_abs rLSR,fLSR,$ff-fnzc + dex + bpl tlsr5 + + ldx #3 +trol4 + set_abs zp1,0 + rol abst + tst_abs rROL,fROL,0 + dex + bpl trol4 + ldx #3 +trol5 + set_abs zp1,$ff-fc + rol abst + tst_abs rROL,fROL,$ff-fnzc + dex + bpl trol5 + + ldx #3 +trolc4 + set_abs zp1,fc + rol abst + tst_abs rROLc,fROLc,0 + dex + bpl trolc4 + ldx #3 +trolc5 + set_abs zp1,$ff + rol abst + tst_abs rROLc,fROLc,$ff-fnzc + dex + bpl trolc5 + + ldx #3 +tror4 + set_abs zp1,0 + ror abst + tst_abs rROR,fROR,0 + dex + bpl tror4 + ldx #3 +tror5 + set_abs zp1,$ff-fc + ror abst + tst_abs rROR,fROR,$ff-fnzc + dex + bpl tror5 + + ldx #3 +trorc4 + set_abs zp1,fc + ror abst + tst_abs rRORc,fRORc,0 + dex + bpl trorc4 + ldx #3 +trorc5 + set_abs zp1,$ff + ror abst + tst_abs rRORc,fRORc,$ff-fnzc + dex + bpl trorc5 + next_test + +; shifts - zp indexed + ldx #3 +tasl6 + set_zx zp1,0 + asl zpt,x + tst_zx rASL,fASL,0 + dex + bpl tasl6 + ldx #3 +tasl7 + set_zx zp1,$ff + asl zpt,x + tst_zx rASL,fASL,$ff-fnzc + dex + bpl tasl7 + + ldx #3 +tlsr6 + set_zx zp1,0 + lsr zpt,x + tst_zx rLSR,fLSR,0 + dex + bpl tlsr6 + ldx #3 +tlsr7 + set_zx zp1,$ff + lsr zpt,x + tst_zx rLSR,fLSR,$ff-fnzc + dex + bpl tlsr7 + + ldx #3 +trol6 + set_zx zp1,0 + rol zpt,x + tst_zx rROL,fROL,0 + dex + bpl trol6 + ldx #3 +trol7 + set_zx zp1,$ff-fc + rol zpt,x + tst_zx rROL,fROL,$ff-fnzc + dex + bpl trol7 + + ldx #3 +trolc6 + set_zx zp1,fc + rol zpt,x + tst_zx rROLc,fROLc,0 + dex + bpl trolc6 + ldx #3 +trolc7 + set_zx zp1,$ff + rol zpt,x + tst_zx rROLc,fROLc,$ff-fnzc + dex + bpl trolc7 + + ldx #3 +tror6 + set_zx zp1,0 + ror zpt,x + tst_zx rROR,fROR,0 + dex + bpl tror6 + ldx #3 +tror7 + set_zx zp1,$ff-fc + ror zpt,x + tst_zx rROR,fROR,$ff-fnzc + dex + bpl tror7 + + ldx #3 +trorc6 + set_zx zp1,fc + ror zpt,x + tst_zx rRORc,fRORc,0 + dex + bpl trorc6 + ldx #3 +trorc7 + set_zx zp1,$ff + ror zpt,x + tst_zx rRORc,fRORc,$ff-fnzc + dex + bpl trorc7 + next_test + +; shifts - abs indexed + ldx #3 +tasl8 + set_absx zp1,0 + asl abst,x + tst_absx rASL,fASL,0 + dex + bpl tasl8 + ldx #3 +tasl9 + set_absx zp1,$ff + asl abst,x + tst_absx rASL,fASL,$ff-fnzc + dex + bpl tasl9 + + ldx #3 +tlsr8 + set_absx zp1,0 + lsr abst,x + tst_absx rLSR,fLSR,0 + dex + bpl tlsr8 + ldx #3 +tlsr9 + set_absx zp1,$ff + lsr abst,x + tst_absx rLSR,fLSR,$ff-fnzc + dex + bpl tlsr9 + + ldx #3 +trol8 + set_absx zp1,0 + rol abst,x + tst_absx rROL,fROL,0 + dex + bpl trol8 + ldx #3 +trol9 + set_absx zp1,$ff-fc + rol abst,x + tst_absx rROL,fROL,$ff-fnzc + dex + bpl trol9 + + ldx #3 +trolc8 + set_absx zp1,fc + rol abst,x + tst_absx rROLc,fROLc,0 + dex + bpl trolc8 + ldx #3 +trolc9 + set_absx zp1,$ff + rol abst,x + tst_absx rROLc,fROLc,$ff-fnzc + dex + bpl trolc9 + + ldx #3 +tror8 + set_absx zp1,0 + ror abst,x + tst_absx rROR,fROR,0 + dex + bpl tror8 + ldx #3 +tror9 + set_absx zp1,$ff-fc + ror abst,x + tst_absx rROR,fROR,$ff-fnzc + dex + bpl tror9 + + ldx #3 +trorc8 + set_absx zp1,fc + ror abst,x + tst_absx rRORc,fRORc,0 + dex + bpl trorc8 + ldx #3 +trorc9 + set_absx zp1,$ff + ror abst,x + tst_absx rRORc,fRORc,$ff-fnzc + dex + bpl trorc9 + next_test + +; testing memory increment/decrement - INC DEC all addressing modes +; zeropage + ldx #0 + lda #$7e + sta zpt +tinc + set_stat 0 + inc zpt + tst_z rINC,fINC,0 + inx + cpx #2 + bne tinc1 + lda #$fe + sta zpt +tinc1 cpx #5 + bne tinc + dex + inc zpt +tdec + set_stat 0 + dec zpt + tst_z rINC,fINC,0 + dex + bmi tdec1 + cpx #1 + bne tdec + lda #$81 + sta zpt + bne tdec +tdec1 + ldx #0 + lda #$7e + sta zpt +tinc10 + set_stat $ff + inc zpt + tst_z rINC,fINC,$ff-fnz + inx + cpx #2 + bne tinc11 + lda #$fe + sta zpt +tinc11 cpx #5 + bne tinc10 + dex + inc zpt +tdec10 + set_stat $ff + dec zpt + tst_z rINC,fINC,$ff-fnz + dex + bmi tdec11 + cpx #1 + bne tdec10 + lda #$81 + sta zpt + bne tdec10 +tdec11 + next_test + +; absolute memory + ldx #0 + lda #$7e + sta abst +tinc2 + set_stat 0 + inc abst + tst_abs rINC,fINC,0 + inx + cpx #2 + bne tinc3 + lda #$fe + sta abst +tinc3 cpx #5 + bne tinc2 + dex + inc abst +tdec2 + set_stat 0 + dec abst + tst_abs rINC,fINC,0 + dex + bmi tdec3 + cpx #1 + bne tdec2 + lda #$81 + sta abst + bne tdec2 +tdec3 + ldx #0 + lda #$7e + sta abst +tinc12 + set_stat $ff + inc abst + tst_abs rINC,fINC,$ff-fnz + inx + cpx #2 + bne tinc13 + lda #$fe + sta abst +tinc13 cpx #5 + bne tinc12 + dex + inc abst +tdec12 + set_stat $ff + dec abst + tst_abs rINC,fINC,$ff-fnz + dex + bmi tdec13 + cpx #1 + bne tdec12 + lda #$81 + sta abst + bne tdec12 +tdec13 + next_test + +; zeropage indexed + ldx #0 + lda #$7e +tinc4 sta zpt,x + set_stat 0 + inc zpt,x + tst_zx rINC,fINC,0 + lda zpt,x + inx + cpx #2 + bne tinc5 + lda #$fe +tinc5 cpx #5 + bne tinc4 + dex + lda #2 +tdec4 sta zpt,x + set_stat 0 + dec zpt,x + tst_zx rINC,fINC,0 + lda zpt,x + dex + bmi tdec5 + cpx #1 + bne tdec4 + lda #$81 + bne tdec4 +tdec5 + ldx #0 + lda #$7e +tinc14 sta zpt,x + set_stat $ff + inc zpt,x + tst_zx rINC,fINC,$ff-fnz + lda zpt,x + inx + cpx #2 + bne tinc15 + lda #$fe +tinc15 cpx #5 + bne tinc14 + dex + lda #2 +tdec14 sta zpt,x + set_stat $ff + dec zpt,x + tst_zx rINC,fINC,$ff-fnz + lda zpt,x + dex + bmi tdec15 + cpx #1 + bne tdec14 + lda #$81 + bne tdec14 +tdec15 + next_test + +; memory indexed + ldx #0 + lda #$7e +tinc6 sta abst,x + set_stat 0 + inc abst,x + tst_absx rINC,fINC,0 + lda abst,x + inx + cpx #2 + bne tinc7 + lda #$fe +tinc7 cpx #5 + bne tinc6 + dex + lda #2 +tdec6 sta abst,x + set_stat 0 + dec abst,x + tst_absx rINC,fINC,0 + lda abst,x + dex + bmi tdec7 + cpx #1 + bne tdec6 + lda #$81 + bne tdec6 +tdec7 + ldx #0 + lda #$7e +tinc16 sta abst,x + set_stat $ff + inc abst,x + tst_absx rINC,fINC,$ff-fnz + lda abst,x + inx + cpx #2 + bne tinc17 + lda #$fe +tinc17 cpx #5 + bne tinc16 + dex + lda #2 +tdec16 sta abst,x + set_stat $ff + dec abst,x + tst_absx rINC,fINC,$ff-fnz + lda abst,x + dex + bmi tdec17 + cpx #1 + bne tdec16 + lda #$81 + bne tdec16 +tdec17 + next_test + +; testing logical instructions - AND EOR ORA all addressing modes +; AND + ldx #3 ;immediate +tand lda zpAN,x + sta ex_andi+1 ;set AND # operand + set_ax absANa,0 + jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,0 + dex + bpl tand + ldx #3 +tand1 lda zpAN,x + sta ex_andi+1 ;set AND # operand + set_ax absANa,$ff + jsr ex_andi ;execute AND # in RAM + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand1 + + ldx #3 ;zp +tand2 lda zpAN,x + sta zpt + set_ax absANa,0 + and zpt + tst_ax absrlo,absflo,0 + dex + bpl tand2 + ldx #3 +tand3 lda zpAN,x + sta zpt + set_ax absANa,$ff + and zpt + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand3 + + ldx #3 ;abs +tand4 lda zpAN,x + sta abst + set_ax absANa,0 + and abst + tst_ax absrlo,absflo,0 + dex + bpl tand4 + ldx #3 +tand5 lda zpAN,x + sta abst + set_ax absANa,$ff + and abst + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand6 + + ldx #3 ;zp,x +tand6 + set_ax absANa,0 + and zpAN,x + tst_ax absrlo,absflo,0 + dex + bpl tand6 + ldx #3 +tand7 + set_ax absANa,$ff + and zpAN,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand7 + + ldx #3 ;abs,x +tand8 + set_ax absANa,0 + and absAN,x + tst_ax absrlo,absflo,0 + dex + bpl tand8 + ldx #3 +tand9 + set_ax absANa,$ff + and absAN,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tand9 + + ldy #3 ;abs,y +tand10 + set_ay absANa,0 + and absAN,y + tst_ay absrlo,absflo,0 + dey + bpl tand10 + ldy #3 +tand11 + set_ay absANa,$ff + and absAN,y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tand11 + + ldx #6 ;(zp,x) + ldy #3 +tand12 + set_ay absANa,0 + and (indAN,x) + tst_ay absrlo,absflo,0 + dex + dex + dey + bpl tand12 + ldx #6 + ldy #3 +tand13 + set_ay absANa,$ff + and (indAN,x) + tst_ay absrlo,absflo,$ff-fnz + dex + dex + dey + bpl tand13 + + ldy #3 ;(zp),y +tand14 + set_ay absANa,0 + and (indAN),y + tst_ay absrlo,absflo,0 + dey + bpl tand14 + ldy #3 +tand15 + set_ay absANa,$ff + and (indAN),y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tand15 + next_test + +; EOR + ldx #3 ;immediate - self modifying code +teor lda zpEO,x + sta ex_eori+1 ;set EOR # operand + set_ax absEOa,0 + jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,0 + dex + bpl teor + ldx #3 +teor1 lda zpEO,x + sta ex_eori+1 ;set EOR # operand + set_ax absEOa,$ff + jsr ex_eori ;execute EOR # in RAM + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor1 + + ldx #3 ;zp +teor2 lda zpEO,x + sta zpt + set_ax absEOa,0 + eor zpt + tst_ax absrlo,absflo,0 + dex + bpl teor2 + ldx #3 +teor3 lda zpEO,x + sta zpt + set_ax absEOa,$ff + eor zpt + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor3 + + ldx #3 ;abs +teor4 lda zpEO,x + sta abst + set_ax absEOa,0 + eor abst + tst_ax absrlo,absflo,0 + dex + bpl teor4 + ldx #3 +teor5 lda zpEO,x + sta abst + set_ax absEOa,$ff + eor abst + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor6 + + ldx #3 ;zp,x +teor6 + set_ax absEOa,0 + eor zpEO,x + tst_ax absrlo,absflo,0 + dex + bpl teor6 + ldx #3 +teor7 + set_ax absEOa,$ff + eor zpEO,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor7 + + ldx #3 ;abs,x +teor8 + set_ax absEOa,0 + eor absEO,x + tst_ax absrlo,absflo,0 + dex + bpl teor8 + ldx #3 +teor9 + set_ax absEOa,$ff + eor absEO,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl teor9 + + ldy #3 ;abs,y +teor10 + set_ay absEOa,0 + eor absEO,y + tst_ay absrlo,absflo,0 + dey + bpl teor10 + ldy #3 +teor11 + set_ay absEOa,$ff + eor absEO,y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl teor11 + + ldx #6 ;(zp,x) + ldy #3 +teor12 + set_ay absEOa,0 + eor (indEO,x) + tst_ay absrlo,absflo,0 + dex + dex + dey + bpl teor12 + ldx #6 + ldy #3 +teor13 + set_ay absEOa,$ff + eor (indEO,x) + tst_ay absrlo,absflo,$ff-fnz + dex + dex + dey + bpl teor13 + + ldy #3 ;(zp),y +teor14 + set_ay absEOa,0 + eor (indEO),y + tst_ay absrlo,absflo,0 + dey + bpl teor14 + ldy #3 +teor15 + set_ay absEOa,$ff + eor (indEO),y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl teor15 + next_test + +; OR + ldx #3 ;immediate - self modifying code +tora lda zpOR,x + sta ex_orai+1 ;set ORA # operand + set_ax absORa,0 + jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,0 + dex + bpl tora + ldx #3 +tora1 lda zpOR,x + sta ex_orai+1 ;set ORA # operand + set_ax absORa,$ff + jsr ex_orai ;execute ORA # in RAM + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora1 + + ldx #3 ;zp +tora2 lda zpOR,x + sta zpt + set_ax absORa,0 + ora zpt + tst_ax absrlo,absflo,0 + dex + bpl tora2 + ldx #3 +tora3 lda zpOR,x + sta zpt + set_ax absORa,$ff + ora zpt + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora3 + + ldx #3 ;abs +tora4 lda zpOR,x + sta abst + set_ax absORa,0 + ora abst + tst_ax absrlo,absflo,0 + dex + bpl tora4 + ldx #3 +tora5 lda zpOR,x + sta abst + set_ax absORa,$ff + ora abst + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora6 + + ldx #3 ;zp,x +tora6 + set_ax absORa,0 + ora zpOR,x + tst_ax absrlo,absflo,0 + dex + bpl tora6 + ldx #3 +tora7 + set_ax absORa,$ff + ora zpOR,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora7 + + ldx #3 ;abs,x +tora8 + set_ax absORa,0 + ora absOR,x + tst_ax absrlo,absflo,0 + dex + bpl tora8 + ldx #3 +tora9 + set_ax absORa,$ff + ora absOR,x + tst_ax absrlo,absflo,$ff-fnz + dex + bpl tora9 + + ldy #3 ;abs,y +tora10 + set_ay absORa,0 + ora absOR,y + tst_ay absrlo,absflo,0 + dey + bpl tora10 + ldy #3 +tora11 + set_ay absORa,$ff + ora absOR,y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tora11 + + ldx #6 ;(zp,x) + ldy #3 +tora12 + set_ay absORa,0 + ora (indOR,x) + tst_ay absrlo,absflo,0 + dex + dex + dey + bpl tora12 + ldx #6 + ldy #3 +tora13 + set_ay absORa,$ff + ora (indOR,x) + tst_ay absrlo,absflo,$ff-fnz + dex + dex + dey + bpl tora13 + + ldy #3 ;(zp),y +tora14 + set_ay absORa,0 + ora (indOR),y + tst_ay absrlo,absflo,0 + dey + bpl tora14 + ldy #3 +tora15 + set_ay absORa,$ff + ora (indOR),y + tst_ay absrlo,absflo,$ff-fnz + dey + bpl tora15 + if I_flag = 3 + cli + endif + next_test + +; full binary add/subtract test +; iterates through all combinations of operands and carry input +; uses increments/decrements to predict result & result flags + cld + ldx #ad2 ;for indexed test + ldy #$ff ;max range + lda #0 ;start with adding zeroes & no carry + sta adfc ;carry in - for diag + sta ad1 ;operand 1 - accumulator + sta ad2 ;operand 2 - memory or immediate + sta ada2 ;non zp + sta adrl ;expected result bits 0-7 + sta adrh ;expected result bit 8 (carry out) + lda #$ff ;complemented operand 2 for subtract + sta sb2 + sta sba2 ;non zp + lda #2 ;expected Z-flag + sta adrf +tadd clc ;test with carry clear + jsr chkadd + inc adfc ;now with carry + inc adrl ;result +1 + php ;save N & Z from low result + php + pla ;accu holds expected flags + and #$82 ;mask N & Z + plp + bne tadd1 + inc adrh ;result bit 8 - carry +tadd1 ora adrh ;merge C to expected flags + sta adrf ;save expected flags except overflow + sec ;test with carry set + jsr chkadd + dec adfc ;same for operand +1 but no carry + inc ad1 + bne tadd ;iterate op1 + lda #0 ;preset result to op2 when op1 = 0 + sta adrh + inc ada2 + inc ad2 + php ;save NZ as operand 2 becomes the new result + pla + and #$82 ;mask N00000Z0 + sta adrf ;no need to check carry as we are adding to 0 + dec sb2 ;complement subtract operand 2 + dec sba2 + lda ad2 + sta adrl + bne tadd ;iterate op2 + if disable_decimal < 1 + next_test + +; decimal add/subtract test +; *** WARNING - tests documented behavior only! *** +; only valid BCD operands are tested, N V Z flags are ignored +; iterates through all valid combinations of operands and carry input +; uses increments/decrements to predict result & carry flag + sed + ldx #ad2 ;for indexed test + ldy #$ff ;max range + lda #$99 ;start with adding 99 to 99 with carry + sta ad1 ;operand 1 - accumulator + sta ad2 ;operand 2 - memory or immediate + sta ada2 ;non zp + sta adrl ;expected result bits 0-7 + lda #1 ;set carry in & out + sta adfc ;carry in - for diag + sta adrh ;expected result bit 8 (carry out) + lda #0 ;complemented operand 2 for subtract + sta sb2 + sta sba2 ;non zp +tdad sec ;test with carry set + jsr chkdad + dec adfc ;now with carry clear + lda adrl ;decimal adjust result + bne tdad1 ;skip clear carry & preset result 99 (9A-1) + dec adrh + lda #$99 + sta adrl + bne tdad3 +tdad1 and #$f ;lower nibble mask + bne tdad2 ;no decimal adjust needed + dec adrl ;decimal adjust (?0-6) + dec adrl + dec adrl + dec adrl + dec adrl + dec adrl +tdad2 dec adrl ;result -1 +tdad3 clc ;test with carry clear + jsr chkdad + inc adfc ;same for operand -1 but with carry + lda ad1 ;decimal adjust operand 1 + beq tdad5 ;iterate operand 2 + and #$f ;lower nibble mask + bne tdad4 ;skip decimal adjust + dec ad1 ;decimal adjust (?0-6) + dec ad1 + dec ad1 + dec ad1 + dec ad1 + dec ad1 +tdad4 dec ad1 ;operand 1 -1 + jmp tdad ;iterate op1 + +tdad5 lda #$99 ;precharge op1 max + sta ad1 + lda ad2 ;decimal adjust operand 2 + beq tdad7 ;end of iteration + and #$f ;lower nibble mask + bne tdad6 ;skip decimal adjust + dec ad2 ;decimal adjust (?0-6) + dec ad2 + dec ad2 + dec ad2 + dec ad2 + dec ad2 + inc sb2 ;complemented decimal adjust for subtract (?9+6) + inc sb2 + inc sb2 + inc sb2 + inc sb2 + inc sb2 +tdad6 dec ad2 ;operand 2 -1 + inc sb2 ;complemented operand for subtract + lda sb2 + sta sba2 ;copy as non zp operand + lda ad2 + sta ada2 ;copy as non zp operand + sta adrl ;new result since op1+carry=00+carry +op2=op2 + inc adrh ;result carry + bne tdad ;iterate op2 +tdad7 + next_test + +; decimal/binary switch test +; tests CLD, SED, PLP, RTI to properly switch between decimal & binary opcode +; tables + clc + cld + php + lda #$55 + adc #$55 + cmp #$aa + trap_ne ;expected binary result after cld + clc + sed + php + lda #$55 + adc #$55 + cmp #$10 + trap_ne ;expected decimal result after sed + cld + plp + lda #$55 + adc #$55 + cmp #$10 + trap_ne ;expected decimal result after plp D=1 + plp + lda #$55 + adc #$55 + cmp #$aa + trap_ne ;expected binary result after plp D=0 + clc + lda #hi bin_rti_ret ;emulated interrupt for rti + pha + lda #lo bin_rti_ret + pha + php + sed + lda #hi dec_rti_ret ;emulated interrupt for rti + pha + lda #lo dec_rti_ret + pha + php + cld + rti +dec_rti_ret + lda #$55 + adc #$55 + cmp #$10 + trap_ne ;expected decimal result after rti D=1 + rti +bin_rti_ret + lda #$55 + adc #$55 + cmp #$aa + trap_ne ;expected binary result after rti D=0 + endif + + lda test_case + cmp #test_num + trap_ne ;previous test is out of sequence + lda #$f0 ;mark opcode testing complete + sta test_case + +; final RAM integrity test +; verifies that none of the previous tests has altered RAM outside of the +; designated write areas. + check_ram +; *** DEBUG INFO *** +; to debug checksum errors uncomment check_ram in the next_test macro to +; narrow down the responsible opcode. +; may give false errors when monitor, OS or other background activity is +; allowed during previous tests. + + +; S U C C E S S ************************************************ +; ------------- + success ;if you get here everything went well +; ------------- +; S U C C E S S ************************************************ + jmp start ;run again + + if disable_decimal < 1 +; core subroutine of the decimal add/subtract test +; *** WARNING - tests documented behavior only! *** +; only valid BCD operands are tested, N V Z flags are ignored +; iterates through all valid combinations of operands and carry input +; uses increments/decrements to predict result & carry flag +chkdad +; decimal ADC / SBC zp + php ;save carry for subtract + lda ad1 + adc ad2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sb2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad flags + plp +; decimal ADC / SBC abs + php ;save carry for subtract + lda ad1 + adc ada2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sba2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC # + php ;save carry for subtract + lda ad2 + sta ex_adci+1 ;set ADC # operand + lda ad1 + jsr ex_adci ;execute ADC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda sb2 + sta ex_sbci+1 ;set SBC # operand + lda ad1 + jsr ex_sbci ;execute SBC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC zp,x + php ;save carry for subtract + lda ad1 + adc 0,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sb2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC abs,x + php ;save carry for subtract + lda ad1 + adc ada2-ad2,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sba2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC abs,y + php ;save carry for subtract + lda ad1 + adc ada2-$ff,y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc sba2-$ff,y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC (zp,x) + php ;save carry for subtract + lda ad1 + adc (lo adi2-ad2,x) ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc (lo sbi2-ad2,x) ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp +; decimal ADC / SBC (abs),y + php ;save carry for subtract + lda ad1 + adc (adiy2),y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + php ;save carry for next add + lda ad1 + sbc (sbiy2),y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #1 ;mask carry + cmp adrh + trap_ne ;bad carry + plp + rts + endif + +; core subroutine of the full binary add/subtract test +; iterates through all combinations of operands and carry input +; uses increments/decrements to predict result & result flags +chkadd lda adrf ;add V-flag if overflow + and #$83 ;keep N-----ZC / clear V + pha + lda ad1 ;test sign unequal between operands + eor ad2 + bmi ckad1 ;no overflow possible - operands have different sign + lda ad1 ;test sign equal between operands and result + eor adrl + bpl ckad1 ;no overflow occured - operand and result have same sign + pla + ora #$40 ;set V + pha +ckad1 pla + sta adrf ;save expected flags +; binary ADC / SBC zp + php ;save carry for subtract + lda ad1 + adc ad2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sb2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC abs + php ;save carry for subtract + lda ad1 + adc ada2 ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sba2 ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC # + php ;save carry for subtract + lda ad2 + sta ex_adci+1 ;set ADC # operand + lda ad1 + jsr ex_adci ;execute ADC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda sb2 + sta ex_sbci+1 ;set SBC # operand + lda ad1 + jsr ex_sbci ;execute SBC # in RAM + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC zp,x + php ;save carry for subtract + lda ad1 + adc 0,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sb2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC abs,x + php ;save carry for subtract + lda ad1 + adc ada2-ad2,x ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sba2-ad2,x ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC abs,y + php ;save carry for subtract + lda ad1 + adc ada2-$ff,y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc sba2-$ff,y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC (zp,x) + php ;save carry for subtract + lda ad1 + adc (lo adi2-ad2,x) ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc (lo sbi2-ad2,x) ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp +; binary ADC / SBC (abs),y + php ;save carry for subtract + lda ad1 + adc (adiy2),y ;perform add + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + php ;save carry for next add + lda ad1 + sbc (sbiy2),y ;perform subtract + php + cmp adrl ;check result + trap_ne ;bad result + pla ;check flags + and #$c3 ;mask NV----ZC + cmp adrf + trap_ne ;bad flags + plp + rts + +; target for the jump absolute test + dey + dey +test_far + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_cs ;flags loaded? + trap_vs + trap_mi + trap_eq + cmp #'F' ;registers loaded? + trap_ne + cpx #'A' + trap_ne + cpy #('R'-3) + trap_ne + pha ;save a,x + txa + pha + tsx + cpx #$fd ;check SP + trap_ne + pla ;restore x + tax + set_stat $ff + pla ;restore a + inx ;return registers with modifications + eor #$aa ;N=1, V=1, Z=0, C=1 + jmp far_ret + +; target for the jump indirect test + align +ptr_tst_ind dw test_ind +ptr_ind_ret dw ind_ret + trap ;runover protection + dey + dey +test_ind + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_cs ;flags loaded? + trap_vs + trap_mi + trap_eq + cmp #'I' ;registers loaded? + trap_ne + cpx #'N' + trap_ne + cpy #('D'-3) + trap_ne + pha ;save a,x + txa + pha + tsx + cpx #$fd ;check SP + trap_ne + pla ;restore x + tax + set_stat $ff + pla ;restore a + inx ;return registers with modifications + eor #$aa ;N=1, V=1, Z=0, C=1 + jmp (ptr_ind_ret) + trap ;runover protection + +; target for the jump subroutine test + dey + dey +test_jsr + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + plp + trap_cs ;flags loaded? + trap_vs + trap_mi + trap_eq + cmp #'J' ;registers loaded? + trap_ne + cpx #'S' + trap_ne + cpy #('R'-3) + trap_ne + pha ;save a,x + txa + pha + tsx ;sp -4? (return addr,a,x) + cpx #$fb + trap_ne + lda $1ff ;propper return on stack + cmp #hi(jsr_ret) + trap_ne + lda $1fe + cmp #lo(jsr_ret) + trap_ne + set_stat $ff + pla ;pull x,a + tax + pla + inx ;return registers with modifications + eor #$aa ;N=1, V=1, Z=0, C=1 + rts + trap ;runover protection + +;trap in case of unexpected IRQ, NMI, BRK, RESET - BRK test target +nmi_trap + trap ;check stack for conditions at NMI +res_trap + trap ;unexpected RESET + + dey + dey +irq_trap ;BRK test or unextpected BRK or IRQ + php ;either SP or Y count will fail, if we do not hit + dey + dey + dey + ;next 4 traps could be caused by unexpected BRK or IRQ + ;check stack for BREAK and originating location + ;possible jump/branch into weeds (uninitialized space) + cmp #'B' ;registers loaded? + trap_ne + cpx #'R' + trap_ne + cpy #('K'-3) + trap_ne + sta irq_a ;save registers during break test + stx irq_x + tsx ;test break on stack + lda $102,x + cmp_flag 0 ;break test should have B=1 + trap_ne ; - no break flag on stack + pla + cmp #fai ;should have added interrupt disable + trap_ne + tsx + cpx #$fc ;sp -3? (return addr, flags) + trap_ne + lda $1ff ;propper return on stack + cmp #hi(brk_ret) + trap_ne + lda $1fe + cmp #lo(brk_ret) + trap_ne + set_stat $ff + ldx irq_x + inx ;return registers with modifications + lda irq_a + eor #$aa ;N=1, V=1, Z=0, C=1 but original flags should be restored + rti + trap ;runover protection + + if report = 1 + include "report.i65" + endif + +;copy of data to initialize BSS segment + if load_data_direct != 1 +zp_init +zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +zp7f_ db $7f ;test pattern for compare +;logical zeropage operands +zpOR_ db 0,$1f,$71,$80 ;test pattern for OR +zpAN_ db $0f,$ff,$7f,$80 ;test pattern for AND +zpEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR +;indirect addressing pointers +ind1_ dw abs1 ;indirect pointer to pattern in absolute memory + dw abs1+1 + dw abs1+2 + dw abs1+3 + dw abs7f +inw1_ dw abs1-$f8 ;indirect pointer for wrap-test pattern +indt_ dw abst ;indirect pointer to store area in absolute memory + dw abst+1 + dw abst+2 + dw abst+3 +inwt_ dw abst-$f8 ;indirect pointer for wrap-test store +indAN_ dw absAN ;indirect pointer to AND pattern in absolute memory + dw absAN+1 + dw absAN+2 + dw absAN+3 +indEO_ dw absEO ;indirect pointer to EOR pattern in absolute memory + dw absEO+1 + dw absEO+2 + dw absEO+3 +indOR_ dw absOR ;indirect pointer to OR pattern in absolute memory + dw absOR+1 + dw absOR+2 + dw absOR+3 +;add/subtract indirect pointers +adi2_ dw ada2 ;indirect pointer to operand 2 in absolute memory +sbi2_ dw sba2 ;indirect pointer to complemented operand 2 (SBC) +adiy2_ dw ada2-$ff ;with offset for indirect indexed +sbiy2_ dw sba2-$ff +zp_end + if (zp_end - zp_init) != (zp_bss_end - zp_bss) + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and zeropage data + endif +data_init +ex_and_ and #0 ;execute immediate opcodes + rts +ex_eor_ eor #0 ;execute immediate opcodes + rts +ex_ora_ ora #0 ;execute immediate opcodes + rts +ex_adc_ adc #0 ;execute immediate opcodes + rts +ex_sbc_ sbc #0 ;execute immediate opcodes + rts +abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR +abs7f_ db $7f ;test pattern for compare +;loads +fLDx_ db fn,fn,0,fz ;expected flags for load +;shifts +rASL_ ;expected result ASL & ROL -carry +rROL_ db $86,$04,$82,0 ; " +rROLc_ db $87,$05,$83,1 ;expected result ROL +carry +rLSR_ ;expected result LSR & ROR -carry +rROR_ db $61,$41,$20,0 ; " +rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carry +fASL_ ;expected flags for shifts +fROL_ db fnc,fc,fn,fz ;no carry in +fROLc_ db fnc,fc,fn,0 ;carry in +fLSR_ +fROR_ db fc,0,fc,fz ;no carry in +fRORc_ db fnc,fn,fnc,fn ;carry in +;increments (decrements) +rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC +fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC +;logical memory operand +absOR_ db 0,$1f,$71,$80 ;test pattern for OR +absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND +absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR +;logical accu operand +absORa_ db 0,$f1,$1f,0 ;test pattern for OR +absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND +absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR +;logical results +absrlo_ db 0,$ff,$7f,$80 +absflo_ db fz,fn,0,fn +data_end + if (data_end - data_init) != (data_bss_end - data_bss) + ;force assembler error if size is different + ERROR ERROR ERROR ;mismatch between bss and data + endif + +vec_init + dw nmi_trap + dw res_trap + dw irq_trap +vec_bss equ $fffa + endif ;end of RAM init data + + if (load_data_direct = 1) & (ROM_vectors = 1) + org $fffa ;vectors + dw nmi_trap + dw res_trap + dw irq_trap + endif + + end start + \ No newline at end of file diff --git a/BCDCodes.dev b/BCDCodes.dev index 8a12981..1a9f0e2 100644 --- a/BCDCodes.dev +++ b/BCDCodes.dev @@ -1,62 +1,62 @@ -[Project] -FileName=BCDCodes.dev -Name=BCDCodes -Type=1 -Ver=2 -ObjFiles= -Includes= -Libs= -PrivateResource= -ResourceIncludes= -MakeIncludes= -Compiler= -CppCompiler= -Linker= -IsCpp=0 -Icon= -ExeOutput= -ObjectOutput= -LogOutput= -LogOutputEnabled=0 -OverrideOutput=0 -OverrideOutputName= -HostApplication= -UseCustomMakefile=0 -CustomMakefile= -CommandLine= -Folders= -IncludeVersionInfo=0 -SupportXPThemes=0 -CompilerSet=3 -CompilerSettings=0000000100000000000000000 -UnitCount=1 - -[VersionInfo] -Major=1 -Minor=0 -Release=0 -Build=0 -LanguageID=1033 -CharsetID=1252 -CompanyName= -FileVersion= -FileDescription=Developed using the Dev-C++ IDE -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion= -AutoIncBuildNr=0 -SyncProduct=1 - -[Unit1] -FileName=bcd.c -CompileCpp=0 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - +[Project] +FileName=BCDCodes.dev +Name=BCDCodes +Type=1 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName= +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=3 +CompilerSettings=0000000100000000000000000 +UnitCount=1 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=bcd.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/BCDCodes.layout b/BCDCodes.layout new file mode 100644 index 0000000..b71ad5b --- /dev/null +++ b/BCDCodes.layout @@ -0,0 +1,8 @@ +[Editors] +Order=0 +Focused=0 +[Editor_0] +CursorCol=1 +CursorRow=34 +TopLine=1 +LeftChar=1 diff --git a/Bin2Hex.dev b/Bin2Hex.dev new file mode 100644 index 0000000..65c0362 --- /dev/null +++ b/Bin2Hex.dev @@ -0,0 +1,62 @@ +[Project] +FileName=Bin2Hex.dev +Name=Bin2Hex +Type=1 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName= +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=3 +CompilerSettings=0000000100000000000000000 +UnitCount=1 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=bin2hex.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/Bin2Hex.layout b/Bin2Hex.layout new file mode 100644 index 0000000..c3de494 --- /dev/null +++ b/Bin2Hex.layout @@ -0,0 +1,8 @@ +[Editor_0] +CursorCol=26 +CursorRow=111 +TopLine=28 +LeftChar=1 +[Editors] +Order=0 +Focused=0 diff --git a/Display.cpp b/Display.cpp index 1c36c90..d0ec1bf 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,245 +1,312 @@ -#include "Display.h" -#include -#include -#include -#include - -using namespace std; - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Display::Display() -{ - InitScr(); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Display::~Display() -{ -} - -/* - *-------------------------------------------------------------------- - * Method: InitScr() - * Purpose: Initialize screen. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Display::InitScr() -{ - ClrScr(); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Display::ScrollUp() -{ - for (int row=0; row= SCREENDIM_ROW) { - ScrollUp(); - mCursorCoord.row = SCREENDIM_ROW-1; - } - } else if (c == SCREENSPECCHARS_CR) { - mCursorCoord.col = 0; - } else if (c == SCREENSPECCHARS_TB) { - mCursorCoord.col += TABSIZE; - if (mCursorCoord.col >= SCREENDIM_COL) { - mCursorCoord.col = SCREENDIM_COL-1; // must work on it some more - } - } else if (c == SCREENSPECCHARS_BS) { - if (mCursorCoord.col > 0) mCursorCoord.col--; - } else if (c == SCREENSPECCHARS_BE) { - // no action - } - else { - mScreen[mCursorCoord.col][mCursorCoord.row] = c; - mCursorCoord.col++; - if (mCursorCoord.col >= SCREENDIM_COL) { - mCursorCoord.col = 0; - mCursorCoord.row++; - if (mCursorCoord.row >= SCREENDIM_ROW) { - ScrollUp(); - mCursorCoord.row = SCREENDIM_ROW-1; - } - } - } - } -} - -/* - *-------------------------------------------------------------------- - * Method: ClrScr() - * Purpose: Fill the screen with spaces. Set cursor in left-upper - * corner. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Display::ClrScr() -{ - for (int col=0; col +#include +#include +#include + +using namespace std; + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Display::Display() +{ + InitScr(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Display::~Display() +{ +} + +/* + *-------------------------------------------------------------------- + * Method: InitScr() + * Purpose: Initialize screen. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Display::InitScr() +{ + mScrLines = SCREENDIM_ROW; + mScrColumns = SCREENDIM_COL; + mShellConsoleWidth = GetConsoleWidth(); + if (mScrColumns > mShellConsoleWidth) { + mScrColumns = mShellConsoleWidth; + } + ClrScr(); +} + +#if defined(WINDOWS) + +#include +#include + +/* + *-------------------------------------------------------------------- + * Method: GetConsoleWidth() + * Purpose: Obtain the width of shell console (the real one, not + * the emulated one) on Windows. + * Arguments: n/a + * Returns: int - width of the shell console. + *-------------------------------------------------------------------- + */ +int Display::GetConsoleWidth() +{ + HANDLE hStdOut; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + if (hStdOut == INVALID_HANDLE_VALUE) return -1; + + if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return -2; + + return csbi.dwSize.X; +} + +#endif + +#if defined(LINUX) + +#include + +/* + *-------------------------------------------------------------------- + * Method: GetConsoleWidth() + * Purpose: Obtain the width of shell console (the real one, not + * the emulated one) on Linux. + * Arguments: n/a + * Returns: int - width of the shell console. + *-------------------------------------------------------------------- + */ +int Display::GetConsoleWidth() +{ + unsigned int conwidth = SCREENDIM_COL; + char *termtype = getenv("TERM"); + static char termbuf[2048]; + + if (tgetent(termbuf, termtype) < 0) { + cout << "WARNING: Could not access the termcap data base." << endl; + cout << " Unable to determine console width." << endl; + } else { + conwidth = tgetnum("co"); + } + + return conwidth; +} + +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Display::ScrollUp() +{ + for (unsigned int row=0; row= mScrLines) { + ScrollUp(); + mCursorCoord.row = mScrLines-1; + } + } else if (c == SCREENSPECCHARS_CR) { + mCursorCoord.col = 0; + } else if (c == SCREENSPECCHARS_TB) { + mCursorCoord.col += TABSIZE; + if (mCursorCoord.col >= mScrColumns) { + mCursorCoord.col = mScrColumns-1; // must work on it some more + } + } else if (c == SCREENSPECCHARS_BS) { + if (mCursorCoord.col > 0) mCursorCoord.col--; + } else if (c == SCREENSPECCHARS_BE) { + // no action + } + else { + mScreen[mCursorCoord.col][mCursorCoord.row] = c; + mCursorCoord.col++; + if (mCursorCoord.col >= mScrColumns) { + mCursorCoord.col = 0; + mCursorCoord.row++; + if (mCursorCoord.row >= mScrLines) { + ScrollUp(); + mCursorCoord.row = mScrLines-1; + } + } + } + } +} + +/* + *-------------------------------------------------------------------- + * Method: ClrScr() + * Purpose: Fill the screen with spaces. Set cursor in left-upper + * corner. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Display::ClrScr() +{ + for (unsigned int col=0; col mScrColumns) cout << endl; + } +} + +/* + *-------------------------------------------------------------------- + * Method: GetCursorCoord() + * Purpose: Get cursor coordinates. + * Arguments: n/a + * Returns: pointer to cursor coordinates + *-------------------------------------------------------------------- + */ +CursorCoord *Display::GetCursorCoord() +{ + return &mCursorCoord; +} + +} // namespace MKBasic diff --git a/Display.h b/Display.h index db80bcc..56993f5 100644 --- a/Display.h +++ b/Display.h @@ -1,54 +1,60 @@ -#ifndef DISPLAY_H -#define DISPLAY_H - -#define TABSIZE 4 - -namespace MKBasic { - -enum eScreenDimensions { - SCREENDIM_COL = 80, - SCREENDIM_ROW = 24 -}; - -enum eScreenSpecChars { - SCREENSPECCHARS_NL = (int)'\n', // new line - SCREENSPECCHARS_CR = (int)'\r', // caret - SCREENSPECCHARS_TB = (int)'\t', // tab - SCREENSPECCHARS_BS = (int)'\b', // backspace - SCREENSPECCHARS_BE = (int)'\a' // bell -}; - -struct CursorCoord { - int row; - int col; -}; - -class Display -{ - public: - - Display(); - ~Display(); - void GotoXY(unsigned int col, unsigned int row); - void PutChar(char c); - void ClrScr(); - char GetCharAt(unsigned int col, unsigned int row); - void ShowScr(); - CursorCoord *GetCursorCoord(); - - protected: - - private: - - char mScreen[SCREENDIM_COL][SCREENDIM_ROW]; - CursorCoord mCursorCoord; - - void InitScr(); - void ScrollUp(); - bool IsSpecChar(char c); - -}; - -} // namespace MKBasic - -#endif +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "system.h" + +#define TABSIZE 4 + +namespace MKBasic { + +enum eScreenDimensions { + SCREENDIM_COL = 80, + SCREENDIM_ROW = 24 +}; + +enum eScreenSpecChars { + SCREENSPECCHARS_NL = (int)'\n', // new line + SCREENSPECCHARS_CR = (int)'\r', // caret + SCREENSPECCHARS_TB = (int)'\t', // tab + SCREENSPECCHARS_BS = (int)'\b', // backspace + SCREENSPECCHARS_BE = (int)'\a' // bell +}; + +struct CursorCoord { + unsigned int row; + unsigned int col; +}; + +class Display +{ + public: + + Display(); + ~Display(); + void GotoXY(unsigned int col, unsigned int row); + void PutChar(char c); + void ClrScr(); + char GetCharAt(unsigned int col, unsigned int row); + void ShowScr(); + CursorCoord *GetCursorCoord(); + + protected: + + private: + + char mScreen[SCREENDIM_COL][SCREENDIM_ROW]; + CursorCoord mCursorCoord; + unsigned int mShellConsoleWidth; + unsigned int mScrLines; + unsigned int mScrColumns; + + void InitScr(); + void ScrollUp(); + bool IsSpecChar(char c); + int GetConsoleWidth(); + +}; + +} // namespace MKBasic + +#endif diff --git a/MKBasic.cpp b/MKBasic.cpp index e1c928f..6f84b69 100644 --- a/MKBasic.cpp +++ b/MKBasic.cpp @@ -1,13 +1,13 @@ -#include "MKBasic.h" - -namespace MKBasic { - -MKBasic::MKBasic() -{ -} - -MKBasic::~MKBasic() -{ -} - -} // namespace MKBasic +#include "MKBasic.h" + +namespace MKBasic { + +MKBasic::MKBasic() +{ +} + +MKBasic::~MKBasic() +{ +} + +} // namespace MKBasic diff --git a/MKBasic.dev b/MKBasic.dev index c14bae8..650819b 100644 --- a/MKBasic.dev +++ b/MKBasic.dev @@ -1,182 +1,192 @@ -[Project] -FileName=MKBasic.dev -Name=MKBasic -Type=1 -Ver=2 -ObjFiles= -Includes= -Libs= -PrivateResource= -ResourceIncludes= -MakeIncludes= -Compiler= -CppCompiler= -Linker= -IsCpp=1 -Icon= -ExeOutput= -ObjectOutput= -LogOutput= -LogOutputEnabled=0 -OverrideOutput=0 -OverrideOutputName=MKBasic.exe -HostApplication= -UseCustomMakefile=0 -CustomMakefile= -CommandLine= -Folders= -IncludeVersionInfo=0 -SupportXPThemes=0 -CompilerSet=3 -CompilerSettings=00000001c0111000001000000 -UnitCount=13 - -[VersionInfo] -Major=1 -Minor=0 -Release=0 -Build=0 -LanguageID=1033 -CharsetID=1252 -CompanyName= -FileVersion=1.0.0.0 -FileDescription=Developed using the Dev-C++ IDE -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -AutoIncBuildNr=0 -SyncProduct=1 - -[Unit1] -FileName=main.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit2] -FileName=VMachine.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit3] -FileName=VMachine.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit4] -FileName=MKBasic.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit5] -FileName=MKBasic.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit6] -FileName=MKCpu.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit7] -FileName=MKCpu.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit8] -FileName=Memory.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit9] -FileName=Memory.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit10] -FileName=Display.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit11] -FileName=Display.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit12] -FileName=MKGenException.h -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[Unit13] -FileName=MKGenException.cpp -CompileCpp=1 -Folder= -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - +[Project] +FileName=MKBasic.dev +Name=MKBasic +Type=1 +Ver=2 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=1 +Icon= +ExeOutput= +ObjectOutput= +LogOutput= +LogOutputEnabled=0 +OverrideOutput=0 +OverrideOutputName=MKBasic.exe +HostApplication= +UseCustomMakefile=0 +CustomMakefile= +CommandLine= +Folders= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=3 +CompilerSettings=00000001c0111000001000000 +UnitCount=14 + +[VersionInfo] +Major=1 +Minor=0 +Release=0 +Build=0 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=1.0.0.0 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=VMachine.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=VMachine.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=MKBasic.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=MKBasic.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=MKCpu.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=MKCpu.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=Memory.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=Memory.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=Display.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=Display.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=MKGenException.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=MKGenException.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=system.h +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/MKBasic.h b/MKBasic.h index 1e7cad6..fbe06ff 100644 --- a/MKBasic.h +++ b/MKBasic.h @@ -1,18 +1,18 @@ -#ifndef MKBASIC_H -#define MKBASIC_H - -#include "VMachine.h" - -namespace MKBasic { - -class MKBasic : public VMachine -{ - public: - MKBasic(); - ~MKBasic(); - protected: -}; - -} // namespace MKBasic - -#endif +#ifndef MKBASIC_H +#define MKBASIC_H + +#include "VMachine.h" + +namespace MKBasic { + +class MKBasic : public VMachine +{ + public: + MKBasic(); + ~MKBasic(); + protected: +}; + +} // namespace MKBasic + +#endif diff --git a/MKBasic.layout b/MKBasic.layout new file mode 100644 index 0000000..0187f9c --- /dev/null +++ b/MKBasic.layout @@ -0,0 +1,38 @@ +[Editors] +Order=0,7,8,1,2,5,6 +Focused=0 +[Editor_0] +CursorCol=17 +CursorRow=470 +TopLine=424 +LeftChar=1 +[Editor_1] +CursorCol=33 +CursorRow=38 +TopLine=28 +LeftChar=1 +[Editor_2] +CursorCol=15 +CursorRow=600 +TopLine=554 +LeftChar=1 +[Editor_5] +CursorCol=1 +CursorRow=1 +TopLine=260 +LeftChar=1 +[Editor_6] +CursorCol=17 +CursorRow=1151 +TopLine=332 +LeftChar=1 +[Editor_7] +CursorCol=1 +CursorRow=1 +TopLine=25 +LeftChar=1 +[Editor_8] +CursorCol=1 +CursorRow=1 +TopLine=220 +LeftChar=1 diff --git a/MKCpu.cpp b/MKCpu.cpp index 3f82456..2973d49 100644 --- a/MKCpu.cpp +++ b/MKCpu.cpp @@ -1,1471 +1,2012 @@ -#include "MKCpu.h" -#include "MKGenException.h" - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -/* - *-------------------------------------------------------------------- - * Method: MKCpu() - * Purpose: Default constructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -MKCpu::MKCpu() -{ - InitCpu(); -} - -/* - *-------------------------------------------------------------------- - * Method: MKCpu() - * Purpose: Custom constructor. - * Arguments: pmem - pointer to Memory object. - * Returns: n/a - *-------------------------------------------------------------------- - */ -MKCpu::MKCpu(Memory *pmem) -{ - mpMem = pmem; - InitCpu(); -} - -/* - *-------------------------------------------------------------------- - * Method: InitCpu() - * Purpose: Initialize internal variables and flags. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::InitCpu() -{ - mReg.Acc = 0; - mReg.Acc16 = 0; - mReg.Flags = FLAGS_UNUSED; - mReg.IndX = 0; - mReg.IndY = 0; - mReg.Ptr16 = 0; - mReg.PtrAddr = 0; - mReg.PtrStack = 0xFF; // top of stack - mReg.SoftIrq = false; - mLocalMem = false; - if (NULL == mpMem) { - mpMem = new Memory(); - if (NULL == mpMem) { - throw MKGenException("Unable to allocate memory!"); - } - mLocalMem = true; - } - // Set default BRK vector. - mpMem->Poke8bit(0xFFFE,0xF0); - mpMem->Poke8bit(0xFFFF,0xFF); - // Put RTI opcode at BRK address. - mpMem->Poke8bit(0xFFF0, OPCODE_RTI); -} - -/* - *-------------------------------------------------------------------- - * Method: SetFlags() - * Purpose: Set CPU status flags ZERO and SIGN based on Acc, X or Y - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::SetFlags(unsigned char reg) -{ - SetFlag((0 == reg), FLAGS_ZERO); - SetFlag(((reg & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_SIGN); -} - -/* - *-------------------------------------------------------------------- - * Method: ShiftLeft() - * Purpose: Arithmetic shift left (1 bit), set Carry flag, shift 0 - * into bit #0. Update flags NZ. - * Arguments: arg8 - 8-bit value - * Returns: 8-bit value after shift - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::ShiftLeft(unsigned char arg8) -{ - // set Carry flag based on original bit #7 - SetFlag(((arg8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); - arg8 = arg8 << 1; // shift left - arg8 &= 0xFE; // shift 0 into bit #0 - - SetFlags(arg8); - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: ShiftRight() - * Purpose: Logical Shift Right, update flags NZC. - * Arguments: arg8 - byte value - * Returns: unsigned char (byte) - after shift - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::ShiftRight(unsigned char arg8) -{ - SetFlag(((arg8 & 0x01) == 0x01), FLAGS_CARRY); - arg8 = arg8 >> 1; - arg8 &= 0x7F; // unset bit #7 - SetFlags(arg8); - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: RotateLeft() - * Purpose: Rotate left, Carry to bit 0, bit 7 to Carry, update - flags N and Z. - * Arguments: arg8 - byte value to rotate - * Returns: unsigned char (byte) - rotated value - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::RotateLeft(unsigned char arg8) -{ - unsigned char tmp8 = 0; - - tmp8 = arg8; - arg8 = arg8 << 1; - // Carry goes to bit #0. - if (mReg.Flags & FLAGS_CARRY) { - arg8 |= 0x01; - } else { - arg8 &= 0xFE; - } - // Original (before ROL) bit #7 goes to Carry. - SetFlag(((tmp8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); - SetFlags(arg8); // set flags Z and N - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: RotateRight() - * Purpose: Rotate Right, Carry to bit 7, bit 0 to Carry, update - flags N and Z. - * Arguments: arg8 - byte value to rotate - * Returns: unsigned char (byte) - rotated value - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::RotateRight(unsigned char arg8) -{ - unsigned char tmp8 = 0; - - tmp8 = arg8; - arg8 = arg8 >> 1; - // Carry goes to bit #7. - if (CheckFlag(FLAGS_CARRY)) { - arg8 |= 0x80; - } else { - arg8 &= 0x7F; - } - // Original (before ROR) bit #0 goes to Carry. - SetFlag(((tmp8 & 0x01) == 0x01), FLAGS_CARRY); - SetFlags(arg8); // set flags Z and N - - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: GetArg16() - * Purpose: Get 2-byte argument, add offset, increase PC. - * Arguments: addr - address of argument in memory - * offs - offset to be added to returned value - * Returns: 16-bit address - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::GetArg16(unsigned char offs) -{ - unsigned short ret = 0; - - ret = mpMem->Peek16bit(mReg.PtrAddr++); - mReg.PtrAddr++; - ret += offs; - - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: LogicOpAcc() - * Purpose: Perform logical bitwise operation between memory - * location and Acc, result in Acc. Set flags. - * Arguments: addr - memory location - * logop - logical operation code: LOGOP_OR, LOGOP_AND, - * LOGOP_EOR - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::LogicOpAcc(unsigned short addr, int logop) -{ - unsigned char val = 0; - - val = mpMem->Peek8bit(addr); - switch (logop) { - case LOGOP_OR: - mReg.Acc |= val; - break; - case LOGOP_AND: - mReg.Acc &= val; - break; - case LOGOP_EOR: - mReg.Acc ^= val; - break; - default: - break; - } - SetFlags(mReg.Acc); -} - -/* - *-------------------------------------------------------------------- - * Method: ComputeRelJump() - * Purpose: Compute new PC based on relative offset. - * Arguments: offs - relative offset [-128 ($80)..127 ($7F)] - * Returns: unsigned short - new PC (Program Counter). - * NOTE: - * Program Counter (http://www.6502.org/tutorials/6502opcodes.html#PC) - * When the 6502 is ready for the next instruction it increments the - * program counter before fetching the instruction. Once it has the op - * code, it increments the program counter by the length of the - * operand, if any. This must be accounted for when calculating - * branches or when pushing bytes to create a false return address - * (i.e. jump table addresses are made up of addresses-1 when it is - * intended to use an RTS rather than a JMP). - * The program counter is loaded least signifigant byte first. - * Therefore the most signifigant byte must be pushed first when - * creating a false return address. - * When calculating branches a forward branch of 6 skips the following - * 6 bytes so, effectively the program counter points to the address - * that is 8 bytes beyond the address of the branch opcode; - * and a backward branch of $FA (256-6) goes to an address 4 bytes - * before the branch instruction. - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::ComputeRelJump(unsigned char offs) -{ - unsigned short newpc = mReg.PtrAddr; // PtrAddr must be at the next - // opcode at this point - if (offs < 0x80) { - newpc += (unsigned short) offs; - } else { - newpc -= (unsigned short) ((unsigned char)(~offs + 1)); // use binary 2's complement instead of arithmetics - } - - return newpc; -} - -/* - *-------------------------------------------------------------------- - * Method: Conv2Bcd() - * Purpose: Convert 16-bit unsigned number to 8-bit BCD - * representation. - * Arguments: v - 16-bit unsigned integer. - * Returns: byte representing BCD code of the 'v'. - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::Conv2Bcd(unsigned short v) -{ - unsigned char arg8 = 0; - arg8 = (unsigned char)((v/10) << 4); - arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; - return arg8; -} - -/* - *-------------------------------------------------------------------- - * Method: Bcd2Num() - * Purpose: Convert 8-bit BCD code to a number. - * Arguments: v - BCD code. - * Returns: 16-bit unsigned integer - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::Bcd2Num(unsigned char v) -{ - unsigned short ret = 0; - ret = 10 * ((v & 0xF0) >> 4) + (unsigned char)(v & 0x0F); - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: CheckFlag() - * Purpose: Check if given bit flag in CPU status register is set - * or not. - * Arguments: flag - byte with the bit to be checked set and other - * bits not set. - * Returns: bool - *-------------------------------------------------------------------- - */ -bool MKCpu::CheckFlag(unsigned char flag) -{ - return ((mReg.Flags & flag) == flag); -} - -/* - *-------------------------------------------------------------------- - * Method: SetFlag() - * Purpose: Set or unset CPU status flag. - * Arguments: set - if true, set flag, if false, unset flag. - * flag - a byte with a bit set on the position of flag - * being altered and zeroes on other positions. - * Returns: n/a - *-------------------------------------------------------------------- - */ -void MKCpu::SetFlag(bool set, unsigned char flag) -{ - if (set) { - mReg.Flags |= flag; - } else { - mReg.Flags &= ~flag; - } -} - -/* - *-------------------------------------------------------------------- - * Method: AddWithCarry() - * Purpose: Add Acc + Mem with Carry, update flags and Acc. - * Arguments: mem8 - memory argument (byte) - * Returns: byte value Acc + Mem + Carry - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::AddWithCarry(unsigned char mem8) -{ - /* This algorithm was shamelessly ripped from Frodo emulator code. - Well, maybe not totally shamelessly, I put up a fight to roll my own. - I gave up after one day of trying to make it right based only on MOS documentation. - For my defense I have this - Frodo also does not work 100% as real metal MOS 6502). - And so doesn't Kowalski's emulator. - E.g.: - Real CPU - Rockwell 6502 AP in BCD mode: - 80 + f0 and C=0 gives d0 and N=1 V=1 Z=0 C=1 (F9) - Kowalski's 6502 emulator gives: d0 and N=0, V=0, Z=0, C=1 - My emulator gives: d0 and N=0, V=1, Z=0, C=1 - */ - unsigned short utmp16 = mReg.Acc + mem8 + (CheckFlag(FLAGS_CARRY) ? 1 : 0); - if (CheckFlag(FLAGS_DEC)) { // BCD mode - - unsigned short al = (mReg.Acc & 0x0F) + (mem8 & 0x0F) + (CheckFlag(FLAGS_CARRY) ? 1 : 0); - if (al > 9) al += 6; - unsigned short ah = (mReg.Acc >> 4) + (mem8 >> 4); - if (al > 0x0F) ah++; - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag((((ah << 4) & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_SIGN); - SetFlag(((((ah << 4) ^ mReg.Acc) & 0x80) && !((mReg.Acc ^ mem8) & 0x80)), FLAGS_OVERFLOW); - if (ah > 9) ah += 6; - SetFlag((ah > 0x0F), FLAGS_CARRY); - mReg.Acc = (ah << 4) | (al & 0x0f); - } else { // binary mode - - SetFlag((utmp16 > 0xff), FLAGS_CARRY); - SetFlag((!((mReg.Acc ^ mem8) & 0x80) && ((mReg.Acc ^ utmp16) & 0x80)), FLAGS_OVERFLOW); - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag(((utmp16 & 0xFF) & FLAGS_SIGN), FLAGS_SIGN); - mReg.Acc = utmp16 & 0xFF; - } - return mReg.Acc; -} - -/* - *-------------------------------------------------------------------- - * Method: SubWithCarry() - * Purpose: Subtract Acc - Mem with Carry, update flags and Acc. - * Arguments: mem8 - memory argument (byte) - * Returns: byte value Acc - Mem - Carry - *-------------------------------------------------------------------- - */ -unsigned char MKCpu::SubWithCarry(unsigned char mem8) -{ - unsigned short utmp16 = mReg.Acc - mem8 - (CheckFlag(FLAGS_CARRY) ? 0 : 1); - - /* This algorithm was shamelessly ripped from Frodo emulator code. - See my comments in AddWithCarry() method. - This method returned the same results when testing BCD mode as Rockwell 6502 AP CPU. - Kowalski's emulator returned different results. - My method also passes BCD mode behavior test by Bruce Clark (TestBCD.65s). - */ - if (CheckFlag(FLAGS_DEC)) { // BCD mode - - unsigned char al = (mReg.Acc & 0x0F) - (mem8 & 0x0F) - (CheckFlag(FLAGS_CARRY) ? 0 : 1); - unsigned char ah = (mReg.Acc >> 4) - (mem8 >> 4); - if (al & 0x10) { - al -= 6; ah--; - } - if (ah & 0x10) ah -= 6; - SetFlag((utmp16 < 0x100), FLAGS_CARRY); - SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag(((utmp16 & 0xFF) & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); - mReg.Acc = (ah << 4) | (al & 0x0f); - - } else { // binary mode - - SetFlag((utmp16 < 0x100), FLAGS_CARRY); - SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); - SetFlag((utmp16 == 0), FLAGS_ZERO); - SetFlag(((utmp16 & 0xFF) & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); - mReg.Acc = utmp16 & 0xFF; - - } - return mReg.Acc; -} - -/* - *-------------------------------------------------------------------- - * Method: ~MKCpu() - * Purpose: Class destructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -MKCpu::~MKCpu() -{ - if (mLocalMem) { - if (NULL != mpMem) - delete mpMem; - } -} - -/* - *-------------------------------------------------------------------- - * Method: GetAddrWithMode() - * Purpose: Get address of the argument with specified mode. - * Increment PC. - * Arguments: mode - code of the addressing mode, see eAddrModes. - * Returns: 16-bit address - *-------------------------------------------------------------------- - */ -unsigned short MKCpu::GetAddrWithMode(int mode) -{ - unsigned short arg16 = 0; - - switch (mode) { - - case ADDRMODE_IMM: - arg16 = mReg.PtrAddr++; - break; - - case ADDRMODE_ABS: - arg16 = GetArg16(0); - break; - - case ADDRMODE_ZP: - arg16 = (unsigned short) mpMem->Peek8bit(mReg.PtrAddr++); - break; - - case ADDRMODE_IMP: - // implied mode is an internal CPU register - break; - - case ADDRMODE_IND: - arg16 = mpMem->Peek16bit(mReg.PtrAddr++); - arg16 = mpMem->Peek16bit(arg16); - break; - - case ADDRMODE_ABX: - arg16 = GetArg16(mReg.IndX); - break; - - case ADDRMODE_ABY: - arg16 = GetArg16(mReg.IndY); - break; - - case ADDRMODE_ZPX: - arg16 = (mpMem->Peek8bit(mReg.PtrAddr++) + mReg.IndX) & 0xFF; - break; - - case ADDRMODE_ZPY: - arg16 = (mpMem->Peek8bit(mReg.PtrAddr++) + mReg.IndY) & 0xFF; - break; - - case ADDRMODE_IZX: - arg16 = (mpMem->Peek8bit(mReg.PtrAddr++) + mReg.IndX) & 0xFF; - arg16 = mpMem->Peek16bit(arg16); - break; - - case ADDRMODE_IZY: - arg16 = mpMem->Peek8bit(mReg.PtrAddr++); - arg16 = mpMem->Peek16bit(arg16) + mReg.IndY; - break; - - case ADDRMODE_REL: - arg16 = ComputeRelJump(mpMem->Peek8bit(mReg.PtrAddr++)); - break; - - case ADDRMODE_ACC: - // acc mode is an internal CPU register - break; - - default: - throw MKGenException("ERROR: Wrong addressing mode!"); - break; - } - - return arg16; -} - -/* - *-------------------------------------------------------------------- - * Method: ExecOpcode() - * Purpose: Execute VM's opcode. - * Arguments: memaddr - address of code in virtual memory. - * Returns: Pointer to CPU registers and flags structure. - *-------------------------------------------------------------------- - */ -Regs *MKCpu::ExecOpcode(unsigned short memaddr) -{ - mReg.PtrAddr = memaddr; - unsigned char opcode = mpMem->Peek8bit(mReg.PtrAddr++); - unsigned char arg8 = 0; - unsigned short arg16 = 0; - - SetFlag(false, FLAGS_BRK); // reset BRK flag - we want to detect - mReg.SoftIrq = false; // software interrupt each time it happens - // (non-maskable) - mReg.LastRTS = false; - - switch (opcode) { - - case OPCODE_BRK: // software interrupt, Implied ($00 : BRK) - arg16 = 0x100; - arg16 += mReg.PtrStack--; - // Note that BRK is really a 2-bytes opcode. Each BRK opcode should be padded by extra byte, - // because the return address put on stack is PC + 1 (where PC is the next address after BRK). - // That means the next opcode after BRK will not be executed upon return from interrupt, - // but the next after that will be. - mReg.PtrAddr++; - mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr) & 0xFF00) >> 8)); // HI(PC+1) - HI part of next instr. addr. + 1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr) & 0x00FF)); // LO(PC+1) - LO part of next instr. addr. + 1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - SetFlag(true, FLAGS_BRK); // The BRK flag that goes on stack is set. - mpMem->Poke8bit(arg16, mReg.Flags); - SetFlag(false, FLAGS_BRK); // The BRK flag that remains in CPU status is unchanged, so unset after putting on stack. - //mReg.SoftIrq = true; - mReg.PtrAddr = mpMem->Peek16bit(0xFFFE); // Load BRK vector into the PC. - break; - - case OPCODE_NOP: // NO oPeration, Implied ($EA : NOP) - break; - - case OPCODE_LDA_IZX: // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ZP: // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg - mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_IMM: // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 - mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ABS: // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_IZY: // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ZPX: // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ABY: // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDA_ABX: // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_LDX_IMM: // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 - mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ZP: // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg - mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ABS: // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mReg.IndX = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ZPY: // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y - arg16 = GetAddrWithMode(ADDRMODE_ZPY); - mReg.IndX = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDX_ABY: // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - mReg.IndX = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndX); - break; - - case OPCODE_LDY_IMM: // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 - mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ZP: // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg - mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ABS: // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mReg.IndY = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ZPX: // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mReg.IndY = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndY); - break; - - case OPCODE_LDY_ABX: // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - mReg.IndY = mpMem->Peek8bit(arg16); - SetFlags(mReg.IndY); - break; - - case OPCODE_TAX: // Transfer A to X, Implied ($AA : TAX) - mReg.IndX = mReg.Acc; - SetFlags(mReg.IndX); - break; - - case OPCODE_TAY: // Transfer A to Y, Implied ($A8 : TAY) - mReg.IndY = mReg.Acc; - SetFlags(mReg.IndY); - break; - - case OPCODE_TXA: // Transfer X to A, Implied ($8A : TXA) - mReg.Acc = mReg.IndX; - SetFlags(mReg.Acc); - break; - - case OPCODE_TYA: // Transfer Y to A, Implied ($98 : TYA) - mReg.Acc = mReg.IndY; - SetFlags(mReg.Acc); - break; - - case OPCODE_TSX: // Transfer Stack ptr to X, Implied ($BA : TSX) - mReg.IndX = mReg.PtrStack; - SetFlags(mReg.IndX); - break; - - case OPCODE_TXS: // Transfer X to Stack ptr, Implied ($9A : TXS) - mReg.PtrStack = mReg.IndX; - break; - - case OPCODE_STA_IZX: // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ZP: // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ABS: // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_IZY: // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ZPX: // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ABY: // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STA_ABX: // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_STX_ZP: // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - mpMem->Poke8bit(arg16, mReg.IndX); - break; - - case OPCODE_STX_ABS: // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mpMem->Poke8bit(arg16, mReg.IndX); - break; - - case OPCODE_STX_ZPY: // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y - arg16 = GetAddrWithMode(ADDRMODE_ZPY); - mpMem->Poke8bit(arg16, mReg.IndX); - break; - - case OPCODE_STY_ZP: // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - mpMem->Poke8bit(arg16, mReg.IndY); - break; - - case OPCODE_STY_ABS: // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - mpMem->Poke8bit(arg16, mReg.IndY); - break; - - case OPCODE_STY_ZPX: // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - mpMem->Poke8bit(arg16, mReg.IndY); - break; - - case OPCODE_BNE_REL: // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_ZERO)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BEQ_REL: // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_ZERO)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BPL_REL: // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_SIGN)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BMI_REL: // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_SIGN)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BVC_REL: // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_OVERFLOW)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BVS_REL: // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_OVERFLOW)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BCC_REL: // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (!CheckFlag(FLAGS_CARRY)) { - mReg.PtrAddr = arg16; - } - break; - - case OPCODE_BCS_REL: // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - arg16 = GetAddrWithMode(ADDRMODE_REL); - if (CheckFlag(FLAGS_CARRY)) { - mReg.PtrAddr = arg16; - } - break; - - /*** - case OPCODE_BRA: // branch always to a relative 1-byte address offset -128 ($80)..127 ($7F) (OPCODE_BEQ reladdr : BEQ reladdr) - arg8 = mpMem->Peek8bit(mReg.PtrAddr++); - mReg.PtrAddr = ComputeRelJump(arg8); - break; - ***/ - - case OPCODE_INC_ZP: // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INC_ABS: // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INC_ZPX: // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INC_ABX: // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16) + 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_INX: // INcrement X, Implied ($E8 : INX) - mReg.IndX++; - SetFlags(mReg.IndX); - break; - - case OPCODE_DEX: // DEcrement X, Implied ($CA : DEX) - mReg.IndX--; - SetFlags(mReg.IndX); - break; - - case OPCODE_INY: // INcrement Y, Implied ($C8 : INY) - mReg.IndY++; - SetFlags(mReg.IndY); - break; - - case OPCODE_DEY: // DEcrement Y, Implied ($88 : DEY) - mReg.IndY--; - SetFlags(mReg.IndY); - break; - - case OPCODE_JMP_ABS: // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr - mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); - break; - - case OPCODE_JMP_IND: // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr - mReg.PtrAddr = GetAddrWithMode(ADDRMODE_IND); - break; - - case OPCODE_ORA_IZX: // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ZP: // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg - LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_OR); - break; - - case OPCODE_ORA_IMM: // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 - LogicOpAcc(GetAddrWithMode(ADDRMODE_IMM), LOGOP_OR); - break; - - case OPCODE_ORA_ABS: // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_IZY: // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ZPX: // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ABY: // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ORA_ABX: // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - LogicOpAcc(arg16, LOGOP_OR); - break; - - case OPCODE_ASL_ZP: // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ASL: // Arithmetic Shift Left, Accumulator ($0A : ASL) - mReg.Acc = ShiftLeft(mReg.Acc); - break; - - case OPCODE_ASL_ABS: // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ASL_ZPX: // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ASL_ABX: // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_JSR_ABS: // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr - // PC - next instruction address - // Push PC-1 on stack (HI, then LO). - // Currently PC (mReg.PtrAddr) is at the 1-st argument of JSR. - // Therefore the actual PC-1 used in calculations equals: mReg.PtrAddr+1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr+1) & 0xFF00) >> 8)); // HI(PC-1) - HI part of next instr. addr. - 1 - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr+1) & 0x00FF)); // LO(PC-1) - LO part of next instr. addr. - 1 - mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); - break; - - case OPCODE_AND_IZX: // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ZP: // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg - LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_AND); - break; - - case OPCODE_AND_IMM: // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 - LogicOpAcc(GetAddrWithMode(ADDRMODE_IMM), LOGOP_AND); - break; - - case OPCODE_AND_ABS: // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_IZY: // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ZPX: // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ABY: // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_AND_ABX: // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - LogicOpAcc(arg16, LOGOP_AND); - break; - - case OPCODE_BIT_ZP: // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 &= mReg.Acc; - SetFlags(arg8); - mReg.Flags |= (arg8 & FLAGS_OVERFLOW); - break; - - case OPCODE_BIT_ABS: // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 &= mReg.Acc; - SetFlags(arg8); - mReg.Flags |= (arg8 & FLAGS_OVERFLOW); - break; - - case OPCODE_ROL_ZP: // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ROL: // ROtate Left, Accumulator ($2A : ROL) - mReg.Acc = RotateLeft(mReg.Acc); - break; - - case OPCODE_ROL_ABS: // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ROL_ZPX: // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ROL_ABX: // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = RotateLeft(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_PHP: // PusH Processor status on Stack, Implied ($08 : PHP) - arg16 = 0x100; - arg16 += mReg.PtrStack--; - arg8 = mReg.Flags | FLAGS_BRK; - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_PHA: // PusH Accumulator, Implied ($48 : PHA) - arg16 = 0x100; - arg16 += mReg.PtrStack--; - mpMem->Poke8bit(arg16, mReg.Acc); - break; - - case OPCODE_PLP: // PuLl Processor status, Implied ($28 : PLP) - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.Flags = mpMem->Peek8bit(arg16); - break; - - case OPCODE_PLA: // PuLl Accumulator, Implied ($68 : PLA) - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.Acc = mpMem->Peek8bit(arg16); - SetFlags(mReg.Acc); - break; - - case OPCODE_CLC: // CLear Carry, Implied ($18 : CLC) - SetFlag(false, FLAGS_CARRY); - break; - - case OPCODE_SEC: // SEt Carry, Implied ($38 : SEC) - SetFlag(true, FLAGS_CARRY); - break; - - case OPCODE_CLI: // CLear Interrupt, Implied ($58 : CLI) - SetFlag(false, FLAGS_IRQ); - break; - - case OPCODE_CLV: // CLear oVerflow, Implied ($B8 : CLV) - SetFlag(false, FLAGS_OVERFLOW); - break; - - case OPCODE_CLD: // CLear Decimal, Implied ($D8 : CLD) - SetFlag(false, FLAGS_DEC); - break; - - case OPCODE_SED: // SEt Decimal, Implied ($F8 : SED) - SetFlag(true, FLAGS_DEC); - break; - - case OPCODE_SEI: // SEt Interrupt, Implied ($78 : SEI) - SetFlag(true, FLAGS_IRQ); - break; - - /* - * RTI retrieves the Processor Status Word (flags) and the Program Counter from the stack in that order - * (interrupts push the PC first and then the PSW). - * Note that unlike RTS, the return address on the stack is the actual address rather than the address-1. - */ - case OPCODE_RTI: // ReTurn from Interrupt, Implied ($40 : RTI) - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.Flags = mpMem->Peek8bit(arg16); - arg16++; mReg.PtrStack++; - mReg.PtrAddr = mpMem->Peek8bit(arg16); - arg16++; mReg.PtrStack++; - mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); - mReg.SoftIrq = CheckFlag(FLAGS_BRK); - break; - - case OPCODE_RTS: // ReTurn from Subroutine, Implied ($60 : RTS) - if (mReg.PtrStack == 0xFF) { - mReg.LastRTS = true; - break; - } - arg16 = 0x100; - arg16 += ++mReg.PtrStack; - mReg.PtrAddr = mpMem->Peek8bit(arg16); - arg16++; mReg.PtrStack++; - mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); - mReg.PtrAddr++; - break; - - case OPCODE_EOR_IZX: // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ZP: // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg - LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_EOR); - break; - - case OPCODE_EOR_IMM: // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 - LogicOpAcc(GetAddrWithMode(ADDRMODE_IMM), LOGOP_EOR); - break; - - case OPCODE_EOR_ABS: // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_IZY: // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ZPX: // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ABY: // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_EOR_ABX: // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - LogicOpAcc(arg16, LOGOP_EOR); - break; - - case OPCODE_LSR_ZP: // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_LSR: // Logical Shift Right, Accumulator ($4A : LSR) - mReg.Acc = ShiftRight(mReg.Acc); - break; - - case OPCODE_LSR_ABS: // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_LSR_ZPX: // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_LSR_ABX: // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - arg8 = ShiftRight(arg8); - mpMem->Poke8bit(arg16, arg8); - break; - - case OPCODE_ADC_IZX: // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ZP: // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_IMM: // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 - AddWithCarry(mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM))); - break; - - case OPCODE_ADC_ABS: // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_IZY: // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ZPX: // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ABY: // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ADC_ABX: // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - AddWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_ROR_ZP: // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_ROR: // ROtate Right, Accumulator ($6A : ROR) - mReg.Acc = RotateRight(mReg.Acc); - break; - - case OPCODE_ROR_ABS: // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_ROR_ZPX: // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_ROR_ABX: // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - mpMem->Poke8bit(arg16, RotateRight(arg8)); - break; - - case OPCODE_CPY_IMM: // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 - arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); - arg8 = mReg.IndY - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPY_ZP: // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); - arg8 = mReg.IndY - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPY_ABS: // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); - arg8 = mReg.IndY - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_IZX: // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ZP: // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_IMM: // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 - arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ABS: // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_IZY: // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ZPX: // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ABY: // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_CMP_ABX: // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); - arg8 = mReg.Acc - arg8; - SetFlags(arg8); - break; - - case OPCODE_DEC_ZP: // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_DEC_ABS: // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_DEC_ZPX: // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_DEC_ABX: // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - arg8 = mpMem->Peek8bit(arg16) - 1; - mpMem->Poke8bit(arg16, arg8); - SetFlags(arg8); - break; - - case OPCODE_CPX_IMM: // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 - arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); - SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); - arg8 = mReg.IndX - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPX_ZP: // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); - arg8 = mReg.IndX - arg8; - SetFlags(arg8); - break; - - case OPCODE_CPX_ABS: // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - arg8 = mpMem->Peek8bit(arg16); - SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); - arg8 = mReg.IndX - arg8; - SetFlags(arg8); - break; - - case OPCODE_SBC_ZP: // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg - arg16 = GetAddrWithMode(ADDRMODE_ZP); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ABS: // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr - arg16 = GetAddrWithMode(ADDRMODE_ABS); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_IZX: // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - arg16 = GetAddrWithMode(ADDRMODE_IZX); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_IZY: // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y - arg16 = GetAddrWithMode(ADDRMODE_IZY); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ZPX: // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X - arg16 = GetAddrWithMode(ADDRMODE_ZPX); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ABY: // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y - arg16 = GetAddrWithMode(ADDRMODE_ABY); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_ABX: // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X - arg16 = GetAddrWithMode(ADDRMODE_ABX); - SubWithCarry(mpMem->Peek8bit(arg16)); - break; - - case OPCODE_SBC_IMM: // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 - SubWithCarry(mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM))); - break; - - default: - break; - } - - return &mReg; -} - -/* - *-------------------------------------------------------------------- - * Method: GetRegs() - * Purpose: Return pointer to CPU registers and status. - * Arguments: n/a - * Returns: pointer to Regs structure. - *-------------------------------------------------------------------- - */ -Regs *MKCpu::GetRegs() -{ - return &mReg; -} - -} // namespace MKBasic + +#include +#include "MKCpu.h" +#include "MKGenException.h" + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +/* + *-------------------------------------------------------------------- + * Method: MKCpu() + * Purpose: Default constructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +MKCpu::MKCpu() +{ + InitCpu(); +} + +/* + *-------------------------------------------------------------------- + * Method: MKCpu() + * Purpose: Custom constructor. + * Arguments: pmem - pointer to Memory object. + * Returns: n/a + *-------------------------------------------------------------------- + */ +MKCpu::MKCpu(Memory *pmem) +{ + mpMem = pmem; + InitCpu(); +} + +/* + *-------------------------------------------------------------------- + * Method: InitCpu() + * Purpose: Initialize internal variables and flags. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + ADDRMODE_IMM = 0, + ADDRMODE_ABS, + ADDRMODE_ZP, + ADDRMODE_IMP, + ADDRMODE_IND, + ADDRMODE_ABX, + ADDRMODE_ABY, + ADDRMODE_ZPX, + ADDRMODE_ZPY, + ADDRMODE_IZX, + ADDRMODE_IZY, + ADDRMODE_REL, + ADDRMODE_ACC, + */ +void MKCpu::InitCpu() +{ + string saArgFmtTbl[] = {"#$%02x", "$%04x", "$%02x", " ", "($%04x)", "$%04x,X", "$%04x,Y", + "$%02x,X", "$%02x,Y", "($%02x,X)", "($%02x),Y", "$%04x", " ", " "}; + int naAddrModesLen[] = {2, 3, 2, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1}; + // Initialize instructions lengths table based on addressing modes + // Initialize assembly argument formats table based on addressing modes + for (int i=0; i $FFF0) + mpMem->Poke8bit(0xFFFE,0xF0); // LSB + mpMem->Poke8bit(0xFFFF,0xFF); // MSB + // Put RTI opcode at BRK procedure address. + mpMem->Poke8bit(0xFFF0, OPCODE_RTI); + // Set default RESET vector ($FFFC -> $0200) + mpMem->Poke8bit(0xFFFC,0x00); // LSB + mpMem->Poke8bit(0xFFFD,0x02); // MSB + // Set BRK code at the RESET procedure address. + mpMem->Poke8bit(0x0200,OPCODE_BRK); +} + +/* + *-------------------------------------------------------------------- + * Method: SetFlags() + * Purpose: Set CPU status flags ZERO and SIGN based on Acc, X or Y + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::SetFlags(unsigned char reg) +{ + SetFlag((0 == reg), FLAGS_ZERO); + SetFlag(((reg & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_SIGN); + SetFlag(true, FLAGS_UNUSED); +} + +/* + *-------------------------------------------------------------------- + * Method: ShiftLeft() + * Purpose: Arithmetic shift left (1 bit), set Carry flag, shift 0 + * into bit #0. Update flags NZ. + * Arguments: arg8 - 8-bit value + * Returns: 8-bit value after shift + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::ShiftLeft(unsigned char arg8) +{ + // set Carry flag based on original bit #7 + SetFlag(((arg8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); + arg8 = arg8 << 1; // shift left + arg8 &= 0xFE; // shift 0 into bit #0 + + SetFlags(arg8); + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: ShiftRight() + * Purpose: Logical Shift Right, update flags NZC. + * Arguments: arg8 - byte value + * Returns: unsigned char (byte) - after shift + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::ShiftRight(unsigned char arg8) +{ + SetFlag(((arg8 & 0x01) == 0x01), FLAGS_CARRY); + arg8 = arg8 >> 1; + arg8 &= 0x7F; // unset bit #7 + SetFlags(arg8); + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: RotateLeft() + * Purpose: Rotate left, Carry to bit 0, bit 7 to Carry, update + flags N and Z. + * Arguments: arg8 - byte value to rotate + * Returns: unsigned char (byte) - rotated value + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::RotateLeft(unsigned char arg8) +{ + unsigned char tmp8 = 0; + + tmp8 = arg8; + arg8 = arg8 << 1; + // Carry goes to bit #0. + if (mReg.Flags & FLAGS_CARRY) { + arg8 |= 0x01; + } else { + arg8 &= 0xFE; + } + // Original (before ROL) bit #7 goes to Carry. + SetFlag(((tmp8 & FLAGS_SIGN) == FLAGS_SIGN), FLAGS_CARRY); + SetFlags(arg8); // set flags Z and N + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: RotateRight() + * Purpose: Rotate Right, Carry to bit 7, bit 0 to Carry, update + flags N and Z. + * Arguments: arg8 - byte value to rotate + * Returns: unsigned char (byte) - rotated value + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::RotateRight(unsigned char arg8) +{ + unsigned char tmp8 = 0; + + tmp8 = arg8; + arg8 = arg8 >> 1; + // Carry goes to bit #7. + if (CheckFlag(FLAGS_CARRY)) { + arg8 |= 0x80; + } else { + arg8 &= 0x7F; + } + // Original (before ROR) bit #0 goes to Carry. + SetFlag(((tmp8 & 0x01) == 0x01), FLAGS_CARRY); + SetFlags(arg8); // set flags Z and N + + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: GetArg16() + * Purpose: Get 2-byte argument, add offset, increase PC. + * Arguments: addr - address of argument in memory + * offs - offset to be added to returned value + * Returns: 16-bit address + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::GetArg16(unsigned char offs) +{ + unsigned short ret = 0; + + ret = mpMem->Peek16bit(mReg.PtrAddr++); + mReg.PtrAddr++; + ret += offs; + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: LogicOpAcc() + * Purpose: Perform logical bitwise operation between memory + * location and Acc, result in Acc. Set flags. + * Arguments: addr - memory location + * logop - logical operation code: LOGOP_OR, LOGOP_AND, + * LOGOP_EOR + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::LogicOpAcc(unsigned short addr, int logop) +{ + unsigned char val = 0; + + val = mpMem->Peek8bit(addr); + switch (logop) { + case LOGOP_OR: + mReg.Acc |= val; + break; + case LOGOP_AND: + mReg.Acc &= val; + break; + case LOGOP_EOR: + mReg.Acc ^= val; + break; + default: + break; + } + SetFlags(mReg.Acc); +} + +/* + *-------------------------------------------------------------------- + * Method: ComputeRelJump() + * Purpose: Compute new PC based on relative offset. + * Arguments: offs - relative offset [-128 ($80)..127 ($7F)] + * Returns: unsigned short - new PC (Program Counter). + * NOTE: + * Program Counter (http://www.6502.org/tutorials/6502opcodes.html#PC) + * When the 6502 is ready for the next instruction it increments the + * program counter before fetching the instruction. Once it has the op + * code, it increments the program counter by the length of the + * operand, if any. This must be accounted for when calculating + * branches or when pushing bytes to create a false return address + * (i.e. jump table addresses are made up of addresses-1 when it is + * intended to use an RTS rather than a JMP). + * The program counter is loaded least signifigant byte first. + * Therefore the most signifigant byte must be pushed first when + * creating a false return address. + * When calculating branches a forward branch of 6 skips the following + * 6 bytes so, effectively the program counter points to the address + * that is 8 bytes beyond the address of the branch opcode; + * and a backward branch of $FA (256-6) goes to an address 4 bytes + * before the branch instruction. + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::ComputeRelJump(unsigned char offs) +{ + // NOTE: mReg.PtrAddr (PC) must be at the next opcode (after branch instr.) at this point. + return ComputeRelJump(mReg.PtrAddr, offs); +} + +/* + *-------------------------------------------------------------------- + * Method: ComputeRelJump() + * Purpose: Compute new address after branch based on relative + * offset. + * Arguments: addr - next opcode address (after branch instr.) + * offs - relative offset [-128 ($80)..127 ($7F)] + * Returns: unsigned short - new address for branch jump + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::ComputeRelJump(unsigned short addr, unsigned char offs) +{ + unsigned short newpc = addr; + + if (offs < 0x80) { + newpc += (unsigned short) offs; + } else { + newpc -= (unsigned short) ((unsigned char)(~offs + 1)); // use binary 2's complement instead of arithmetics + } + + return newpc; +} + +/* + *-------------------------------------------------------------------- + * Method: Conv2Bcd() + * Purpose: Convert 16-bit unsigned number to 8-bit BCD + * representation. + * Arguments: v - 16-bit unsigned integer. + * Returns: byte representing BCD code of the 'v'. + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::Conv2Bcd(unsigned short v) +{ + unsigned char arg8 = 0; + arg8 = (unsigned char)((v/10) << 4); + arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; + return arg8; +} + +/* + *-------------------------------------------------------------------- + * Method: Bcd2Num() + * Purpose: Convert 8-bit BCD code to a number. + * Arguments: v - BCD code. + * Returns: 16-bit unsigned integer + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::Bcd2Num(unsigned char v) +{ + unsigned short ret = 0; + ret = 10 * ((v & 0xF0) >> 4) + (unsigned char)(v & 0x0F); + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: CheckFlag() + * Purpose: Check if given bit flag in CPU status register is set + * or not. + * Arguments: flag - byte with the bit to be checked set and other + * bits not set. + * Returns: bool + *-------------------------------------------------------------------- + */ +bool MKCpu::CheckFlag(unsigned char flag) +{ + return ((mReg.Flags & flag) == flag); +} + +/* + *-------------------------------------------------------------------- + * Method: SetFlag() + * Purpose: Set or unset CPU status flag. + * Arguments: set - if true, set flag, if false, unset flag. + * flag - a byte with a bit set on the position of flag + * being altered and zeroes on other positions. + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::SetFlag(bool set, unsigned char flag) +{ + if (set) { + mReg.Flags |= flag; + } else { + mReg.Flags &= ~flag; + } +} + +/* + *-------------------------------------------------------------------- + * Method: AddWithCarry() + * Purpose: Add Acc + Mem with Carry, update flags and Acc. + * Arguments: mem8 - memory argument (byte) + * Returns: byte value Acc + Mem + Carry + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::AddWithCarry(unsigned char mem8) +{ + // This algorithm was adapted from Frodo emulator code. + unsigned short utmp16 = mReg.Acc + mem8 + (CheckFlag(FLAGS_CARRY) ? 1 : 0); + if (CheckFlag(FLAGS_DEC)) { // BCD mode + + unsigned short al = (mReg.Acc & 0x0F) + (mem8 & 0x0F) + (CheckFlag(FLAGS_CARRY) ? 1 : 0); + if (al > 9) al += 6; + unsigned short ah = (mReg.Acc >> 4) + (mem8 >> 4); + if (al > 0x0F) ah++; + SetFlag((utmp16 == 0), FLAGS_ZERO); + SetFlag(((((ah << 4) ^ mReg.Acc) & 0x80) && !((mReg.Acc ^ mem8) & 0x80)), FLAGS_OVERFLOW); + if (ah > 9) ah += 6; + SetFlag((ah > 0x0F), FLAGS_CARRY); + mReg.Acc = (ah << 4) | (al & 0x0f); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + } else { // binary mode + + SetFlag((utmp16 > 0xff), FLAGS_CARRY); + SetFlag((!((mReg.Acc ^ mem8) & 0x80) && ((mReg.Acc ^ utmp16) & 0x80)), FLAGS_OVERFLOW); + mReg.Acc = utmp16 & 0xFF; + SetFlag((mReg.Acc == 0), FLAGS_ZERO); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + } + SetFlag(true, FLAGS_UNUSED); + return mReg.Acc; +} + +/* + *-------------------------------------------------------------------- + * Method: SubWithCarry() + * Purpose: Subtract Acc - Mem with Carry, update flags and Acc. + * Arguments: mem8 - memory argument (byte) + * Returns: byte value Acc - Mem - Carry + *-------------------------------------------------------------------- + */ +unsigned char MKCpu::SubWithCarry(unsigned char mem8) +{ + unsigned short utmp16 = mReg.Acc - mem8 - (CheckFlag(FLAGS_CARRY) ? 0 : 1); + + // This algorithm was adapted from Frodo emulator code. + if (CheckFlag(FLAGS_DEC)) { // BCD mode + + unsigned char al = (mReg.Acc & 0x0F) - (mem8 & 0x0F) - (CheckFlag(FLAGS_CARRY) ? 0 : 1); + unsigned char ah = (mReg.Acc >> 4) - (mem8 >> 4); + if (al & 0x10) { + al -= 6; ah--; + } + if (ah & 0x10) ah -= 6; + SetFlag((utmp16 < 0x100), FLAGS_CARRY); + SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); + SetFlag((utmp16 == 0), FLAGS_ZERO); + mReg.Acc = (ah << 4) | (al & 0x0f); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + + } else { // binary mode + + SetFlag((utmp16 < 0x100), FLAGS_CARRY); + SetFlag(((mReg.Acc ^ utmp16) & 0x80) && ((mReg.Acc ^ mem8) & 0x80), FLAGS_OVERFLOW); + mReg.Acc = utmp16 & 0xFF; + SetFlag((mReg.Acc == 0), FLAGS_ZERO); + SetFlag((mReg.Acc & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + + } + SetFlag(true, FLAGS_UNUSED); + return mReg.Acc; +} + +/* + *-------------------------------------------------------------------- + * Method: ~MKCpu() + * Purpose: Class destructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +MKCpu::~MKCpu() +{ + if (mLocalMem) { + if (NULL != mpMem) + delete mpMem; + } +} + +/* + *-------------------------------------------------------------------- + * Method: GetAddrWithMode() + * Purpose: Get address of the argument with specified mode. + * Increment PC. + * Arguments: mode - code of the addressing mode, see eAddrModes. + * Returns: 16-bit address + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::GetAddrWithMode(int mode) +{ + unsigned short arg16 = 0; + + mReg.LastAddrMode = mode; + switch (mode) { + + case ADDRMODE_IMM: + arg16 = mReg.PtrAddr++; + break; + + case ADDRMODE_ABS: + mReg.LastArg = arg16 = GetArg16(0); + break; + + case ADDRMODE_ZP: + mReg.LastArg = arg16 = (unsigned short) mpMem->Peek8bit(mReg.PtrAddr++); + break; + + case ADDRMODE_IMP: + // DO NOTHING - implied mode operates on internal CPU register + break; + + case ADDRMODE_IND: + mReg.LastArg = arg16 = mpMem->Peek16bit(mReg.PtrAddr++); + arg16 = mpMem->Peek16bit(arg16); + break; + + case ADDRMODE_ABX: + arg16 = GetArg16(mReg.IndX); + mReg.LastArg = arg16 - mReg.IndX; + break; + + case ADDRMODE_ABY: + arg16 = GetArg16(mReg.IndY); + mReg.LastArg = arg16 - mReg.IndY; + break; + + case ADDRMODE_ZPX: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = (arg16 + mReg.IndX) & 0xFF; + break; + + case ADDRMODE_ZPY: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = (arg16 + mReg.IndY) & 0xFF; + break; + + case ADDRMODE_IZX: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = (arg16 + mReg.IndX) & 0xFF; + arg16 = mpMem->Peek16bit(arg16); + break; + + case ADDRMODE_IZY: + mReg.LastArg = arg16 = mpMem->Peek8bit(mReg.PtrAddr++); + arg16 = mpMem->Peek16bit(arg16) + mReg.IndY; + break; + + case ADDRMODE_REL: + mReg.LastArg = arg16 = ComputeRelJump(mpMem->Peek8bit(mReg.PtrAddr++)); + break; + + case ADDRMODE_ACC: + // DO NOTHING - acc mode operates on internal CPU register + break; + + default: + throw MKGenException("ERROR: Wrong addressing mode!"); + break; + } + + return arg16; +} + +/* + *-------------------------------------------------------------------- + * Method: GetArgWithMode() + * Purpose: Get argument from address with specified mode. + * Arguments: addr - address in memory + * mode - code of the addressing mode, see eAddrModes. + * Returns: argument + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::GetArgWithMode(unsigned short addr, int mode) +{ + unsigned short arg16 = 0; + + switch (mode) { + + case ADDRMODE_IMM: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_ABS: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ZP: + arg16 = (unsigned short) mpMem->Peek8bit(addr); + break; + + case ADDRMODE_IMP: + // DO NOTHING - implied mode operates on internal CPU register + break; + + case ADDRMODE_IND: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ABX: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ABY: + arg16 = mpMem->Peek16bit(addr); + break; + + case ADDRMODE_ZPX: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_ZPY: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_IZX: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_IZY: + arg16 = mpMem->Peek8bit(addr); + break; + + case ADDRMODE_REL: + arg16 = ComputeRelJump(addr+1, mpMem->Peek8bit(addr)); + break; + + case ADDRMODE_ACC: + // DO NOTHING - acc mode operates on internal CPU register + break; + + default: + break; + } + + return arg16; +} + +/* + *-------------------------------------------------------------------- + * Method: Disassemble() + * Purpose: Disassemble instruction and argument per addressing mode + * Arguments: n/a - internal + * Returns: 0 + *-------------------------------------------------------------------- + */ +unsigned short MKCpu::Disassemble() +{ + char sArg[40]; + char sFmt[20]; + + strcpy(sFmt, "%s "); + strcat(sFmt, mArgFmtTbl[mReg.LastAddrMode].c_str()); + sprintf(sArg, sFmt, + ((mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.c_str() : "???"), + mReg.LastArg); + for (unsigned int i=0; iPeek8bit(addr++); + addrmode = (mOpCodesMap[(eOpCodes)opcode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)opcode]).addrmode : -1; + + if (addrmode < 0 || NULL == instrbuf) return 0; + switch (mAddrModesLen[addrmode]) + { + case 2: + sprintf(sBuf, "$%02x ", mpMem->Peek8bit(addr)); + break; + + case 3: + sprintf(sBuf, "$%02x $%02x", mpMem->Peek8bit(addr), mpMem->Peek8bit(addr+1)); + break; + + default: + strcpy(sBuf, " "); + break; + } + strcpy(sFmt, "$%04x: $%02x %s %s "); + strcat(sFmt, mArgFmtTbl[addrmode].c_str()); + sprintf(sArg, sFmt, opcaddr, mpMem->Peek8bit(opcaddr), sBuf, + ((mOpCodesMap[(eOpCodes)opcode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)opcode]).amf.c_str() : "???"), + GetArgWithMode(addr,addrmode)); + for (unsigned int i=0; iPeek8bit(mReg.PtrAddr++); + unsigned char arg8 = 0; + unsigned short arg16 = 0; + + SetFlag(false, FLAGS_BRK); // reset BRK flag - we want to detect + mReg.SoftIrq = false; // software interrupt each time it happens + // (non-maskable) + mReg.LastRTS = false; + mReg.LastOpCode = opcode; + mReg.LastAddrMode = ADDRMODE_UND; + mReg.LastArg = 0; + + switch (opcode) { + + case OPCODE_BRK: // software interrupt, Implied ($00 : BRK) + mReg.LastAddrMode = ADDRMODE_IMP; + if (!CheckFlag(FLAGS_IRQ)) { // only if IRQ not masked + arg16 = 0x100; + arg16 += mReg.PtrStack--; + // Note that BRK is really a 2-bytes opcode. Each BRK opcode should be padded by extra byte, + // because the return address put on stack is PC + 1 (where PC is the next address after BRK). + // That means the next opcode after BRK will not be executed upon return from interrupt, + // but the next after that will be. + mReg.PtrAddr++; + mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr) & 0xFF00) >> 8)); // HI(PC+1) - HI part of next instr. addr. + 1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr) & 0x00FF)); // LO(PC+1) - LO part of next instr. addr. + 1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + SetFlag(true, FLAGS_BRK); // The BRK flag that goes on stack is set. + mpMem->Poke8bit(arg16, mReg.Flags); + SetFlag(false, FLAGS_BRK); // The BRK flag that remains in CPU status is unchanged, so unset after putting on stack. + //mReg.SoftIrq = true; + mReg.PtrAddr = mpMem->Peek16bit(0xFFFE); // Load BRK vector into the PC. + SetFlag(true,FLAGS_IRQ); + } else { + mReg.PtrAddr++; + } + break; + + case OPCODE_NOP: // NO oPeration, Implied ($EA : NOP) + mReg.LastAddrMode = ADDRMODE_IMP; + break; + + case OPCODE_LDA_IZX: // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ZP: // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg + mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_IMM: // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mReg.Acc = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ABS: // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_IZY: // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ZPX: // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ABY: // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDA_ABX: // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_LDX_IMM: // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ZP: // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg + mReg.IndX = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ABS: // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mReg.IndX = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ZPY: // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y + arg16 = GetAddrWithMode(ADDRMODE_ZPY); + mReg.IndX = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDX_ABY: // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + mReg.IndX = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndX); + break; + + case OPCODE_LDY_IMM: // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ZP: // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg + mReg.IndY = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_ZP)); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ABS: // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mReg.IndY = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ZPX: // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mReg.IndY = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndY); + break; + + case OPCODE_LDY_ABX: // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + mReg.IndY = mpMem->Peek8bit(arg16); + SetFlags(mReg.IndY); + break; + + case OPCODE_TAX: // Transfer A to X, Implied ($AA : TAX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX = mReg.Acc; + SetFlags(mReg.IndX); + break; + + case OPCODE_TAY: // Transfer A to Y, Implied ($A8 : TAY) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndY = mReg.Acc; + SetFlags(mReg.IndY); + break; + + case OPCODE_TXA: // Transfer X to A, Implied ($8A : TXA) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.Acc = mReg.IndX; + SetFlags(mReg.Acc); + break; + + case OPCODE_TYA: // Transfer Y to A, Implied ($98 : TYA) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.Acc = mReg.IndY; + SetFlags(mReg.Acc); + break; + + case OPCODE_TSX: // Transfer Stack ptr to X, Implied ($BA : TSX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX = mReg.PtrStack; + SetFlags(mReg.IndX); + break; + + case OPCODE_TXS: // Transfer X to Stack ptr, Implied ($9A : TXS) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.PtrStack = mReg.IndX; + break; + + case OPCODE_STA_IZX: // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ZP: // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ABS: // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_IZY: // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ZPX: // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ABY: // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STA_ABX: // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_STX_ZP: // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + mpMem->Poke8bit(arg16, mReg.IndX); + break; + + case OPCODE_STX_ABS: // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mpMem->Poke8bit(arg16, mReg.IndX); + break; + + case OPCODE_STX_ZPY: // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y + arg16 = GetAddrWithMode(ADDRMODE_ZPY); + mpMem->Poke8bit(arg16, mReg.IndX); + break; + + case OPCODE_STY_ZP: // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + mpMem->Poke8bit(arg16, mReg.IndY); + break; + + case OPCODE_STY_ABS: // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + mpMem->Poke8bit(arg16, mReg.IndY); + break; + + case OPCODE_STY_ZPX: // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + mpMem->Poke8bit(arg16, mReg.IndY); + break; + + case OPCODE_BNE_REL: // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_ZERO)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BEQ_REL: // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_ZERO)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BPL_REL: // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_SIGN)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BMI_REL: // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_SIGN)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BVC_REL: // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_OVERFLOW)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BVS_REL: // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_OVERFLOW)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BCC_REL: // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (!CheckFlag(FLAGS_CARRY)) { + mReg.PtrAddr = arg16; + } + break; + + case OPCODE_BCS_REL: // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + arg16 = GetAddrWithMode(ADDRMODE_REL); + if (CheckFlag(FLAGS_CARRY)) { + mReg.PtrAddr = arg16; + } + break; + + /*** + case OPCODE_BRA: // branch always to a relative 1-byte address offset -128 ($80)..127 ($7F) (OPCODE_BEQ reladdr : BEQ reladdr) + arg8 = mpMem->Peek8bit(mReg.PtrAddr++); + mReg.PtrAddr = ComputeRelJump(arg8); + break; + ***/ + + case OPCODE_INC_ZP: // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INC_ABS: // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INC_ZPX: // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INC_ABX: // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16) + 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_INX: // INcrement X, Implied ($E8 : INX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX++; + SetFlags(mReg.IndX); + break; + + case OPCODE_DEX: // DEcrement X, Implied ($CA : DEX) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndX--; + SetFlags(mReg.IndX); + break; + + case OPCODE_INY: // INcrement Y, Implied ($C8 : INY) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndY++; + SetFlags(mReg.IndY); + break; + + case OPCODE_DEY: // DEcrement Y, Implied ($88 : DEY) + mReg.LastAddrMode = ADDRMODE_IMP; + mReg.IndY--; + SetFlags(mReg.IndY); + break; + + case OPCODE_JMP_ABS: // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr + mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); + break; + + case OPCODE_JMP_IND: // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr + mReg.PtrAddr = GetAddrWithMode(ADDRMODE_IND); + break; + + case OPCODE_ORA_IZX: // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ZP: // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg + LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_OR); + break; + + case OPCODE_ORA_IMM: // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 + arg16 = GetAddrWithMode(ADDRMODE_IMM); + mReg.LastArg = mpMem->Peek8bit(arg16); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ABS: // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_IZY: // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ZPX: // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ABY: // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ORA_ABX: // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + LogicOpAcc(arg16, LOGOP_OR); + break; + + case OPCODE_ASL_ZP: // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ASL: // Arithmetic Shift Left, Accumulator ($0A : ASL) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = ShiftLeft(mReg.Acc); + break; + + case OPCODE_ASL_ABS: // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ASL_ZPX: // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ASL_ABX: // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_JSR_ABS: // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr + // PC - next instruction address + // Push PC-1 on stack (HI, then LO). + // Currently PC (mReg.PtrAddr) is at the 1-st argument of JSR. + // Therefore the actual PC-1 used in calculations equals: mReg.PtrAddr+1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, (unsigned char) (((mReg.PtrAddr+1) & 0xFF00) >> 8)); // HI(PC-1) - HI part of next instr. addr. - 1 + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, (unsigned char) ((mReg.PtrAddr+1) & 0x00FF)); // LO(PC-1) - LO part of next instr. addr. - 1 + mReg.PtrAddr = GetAddrWithMode(ADDRMODE_ABS); + break; + + case OPCODE_AND_IZX: // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ZP: // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg + LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_AND); + break; + + case OPCODE_AND_IMM: // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 + arg16 = GetAddrWithMode(ADDRMODE_IMM); + mReg.LastArg = mpMem->Peek8bit(arg16); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ABS: // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_IZY: // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ZPX: // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ABY: // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_AND_ABX: // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + LogicOpAcc(arg16, LOGOP_AND); + break; + + case OPCODE_BIT_ZP: // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((arg8 & FLAGS_OVERFLOW) == FLAGS_OVERFLOW, FLAGS_OVERFLOW); + SetFlag((arg8 & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + arg8 &= mReg.Acc; + SetFlag((arg8 == 0), FLAGS_ZERO); + break; + + case OPCODE_BIT_ABS: // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((arg8 & FLAGS_OVERFLOW) == FLAGS_OVERFLOW, FLAGS_OVERFLOW); + SetFlag((arg8 & FLAGS_SIGN) == FLAGS_SIGN, FLAGS_SIGN); + arg8 &= mReg.Acc; + SetFlag((arg8 == 0), FLAGS_ZERO); + break; + + case OPCODE_ROL_ZP: // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ROL: // ROtate Left, Accumulator ($2A : ROL) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = RotateLeft(mReg.Acc); + break; + + case OPCODE_ROL_ABS: // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ROL_ZPX: // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ROL_ABX: // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = RotateLeft(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_PHP: // PusH Processor status on Stack, Implied ($08 : PHP) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += mReg.PtrStack--; + arg8 = mReg.Flags | FLAGS_BRK | FLAGS_UNUSED; + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_PHA: // PusH Accumulator, Implied ($48 : PHA) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += mReg.PtrStack--; + mpMem->Poke8bit(arg16, mReg.Acc); + break; + + case OPCODE_PLP: // PuLl Processor status, Implied ($28 : PLP) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.Flags = mpMem->Peek8bit(arg16) | FLAGS_UNUSED; + break; + + case OPCODE_PLA: // PuLl Accumulator, Implied ($68 : PLA) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.Acc = mpMem->Peek8bit(arg16); + SetFlags(mReg.Acc); + break; + + case OPCODE_CLC: // CLear Carry, Implied ($18 : CLC) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_CARRY); + break; + + case OPCODE_SEC: // SEt Carry, Implied ($38 : SEC) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(true, FLAGS_CARRY); + break; + + case OPCODE_CLI: // CLear Interrupt, Implied ($58 : CLI) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_IRQ); + break; + + case OPCODE_CLV: // CLear oVerflow, Implied ($B8 : CLV) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_OVERFLOW); + break; + + case OPCODE_CLD: // CLear Decimal, Implied ($D8 : CLD) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(false, FLAGS_DEC); + break; + + case OPCODE_SED: // SEt Decimal, Implied ($F8 : SED) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(true, FLAGS_DEC); + break; + + case OPCODE_SEI: // SEt Interrupt, Implied ($78 : SEI) + mReg.LastAddrMode = ADDRMODE_IMP; + SetFlag(true, FLAGS_IRQ); + break; + + /* + * RTI retrieves the Processor Status Word (flags) and the Program Counter from the stack in that order + * (interrupts push the PC first and then the PSW). + * Note that unlike RTS, the return address on the stack is the actual address rather than the address-1. + */ + case OPCODE_RTI: // ReTurn from Interrupt, Implied ($40 : RTI) + mReg.LastAddrMode = ADDRMODE_IMP; + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.Flags = mpMem->Peek8bit(arg16); + SetFlag(true,FLAGS_UNUSED); + arg16++; mReg.PtrStack++; + mReg.PtrAddr = mpMem->Peek8bit(arg16); + arg16++; mReg.PtrStack++; + mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); + mReg.SoftIrq = CheckFlag(FLAGS_BRK); + SetFlag(false,FLAGS_IRQ); + break; + + case OPCODE_RTS: // ReTurn from Subroutine, Implied ($60 : RTS) + mReg.LastAddrMode = ADDRMODE_IMP; + if (mReg.PtrStack == 0xFF) { + mReg.LastRTS = true; + break; + } + arg16 = 0x100; + arg16 += ++mReg.PtrStack; + mReg.PtrAddr = mpMem->Peek8bit(arg16); + arg16++; mReg.PtrStack++; + mReg.PtrAddr += (mpMem->Peek8bit(arg16) * 0x100); + mReg.PtrAddr++; + break; + + case OPCODE_EOR_IZX: // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ZP: // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg + LogicOpAcc(GetAddrWithMode(ADDRMODE_ZP), LOGOP_EOR); + break; + + case OPCODE_EOR_IMM: // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 + arg16 = GetAddrWithMode(ADDRMODE_IMM); + mReg.LastArg = mpMem->Peek8bit(arg16); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ABS: // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_IZY: // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ZPX: // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ABY: // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_EOR_ABX: // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + LogicOpAcc(arg16, LOGOP_EOR); + break; + + case OPCODE_LSR_ZP: // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_LSR: // Logical Shift Right, Accumulator ($4A : LSR) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = ShiftRight(mReg.Acc); + break; + + case OPCODE_LSR_ABS: // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_LSR_ZPX: // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_LSR_ABX: // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + arg8 = ShiftRight(arg8); + mpMem->Poke8bit(arg16, arg8); + break; + + case OPCODE_ADC_IZX: // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ZP: // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_IMM: // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + AddWithCarry(mReg.LastArg); + break; + + case OPCODE_ADC_ABS: // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_IZY: // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ZPX: // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ABY: // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ADC_ABX: // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + AddWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_ROR_ZP: // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_ROR: // ROtate Right, Accumulator ($6A : ROR) + mReg.LastAddrMode = ADDRMODE_ACC; + mReg.Acc = RotateRight(mReg.Acc); + break; + + case OPCODE_ROR_ABS: // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_ROR_ZPX: // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_ROR_ABX: // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + mpMem->Poke8bit(arg16, RotateRight(arg8)); + break; + + case OPCODE_CPY_IMM: // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); + arg8 = mReg.IndY - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPY_ZP: // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); + arg8 = mReg.IndY - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPY_ABS: // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndY >= arg8), FLAGS_CARRY); + arg8 = mReg.IndY - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_IZX: // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ZP: // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_IMM: // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ABS: // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_IZY: // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ZPX: // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ABY: // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_CMP_ABX: // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.Acc >= arg8), FLAGS_CARRY); + arg8 = mReg.Acc - arg8; + SetFlags(arg8); + break; + + case OPCODE_DEC_ZP: // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_DEC_ABS: // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_DEC_ZPX: // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_DEC_ABX: // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + arg8 = mpMem->Peek8bit(arg16) - 1; + mpMem->Poke8bit(arg16, arg8); + SetFlags(arg8); + break; + + case OPCODE_CPX_IMM: // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = arg8 = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); + arg8 = mReg.IndX - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPX_ZP: // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); + arg8 = mReg.IndX - arg8; + SetFlags(arg8); + break; + + case OPCODE_CPX_ABS: // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + arg8 = mpMem->Peek8bit(arg16); + SetFlag((mReg.IndX >= arg8), FLAGS_CARRY); + arg8 = mReg.IndX - arg8; + SetFlags(arg8); + break; + + case OPCODE_SBC_ZP: // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg + arg16 = GetAddrWithMode(ADDRMODE_ZP); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ABS: // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr + arg16 = GetAddrWithMode(ADDRMODE_ABS); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_IZX: // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + arg16 = GetAddrWithMode(ADDRMODE_IZX); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_IZY: // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y + arg16 = GetAddrWithMode(ADDRMODE_IZY); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ZPX: // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X + arg16 = GetAddrWithMode(ADDRMODE_ZPX); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ABY: // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y + arg16 = GetAddrWithMode(ADDRMODE_ABY); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_ABX: // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X + arg16 = GetAddrWithMode(ADDRMODE_ABX); + SubWithCarry(mpMem->Peek8bit(arg16)); + break; + + case OPCODE_SBC_IMM: // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 + mReg.LastArg = mpMem->Peek8bit(GetAddrWithMode(ADDRMODE_IMM)); + SubWithCarry(mReg.LastArg); + break; + + default: + // trap illegal opcode that has unidentified behavior + { + string s = ((mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.length() > 0 + ? (mOpCodesMap[(eOpCodes)mReg.LastOpCode]).amf.c_str() : "???"); + if (s.compare("ILL") == 0) { + mReg.SoftIrq = true; + } + } + break; + } + + Disassemble(); + char histentry[80]; + sprintf(histentry, "$%04x: %-16s \t$%02x | $%02x | $%02x | $%02x | $%02x", + mReg.LastAddr, mReg.LastInstr.c_str(), mReg.Acc, mReg.IndX, mReg.IndY, mReg.Flags, mReg.PtrStack); + Add2History(histentry); + + return &mReg; +} + +/* + *-------------------------------------------------------------------- + * Method: GetRegs() + * Purpose: Return pointer to CPU registers and status. + * Arguments: n/a + * Returns: pointer to Regs structure. + *-------------------------------------------------------------------- + */ +Regs *MKCpu::GetRegs() +{ + return &mReg; +} + +/* + *-------------------------------------------------------------------- + * Method: Add2History() + * Purpose: Add entry to execute history. + * Arguments: s - string (entry) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void MKCpu::Add2History(string s) +{ + mExecHistory.push(s); + while (mExecHistory.size() > 20) mExecHistory.pop(); +} + +/* + *-------------------------------------------------------------------- + * Method: GetExecHistory() + * Purpose: Return queue with execute history. + * Arguments: n/a + * Returns: queue + *-------------------------------------------------------------------- + */ +queue MKCpu::GetExecHistory() +{ + return mExecHistory; +} + +} // namespace MKBasic diff --git a/MKCpu.h b/MKCpu.h index ddcdf94..3ccdf4f 100644 --- a/MKCpu.h +++ b/MKCpu.h @@ -1,424 +1,462 @@ -#ifndef MKCPU_H -#define MKCPU_H - -#include "Memory.h" - -namespace MKBasic { - -struct Regs { - unsigned char Acc; // 8-bit accumulator - unsigned short Acc16; // 16-bit accumulator - unsigned char IndX; // 8-bit index register X - unsigned char IndY; // 8-bit index register Y - unsigned short Ptr16; // general purpose 16-bit register - unsigned short PtrAddr; // cpu code counter - current read/write address - unsigned char PtrStack; // 8-bit stack pointer (0-255). - unsigned char Flags; // CPU flags - bool SoftIrq; // true when interrupted with BRK - bool LastRTS; // true if RTS encountered and stack empty. -}; - -/* - * Virtual CPU, 6502 addressing modes: - - +---------------------+--------------------------+ - | mode | assembler format | - +=====================+==========================+ - | Immediate | #aa | - | Absolute | aaaa | - | Zero Page | aa | Note: - | Implied | | - | Indirect Absolute | (aaaa) | aa = 2 hex digits - | Absolute Indexed,X | aaaa,X | as $FF - | Absolute Indexed,Y | aaaa,Y | - | Zero Page Indexed,X | aa,X | aaaa = 4 hex - | Zero Page Indexed,Y | aa,Y | digits as - | Indexed Indirect | (aa,X) | $FFFF - | Indirect Indexed | (aa),Y | - | Relative | aaaa | Can also be - | Accumulator | A | assembler labels - +---------------------+--------------------------+ - -Short notation: - -imm = #$00 -zp = $00 -zpx = $00,X -zpy = $00,Y -izx = ($00,X) -izy = ($00),Y -abs = $0000 -abx = $0000,X -aby = $0000,Y -ind = ($0000) -rel = $0000 (PC-relative) - -See: 6502AssemblyInOneStep.txt for details. - - */ -enum eAddrModes { - ADDRMODE_IMM = 0, - ADDRMODE_ABS, - ADDRMODE_ZP, - ADDRMODE_IMP, - ADDRMODE_IND, - ADDRMODE_ABX, - ADDRMODE_ABY, - ADDRMODE_ZPX, - ADDRMODE_ZPY, - ADDRMODE_IZX, - ADDRMODE_IZY, - ADDRMODE_REL, - ADDRMODE_ACC -}; -// assumed little-endian order of bytes (start with least significant) -// MEM - memory location from where the value is read/written, -// & - reference operator (e.g.: &addr means: value under addr memory location) -// PC - program counter (PC+1 means - next memory location after opcode) -enum eOpCodes { - OPCODE_BRK = 0x00, // software interrupt, no arguments ($00 : BRK) - - /* full compatibility with 65C02 (illegal opcodes not supported, will be used for extended functions */ - OPCODE_ORA_IZX = 0x01, // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_02 = 0x02, // illegal opcode - OPCODE_ILL_03 = 0x03, // illegal opcode - OPCODE_ILL_04 = 0x04, // illegal opcode - OPCODE_ORA_ZP = 0x05, // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg - OPCODE_ASL_ZP = 0x06, // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_07 = 0x07, // illegal opcode - OPCODE_PHP = 0x08, // PusH Processor status on Stack, Implied ($08 : PHP) - OPCODE_ORA_IMM = 0x09, // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ASL = 0x0A, // Arithmetic Shift Left, Accumulator ($0A : ASL) - OPCODE_ILL_0B = 0x0B, // illegal opcode - OPCODE_ILL_0C = 0x0C, // illegal opcode - OPCODE_ORA_ABS = 0x0D, // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr - OPCODE_ASL_ABS = 0x0E, // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_0F = 0x0F, // illegal opcode - OPCODE_BPL_REL = 0x10, // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_ORA_IZY = 0x11, // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_12 = 0x12, // illegal opcode - OPCODE_ILL_13 = 0x13, // illegal opcode - OPCODE_ILL_14 = 0x14, // illegal opcode - OPCODE_ORA_ZPX = 0x15, // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ASL_ZPX = 0x16, // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_17 = 0x17, // illegal opcode - OPCODE_CLC = 0x18, // CLear Carry, Implied ($18 : CLC) - OPCODE_ORA_ABY = 0x19, // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_1A = 0x1A, // illegal opcode - OPCODE_ILL_1B = 0x1B, // illegal opcode - OPCODE_ILL_1C = 0x1C, // illegal opcode - OPCODE_ORA_ABX = 0x1D, // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ASL_ABX = 0x1E, // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_1F = 0x1F, // illegal opcode - OPCODE_JSR_ABS = 0x20, // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr - OPCODE_AND_IZX = 0x21, // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_22 = 0x22, // illegal opcode - OPCODE_ILL_23 = 0x23, // illegal opcode - OPCODE_BIT_ZP = 0x24, // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg - OPCODE_AND_ZP = 0x25, // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg - OPCODE_ROL_ZP = 0x26, // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_27 = 0x27, // illegal opcode - OPCODE_PLP = 0x28, // PuLl Processor status, Implied ($28 : PLP) - OPCODE_AND_IMM = 0x29, // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ROL = 0x2A, // ROtate Left, Accumulator ($2A : ROL) - OPCODE_ILL_2B = 0x2B, // illegal opcode - OPCODE_BIT_ABS = 0x2C, // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr - OPCODE_AND_ABS = 0x2D, // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr - OPCODE_ROL_ABS = 0x2E, // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_2F = 0x2F, // illegal opcode - OPCODE_BMI_REL = 0x30, // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_AND_IZY = 0x31, // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_32 = 0x32, // illegal opcode - OPCODE_ILL_33 = 0x33, // illegal opcode - OPCODE_ILL_34 = 0x34, // illegal opcode - OPCODE_AND_ZPX = 0x35, // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ROL_ZPX = 0x36, // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_37 = 0x37, // illegal opcode - OPCODE_SEC = 0x38, // SEt Carry, Implied ($38 : SEC) - OPCODE_AND_ABY = 0x39, // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_3A = 0x3A, // illegal opcode - OPCODE_ILL_3B = 0x3B, // illegal opcode - OPCODE_ILL_3C = 0x3C, // illegal opcode - OPCODE_AND_ABX = 0x3D, // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ROL_ABX = 0x3E, // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_3F = 0x3F, // illegal opcode - OPCODE_RTI = 0x40, // ReTurn from Interrupt, Implied ($40 : RTI) - OPCODE_EOR_IZX = 0x41, // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_42 = 0x42, // illegal opcode - OPCODE_ILL_43 = 0x43, // illegal opcode - OPCODE_ILL_44 = 0x44, // illegal opcode - OPCODE_EOR_ZP = 0x45, // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg - OPCODE_LSR_ZP = 0x46, // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_47 = 0x47, // illegal opcode - OPCODE_PHA = 0x48, // PusH Accumulator, Implied ($48 : PHA) - OPCODE_EOR_IMM = 0x49, // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_LSR = 0x4A, // Logical Shift Right, Accumulator ($4A : LSR) - OPCODE_ILL_4B = 0x4B, // illegal opcode - OPCODE_JMP_ABS = 0x4C, // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr - OPCODE_EOR_ABS = 0x4D, // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr - OPCODE_LSR_ABS = 0x4E, // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_4F = 0x4F, // illegal opcode - OPCODE_BVC_REL = 0x50, // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_EOR_IZY = 0x51, // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_52 = 0x52, // illegal opcode - OPCODE_ILL_53 = 0x53, // illegal opcode - OPCODE_ILL_54 = 0x54, // illegal opcode - OPCODE_EOR_ZPX = 0x55, // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_LSR_ZPX = 0x56, // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_57 = 0x57, // illegal opcode - OPCODE_CLI = 0x58, // CLear Interrupt, Implied ($58 : CLI) - OPCODE_EOR_ABY = 0x59, // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_5A = 0x5A, // illegal opcode - OPCODE_ILL_5B = 0x5B, // illegal opcode - OPCODE_ILL_5C = 0x5C, // illegal opcode - OPCODE_EOR_ABX = 0x5D, // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_LSR_ABX = 0x5E, // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_5F = 0x5F, // illegal opcode - OPCODE_RTS = 0x60, // ReTurn from Subroutine, Implied ($60 : RTS) - OPCODE_ADC_IZX = 0x61, // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_62 = 0x62, // illegal opcode - OPCODE_ILL_63 = 0x63, // illegal opcode - OPCODE_ILL_64 = 0x64, // illegal opcode - OPCODE_ADC_ZP = 0x65, // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg - OPCODE_ROR_ZP = 0x66, // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_67 = 0x67, // illegal opcode - OPCODE_PLA = 0x68, // PuLl Accumulator, Implied ($68 : PLA) - OPCODE_ADC_IMM = 0x69, // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ROR = 0x6A, // ROtate Right, Accumulator ($6A : ROR) - OPCODE_ILL_6B = 0x6B, // illegal opcode - OPCODE_JMP_IND = 0x6C, // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr - OPCODE_ADC_ABS = 0x6D, // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr - OPCODE_ROR_ABS = 0x6E, // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_6F = 0x6F, // illegal opcode - OPCODE_BVS_REL = 0x70, // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_ADC_IZY = 0x71, // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_72 = 0x72, // illegal opcode - OPCODE_ILL_73 = 0x73, // illegal opcode - OPCODE_ILL_74 = 0x74, // illegal opcode - OPCODE_ADC_ZPX = 0x75, // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ROR_ZPX = 0x76, // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_77 = 0x77, // illegal opcode - OPCODE_SEI = 0x78, // SEt Interrupt, Implied ($78 : SEI) - OPCODE_ADC_ABY = 0x79, // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_7A = 0x7A, // illegal opcode - OPCODE_ILL_7B = 0x7B, // illegal opcode - OPCODE_ILL_7C = 0x7C, // illegal opcode - OPCODE_ADC_ABX = 0x7D, // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ROR_ABX = 0x7E, // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_7F = 0x7F, // illegal opcode - OPCODE_ILL_80 = 0x80, // illegal opcode - OPCODE_STA_IZX = 0x81, // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_82 = 0x82, // illegal opcode - OPCODE_ILL_83 = 0x83, // illegal opcode - OPCODE_STY_ZP = 0x84, // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg - OPCODE_STA_ZP = 0x85, // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg - OPCODE_STX_ZP = 0x86, // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_87 = 0x87, // illegal opcode - OPCODE_DEY = 0x88, // DEcrement Y, Implied ($88 : DEY) - OPCODE_ILL_89 = 0x89, // illegal opcode - OPCODE_TXA = 0x8A, // Transfer X to A, Implied ($8A : TXA) - OPCODE_ILL_8B = 0x8B, // illegal opcode - OPCODE_STY_ABS = 0x8C, // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr - OPCODE_STA_ABS = 0x8D, // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr - OPCODE_STX_ABS = 0x8E, // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_8F = 0x8F, // illegal opcode - OPCODE_BCC_REL = 0x90, // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_STA_IZY = 0x91, // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_92 = 0x92, // illegal opcode - OPCODE_ILL_93 = 0x93, // illegal opcode - OPCODE_STY_ZPX = 0x94, // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_STA_ZPX = 0x95, // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_STX_ZPY = 0x96, // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y - OPCODE_ILL_97 = 0x97, // illegal opcode - OPCODE_TYA = 0x98, // Transfer Y to A, Implied ($98 : TYA) - OPCODE_STA_ABY = 0x99, // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_TXS = 0x9A, // Transfer X to Stack ptr, Implied ($9A : TXS) - OPCODE_ILL_9B = 0x9B, // illegal opcode - OPCODE_ILL_9C = 0x9C, // illegal opcode - OPCODE_STA_ABX = 0x9D, // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_9E = 0x9E, // illegal opcode - OPCODE_ILL_9F = 0x9F, // illegal opcode - OPCODE_LDY_IMM = 0xA0, // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_LDA_IZX = 0xA1, // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_LDX_IMM = 0xA2, // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_ILL_A3 = 0xA3, // illegal opcode - OPCODE_LDY_ZP = 0xA4, // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg - OPCODE_LDA_ZP = 0xA5, // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg - OPCODE_LDX_ZP = 0xA6, // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_A7 = 0xA7, // illegal opcode - OPCODE_TAY = 0xA8, // Transfer A to Y, Implied ($A8 : TAY) - OPCODE_LDA_IMM = 0xA9, // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_TAX = 0xAA, // Transfer A to X, Implied ($AA : TAX) - OPCODE_ILL_AB = 0xAB, // illegal opcode - OPCODE_LDY_ABS = 0xAC, // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr - OPCODE_LDA_ABS = 0xAD, // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr - OPCODE_LDX_ABS = 0xAE, // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_AF = 0xAF, // illegal opcode - OPCODE_BCS_REL = 0xB0, // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_LDA_IZY = 0xB1, // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_B2 = 0xB2, // illegal opcode - OPCODE_ILL_B3 = 0xB3, // illegal opcode - OPCODE_LDY_ZPX = 0xB4, // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_LDA_ZPX = 0xB5, // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_LDX_ZPY = 0xB6, // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y - OPCODE_ILL_B7 = 0xB7, // illegal opcode - OPCODE_CLV = 0xB8, // CLear oVerflow, Implied ($B8 : CLV) - OPCODE_LDA_ABY = 0xB9, // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_TSX = 0xBA, // Transfer Stack ptr to X, Implied ($BA : TSX) - OPCODE_ILL_BB = 0xBB, // illegal opcode - OPCODE_LDY_ABX = 0xBC, // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_LDA_ABX = 0xBD, // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_LDX_ABY = 0xBE, // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_BF = 0xBF, // illegal opcode - OPCODE_CPY_IMM = 0xC0, // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_CMP_IZX = 0xC1, // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_C2 = 0xC2, // illegal opcode - OPCODE_ILL_C3 = 0xC3, // illegal opcode - OPCODE_CPY_ZP = 0xC4, // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg - OPCODE_CMP_ZP = 0xC5, // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg - OPCODE_DEC_ZP = 0xC6, // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_C7 = 0xC7, // illegal opcode - OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY)OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY) - OPCODE_CMP_IMM = 0xC9, // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_DEX = 0xCA, // DEcrement X, Implied ($CA : DEX) - OPCODE_ILL_CB = 0xCB, // illegal opcode - OPCODE_CPY_ABS = 0xCC, // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr - OPCODE_CMP_ABS = 0xCD, // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - OPCODE_DEC_ABS = 0xCE, // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_CF = 0xCF, // illegal opcode - OPCODE_BNE_REL = 0xD0, // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_CMP_IZY = 0xD1, // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_D2 = 0xD2, // illegal opcode - OPCODE_ILL_D3 = 0xD3, // illegal opcode - OPCODE_ILL_D4 = 0xD4, // illegal opcode - OPCODE_CMP_ZPX = 0xD5, // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_DEC_ZPX = 0xD6, // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_D7 = 0xD7, // illegal opcode - OPCODE_CLD = 0xD8, // CLear Decimal, Implied ($D8 : CLD) - OPCODE_CMP_ABY = 0xD9, // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_DA = 0xDA, // illegal opcode - OPCODE_ILL_DB = 0xDB, // illegal opcode - OPCODE_ILL_DC = 0xDC, // illegal opcode - OPCODE_CMP_ABX = 0xDD, // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_DEC_ABX = 0xDE, // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_DF = 0xDF, // illegal opcode - OPCODE_CPX_IMM = 0xE0, // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_SBC_IZX = 0xE1, // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) - OPCODE_ILL_E2 = 0xE2, // illegal opcode - OPCODE_ILL_E3 = 0xE3, // illegal opcode - OPCODE_CPX_ZP = 0xE4, // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg - OPCODE_SBC_ZP = 0xE5, // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg - OPCODE_INC_ZP = 0xE6, // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg - OPCODE_ILL_E7 = 0xE7, // illegal opcode - OPCODE_INX = 0xE8, // INcrement X, Implied ($E8 : INX) - OPCODE_SBC_IMM = 0xE9, // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 - OPCODE_NOP = 0xEA, // NO oPeration, Implied ($EA : NOP) - OPCODE_ILL_EB = 0xEB, // illegal opcode - OPCODE_CPX_ABS = 0xEC, // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr - OPCODE_SBC_ABS = 0xED, // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr - OPCODE_INC_ABS = 0xEE, // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr - OPCODE_ILL_EF = 0xEF, // illegal opcode - OPCODE_BEQ_REL = 0xF0, // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) - OPCODE_SBC_IZY = 0xF1, // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y - OPCODE_ILL_F2 = 0xF2, // illegal opcode - OPCODE_ILL_F3 = 0xF3, // illegal opcode - OPCODE_ILL_F4 = 0xF4, // illegal opcode - OPCODE_SBC_ZPX = 0xF5, // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_INC_ZPX = 0xF6, // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X - OPCODE_ILL_F7 = 0xF7, // illegal opcode - OPCODE_SED = 0xF8, // SEt Decimal, Implied ($F8 : SED) - OPCODE_SBC_ABY = 0xF9, // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y - OPCODE_ILL_FA = 0xFA, // illegal opcode - OPCODE_ILL_FB = 0xFB, // illegal opcode - OPCODE_ILL_FC = 0xFC, // illegal opcode - OPCODE_SBC_ABX = 0xFD, // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_INC_ABX = 0xFE, // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X - OPCODE_ILL_FF = 0xFF, // illegal opcode -}; - -/* - *------------------------------------------------------------------------------ - bit -> 7 0 - +---+---+---+---+---+---+---+---+ - | N | V | | B | D | I | Z | C | <-- flag, 0/1 = reset/set - +---+---+---+---+---+---+---+---+ - - - N = NEGATIVE. Set if bit 7 of the accumulator is set. - - V = OVERFLOW. Set if the addition of two like-signed numbers or the - subtraction of two unlike-signed numbers produces a result - greater than +127 or less than -128. - - B = BRK COMMAND. Set if an interrupt caused by a BRK, reset if - caused by an external interrupt. - - D = DECIMAL MODE. Set if decimal mode active. - - I = IRQ DISABLE. Set if maskable interrupts are disabled. - - Z = ZERO. Set if the result of the last operation (load/inc/dec/ - add/sub) was zero. - - C = CARRY. Set if the add produced a carry, or if the subtraction - produced a borrow. Also holds bits after a logical shift. - *------------------------------------------------------------------------------ - */ -enum eCpuFlagMasks { - FLAGS_CARRY = 0x01, // 0: C - FLAGS_ZERO = 0x02, // 1: Z - FLAGS_IRQ = 0x04, // 2: I - FLAGS_DEC = 0x08, // 3: D - FLAGS_BRK = 0x10, // 4: B (Clear if interrupt vectoring, set if BRK or PHP) - FLAGS_UNUSED = 0x20, // 5: Unused flag (always set). - FLAGS_OVERFLOW = 0x40, // 6: V - FLAGS_SIGN = 0x80 // 7: N -}; - -enum eLogicOps { - LOGOP_OR, - LOGOP_AND, - LOGOP_EOR -}; - -class MKCpu -{ - public: - - MKCpu(); - MKCpu(Memory *pmem); - ~MKCpu(); - - Regs *ExecOpcode(unsigned short memaddr); - Regs *GetRegs(); - - protected: - - private: - - struct Regs mReg; // CPU registers - Memory *mpMem; // pointer to memory object - bool mLocalMem; // true - memory locally allocated - - void InitCpu(); - void SetFlags(unsigned char reg); // set CPU flags ZERO and SIGN based on Acc, X or Y - unsigned char ShiftLeft(unsigned char arg8); // Arithmetic Shift Left, set Carry flag - unsigned char ShiftRight(unsigned char arg8); // Logical Shift Right, update flags NZC. - unsigned char RotateLeft(unsigned char arg8); // Rotate left, Carry to bit 0, bit 7 to Carry, update flags N and Z. - unsigned char RotateRight(unsigned char arg8); // Rotate left, Carry to bit 7, bit 0 to Carry, update flags N and Z. - unsigned short GetArg16(unsigned char offs); // Get 2-byte argument, add offset, increase PC. - void LogicOpAcc(unsigned short addr, int logop); // Perform logical bitwise operation between memory location and Acc. - // Result in Acc. Set flags. - unsigned short ComputeRelJump(unsigned char offs); // Compute new PC based on relative offset. - unsigned char Conv2Bcd(unsigned short v); // Convert number to BCD representation. - unsigned short Bcd2Num(unsigned char v); // Convert BCD code to number. - bool CheckFlag(unsigned char flag); // Return true if given CPU status flag is set, false otherwise. - void SetFlag(bool set, unsigned char flag); // Set or unset processor status flag. - unsigned char AddWithCarry(unsigned char mem8); // Add With Carry, update flags and Acc. - unsigned char SubWithCarry(unsigned char mem8); // Subtract With Carry, update flags and Acc. - unsigned short GetAddrWithMode(int mode); // Get address of the byte argument with specified addr. mode -}; - -} // namespace MKBasic - -#endif +#ifndef MKCPU_H +#define MKCPU_H + +#include +#include +#include +#include "system.h" +#include "Memory.h" + +using namespace std; + +namespace MKBasic { + +#define DISS_BUF_SIZE 60 // disassembled instruction buffer size + +struct Regs { + unsigned char Acc; // 8-bit accumulator + unsigned short Acc16; // 16-bit accumulator + unsigned char IndX; // 8-bit index register X + unsigned char IndY; // 8-bit index register Y + unsigned short Ptr16; // general purpose 16-bit register + unsigned short PtrAddr; // cpu code counter (PC) - current read/write address + unsigned char PtrStack; // 8-bit stack pointer (0-255). + unsigned char Flags; // CPU flags + bool SoftIrq; // true when interrupted with BRK or trapped opcode + bool LastRTS; // true if RTS encountered and stack empty. + unsigned short LastAddr; // PC at the time of previous op-code + string LastInstr; // instruction and argument executed in previous step + int LastOpCode; // op-code of last instruction + unsigned short LastArg; // argument to the last instruction + int LastAddrMode; // addressing mode of last instruction +}; + +/* + * Virtual CPU, 6502 addressing modes: + + +---------------------+--------------------------+ + | mode | assembler format | + +=====================+==========================+ + | Immediate | #aa | + | Absolute | aaaa | + | Zero Page | aa | Note: + | Implied | | + | Indirect Absolute | (aaaa) | aa = 2 hex digits + | Absolute Indexed,X | aaaa,X | as $FF + | Absolute Indexed,Y | aaaa,Y | + | Zero Page Indexed,X | aa,X | aaaa = 4 hex + | Zero Page Indexed,Y | aa,Y | digits as + | Indexed Indirect | (aa,X) | $FFFF + | Indirect Indexed | (aa),Y | + | Relative | aaaa | Can also be + | Accumulator | A | assembler labels + +---------------------+--------------------------+ + +Short notation: + +imm = #$00 +zp = $00 +zpx = $00,X +zpy = $00,Y +izx = ($00,X) +izy = ($00),Y +abs = $0000 +abx = $0000,X +aby = $0000,Y +ind = ($0000) +rel = $0000 (PC-relative) + +See: 6502AssemblyInOneStep.txt for details. + + */ +enum eAddrModes { + ADDRMODE_IMM = 0, + ADDRMODE_ABS, + ADDRMODE_ZP, + ADDRMODE_IMP, + ADDRMODE_IND, + ADDRMODE_ABX, + ADDRMODE_ABY, + ADDRMODE_ZPX, + ADDRMODE_ZPY, + ADDRMODE_IZX, + ADDRMODE_IZY, + ADDRMODE_REL, + ADDRMODE_ACC, + ADDRMODE_UND, // undetermined (for some illegal codes) + ADDRMODE_LENGTH // should be always last +}; +// assumed little-endian order of bytes (start with least significant) +// MEM - memory location from where the value is read/written, +// & - reference operator (e.g.: &addr means: value under addr memory location) +// PC - program counter (PC+1 means - next memory location after opcode) +enum eOpCodes { + OPCODE_BRK = 0x00, // software interrupt, no arguments ($00 : BRK) + + /* full compatibility with 65C02 (illegal opcodes not supported, will be used for extended functions */ + OPCODE_ORA_IZX = 0x01, // bitwise OR with Accumulator, Indexed Indirect ($01 arg : ORA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_02 = 0x02, // illegal opcode + OPCODE_ILL_03 = 0x03, // illegal opcode + OPCODE_ILL_04 = 0x04, // illegal opcode + OPCODE_ORA_ZP = 0x05, // bitwise OR with Accumulator, Zero Page ($05 arg : ORA arg ;arg=0..$FF), MEM=arg + OPCODE_ASL_ZP = 0x06, // Arithmetic Shift Left, Zero Page ($06 arg : ASL arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_07 = 0x07, // illegal opcode + OPCODE_PHP = 0x08, // PusH Processor status on Stack, Implied ($08 : PHP) + OPCODE_ORA_IMM = 0x09, // bitwise OR with Accumulator, Immediate ($09 arg : ORA #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ASL = 0x0A, // Arithmetic Shift Left, Accumulator ($0A : ASL) + OPCODE_ILL_0B = 0x0B, // illegal opcode + OPCODE_ILL_0C = 0x0C, // illegal opcode + OPCODE_ORA_ABS = 0x0D, // bitwise OR with Accumulator, Absolute ($0D addrlo addrhi : ORA addr ;addr=0..$FFFF), MEM=addr + OPCODE_ASL_ABS = 0x0E, // Arithmetic Shift Left, Absolute ($0E addrlo addrhi : ASL addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_0F = 0x0F, // illegal opcode + OPCODE_BPL_REL = 0x10, // Branch on PLus, Relative ($10 signoffs : BPL signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_ORA_IZY = 0x11, // bitwise OR with Accumulator, Indirect Indexed ($11 arg : ORA (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_12 = 0x12, // illegal opcode + OPCODE_ILL_13 = 0x13, // illegal opcode + OPCODE_ILL_14 = 0x14, // illegal opcode + OPCODE_ORA_ZPX = 0x15, // bitwise OR with Accumulator, Zero Page Indexed, X ($15 arg : ORA arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ASL_ZPX = 0x16, // Arithmetic Shift Left, Zero Page Indexed, X ($16 arg : ASL arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_17 = 0x17, // illegal opcode + OPCODE_CLC = 0x18, // CLear Carry, Implied ($18 : CLC) + OPCODE_ORA_ABY = 0x19, // bitwise OR with Accumulator, Absolute Indexed, Y ($19 addrlo addrhi : ORA addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_1A = 0x1A, // illegal opcode + OPCODE_ILL_1B = 0x1B, // illegal opcode + OPCODE_ILL_1C = 0x1C, // illegal opcode + OPCODE_ORA_ABX = 0x1D, // bitwise OR with Accumulator, Absolute Indexed, X ($1D addrlo addrhi : ORA addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ASL_ABX = 0x1E, // Arithmetic Shift Left, Absolute Indexed, X ($1E addrlo addrhi : ASL addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_1F = 0x1F, // illegal opcode + OPCODE_JSR_ABS = 0x20, // Jump to SubRoutine, Absolute ($20 addrlo addrhi : JSR addr ;addr=0..$FFFF), MEM=addr + OPCODE_AND_IZX = 0x21, // bitwise AND with accumulator, Indexed Indirect ($21 arg : AND (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_22 = 0x22, // illegal opcode + OPCODE_ILL_23 = 0x23, // illegal opcode + OPCODE_BIT_ZP = 0x24, // test BITs, Zero Page ($24 arg : BIT arg ;arg=0..$FF), MEM=arg + OPCODE_AND_ZP = 0x25, // bitwise AND with accumulator, Zero Page ($25 arg : AND arg ;arg=0..$FF), MEM=arg + OPCODE_ROL_ZP = 0x26, // ROtate Left, Zero Page ($26 arg : ROL arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_27 = 0x27, // illegal opcode + OPCODE_PLP = 0x28, // PuLl Processor status, Implied ($28 : PLP) + OPCODE_AND_IMM = 0x29, // bitwise AND with accumulator, Immediate ($29 arg : AND #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ROL = 0x2A, // ROtate Left, Accumulator ($2A : ROL) + OPCODE_ILL_2B = 0x2B, // illegal opcode + OPCODE_BIT_ABS = 0x2C, // test BITs, Absolute ($2C addrlo addrhi : BIT addr ;addr=0..$FFFF), MEM=addr + OPCODE_AND_ABS = 0x2D, // bitwise AND with accumulator, Absolute ($2D addrlo addrhi : AND addr ;addr=0..$FFFF), MEM=addr + OPCODE_ROL_ABS = 0x2E, // ROtate Left, Absolute ($2E addrlo addrhi : ROL addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_2F = 0x2F, // illegal opcode + OPCODE_BMI_REL = 0x30, // Branch on MInus, Relative ($30 signoffs : BMI signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_AND_IZY = 0x31, // bitwise AND with accumulator, Indirect Indexed ($31 arg : AND (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_32 = 0x32, // illegal opcode + OPCODE_ILL_33 = 0x33, // illegal opcode + OPCODE_ILL_34 = 0x34, // illegal opcode + OPCODE_AND_ZPX = 0x35, // bitwise AND with accumulator, Zero Page Indexed, X ($35 arg : AND arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ROL_ZPX = 0x36, // ROtate Left, Zero Page Indexed, X ($36 arg : ROL arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_37 = 0x37, // illegal opcode + OPCODE_SEC = 0x38, // SEt Carry, Implied ($38 : SEC) + OPCODE_AND_ABY = 0x39, // bitwise AND with accumulator, Absolute Indexed, Y ($39 addrlo addrhi : AND addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_3A = 0x3A, // illegal opcode + OPCODE_ILL_3B = 0x3B, // illegal opcode + OPCODE_ILL_3C = 0x3C, // illegal opcode + OPCODE_AND_ABX = 0x3D, // bitwise AND with accumulator, Absolute Indexed, X ($3D addrlo addrhi : AND addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ROL_ABX = 0x3E, // ROtate Left, Absolute Indexed, X ($3E addrlo addrhi : ROL addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_3F = 0x3F, // illegal opcode + OPCODE_RTI = 0x40, // ReTurn from Interrupt, Implied ($40 : RTI) + OPCODE_EOR_IZX = 0x41, // bitwise Exclusive OR, Indexed Indirect ($41 arg : EOR (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_42 = 0x42, // illegal opcode + OPCODE_ILL_43 = 0x43, // illegal opcode + OPCODE_ILL_44 = 0x44, // illegal opcode + OPCODE_EOR_ZP = 0x45, // bitwise Exclusive OR, Zero Page ($45 arg : EOR arg ;arg=0..$FF), MEM=arg + OPCODE_LSR_ZP = 0x46, // Logical Shift Right, Zero Page ($46 arg : LSR arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_47 = 0x47, // illegal opcode + OPCODE_PHA = 0x48, // PusH Accumulator, Implied ($48 : PHA) + OPCODE_EOR_IMM = 0x49, // bitwise Exclusive OR, Immediate ($49 arg : EOR #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_LSR = 0x4A, // Logical Shift Right, Accumulator ($4A : LSR) + OPCODE_ILL_4B = 0x4B, // illegal opcode + OPCODE_JMP_ABS = 0x4C, // JuMP, Absolute ($4C addrlo addrhi : JMP addr ;addr=0..$FFFF), MEM=addr + OPCODE_EOR_ABS = 0x4D, // bitwise Exclusive OR, Absolute ($4D addrlo addrhi : EOR addr ;addr=0..$FFFF), MEM=addr + OPCODE_LSR_ABS = 0x4E, // Logical Shift Right, Absolute ($4E addrlo addrhi : LSR addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_4F = 0x4F, // illegal opcode + OPCODE_BVC_REL = 0x50, // Branch on oVerflow Clear, Relative ($50 signoffs : BVC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_EOR_IZY = 0x51, // bitwise Exclusive OR, Indirect Indexed ($51 arg : EOR (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_52 = 0x52, // illegal opcode + OPCODE_ILL_53 = 0x53, // illegal opcode + OPCODE_ILL_54 = 0x54, // illegal opcode + OPCODE_EOR_ZPX = 0x55, // bitwise Exclusive OR, Zero Page Indexed, X ($55 arg : EOR arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_LSR_ZPX = 0x56, // Logical Shift Right, Zero Page Indexed, X ($56 arg : LSR arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_57 = 0x57, // illegal opcode + OPCODE_CLI = 0x58, // CLear Interrupt, Implied ($58 : CLI) + OPCODE_EOR_ABY = 0x59, // bitwise Exclusive OR, Absolute Indexed, Y ($59 addrlo addrhi : EOR addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_5A = 0x5A, // illegal opcode + OPCODE_ILL_5B = 0x5B, // illegal opcode + OPCODE_ILL_5C = 0x5C, // illegal opcode + OPCODE_EOR_ABX = 0x5D, // bitwise Exclusive OR, Absolute Indexed, X ($5D addrlo addrhi : EOR addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_LSR_ABX = 0x5E, // Logical Shift Right, Absolute Indexed, X ($5E addrlo addrhi : LSR addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_5F = 0x5F, // illegal opcode + OPCODE_RTS = 0x60, // ReTurn from Subroutine, Implied ($60 : RTS) + OPCODE_ADC_IZX = 0x61, // ADd with Carry, Indexed Indirect ($61 arg : ADC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_62 = 0x62, // illegal opcode + OPCODE_ILL_63 = 0x63, // illegal opcode + OPCODE_ILL_64 = 0x64, // illegal opcode + OPCODE_ADC_ZP = 0x65, // ADd with Carry, Zero Page ($65 arg : ADC arg ;arg=0..$FF), MEM=arg + OPCODE_ROR_ZP = 0x66, // ROtate Right, Zero Page ($66 arg : ROR arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_67 = 0x67, // illegal opcode + OPCODE_PLA = 0x68, // PuLl Accumulator, Implied ($68 : PLA) + OPCODE_ADC_IMM = 0x69, // ADd with Carry, Immediate ($69 arg : ADC #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ROR = 0x6A, // ROtate Right, Accumulator ($6A : ROR) + OPCODE_ILL_6B = 0x6B, // illegal opcode + OPCODE_JMP_IND = 0x6C, // JuMP, Indirect Absolute ($6C addrlo addrhi : JMP (addr) ;addr=0..FFFF), MEM=&addr + OPCODE_ADC_ABS = 0x6D, // ADd with Carry, Absolute ($6D addrlo addrhi : ADC addr ;addr=0..$FFFF), MEM=addr + OPCODE_ROR_ABS = 0x6E, // ROtate Right, Absolute ($6E addrlo addrhi : ROR addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_6F = 0x6F, // illegal opcode + OPCODE_BVS_REL = 0x70, // Branch on oVerflow Set, Relative ($70 signoffs : BVS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_ADC_IZY = 0x71, // ADd with Carry, Indirect Indexed ($71 arg : ADC (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_72 = 0x72, // illegal opcode + OPCODE_ILL_73 = 0x73, // illegal opcode + OPCODE_ILL_74 = 0x74, // illegal opcode + OPCODE_ADC_ZPX = 0x75, // ADd with Carry, Zero Page Indexed, X ($75 arg : ADC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ROR_ZPX = 0x76, // ROtate Right, Zero Page Indexed, X ($76 arg : ROR arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_77 = 0x77, // illegal opcode + OPCODE_SEI = 0x78, // SEt Interrupt, Implied ($78 : SEI) + OPCODE_ADC_ABY = 0x79, // ADd with Carry, Absolute Indexed, Y ($79 addrlo addrhi : ADC addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_7A = 0x7A, // illegal opcode + OPCODE_ILL_7B = 0x7B, // illegal opcode + OPCODE_ILL_7C = 0x7C, // illegal opcode + OPCODE_ADC_ABX = 0x7D, // ADd with Carry, Absolute Indexed, X ($7D addrlo addrhi : ADC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ROR_ABX = 0x7E, // ROtate Right, Absolute Indexed, X ($7E addrlo addrhi : ROR addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_7F = 0x7F, // illegal opcode + OPCODE_ILL_80 = 0x80, // illegal opcode + OPCODE_STA_IZX = 0x81, // STore Accumulator, Indexed Indirect ($81 arg : STA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_82 = 0x82, // illegal opcode + OPCODE_ILL_83 = 0x83, // illegal opcode + OPCODE_STY_ZP = 0x84, // STore Y register, Zero Page ($84 arg : STY arg ;arg=0..$FF), MEM=arg + OPCODE_STA_ZP = 0x85, // STore Accumulator, Zero Page ($85 arg : STA arg ;arg=0..$FF), MEM=arg + OPCODE_STX_ZP = 0x86, // STore X register, Zero Page ($86 arg : STX arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_87 = 0x87, // illegal opcode + OPCODE_DEY = 0x88, // DEcrement Y, Implied ($88 : DEY) + OPCODE_ILL_89 = 0x89, // illegal opcode + OPCODE_TXA = 0x8A, // Transfer X to A, Implied ($8A : TXA) + OPCODE_ILL_8B = 0x8B, // illegal opcode + OPCODE_STY_ABS = 0x8C, // STore Y register, Absolute ($8C addrlo addrhi : STY addr ;addr=0..$FFFF), MEM=addr + OPCODE_STA_ABS = 0x8D, // STore Accumulator, Absolute ($8D addrlo addrhi : STA addr ;addr=0..$FFFF), MEM=addr + OPCODE_STX_ABS = 0x8E, // STore X register, Absolute ($8E addrlo addrhi : STX addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_8F = 0x8F, // illegal opcode + OPCODE_BCC_REL = 0x90, // Branch on Carry Clear, Relative ($90 signoffs : BCC signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_STA_IZY = 0x91, // STore Accumulator, Indirect Indexed ($91 arg : STA (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_92 = 0x92, // illegal opcode + OPCODE_ILL_93 = 0x93, // illegal opcode + OPCODE_STY_ZPX = 0x94, // STore Y register, Zero Page Indexed, X ($94 arg : STY arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_STA_ZPX = 0x95, // STore Accumulator, Zero Page Indexed, X ($95 arg : STA arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_STX_ZPY = 0x96, // STore X register, Zero Page Indexed, Y ($96 arg : STX arg,Y ;arg=0..$FF), MEM=arg+Y + OPCODE_ILL_97 = 0x97, // illegal opcode + OPCODE_TYA = 0x98, // Transfer Y to A, Implied ($98 : TYA) + OPCODE_STA_ABY = 0x99, // STore Accumulator, Absolute Indexed, Y ($99 addrlo addrhi : STA addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_TXS = 0x9A, // Transfer X to Stack ptr, Implied ($9A : TXS) + OPCODE_ILL_9B = 0x9B, // illegal opcode + OPCODE_ILL_9C = 0x9C, // illegal opcode + OPCODE_STA_ABX = 0x9D, // STore Accumulator, Absolute Indexed, X ($9D addrlo addrhi : STA addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_9E = 0x9E, // illegal opcode + OPCODE_ILL_9F = 0x9F, // illegal opcode + OPCODE_LDY_IMM = 0xA0, // LoaD Y register, Immediate ($A0 arg : LDY #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_LDA_IZX = 0xA1, // LoaD Accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_LDX_IMM = 0xA2, // LoaD X register, Immediate ($A2 arg : LDX #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_ILL_A3 = 0xA3, // illegal opcode + OPCODE_LDY_ZP = 0xA4, // LoaD Y register, Zero Page ($A4 arg : LDY arg ;arg=0..$FF), MEM=arg + OPCODE_LDA_ZP = 0xA5, // LoaD Accumulator, Zero Page ($A5 arg : LDA arg ;arg=0..$FF), MEM=arg + OPCODE_LDX_ZP = 0xA6, // LoaD X register, Zero Page ($A6 arg : LDX arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_A7 = 0xA7, // illegal opcode + OPCODE_TAY = 0xA8, // Transfer A to Y, Implied ($A8 : TAY) + OPCODE_LDA_IMM = 0xA9, // LoaD Accumulator, Immediate ($A9 arg : LDA #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_TAX = 0xAA, // Transfer A to X, Implied ($AA : TAX) + OPCODE_ILL_AB = 0xAB, // illegal opcode + OPCODE_LDY_ABS = 0xAC, // LoaD Y register, Absolute ($AC addrlo addrhi : LDY addr ;addr=0..$FFFF), MEM=addr + OPCODE_LDA_ABS = 0xAD, // LoaD Accumulator, Absolute ($AD addrlo addrhi : LDA addr ;addr=0..$FFFF), MEM=addr + OPCODE_LDX_ABS = 0xAE, // LoaD X register, Absolute ($AE addrlo addrhi : LDX addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_AF = 0xAF, // illegal opcode + OPCODE_BCS_REL = 0xB0, // Branch on Carry Set, Relative ($B0 signoffs : BCS signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_LDA_IZY = 0xB1, // LoaD Accumulator, Indirect Indexed ($B1 arg : LDA (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_B2 = 0xB2, // illegal opcode + OPCODE_ILL_B3 = 0xB3, // illegal opcode + OPCODE_LDY_ZPX = 0xB4, // LoaD Y register, Zero Page Indexed, X ($B4 arg : LDY arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_LDA_ZPX = 0xB5, // LoaD Accumulator, Zero Page Indexed, X ($B5 arg : LDA arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_LDX_ZPY = 0xB6, // LoaD X register, Zero Page Indexed, Y ($B6 arg : LDX arg,Y ;arg=0..$FF), MEM=arg+Y + OPCODE_ILL_B7 = 0xB7, // illegal opcode + OPCODE_CLV = 0xB8, // CLear oVerflow, Implied ($B8 : CLV) + OPCODE_LDA_ABY = 0xB9, // LoaD Accumulator, Absolute Indexed, Y ($B9 addrlo addrhi : LDA addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_TSX = 0xBA, // Transfer Stack ptr to X, Implied ($BA : TSX) + OPCODE_ILL_BB = 0xBB, // illegal opcode + OPCODE_LDY_ABX = 0xBC, // LoaD Y register, Absolute Indexed, X ($BC addrlo addrhi : LDY addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_LDA_ABX = 0xBD, // LoaD Accumulator, Absolute Indexed, X ($BD addrlo addrhi : LDA addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_LDX_ABY = 0xBE, // LoaD X register, Absolute Indexed, Y ($BE addrlo addrhi : LDX addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_BF = 0xBF, // illegal opcode + OPCODE_CPY_IMM = 0xC0, // ComPare Y register, Immediate ($C0 arg : CPY #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_CMP_IZX = 0xC1, // CoMPare accumulator, Indexed Indirect ($A1 arg : LDA (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_C2 = 0xC2, // illegal opcode + OPCODE_ILL_C3 = 0xC3, // illegal opcode + OPCODE_CPY_ZP = 0xC4, // ComPare Y register, Zero Page ($C4 arg : CPY arg ;arg=0..$FF), MEM=arg + OPCODE_CMP_ZP = 0xC5, // CoMPare accumulator, Zero Page ($C5 arg : CMP arg ;arg=0..$FF), MEM=arg + OPCODE_DEC_ZP = 0xC6, // DECrement memory, Zero Page ($C6 arg : DEC arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_C7 = 0xC7, // illegal opcode + OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY)OPCODE_INY = 0xC8, // INcrement Y, Implied ($C8 : INY) + OPCODE_CMP_IMM = 0xC9, // CoMPare accumulator, Immediate ($C9 arg : CMP #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_DEX = 0xCA, // DEcrement X, Implied ($CA : DEX) + OPCODE_ILL_CB = 0xCB, // illegal opcode + OPCODE_CPY_ABS = 0xCC, // ComPare Y register, Absolute ($CC addrlo addrhi : CPY addr ;addr=0..$FFFF), MEM=addr + OPCODE_CMP_ABS = 0xCD, // CoMPare accumulator, Absolute ($CD addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + OPCODE_DEC_ABS = 0xCE, // DECrement memory, Absolute ($CE addrlo addrhi : CMP addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_CF = 0xCF, // illegal opcode + OPCODE_BNE_REL = 0xD0, // Branch on Not Equal, Relative ($D0 signoffs : BNE signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_CMP_IZY = 0xD1, // CoMPare accumulator, Indirect Indexed ($D1 arg : CMP (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_D2 = 0xD2, // illegal opcode + OPCODE_ILL_D3 = 0xD3, // illegal opcode + OPCODE_ILL_D4 = 0xD4, // illegal opcode + OPCODE_CMP_ZPX = 0xD5, // CoMPare accumulator, Zero Page Indexed, X ($D5 arg : CMP arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_DEC_ZPX = 0xD6, // DECrement memory, Zero Page Indexed, X ($D6 arg : DEC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_D7 = 0xD7, // illegal opcode + OPCODE_CLD = 0xD8, // CLear Decimal, Implied ($D8 : CLD) + OPCODE_CMP_ABY = 0xD9, // CoMPare accumulator, Absolute Indexed, Y ($D9 addrlo addrhi : CMP addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_DA = 0xDA, // illegal opcode + OPCODE_ILL_DB = 0xDB, // illegal opcode + OPCODE_ILL_DC = 0xDC, // illegal opcode + OPCODE_CMP_ABX = 0xDD, // CoMPare accumulator, Absolute Indexed, X ($DD addrlo addrhi : CMP addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_DEC_ABX = 0xDE, // DECrement memory, Absolute Indexed, X ($DE addrlo addrhi : DEC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_DF = 0xDF, // illegal opcode + OPCODE_CPX_IMM = 0xE0, // ComPare X register, Immediate ($E0 arg : CPX #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_SBC_IZX = 0xE1, // SuBtract with Carry, Indexed Indirect ($E1 arg : SBC (arg,X) ;arg=0..$FF), MEM=&(arg+X) + OPCODE_ILL_E2 = 0xE2, // illegal opcode + OPCODE_ILL_E3 = 0xE3, // illegal opcode + OPCODE_CPX_ZP = 0xE4, // ComPare X register, Zero Page ($E4 arg : CPX arg ;arg=0..$FF), MEM=arg + OPCODE_SBC_ZP = 0xE5, // SuBtract with Carry, Zero Page ($E5 arg : SBC arg ;arg=0..$FF), MEM=arg + OPCODE_INC_ZP = 0xE6, // INCrement memory, Zero Page ($E6 arg : INC arg ;arg=0..$FF), MEM=arg + OPCODE_ILL_E7 = 0xE7, // illegal opcode + OPCODE_INX = 0xE8, // INcrement X, Implied ($E8 : INX) + OPCODE_SBC_IMM = 0xE9, // SuBtract with Carry, Immediate ($E9 arg : SBC #arg ;arg=0..$FF), MEM=PC+1 + OPCODE_NOP = 0xEA, // NO oPeration, Implied ($EA : NOP) + OPCODE_ILL_EB = 0xEB, // illegal opcode + OPCODE_CPX_ABS = 0xEC, // ComPare X register, Absolute ($EC addrlo addrhi : CPX addr ;addr=0..$FFFF), MEM=addr + OPCODE_SBC_ABS = 0xED, // SuBtract with Carry, Absolute ($ED addrlo addrhi : SBC addr ;addr=0..$FFFF), MEM=addr + OPCODE_INC_ABS = 0xEE, // INCrement memory, Absolute ($EE addrlo addrhi : INC addr ;addr=0..$FFFF), MEM=addr + OPCODE_ILL_EF = 0xEF, // illegal opcode + OPCODE_BEQ_REL = 0xF0, // Branch on EQual, Relative ($F0 signoffs : BEQ signoffs ;signoffs=0..$FF [-128 ($80)..127 ($7F)]) + OPCODE_SBC_IZY = 0xF1, // SuBtract with Carry, Indirect Indexed ($F1 arg : SBC (arg),Y ;arg=0..$FF), MEM=&arg+Y + OPCODE_ILL_F2 = 0xF2, // illegal opcode + OPCODE_ILL_F3 = 0xF3, // illegal opcode + OPCODE_ILL_F4 = 0xF4, // illegal opcode + OPCODE_SBC_ZPX = 0xF5, // SuBtract with Carry, Zero Page Indexed, X ($F5 arg : SBC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_INC_ZPX = 0xF6, // INCrement memory, Zero Page Indexed, X ($F6 arg : INC arg,X ;arg=0..$FF), MEM=arg+X + OPCODE_ILL_F7 = 0xF7, // illegal opcode + OPCODE_SED = 0xF8, // SEt Decimal, Implied ($F8 : SED) + OPCODE_SBC_ABY = 0xF9, // SuBtract with Carry, Absolute Indexed, Y ($F9 addrlo addrhi : SBC addr,Y ;addr=0..$FFFF), MEM=addr+Y + OPCODE_ILL_FA = 0xFA, // illegal opcode + OPCODE_ILL_FB = 0xFB, // illegal opcode + OPCODE_ILL_FC = 0xFC, // illegal opcode + OPCODE_SBC_ABX = 0xFD, // SuBtract with Carry, Absolute Indexed, X ($FD addrlo addrhi : SBC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_INC_ABX = 0xFE, // INCrement memory, Absolute Indexed, X ($FE addrlo addrhi : INC addr,X ;addr=0..$FFFF), MEM=addr+X + OPCODE_ILL_FF = 0xFF // illegal opcode +}; + +struct OpCode { + int code; // the byte value of the opcode + int addrmode; // addressing mode (see eAddrModes) + int time; // # of cycles + string amf; // assembler mnemonic +}; + +typedef map OpCodesMap; + +/* + *------------------------------------------------------------------------------ + bit -> 7 0 + +---+---+---+---+---+---+---+---+ + | N | V | | B | D | I | Z | C | <-- flag, 0/1 = reset/set + +---+---+---+---+---+---+---+---+ + + + N = NEGATIVE. Set if bit 7 of the accumulator is set. + + V = OVERFLOW. Set if the addition of two like-signed numbers or the + subtraction of two unlike-signed numbers produces a result + greater than +127 or less than -128. + + B = BRK COMMAND. Set if an interrupt caused by a BRK, reset if + caused by an external interrupt. + + D = DECIMAL MODE. Set if decimal mode active. + + I = IRQ DISABLE. Set if maskable interrupts are disabled. + + Z = ZERO. Set if the result of the last operation (load/inc/dec/ + add/sub) was zero. + + C = CARRY. Set if the add produced a carry, or if the subtraction + produced a borrow. Also holds bits after a logical shift. + *------------------------------------------------------------------------------ + */ +enum eCpuFlagMasks { + FLAGS_CARRY = 0x01, // 0: C + FLAGS_ZERO = 0x02, // 1: Z + FLAGS_IRQ = 0x04, // 2: I + FLAGS_DEC = 0x08, // 3: D + FLAGS_BRK = 0x10, // 4: B (Clear if interrupt vectoring, set if BRK or PHP) + FLAGS_UNUSED = 0x20, // 5: Unused flag (always set). + FLAGS_OVERFLOW = 0x40, // 6: V + FLAGS_SIGN = 0x80 // 7: N +}; + +enum eLogicOps { + LOGOP_OR, + LOGOP_AND, + LOGOP_EOR +}; + +class MKCpu +{ + public: + + MKCpu(); + MKCpu(Memory *pmem); + ~MKCpu(); + + Regs *ExecOpcode(unsigned short memaddr); + Regs *GetRegs(); + queue GetExecHistory(); + unsigned short Disassemble(unsigned short addr, + char *instrbuf); // Disassemble instruction in memory, return next instruction addr. + + protected: + + private: + + struct Regs mReg; // CPU registers + Memory *mpMem; // pointer to memory object + bool mLocalMem; // true - memory locally allocated + OpCodesMap mOpCodesMap; // hash table of all opcodes + int mAddrModesLen[ADDRMODE_LENGTH]; // array of instructions lengths per addressing mode + string mArgFmtTbl[ADDRMODE_LENGTH]; // array of instructions assembly formats per addressing mode + queue mExecHistory; // history of last 20 op-codes with arguments and registers statuses + + + void InitCpu(); + void SetFlags(unsigned char reg); // set CPU flags ZERO and SIGN based on Acc, X or Y + unsigned char ShiftLeft(unsigned char arg8); // Arithmetic Shift Left, set Carry flag + unsigned char ShiftRight(unsigned char arg8); // Logical Shift Right, update flags NZC. + unsigned char RotateLeft(unsigned char arg8); // Rotate left, Carry to bit 0, bit 7 to Carry, update flags N and Z. + unsigned char RotateRight(unsigned char arg8); // Rotate left, Carry to bit 7, bit 0 to Carry, update flags N and Z. + unsigned short GetArg16(unsigned char offs); // Get 2-byte argument, add offset, increase PC. + void LogicOpAcc(unsigned short addr, int logop); // Perform logical bitwise operation between memory location and Acc. + // Result in Acc. Set flags. + unsigned short ComputeRelJump(unsigned char offs); // Compute new PC based on relative offset. + unsigned short ComputeRelJump(unsigned short addr, + unsigned char offs); // Compute new address after branch based on relative offset. + unsigned char Conv2Bcd(unsigned short v); // Convert number to BCD representation. + unsigned short Bcd2Num(unsigned char v); // Convert BCD code to number. + bool CheckFlag(unsigned char flag); // Return true if given CPU status flag is set, false otherwise. + void SetFlag(bool set, unsigned char flag); // Set or unset processor status flag. + unsigned char AddWithCarry(unsigned char mem8); // Add With Carry, update flags and Acc. + unsigned char SubWithCarry(unsigned char mem8); // Subtract With Carry, update flags and Acc. + unsigned short GetAddrWithMode(int mode); // Get address of the byte argument with specified addr. mode + unsigned short GetArgWithMode(unsigned short opcaddr, + int mode); // Get argument from address with specified addr. mode + unsigned short Disassemble(); // Disassemble instruction and argument per addressing mode + void Add2History(string s); // add entry to op-codes execute history +}; + +} // namespace MKBasic + +#endif diff --git a/MKGenException.cpp b/MKGenException.cpp index 2ab9ac3..0686d2f 100644 --- a/MKGenException.cpp +++ b/MKGenException.cpp @@ -1,20 +1,20 @@ -#include "MKGenException.h" - -namespace MKBasic { - -MKGenException::MKGenException() -{ - msCause = "Ouch!"; -} - -MKGenException::MKGenException(string cause) -{ - msCause = cause; -} - -string MKGenException::GetCause() -{ - return msCause; -} - -} // namespace MKBasic +#include "MKGenException.h" + +namespace MKBasic { + +MKGenException::MKGenException() +{ + msCause = "Ouch!"; +} + +MKGenException::MKGenException(string cause) +{ + msCause = cause; +} + +string MKGenException::GetCause() +{ + return msCause; +} + +} // namespace MKBasic diff --git a/MKGenException.h b/MKGenException.h index ce10000..ae53913 100644 --- a/MKGenException.h +++ b/MKGenException.h @@ -1,23 +1,24 @@ -#ifndef MKGENEXCEPTION_H -#define MKGENEXCEPTION_H - -#include -#include - -using namespace std; - -namespace MKBasic { - -class MKGenException : public exception { - public: - MKGenException(); - MKGenException(string cause); - string GetCause(); - - private: - string msCause; -}; - -} // namespace MKBasic - -#endif +#ifndef MKGENEXCEPTION_H +#define MKGENEXCEPTION_H + +#include +#include + +using namespace std; + +namespace MKBasic { + +class MKGenException : public exception { + public: + MKGenException(); + MKGenException(string cause); + ~MKGenException() throw() {}; + string GetCause(); + + private: + string msCause; +}; + +} // namespace MKBasic + +#endif diff --git a/Makefile.win b/Makefile.win new file mode 100644 index 0000000..29fd844 --- /dev/null +++ b/Makefile.win @@ -0,0 +1,46 @@ +# Project: MKBasic +# Makefile created by Dev-C++ 5.11 + +CPP = g++.exe -D__DEBUG__ +CC = gcc.exe -D__DEBUG__ +WINDRES = windres.exe +OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LIBS = -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib32" -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32" -static-libgcc -m32 -g3 +INCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" +CXXINCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include/c++" +BIN = MKBasic.exe +CXXFLAGS = $(CXXINCS) -m32 -std=c++11 -Wall -Wextra -pedantic -g3 +CFLAGS = $(INCS) -m32 -std=c++11 -Wall -Wextra -pedantic -g3 +RM = rm.exe -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +VMachine.o: VMachine.cpp + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + +MKBasic.o: MKBasic.cpp + $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) + +MKCpu.o: MKCpu.cpp + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + +Memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + +Display.o: Display.cpp + $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) + +MKGenException.o: MKGenException.cpp + $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) diff --git a/Memory.cpp b/Memory.cpp index b9c56d0..2ea11f7 100644 --- a/Memory.cpp +++ b/Memory.cpp @@ -1,310 +1,463 @@ -#include "Memory.h" -#include -#include - -//#define DBG 1 -#if defined (DBG) -#include -using namespace std; -#endif - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Memory::Memory() -{ - Initialize(); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -Memory::~Memory() -{ -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Memory::Initialize() -{ - unsigned short addr = 0; - for (int i=0; i < 0xFFFF; i++) { - m8bitMem[addr++] = 0; - } - mCharIOAddr = CHARIO_ADDR; - mCharIOActive = false; - mIOEcho = false; - mInBufDataBegin = mInBufDataEnd = 0; - mOutBufDataBegin = mOutBufDataEnd = 0; - mROMBegin = ROM_BEGIN; - mROMEnd = ROM_END; - mROMActive = false; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Memory::EnableROM() -{ - mROMActive = true; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void Memory::EnableROM(unsigned short start, unsigned short end) -{ - if (mROMEnd > mROMBegin) { - mROMBegin = start; - mROMEnd = end; - } - EnableROM(); -} - -/* - *-------------------------------------------------------------------- - * Method: ReadCharKb() - * Purpose: If char I/O active, read character from console - * (non-blocking) and put in an input FIFO buffer. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -unsigned char Memory::ReadCharKb() -{ - unsigned char ret = 0; - if (mCharIOActive) { - int c; - putchar('?'); - while(!kbhit()); - c = getch(); - if (mIOEcho) putchar(c); - mCharIOBufIn[mInBufDataEnd] = c; - mInBufDataEnd++; - if (mInBufDataEnd >= CHARIO_BUF_SIZE) mInBufDataEnd = 0; - ret = c; - } - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIn() - * Purpose: Return character from the emulated character I/O FIFO - * input buffer or -1 if FIFO empty or char I/O not active. - * Arguments: n/a - * Returns: character - *-------------------------------------------------------------------- - */ -char Memory::GetCharIn() -{ - char ret = -1; - if (mCharIOActive) { - if (mInBufDataEnd != mInBufDataBegin) { - ret = mCharIOBufIn[mInBufDataBegin]; - mInBufDataBegin++; - if (mInBufDataBegin >= CHARIO_BUF_SIZE) mInBufDataBegin = 0; - } - } - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharOut() - * Purpose: Return character from the emulated character I/O FIFO - * output buffer or -1 if FIFO empty or char I/O not - * active. - * Arguments: n/a - * Returns: character - *-------------------------------------------------------------------- - */ -char Memory::GetCharOut() -{ - char ret = -1; - if (mCharIOActive) { - if (mOutBufDataEnd != mOutBufDataBegin) { - ret = mCharIOBufOut[mOutBufDataBegin]; - mOutBufDataBegin++; - if (mOutBufDataBegin >= CHARIO_BUF_SIZE) mOutBufDataBegin = 0; - } - } - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: PutCharIO() - * Purpose: Put character in the output char I/O FIFO buffer. - * Arguments: c - character - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::PutCharIO(char c) -{ - if (mCharIOActive) { - mCharIOBufOut[mOutBufDataEnd] = c; - mOutBufDataEnd++; - if (mOutBufDataEnd >= CHARIO_BUF_SIZE) mOutBufDataEnd = 0; - } -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -unsigned char Memory::Peek8bit(unsigned short addr) -{ - if (mCharIOActive && addr == mCharIOAddr) { -#if defined (DBG) - cout << "DBG: Peek8bit($" << hex << addr << ") BEFORE ReadCharKb()" << endl; - cout << "DBG: m8bitMem[$" << hex << addr << "] = $" << hex << (unsigned short)m8bitMem[addr] << endl; - for (unsigned int a = 0xFFF0; a < 0x10000; a++) { - cout << "DBG: m8bitMem[$" << hex << a << "] = $" << hex << (unsigned short)m8bitMem[a] << endl; - } -#endif - m8bitMem[addr] = ReadCharKb(); -#if defined (DBG) - cout << "************************" << endl; - cout << "DBG: Peek8bit($" << hex << addr << ") AFTER ReadCharKb()" << endl; - cout << "DBG: m8bitMem[$" << hex << addr << "] = $" << hex << (unsigned short)m8bitMem[addr] << endl; - for (unsigned int a = 0xFFF0; a < 0x10000; a++) { - cout << "DBG: m8bitMem[$" << hex << a << "] = $" << hex << (unsigned short)m8bitMem[a] << endl; - } -#endif - } - - return m8bitMem[addr]; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -unsigned short Memory::Peek16bit(unsigned short addr) -{ - unsigned short ret = 0; - - if (mCharIOActive && addr == mCharIOAddr) { -#if defined (DBG) - cout << "DBG: Peek16bit(" << addr << ")" << endl; -#endif - m8bitMem[addr] = ReadCharKb(); - } - - ret = m8bitMem[addr++]; - ret += m8bitMem[addr] * 256; - - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: Poke8bit() - * Purpose: Write byte to specified memory location. - * If the memory location is mapped to character I/O, - * write value to output buffer and memory location. - * If the memory location is protected (ROM), do not - * write the value. - * Arguments: addr - (0x0000..0xffff) memory address, - * val - value (0x00..0xff) - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::Poke8bit(unsigned short addr, unsigned char val) -{ - if (mCharIOActive && addr == mCharIOAddr) - PutCharIO(val); - if (!mROMActive || (addr < ROM_BEGIN || addr > ROM_END)) { - m8bitMem[addr] = val; - } -} - -/* - *-------------------------------------------------------------------- - * Method: SetCharIO() - * Purpose: Activates and sets an address of basic character I/O - * emulation (console). - * Arguments: addr - address of I/O area (0x0000..0xFFFF) - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::SetCharIO(unsigned short addr, bool echo) -{ - mCharIOAddr = addr; - mCharIOActive = true; - mIOEcho = echo; -} - -/* - *-------------------------------------------------------------------- - * Method: DisableCharIO() - * Purpose: Deactivates basic character I/O emulation (console). - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void Memory::DisableCharIO() -{ - mCharIOActive = false; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIOAddr() - * Purpose: Returns current address of basic character I/O area. - * Arguments: n/a - * Returns: address of I/O area - *-------------------------------------------------------------------- - */ -unsigned short Memory::GetCharIOAddr() -{ - return mCharIOAddr; -} - -} // namespace MKBasic + +#include "Memory.h" + +#include +#include +#if defined(WINDOWS) +#include +#endif + +//#define DBG 1 +#if defined (DBG) +#include +using namespace std; +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Memory::Memory() +{ + Initialize(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +Memory::~Memory() +{ +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::Initialize() +{ + unsigned short addr = 0; + for (int i=0; i < 0xFFFF; i++) { + m8bitMem[addr++] = 0; + } + mCharIOAddr = CHARIO_ADDR; + mCharIOActive = false; + mIOEcho = false; + mInBufDataBegin = mInBufDataEnd = 0; + mOutBufDataBegin = mOutBufDataEnd = 0; + mROMBegin = ROM_BEGIN; + mROMEnd = ROM_END; + mROMActive = false; +} + +#if defined(LINUX) +#include +#include +#include + +struct termios orig_termios; + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void reset_terminal_mode() +{ + tcsetattr(0, TCSANOW, &orig_termios); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::set_conio_terminal_mode() +{ + struct termios new_termios; + + /* take two copies - one for now, one for later */ + tcgetattr(0, &orig_termios); + memcpy(&new_termios, &orig_termios, sizeof(new_termios)); + + /* register cleanup handler, and set the new terminal mode */ + atexit(reset_terminal_mode); + cfmakeraw(&new_termios); + tcsetattr(0, TCSANOW, &new_termios); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +int Memory::kbhit() +{ + struct timeval tv = { 0L, 0L }; + fd_set fds; + FD_ZERO(&fds); + FD_SET(0, &fds); + return select(1, &fds, NULL, NULL, &tv); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +int Memory::getch() +{ + int r; + unsigned char c; + if ((r = read(0, &c, sizeof(c))) < 0) { + return r; + } else { + return c; + } +} +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::EnableROM() +{ + mROMActive = true; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::DisableROM() +{ + mROMActive = false; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::SetROM(unsigned short start, unsigned short end) +{ + if (mROMEnd > mROMBegin) { + mROMBegin = start; + mROMEnd = end; + } +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void Memory::EnableROM(unsigned short start, unsigned short end) +{ + SetROM(start,end); + EnableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: ReadCharKb() + * Purpose: If char I/O active, read character from console + * (non-blocking) and put in an input FIFO buffer. + * Arguments: nonblock - if true, works in non-blocking mode + * Returns: n/a + *-------------------------------------------------------------------- + */ +unsigned char Memory::ReadCharKb(bool nonblock) +{ + unsigned char ret = 0; + if (mCharIOActive) { +#if defined(LINUX) + set_conio_terminal_mode(); +#endif + static int c = ' '; + putchar('\n'); + if (mIOEcho && isprint(c)) putchar(c); + else putchar(' '); + fputs("<-Character Input (CTRL-Y to BREAK) ?\r",stdout); + fflush(stdout); + if (!nonblock) while(!kbhit()); + else c = 0; + c = getch(); +#if defined(LINUX) + if (c == 3) { // capture CTRL-C in CONIO mode + reset_terminal_mode(); + kill(getpid(),SIGINT); + } +#endif + fputs(" \r",stdout); + fflush(stdout); + mCharIOBufIn[mInBufDataEnd] = c; + mInBufDataEnd++; + if (mInBufDataEnd >= CHARIO_BUF_SIZE) mInBufDataEnd = 0; + ret = c; +#if defined(LINUX) + reset_terminal_mode(); +#endif + } + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIn() + * Purpose: Return character from the emulated character I/O FIFO + * input buffer or -1 if FIFO empty or char I/O not active. + * Arguments: n/a + * Returns: character + *-------------------------------------------------------------------- + */ +char Memory::GetCharIn() +{ + char ret = -1; + if (mCharIOActive) { + if (mInBufDataEnd != mInBufDataBegin) { + ret = mCharIOBufIn[mInBufDataBegin]; + mInBufDataBegin++; + if (mInBufDataBegin >= CHARIO_BUF_SIZE) mInBufDataBegin = 0; + } + } + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharOut() + * Purpose: Return character from the emulated character I/O FIFO + * output buffer or -1 if FIFO empty or char I/O not + * active. + * Arguments: n/a + * Returns: character + *-------------------------------------------------------------------- + */ +char Memory::GetCharOut() +{ + char ret = -1; + if (mCharIOActive) { + if (mOutBufDataEnd != mOutBufDataBegin) { + ret = mCharIOBufOut[mOutBufDataBegin]; + mOutBufDataBegin++; + if (mOutBufDataBegin >= CHARIO_BUF_SIZE) mOutBufDataBegin = 0; + } + } + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: PutCharIO() + * Purpose: Put character in the output char I/O FIFO buffer. + * Arguments: c - character + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::PutCharIO(char c) +{ + if (mCharIOActive) { + mCharIOBufOut[mOutBufDataEnd] = c; + mOutBufDataEnd++; + if (mOutBufDataEnd >= CHARIO_BUF_SIZE) mOutBufDataEnd = 0; + } +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned char Memory::Peek8bit(unsigned short addr) +{ + if (mCharIOActive && addr == mCharIOAddr) { + m8bitMem[addr] = ReadCharKb(false); // blocking mode input + } else if (mCharIOActive && addr == mCharIOAddr+1) { + m8bitMem[addr] = ReadCharKb(true); // non-blocking mode input + } + + return m8bitMem[addr]; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short Memory::Peek16bit(unsigned short addr) +{ + unsigned short ret = 0; + + if (mCharIOActive && addr == mCharIOAddr) { + m8bitMem[addr] = ReadCharKb(false); // blocking mode input + } else if (mCharIOActive && addr == mCharIOAddr+1) { + m8bitMem[addr] = ReadCharKb(true); // non-blocking mode input + } + + ret = m8bitMem[addr++]; + ret += m8bitMem[addr] * 256; + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: Poke8bit() + * Purpose: Write byte to specified memory location. + * If the memory location is mapped to character I/O, + * write value to output buffer and memory location. + * If the memory location is protected (ROM), do not + * write the value. + * Arguments: addr - (0x0000..0xffff) memory address, + * val - value (0x00..0xff) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::Poke8bit(unsigned short addr, unsigned char val) +{ + if (mCharIOActive && addr == mCharIOAddr) + PutCharIO(val); + if (!mROMActive || (addr < mROMBegin || addr > mROMEnd)) { + m8bitMem[addr] = val; + } +} + +/* + *-------------------------------------------------------------------- + * Method: SetCharIO() + * Purpose: Activates and sets an address of basic character I/O + * emulation (console). + * Arguments: addr - address of I/O area (0x0000..0xFFFF) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::SetCharIO(unsigned short addr, bool echo) +{ + mCharIOAddr = addr; + mCharIOActive = true; + mIOEcho = echo; +} + +/* + *-------------------------------------------------------------------- + * Method: DisableCharIO() + * Purpose: Deactivates basic character I/O emulation (console). + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void Memory::DisableCharIO() +{ + mCharIOActive = false; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIOAddr() + * Purpose: Returns current address of basic character I/O area. + * Arguments: n/a + * Returns: address of I/O area + *-------------------------------------------------------------------- + */ +unsigned short Memory::GetCharIOAddr() +{ + return mCharIOAddr; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short Memory::GetROMBegin() +{ + return mROMBegin; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short Memory::GetROMEnd() +{ + return mROMEnd; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +bool Memory::IsROMEnabled() +{ + return mROMActive; +} + +} // namespace MKBasic diff --git a/Memory.h b/Memory.h index e75533c..2151a63 100644 --- a/Memory.h +++ b/Memory.h @@ -1,55 +1,77 @@ -#ifndef MEMORY_H -#define MEMORY_H - -#define MAX_8BIT_ADDR 0xFFFF -#define CHARIO_ADDR 0xE000 -#define CHARIO_BUF_SIZE 256 -#define ROM_BEGIN 0xD000 -#define ROM_END 0xDFFF - -namespace MKBasic { - -class Memory -{ - public: - - Memory(); - ~Memory(); - - void Initialize(); - unsigned char Peek8bit(unsigned short addr); - unsigned short Peek16bit(unsigned short addr); - void Poke8bit(unsigned short addr, unsigned char val); - void SetCharIO(unsigned short addr, bool echo); - void DisableCharIO(); - unsigned short GetCharIOAddr(); - char GetCharIn(); - char GetCharOut(); - void EnableROM(); - void EnableROM(unsigned short start, unsigned short end); - - protected: - - private: - - unsigned char m8bitMem[MAX_8BIT_ADDR+1]; - char mCharIOBufIn[CHARIO_BUF_SIZE]; - char mCharIOBufOut[CHARIO_BUF_SIZE]; - unsigned int mInBufDataBegin; - unsigned int mInBufDataEnd; - unsigned int mOutBufDataBegin; - unsigned int mOutBufDataEnd; - unsigned short mCharIOAddr; - bool mCharIOActive; - bool mIOEcho; - unsigned short mROMBegin; - unsigned short mROMEnd; - bool mROMActive; - - unsigned char ReadCharKb(); - void PutCharIO(char c); -}; - -} // namespace MKBasic - -#endif +#ifndef MEMORY_H +#define MEMORY_H + +#include "system.h" + +#if defined(LINUX) +#include +#include +#include +#endif + +#define MAX_8BIT_ADDR 0xFFFF +#define CHARIO_ADDR 0xE000 +#define CHARIO_BUF_SIZE 256 +#define ROM_BEGIN 0xD000 +#define ROM_END 0xDFFF +#define MIN_ROM_BEGIN 0x0200 + +namespace MKBasic { + +class Memory +{ + public: + + Memory(); + ~Memory(); + + void Initialize(); + unsigned char Peek8bit(unsigned short addr); + unsigned short Peek16bit(unsigned short addr); + void Poke8bit(unsigned short addr, unsigned char val); + void SetCharIO(unsigned short addr, bool echo); + void DisableCharIO(); + unsigned short GetCharIOAddr(); + char GetCharIn(); + char GetCharOut(); + void EnableROM(); + void DisableROM(); + void SetROM(unsigned short start, unsigned short end); + void EnableROM(unsigned short start, unsigned short end); + unsigned short GetROMBegin(); + unsigned short GetROMEnd(); + bool IsROMEnabled(); + + protected: + + private: + + unsigned char m8bitMem[MAX_8BIT_ADDR+1]; + char mCharIOBufIn[CHARIO_BUF_SIZE]; + char mCharIOBufOut[CHARIO_BUF_SIZE]; + unsigned int mInBufDataBegin; + unsigned int mInBufDataEnd; + unsigned int mOutBufDataBegin; + unsigned int mOutBufDataEnd; + unsigned short mCharIOAddr; + bool mCharIOActive; + bool mIOEcho; + unsigned short mROMBegin; + unsigned short mROMEnd; + bool mROMActive; + + unsigned char ReadCharKb(bool nonblock); + void PutCharIO(char c); + +#if defined(LINUX) + + void set_conio_terminal_mode(); + int kbhit(); + int getch(); + +#endif +}; + +} // namespace MKBasic + +#endif diff --git a/Notes.txt b/Notes.txt index b2d55fc..103a6cc 100644 --- a/Notes.txt +++ b/Notes.txt @@ -1,25 +1,25 @@ - -http://visual6502.org/wiki/index.php?title=6502DecimalMode - - -NV-BDIZC - -Tests for ADC -00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (simulate) -79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (simulate) -24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (simulate) -93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (simulate) -89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (simulate) -89 + 76 and C=1 gives 66 and N=0 V=0 Z=1 C=1 (simulate) -80 + f0 and C=0 gives d0 and N=0 V=1 Z=0 C=1 (simulate) -80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (simulate) -2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (simulate) -6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (simulate) -Tests for SBC -00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (simulate) -00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (simulate) -00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (simulate) -0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (simulate) -0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (simulate) -9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (simulate) + +http://visual6502.org/wiki/index.php?title=6502DecimalMode + + +NV-BDIZC + +Tests for ADC +00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (simulate) +79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (simulate) +24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (simulate) +93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (simulate) +89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (simulate) +89 + 76 and C=1 gives 66 and N=0 V=0 Z=1 C=1 (simulate) +80 + f0 and C=0 gives d0 and N=0 V=1 Z=0 C=1 (simulate) +80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (simulate) +2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (simulate) +6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (simulate) +Tests for SBC +00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (simulate) +00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (simulate) +00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (simulate) +0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (simulate) +0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (simulate) +9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (simulate) 9b - 00 and C=0 gives 9a and N=1 V=0 Z=0 C=1 (simulate) \ No newline at end of file diff --git a/ReadMe.txt b/ReadMe.txt index 13c82ec..8a2d3b2 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,62 +1,262 @@ - -Project: MKBasic -Author: Copyright (C) Marek Karcz 2016. All rights reserved. -Purpose: -MOS 6502 emulator, Virtual CPU/Machine and potentially retro-style 8-bit computer emulator, -MOS-6502-compatible virtual computer featuring BASIC interpreter, machine code monitor etc. - -Memory images extensions: .RAM, .ROM - -Format of the memory definition file: - -; comment -ADDR -address -data -ORG -address - -Where: -ADDR - label indicating that starting address will follow in next - line -ORG - label indicating that the address counter will change to the - value provided in next line -address - decimal or hexadecimal (prefix $) address in memory - -E.g: -ADDR -$200 - -or - -ADDR -512 - -changes the default start address (256) to 512. - -ORG -49152 - -moves address counter to address 49152, following data will be -loaded from that address forward - -data - the multi-line stream of decimal of hexadecimal ($xx) values - of size unsigned char (byte: 0-255) separated with spaces - or commas. - -E.g.: -$00 $00 $00 $00 -$00 $00 $00 $00 - -or - -$00,$00,$00,$00 - -or - -0 0 0 0 - -or - -0,0,0,0 -0 0 0 0 \ No newline at end of file + +Project: MKBasic (VM6502). + +Author: Copyright (C) Marek Karcz 2016. All rights reserved. + Free for personal and non-commercial use. + Code can be distributed and included in derivative work under + condition that the original copyright notice is preserved. + For use in commercial product, please contact me to obtain + permission and discuss possible fees, at: makarcz@yahoo.com + This software is provided with no warranty. + +Purpose: + +MOS 6502 emulator, Virtual CPU/Machine and potentially retro-style 8-bit +computer emulator. +MOS-6502-compatible virtual computer featuring BASIC interpreter, machine code +monitor, input/output device emulation etc. +Program works in DOS/shell console (text mode) only. +Makefile are included to build under Windows 32/64 (mingw compiler required) +and under Linux Ubuntu or Ubuntu based. + +To build under Windows 32/64: + +* Install MINGW64 under C:\mingw-w64\x86_64-5.3.0 folder. +* Run mingw terminal. +* Change current directory to that of this project. +* Run: makeming.bat + +To build under Linux: + +* Make sure C++11 compliant version of GCC compiler is installed. +* Change current directory to that of this project. +* Run: make clean all + +Program passed following tests: + +* 6502 functional test by Klaus Dormann +* AllSuiteA.asm from project hmc-6502 + +1. Credits/attributions: + +Parts of this project is based on or contains 3-rd party work: + +- Tiny Basic. +- Enhanced Basic by Lee Davison. +- Microchess by Peter Jennings (http://www.benlo.com/microchess/index.html). +- 6502 functional test by Klaus Dormann. +- All Suite test from project hmc-6502. + +2. Format of the memory image definition file. + +Program can load raw binary image of MOS 6502 opcodes. +Binary image is always loaded from address $0000 and can be up to 64 kB long, +so the code must be properly located inside that image. +Depending on your favorite 6502 assembler, you may need to use proper command +line arguments or configuration to achieve properly formatted binary file. +E.g.: if using CL65 from CC65 package, create configuration file that defines +memory segments that your 6502 code uses, then all of the segments (except the +last one) must have attribute 'fill' set to 'yes' so the unsused areas are +filled with 0-s. +Two CFG files, one for microchess and one for All Suite from hmc-6502 project +are supplied with this project and assembler source code adapted to be +compiled with CL65. +Other assemblers may need a different approach or may not be able to generate +binary images that are required for this emulator. + +Program can also load memory image definition file (plain text), which is +a format developed especially for this project. + +The format of the plain text memory image definition file is described below: + +; comments +ADDR +address +data +ORG +address +data +IOADDR +address +ROMBEGIN +address +ROMEND +address +ENROM +ENIO +EXEC +address + +Where: +ADDR - label indicating that starting and run address will follow in + the next line +ORG - label indicating that the address counter will change to the + value provided in next line +IOADDR - label indicating that character I/O emulation trap address will + follow in the next line +ROMBEGIN - label indicating that the emulated read-only memory start address + will follow in the next line +ROMEND - label indicating that the emulated read-only memory end address + will follow in the next line +ENROM - enable read-only memory emulation +ENIO - enable character I/O emulation +EXEC - label indicating that the auto-execute address will follow + in the next line + + +address - decimal or hexadecimal (prefix $) address in memory + +E.g: +ADDR +$0200 + +or + +ADDR +512 + +changes the default start address (256) to 512. + +ORG +49152 + +moves address counter to address 49152, following data will be +loaded from that address forward + +data - the multi-line stream of decimal of hexadecimal ($xx) values + of size unsigned char (byte: 0-255) separated with spaces + or commas. + +E.g.: +$00 $00 $00 $00 +$00 $00 $00 $00 + +or + +$00,$00,$00,$00 + +or + +0 0 0 0 + +or + +0,0,0,0 +0 0 0 0 + +Each described above element of the memory image definition file is optional. + +3. Character I/O emulation. + +Emulator has ability to simulate a 80x25 text output display device and +rudimentary character I/O functions. The emulation is implemented by the means +of trapping memory locations defined to be designated I/O emulation addresses. +The default memory location is $E000 and also by default, the character I/O +is disabled. It can be enabled from the debug console with 'I' command: + +I hexaddr + +E.g.: + +I E000 + +or + +I FE00 + +or by putting optional statements in the memory image dedinition file: + +ENIO + +or + +IOADDR +address +ENIO + +Where: + +address - decimal or hexadecimal (with prefix '$') address in memory + $0000 - $FFFF. + +The same address is used for both, input and output operations. + +Reading from IOADDR inside the 6502 code invokes a blocking character +input function from user's DOS/shell session. +After user enters the character, the memory location contains the character +code and also emulated CPU Acc register contains the same code. + +Reading from IOADDR+1 inside 6502 code invokes a non-blocking character +input function from user's DOS/shell session. +This function is different than blocking one in one respect. +This function will return value 0 in the memory location and Acc register +if there was no key pressed by the user (no character waiting in buffer). +If there was a key typed, the function will act as the blocking counterpart. + +Writing to IOADDR inside the 6502 code will result in character code +being put in the IOADDR memory location and also written to the character +output buffer of the emulated display device. That character is not +immediately transferred to the user's DOS/shell session. It is written to the +emulated display's text memory instead. Depending on the mode in which +emulator is currently working (continuous or step-by-step code execution), +the emulated display device contents may or may not be updated on the user's +screen in real time fashion. Remember that this is a DOS/shell console +application. The user's console is shared among various functions of the +program. In step-by-step mode, if the character I/O emulation is enabled, the +current contents of the emulated display device can be displayed with +corresponding debug console command: 'T'. + +4. ROM (read-only memory) emulation. + +This facility provides very basic means for memory mapping of the read-only +area. This may be required by some 6502 programs that check for non-writable +memory to establish the bounds of memory that can be used for data and code. +One good example is Tiny Basic. +By default the ROM emulation is disabled and the memory range of ROM is +defined as $D000 - $DFFF. +ROM emulation can be enabled (and the memory range defined) using debug +console's command 'K': + +K [rombegin] [romend] - to enable + +or + +K - to disable + +The ROM emulation can also be defined and enabled in the memory image +definition file with following statements: + +ROMBEGIN +address +ROMEND +address +ENROM + +5. Additional comments and remarks. + +IOADDR is permitted to be located in the emulated ROM memory range. +The writing to IOADDR is trapped first before checking ROM range and writing +to it is permitted when character I/O emulation and ROM are enabled at the +same time. It is a good idea in fact to put the IOADDR inside ROM range, +otherwise memory scanning routines like the one in Tiny Basic may trigger +unexpected character input because of the reading from IOADDR during the scan. +If you experience unexpected character input prompt while emulating +6502 code, this may be the case. Reconfigure your IOADDR to be inside ROM in +such case and try again. + +6. Warranty and License Agreement. + +This software is provided with No Warranty. +I (The Author) will not be held responsible for any damage to computer +systems, data or user's health resulting from using this software. +Please use responsibly. +This software is provided in hope that it will be be useful and free of +charge for non-commercial and educational use. +Distribution of this software in non-commercial and educational derivative +work is permitted under condition that original copyright notices and +comments are preserved. Some 3-rd party work included with this project +may require separate application for permission from their respective +authors/copyright owners. + + + diff --git a/TestBCD.65s b/TestBCD.65s index b0f3f22..8cad2ed 100644 --- a/TestBCD.65s +++ b/TestBCD.65s @@ -1,291 +1,291 @@ -; Verify decimal mode behavior -; Written by Bruce Clark. This code is public domain. -; -; Returns: -; ERROR = 0 if the test passed -; ERROR = 1 if the test failed -; -; This routine requires 17 bytes of RAM -- 1 byte each for: -; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF -; and 2 bytes for N2H -; -; Variables: -; N1 and N2 are the two numbers to be added or subtracted -; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2 -; DA and DNVZC are the actual accumulator and flag results in decimal mode -; HA and HNVZC are the accumulator and flag results when N1 and N2 are -; added or subtracted using binary arithmetic -; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and -; flag results, calculated using binary arithmetic -; -; This program takes approximately 1 minute at 1 MHz (a few seconds more on -; a 65C02 than a 6502 or 65816) -; - *=$0300 - -AR: .DB 0 -CF: .DB 0 -DA: .DB 0 -DNVZC: .DB 0 -ERROR: .DB 0 -HA: .DB 0 -HNVZC: .DB 0 -N1: .DB 0 -N1H: .DB 0 -N1L: .DB 0 -N2: .DB 0 -N2L: .DB 0 -NF: .DB 0 -VF: .DB 0 -ZF: .DB 0 -N2H: .DB 0,0 - - *=$0400 - -TEST: LDY #1 ; initialize Y (used to loop through carry flag values) - STY ERROR ; store 1 in ERROR until the test passes - LDA #0 ; initialize N1 and N2 - STA N1 - STA N2 -LOOP1: LDA N2 ; N2L = N2 & $0F - AND #$0F ; [1] see text - STA N2L - LDA N2 ; N2H = N2 & $F0 - AND #$F0 ; [2] see text - STA N2H - ORA #$0F ; N2H+1 = (N2 & $F0) + $0F - STA N2H+1 -LOOP2: LDA N1 ; N1L = N1 & $0F - AND #$0F ; [3] see text - STA N1L - LDA N1 ; N1H = N1 & $F0 - AND #$F0 ; [4] see text - STA N1H - JSR ADD - JSR A6502 - JSR COMPARE - BNE DONE - JSR SUB - JSR S6502 - JSR COMPARE - BNE DONE - INC N1 ; [5] see text - BNE LOOP2 ; loop through all 256 values of N1 - INC N2 ; [6] see text - BNE LOOP1 ; loop through all 256 values of N2 - DEY - BPL LOOP1 ; loop through both values of the carry flag - LDA #0 ; test passed, so store 0 in ERROR - STA ERROR -DONE: RTS - BRK - -; Calculate the actual decimal mode accumulator and flags, the accumulator -; and flag results when N1 is added to N2 using binary arithmetic, the -; predicted accumulator result, the predicted carry flag, and the predicted -; V flag -; -ADD: SED ; decimal mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - ADC N2 - STA DA ; actual accumulator result in decimal mode - PHP - PLA - STA DNVZC ; actual flags result in decimal mode - CLD ; binary mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - ADC N2 - STA HA ; accumulator result of N1+N2 using binary arithmetic - - PHP - PLA - STA HNVZC ; flags result of N1+N2 using binary arithmetic - CPY #1 - LDA N1L - ADC N2L - CMP #$0A - LDX #0 - BCC A1 - INX - ADC #5 ; add 6 (carry is set) - AND #$0F - SEC -A1: ORA N1H -; -; if N1L + N2L < $0A, then add N2 & $F0 -; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set) -; - ADC N2H,X - PHP - BCS A2 - CMP #$A0 - BCC A3 -A2: ADC #$5F ; add $60 (carry is set) - SEC -A3: STA AR ; predicted accumulator result - PHP - PLA - STA CF ; predicted carry result - PLA -; -; note that all 8 bits of the P register are stored in VF -; - STA VF ; predicted V flags - RTS - -; Calculate the actual decimal mode accumulator and flags, and the -; accumulator and flag results when N2 is subtracted from N1 using binary -; arithmetic -; -SUB: SED ; decimal mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - SBC N2 - STA DA ; actual accumulator result in decimal mode - PHP - PLA - STA DNVZC ; actual flags result in decimal mode - CLD ; binary mode - CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1 - SBC N2 - STA HA ; accumulator result of N1-N2 using binary arithmetic - - PHP - PLA - STA HNVZC ; flags result of N1-N2 using binary arithmetic - RTS - -; Calculate the predicted SBC accumulator result for the 6502 and 65816 - -; -SUB1: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1L - SBC N2L - LDX #0 - BCS S11 - INX - SBC #5 ; subtract 6 (carry is clear) - AND #$0F - CLC -S11: ORA N1H -; -; if N1L - N2L >= 0, then subtract N2 & $F0 -; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) -; - SBC N2H,X - BCS S12 - SBC #$5F ; subtract $60 (carry is clear) -S12: STA AR - RTS - -; Calculate the predicted SBC accumulator result for the 6502 and 65C02 - -; -SUB2: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 - LDA N1L - SBC N2L - LDX #0 - BCS S21 - INX - AND #$0F - CLC -S21: ORA N1H -; -; if N1L - N2L >= 0, then subtract N2 & $F0 -; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) -; - SBC N2H,X - BCS S22 - SBC #$5F ; subtract $60 (carry is clear) -S22: CPX #0 - BEQ S23 - SBC #6 -S23: STA AR ; predicted accumulator result - RTS - -; Compare accumulator actual results to predicted results -; -; Return: -; Z flag = 1 (BEQ branch) if same -; Z flag = 0 (BNE branch) if different -; -COMPARE: - LDA DA - CMP AR - BNE C1 - LDA DNVZC ; [7] see text - EOR NF - AND #$80 ; mask off N flag - BNE C1 - LDA DNVZC ; [8] see text - EOR VF - AND #$40 ; mask off V flag - BNE C1 ; [9] see text - LDA DNVZC - EOR ZF ; mask off Z flag - AND #2 - BNE C1 ; [10] see text - LDA DNVZC - EOR CF - AND #1 ; mask off C flag -C1: RTS - -; These routines store the predicted values for ADC and SBC for the 6502, -; 65C02, and 65816 in AR, CF, NF, VF, and ZF - -A6502: LDA VF -; -; since all 8 bits of the P register were stored in VF, bit 7 of VF contains -; the N flag for NF -; - STA NF - LDA HNVZC - STA ZF - RTS - -S6502: JSR SUB1 - LDA HNVZC - STA NF - STA VF - STA ZF - STA CF - RTS - -A65C02: LDA AR - PHP - PLA - STA NF - STA ZF - RTS - -S65C02: JSR SUB2 - LDA AR - PHP - PLA - STA NF - STA ZF - LDA HNVZC - STA VF - STA CF - RTS - -A65816: LDA AR - PHP - PLA - STA NF - STA ZF - RTS - -S65816: JSR SUB1 - LDA AR - PHP - PLA - STA NF - STA ZF - LDA HNVZC - STA VF - STA CF - RTS +; Verify decimal mode behavior +; Written by Bruce Clark. This code is public domain. +; +; Returns: +; ERROR = 0 if the test passed +; ERROR = 1 if the test failed +; +; This routine requires 17 bytes of RAM -- 1 byte each for: +; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF +; and 2 bytes for N2H +; +; Variables: +; N1 and N2 are the two numbers to be added or subtracted +; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2 +; DA and DNVZC are the actual accumulator and flag results in decimal mode +; HA and HNVZC are the accumulator and flag results when N1 and N2 are +; added or subtracted using binary arithmetic +; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and +; flag results, calculated using binary arithmetic +; +; This program takes approximately 1 minute at 1 MHz (a few seconds more on +; a 65C02 than a 6502 or 65816) +; + *=$0300 + +AR: .DB 0 +CF: .DB 0 +DA: .DB 0 +DNVZC: .DB 0 +ERROR: .DB 0 +HA: .DB 0 +HNVZC: .DB 0 +N1: .DB 0 +N1H: .DB 0 +N1L: .DB 0 +N2: .DB 0 +N2L: .DB 0 +NF: .DB 0 +VF: .DB 0 +ZF: .DB 0 +N2H: .DB 0,0 + + *=$0400 + +TEST: LDY #1 ; initialize Y (used to loop through carry flag values) + STY ERROR ; store 1 in ERROR until the test passes + LDA #0 ; initialize N1 and N2 + STA N1 + STA N2 +LOOP1: LDA N2 ; N2L = N2 & $0F + AND #$0F ; [1] see text + STA N2L + LDA N2 ; N2H = N2 & $F0 + AND #$F0 ; [2] see text + STA N2H + ORA #$0F ; N2H+1 = (N2 & $F0) + $0F + STA N2H+1 +LOOP2: LDA N1 ; N1L = N1 & $0F + AND #$0F ; [3] see text + STA N1L + LDA N1 ; N1H = N1 & $F0 + AND #$F0 ; [4] see text + STA N1H + JSR ADD + JSR A6502 + JSR COMPARE + BNE DONE + JSR SUB + JSR S6502 + JSR COMPARE + BNE DONE + INC N1 ; [5] see text + BNE LOOP2 ; loop through all 256 values of N1 + INC N2 ; [6] see text + BNE LOOP1 ; loop through all 256 values of N2 + DEY + BPL LOOP1 ; loop through both values of the carry flag + LDA #0 ; test passed, so store 0 in ERROR + STA ERROR +DONE: RTS + BRK + +; Calculate the actual decimal mode accumulator and flags, the accumulator +; and flag results when N1 is added to N2 using binary arithmetic, the +; predicted accumulator result, the predicted carry flag, and the predicted +; V flag +; +ADD: SED ; decimal mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + ADC N2 + STA DA ; actual accumulator result in decimal mode + PHP + PLA + STA DNVZC ; actual flags result in decimal mode + CLD ; binary mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + ADC N2 + STA HA ; accumulator result of N1+N2 using binary arithmetic + + PHP + PLA + STA HNVZC ; flags result of N1+N2 using binary arithmetic + CPY #1 + LDA N1L + ADC N2L + CMP #$0A + LDX #0 + BCC A1 + INX + ADC #5 ; add 6 (carry is set) + AND #$0F + SEC +A1: ORA N1H +; +; if N1L + N2L < $0A, then add N2 & $F0 +; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set) +; + ADC N2H,X + PHP + BCS A2 + CMP #$A0 + BCC A3 +A2: ADC #$5F ; add $60 (carry is set) + SEC +A3: STA AR ; predicted accumulator result + PHP + PLA + STA CF ; predicted carry result + PLA +; +; note that all 8 bits of the P register are stored in VF +; + STA VF ; predicted V flags + RTS + +; Calculate the actual decimal mode accumulator and flags, and the +; accumulator and flag results when N2 is subtracted from N1 using binary +; arithmetic +; +SUB: SED ; decimal mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + SBC N2 + STA DA ; actual accumulator result in decimal mode + PHP + PLA + STA DNVZC ; actual flags result in decimal mode + CLD ; binary mode + CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1 + SBC N2 + STA HA ; accumulator result of N1-N2 using binary arithmetic + + PHP + PLA + STA HNVZC ; flags result of N1-N2 using binary arithmetic + RTS + +; Calculate the predicted SBC accumulator result for the 6502 and 65816 + +; +SUB1: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1L + SBC N2L + LDX #0 + BCS S11 + INX + SBC #5 ; subtract 6 (carry is clear) + AND #$0F + CLC +S11: ORA N1H +; +; if N1L - N2L >= 0, then subtract N2 & $F0 +; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) +; + SBC N2H,X + BCS S12 + SBC #$5F ; subtract $60 (carry is clear) +S12: STA AR + RTS + +; Calculate the predicted SBC accumulator result for the 6502 and 65C02 + +; +SUB2: CPY #1 ; set carry if Y = 1, clear carry if Y = 0 + LDA N1L + SBC N2L + LDX #0 + BCS S21 + INX + AND #$0F + CLC +S21: ORA N1H +; +; if N1L - N2L >= 0, then subtract N2 & $F0 +; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear) +; + SBC N2H,X + BCS S22 + SBC #$5F ; subtract $60 (carry is clear) +S22: CPX #0 + BEQ S23 + SBC #6 +S23: STA AR ; predicted accumulator result + RTS + +; Compare accumulator actual results to predicted results +; +; Return: +; Z flag = 1 (BEQ branch) if same +; Z flag = 0 (BNE branch) if different +; +COMPARE: + LDA DA + CMP AR + BNE C1 + LDA DNVZC ; [7] see text + EOR NF + AND #$80 ; mask off N flag + BNE C1 + LDA DNVZC ; [8] see text + EOR VF + AND #$40 ; mask off V flag + BNE C1 ; [9] see text + LDA DNVZC + EOR ZF ; mask off Z flag + AND #2 + BNE C1 ; [10] see text + LDA DNVZC + EOR CF + AND #1 ; mask off C flag +C1: RTS + +; These routines store the predicted values for ADC and SBC for the 6502, +; 65C02, and 65816 in AR, CF, NF, VF, and ZF + +A6502: LDA VF +; +; since all 8 bits of the P register were stored in VF, bit 7 of VF contains +; the N flag for NF +; + STA NF + LDA HNVZC + STA ZF + RTS + +S6502: JSR SUB1 + LDA HNVZC + STA NF + STA VF + STA ZF + STA CF + RTS + +A65C02: LDA AR + PHP + PLA + STA NF + STA ZF + RTS + +S65C02: JSR SUB2 + LDA AR + PHP + PLA + STA NF + STA ZF + LDA HNVZC + STA VF + STA CF + RTS + +A65816: LDA AR + PHP + PLA + STA NF + STA ZF + RTS + +S65816: JSR SUB1 + LDA AR + PHP + PLA + STA NF + STA ZF + LDA HNVZC + STA VF + STA CF + RTS diff --git a/VMachine.cpp b/VMachine.cpp index 73c7f13..944585e 100644 --- a/VMachine.cpp +++ b/VMachine.cpp @@ -1,579 +1,943 @@ -#include -#include -#include -#include -#include "VMachine.h" -#include "MKGenException.h" - -using namespace std; - -namespace MKBasic { - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ - -/* - *-------------------------------------------------------------------- - * Method: VMachine() - * Purpose: Default class constructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -VMachine::VMachine() -{ - InitVM(); -} - -/* - *-------------------------------------------------------------------- - * Method: VMachine() - * Purpose: Custom class constructor. - * Arguments: romfname - name of the ROM definition file - * ramfname - name of the RAM definition file - * Returns: n/a - *-------------------------------------------------------------------- - */ -VMachine::VMachine(string romfname, string ramfname) -{ - InitVM(); - LoadROM(romfname); - LoadRAM(ramfname); -} - -/* - *-------------------------------------------------------------------- - * Method: ~VMachine() - * Purpose: Class destructor. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -VMachine::~VMachine() -{ - delete mpDisp; - delete mpCPU; - delete mpROM; - delete mpRAM; -} - -/* - *-------------------------------------------------------------------- - * Method: InitVM() - * Purpose: Initialize class. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::InitVM() -{ - mpRAM = new Memory(); - mRunAddr = 0x200; - mCharIOAddr = CHARIO_ADDR; - mCharIOActive = mCharIO = false; - if (NULL == mpRAM) { - throw MKGenException("Unable to initialize VM (RAM)."); - } - mpROM = new Memory(); - if (NULL == mpROM) { - throw MKGenException("Unable to initialize VM (ROM)."); - } - mpCPU = new MKCpu(mpRAM); - if (NULL == mpCPU) { - throw MKGenException("Unable to initialize VM (CPU)."); - } - mpDisp = new Display(); - if (NULL == mpDisp) { - throw MKGenException("Unable to initialize VM (Display)."); - } -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void VMachine::ClearScreen() -{ - HANDLE hStdOut; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD count; - DWORD cellCount; - COORD homeCoords = { 0, 0 }; - - hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); - if (hStdOut == INVALID_HANDLE_VALUE) return; - - /* Get the number of cells in the current buffer */ - if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return; - cellCount = csbi.dwSize.X *csbi.dwSize.Y; - - /* Fill the entire buffer with spaces */ - if (!FillConsoleOutputCharacter( - hStdOut, - (TCHAR) ' ', - cellCount, - homeCoords, - &count - )) return; - - /* Fill the entire buffer with the current colors and attributes */ - if (!FillConsoleOutputAttribute( - hStdOut, - csbi.wAttributes, - cellCount, - homeCoords, - &count - )) return; - - /* Move the cursor home */ - SetConsoleCursorPosition( hStdOut, homeCoords ); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void VMachine::ScrHome() -{ - HANDLE hStdOut; - COORD homeCoords = { 0, 0 }; - - hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); - if (hStdOut == INVALID_HANDLE_VALUE) return; - - /* Move the cursor home */ - SetConsoleCursorPosition( hStdOut, homeCoords ); -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void VMachine::ShowDisp() -{ - if (mCharIOActive) { -#if defined (WINDOWS) - //ClearScreen(); - ScrHome(); -#elif defined (LINUX) - system("clear"); -#endif - mpDisp->ShowScr(); - } -} - -/* - *-------------------------------------------------------------------- - * Method: Run() - * Purpose: Run VM until software break instruction. - * Arguments: n/a - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Run() -{ - Regs *cpureg = NULL; - -#if defined (WINDOWS) - ClearScreen(); -#elif defined (LINUX) - system("clear"); -#endif - ShowDisp(); - while (true) { - cpureg = Step(); - if (mCharIO) { - ShowDisp(); - } - if (cpureg->SoftIrq) - break; - } - - ShowDisp(); - - return cpureg; -} - -/* - *-------------------------------------------------------------------- - * Method: Run() - * Purpose: Run VM from specified address until software break - * instruction. - * Arguments: addr - start execution address - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Run(unsigned short addr) -{ - mRunAddr = addr; - return Run(); -} - -/* - *-------------------------------------------------------------------- - * Method: Exec() - * Purpose: Run VM from current address until last RTS. - * NOTE: Stack must be empty! - * Arguments: n/a - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Exec() -{ - Regs *cpureg = NULL; - -#if defined (WINDOWS) - ClearScreen(); -#elif defined (LINUX) - system("clear"); -#endif - ShowDisp(); - while (true) { - cpureg = Step(); - if (mCharIO) { - ShowDisp(); - } - if (cpureg->LastRTS) break; - } - - ShowDisp(); - - return cpureg; -} - -/* - *-------------------------------------------------------------------- - * Method: Exec() - * Purpose: Run VM from specified address until RTS. - * Arguments: addr - start execution address - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Exec(unsigned short addr) -{ - mRunAddr = addr; - return Exec(); -} - -/* - *-------------------------------------------------------------------- - * Method: Step() - * Purpose: Execute single opcode. - * Arguments: n/a - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Step() -{ - unsigned short addr = mRunAddr; - Regs *cpureg = NULL; - - cpureg = mpCPU->ExecOpcode(addr); - addr = cpureg->PtrAddr; - mRunAddr = addr; - - if (mCharIOActive) { - char c = -1; - mCharIO = false; - while ((c = mpRAM->GetCharOut()) != -1) { - mpDisp->PutChar(c); - mCharIO = true; - } - } - - return cpureg; -} - -/* - *-------------------------------------------------------------------- - * Method: Step() - * Purpose: Execute single opcode. - * Arguments: addr (unsigned short) - opcode address - * Returns: Pointer to CPU registers and flags. - *-------------------------------------------------------------------- - */ -Regs *VMachine::Step(unsigned short addr) -{ - mRunAddr = addr; - return Step(); -} - -/* - *-------------------------------------------------------------------- - * Method: LoadROM() - * Purpose: Load data from memory definition file to the memory. - * Arguments: romfname - name of the ROM file definition - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::LoadROM(string romfname) -{ - LoadMEM(romfname, mpROM); -} - -/* - *-------------------------------------------------------------------- - * Method: LoadRAM() - * Purpose: Load data from memory definition file to the memory. - * Arguments: ramfname - name of the RAM file definition - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::LoadRAM(string ramfname) -{ - LoadMEM(ramfname, mpRAM); - mpRAM->EnableROM(); -} - -/* - *-------------------------------------------------------------------- - * Method: LoadMEM() - * Purpose: Load data from memory definition file to the memory. - * Arguments: memfname - name of memory definition file - * pmem - pointer to memory object - * Returns: n/a - * Details: - * Format of the memory definition file: - * ; comment - * ADDR - * address - * data - * ORG - * address - * - * Where: - * ADDR - label indicating that starting address will follow in next - * line - * ORG - label indicating that the address counter will change to the - * value provided in next line - * address - decimal or hexadecimal (prefix $) address in memory - * E.g: - * ADDR - * $200 - * - * or - * - * ADDR - * 512 - * - * changes the default start address (256) to 512. - * - * ORG - * 49152 - * - * moves address counter to address 49152, following data will be - * loaded from that address forward - * - * data - the multi-line stream of decimal of hexadecimal ($xx) values - * of size unsigned char (byte: 0-255) separated with spaces - * or commas. - * E.g.: - * $00 $00 $00 $00 - * $00 $00 $00 $00 - * - * or - * - * $00,$00,$00,$00 - * - * or - * - * 0 0 0 0 - * - * or - * - * 0,0,0,0 - * 0 0 0 0 - *-------------------------------------------------------------------- - */ -void VMachine::LoadMEM(string memfname, Memory *pmem) -{ - FILE *fp = NULL; - char line[256] = "\0"; - unsigned short addr = 0x200; - unsigned int nAddr; - Memory *pm = pmem; - - if ((fp = fopen(memfname.c_str(), "r")) != NULL) { - fgets(line, 256, fp); - if (0 == strcmp(line, "ADDR")) { - line[0] = '\0'; - fgets(line, 256, fp); - if (*line == '$') { - sscanf(line+1, "%04x", &nAddr); - addr = nAddr; - } else { - addr = (unsigned short) atoi(line); - } - mRunAddr = addr; - } - while (0 == feof(fp) && 0 == ferror(fp)) - { - line[0] = '\0'; - fgets(line, 256, fp); - if (0 == strncmp(line, "ORG", 3)) { - line[0] = '\0'; - fgets(line, 256, fp); - if (*line == '$') { - sscanf(line+1, "%04x", &nAddr); - addr = nAddr; - } else { - addr = (unsigned short) atoi(line); - } - continue; - } - if (';' == *line) continue; // skip comment lines - char *s = strtok (line, " ,"); - while (NULL != s) { - unsigned int nVal; - if (*s == '$') { - sscanf(s+1, "%02x", &nVal); - pm->Poke8bit(addr++, (unsigned short)nVal); - } else { - pm->Poke8bit(addr++, (unsigned short)atoi(s)); - } - s = strtok(NULL, " ,"); - } - } - } - else { - cout << "WARNING: Unable to open memory definition file: " << memfname << endl; - cout << "Press [ENTER]..."; - getchar(); - //throw MKGenException("Unable to open memory definition file: " + memfname); - } -} - -/* - *-------------------------------------------------------------------- - * Method: MemPeek8bit() - * Purpose: Read value from specified RAM address. - * Arguments: addr - RAM address (0..0xFFFF) - * Returns: unsigned short - value read from specified RAM address - *-------------------------------------------------------------------- - */ -unsigned short VMachine::MemPeek8bit(unsigned short addr) -{ - unsigned short ret = 0; - - ret = (unsigned short)mpRAM->Peek8bit(addr); - - return ret; -} - -/* - *-------------------------------------------------------------------- - * Method: MemPoke8bit() - * Purpose: Write value to specified RAM address. - * Arguments: addr - RAM address (0..0xFFFF) - * v - 8-bit byte value - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::MemPoke8bit(unsigned short addr, unsigned char v) -{ - mpRAM->Poke8bit(addr, v); -} - -/* - *-------------------------------------------------------------------- - * Method: GetRegs() - * Purpose: Return pointer to CPU status register. - * Arguments: n/a - * Returns: pointer to status register - *-------------------------------------------------------------------- - */ -Regs *VMachine::GetRegs() -{ - return mpCPU->GetRegs(); -} - -/* - *-------------------------------------------------------------------- - * Method: SetCharIO() - * Purpose: Activates and sets an address of basic character I/O - * emulation (console). - * Arguments: addr - address of I/O area (0x0000..0xFFFF) - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::SetCharIO(unsigned short addr, bool echo) -{ - mCharIOAddr = addr; - mCharIOActive = true; - mpRAM->SetCharIO(addr, echo); - mpDisp->ClrScr(); -} - -/* - *-------------------------------------------------------------------- - * Method: DisableCharIO() - * Purpose: Deactivates basic character I/O emulation (console). - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::DisableCharIO() -{ - mCharIOActive = false; - mpRAM->DisableCharIO(); -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIOAddr() - * Purpose: Returns current address of basic character I/O area. - * Arguments: n/a - * Returns: address of I/O area - *-------------------------------------------------------------------- - */ -unsigned short VMachine::GetCharIOAddr() -{ - return mCharIOAddr; -} - -/* - *-------------------------------------------------------------------- - * Method: GetCharIOActive() - * Purpose: Returns status of character I/O emulation. - * Arguments: n/a - * Returns: true if I/O emulation active - *-------------------------------------------------------------------- - */ -bool VMachine::GetCharIOActive() -{ - return mCharIOActive; -} - -/* - *-------------------------------------------------------------------- - * Method: ShowIO() - * Purpose: Show contents of emulated char I/O. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void VMachine::ShowIO() -{ - if (mCharIOActive) - mpDisp->ShowScr(); -} - -} // namespace MKBasic + +#include +#include +#include +#include "system.h" +#include "VMachine.h" +#include "MKGenException.h" + +#if defined(WINDOWS) +#include +#endif + +using namespace std; + +namespace MKBasic { + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ + +/* + *-------------------------------------------------------------------- + * Method: VMachine() + * Purpose: Default class constructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +VMachine::VMachine() +{ + InitVM(); +} + +/* + *-------------------------------------------------------------------- + * Method: VMachine() + * Purpose: Custom class constructor. + * Arguments: romfname - name of the ROM definition file + * ramfname - name of the RAM definition file + * Returns: n/a + *-------------------------------------------------------------------- + */ +VMachine::VMachine(string romfname, string ramfname) +{ + InitVM(); + LoadROM(romfname); + LoadRAM(ramfname); +} + +/* + *-------------------------------------------------------------------- + * Method: ~VMachine() + * Purpose: Class destructor. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +VMachine::~VMachine() +{ + delete mpDisp; + delete mpCPU; + delete mpROM; + delete mpRAM; +} + +/* + *-------------------------------------------------------------------- + * Method: InitVM() + * Purpose: Initialize class. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::InitVM() +{ + mOpInterrupt = false; + mpRAM = new Memory(); + + mAutoExec = false; + mCharIOAddr = CHARIO_ADDR; + mCharIOActive = mCharIO = false; + if (NULL == mpRAM) { + throw MKGenException("Unable to initialize VM (RAM)."); + } + mRunAddr = mpRAM->Peek16bit(0xFFFC); // address under RESET vector + mpROM = new Memory(); + if (NULL == mpROM) { + throw MKGenException("Unable to initialize VM (ROM)."); + } + mpCPU = new MKCpu(mpRAM); + if (NULL == mpCPU) { + throw MKGenException("Unable to initialize VM (CPU)."); + } + mpDisp = new Display(); + if (NULL == mpDisp) { + throw MKGenException("Unable to initialize VM (Display)."); + } +} + +#if defined(WINDOWS) + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ClearScreen() +{ + HANDLE hStdOut; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD count; + DWORD cellCount; + COORD homeCoords = { 0, 0 }; + + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + if (hStdOut == INVALID_HANDLE_VALUE) return; + + /* Get the number of cells in the current buffer */ + if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return; + cellCount = csbi.dwSize.X *csbi.dwSize.Y; + + /* Fill the entire buffer with spaces */ + if (!FillConsoleOutputCharacter( + hStdOut, + (TCHAR) ' ', + cellCount, + homeCoords, + &count + )) return; + + /* Fill the entire buffer with the current colors and attributes */ + if (!FillConsoleOutputAttribute( + hStdOut, + csbi.wAttributes, + cellCount, + homeCoords, + &count + )) return; + + /* Move the cursor home */ + SetConsoleCursorPosition( hStdOut, homeCoords ); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ScrHome() +{ + HANDLE hStdOut; + COORD homeCoords = { 0, 0 }; + + hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); + if (hStdOut == INVALID_HANDLE_VALUE) return; + + /* Move the cursor home */ + SetConsoleCursorPosition( hStdOut, homeCoords ); +} + +#endif + +#if defined(LINUX) + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ClearScreen() +{ + system("clear"); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ScrHome() +{ + cout << "\033[1;1H"; +} + +#endif + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::ShowDisp() +{ + if (mCharIOActive) { + ScrHome(); + mpDisp->ShowScr(); + } +} + +/* + *-------------------------------------------------------------------- + * Method: Run() + * Purpose: Run VM until software break instruction. + * Arguments: n/a + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Run() +{ + Regs *cpureg = NULL; + + mOpInterrupt = false; + ClearScreen(); + ShowDisp(); + while (true) { + cpureg = Step(); + if (mCharIO) { + ShowDisp(); + } + if (cpureg->SoftIrq || mOpInterrupt) + break; + } + + ShowDisp(); + + return cpureg; +} + +/* + *-------------------------------------------------------------------- + * Method: Run() + * Purpose: Run VM from specified address until software break + * instruction. + * Arguments: addr - start execution address + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Run(unsigned short addr) +{ + mRunAddr = addr; + return Run(); +} + +/* + *-------------------------------------------------------------------- + * Method: Exec() + * Purpose: Run VM from current address until last RTS. + * NOTE: Stack must be empty! + * Arguments: n/a + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Exec() +{ + Regs *cpureg = NULL; + + mOpInterrupt = false; + ClearScreen(); + ShowDisp(); + while (true) { + cpureg = Step(); + if (mCharIO) { + ShowDisp(); + } + if (cpureg->LastRTS || mOpInterrupt) break; + } + + ShowDisp(); + + return cpureg; +} + +/* + *-------------------------------------------------------------------- + * Method: Exec() + * Purpose: Run VM from specified address until RTS. + * Arguments: addr - start execution address + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Exec(unsigned short addr) +{ + mRunAddr = addr; + return Exec(); +} + +/* + *-------------------------------------------------------------------- + * Method: Step() + * Purpose: Execute single opcode. + * Arguments: n/a + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Step() +{ + unsigned short addr = mRunAddr; + Regs *cpureg = NULL; + + cpureg = mpCPU->ExecOpcode(addr); + addr = cpureg->PtrAddr; + mRunAddr = addr; + + if (mCharIOActive && !mOpInterrupt) { + char c = -1; + mCharIO = false; + while ((c = mpRAM->GetCharOut()) != -1) { + mOpInterrupt = (c == OPINTERRUPT); + if (!mOpInterrupt) { + mpDisp->PutChar(c); + mCharIO = true; + } + } + } + + return cpureg; +} + +/* + *-------------------------------------------------------------------- + * Method: Step() + * Purpose: Execute single opcode. + * Arguments: addr (unsigned short) - opcode address + * Returns: Pointer to CPU registers and flags. + *-------------------------------------------------------------------- + */ +Regs *VMachine::Step(unsigned short addr) +{ + mRunAddr = addr; + return Step(); +} + +/* + *-------------------------------------------------------------------- + * Method: LoadROM() + * Purpose: Load data from memory definition file to the memory. + * Arguments: romfname - name of the ROM file definition + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::LoadROM(string romfname) +{ + LoadMEM(romfname, mpROM); +} + +/* + *-------------------------------------------------------------------- + * Method: LoadRAM() + * Purpose: Load data from memory definition file to the memory. + * Arguments: ramfname - name of the RAM file definition + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::LoadRAM(string ramfname) +{ + LoadMEM(ramfname, mpRAM); + //mpRAM->EnableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: LoadRAMBin() + * Purpose: Load data from binary image file to the memory. + * Arguments: ramfname - name of the RAM file definition + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::LoadRAMBin(string ramfname) +{ + FILE *fp = NULL; + unsigned short addr = 0x0000; + int n = 0; + Memory *pm = mpRAM; + + if ((fp = fopen(ramfname.c_str(), "rb")) != NULL) { + while (0 == feof(fp) && 0 == ferror(fp)) { + unsigned char val = fgetc(fp); + pm->Poke8bit(addr, val); + addr++; n++; + } + fclose(fp); + if (n <= 0xFFFF) { + cout << "WARNING: Unexpected EOF." << endl; + } + } + else { + cout << "WARNING: Unable to open memory image file: " << ramfname << endl; + cout << "Press [ENTER]..."; + getchar(); + } +} + +/* + *-------------------------------------------------------------------- + * Method: LoadMEM() + * Purpose: Load data from memory definition file to the memory. + * Arguments: memfname - name of memory definition file + * pmem - pointer to memory object + * Returns: n/a + * Details: + * Format of the memory definition file: + * [; comment] + * [ADDR + * address] + * [data] + * [ORG + * address] + * [data] + * [IOADDR + * address] + * [ROMBEGIN + * address] + * [ROMEND + * address] + * [ENIO] + * [ENROM] + * [EXEC + * addrress] + * + * Where: + * [] - optional token + * ADDR - label indicating that starting address will follow in next + * line, it also defines run address + * ORG - label indicating that the address counter will change to the + * value provided in next line + * IOADDR - label indicating that char IO trap address will be defined + * in the next line + * ROMBEGIN - label indicating that ROM begin address will be defined + * in the next line + * ROMEND - label indicating that ROM end address will be defined + * in the next line + * ENIO - label enabling char IO emulation + * ENROM - label enabling ROM emulation + * EXEC - label enabling auto-execute of code, address follows in the + * next line + * address - decimal or hexadecimal (prefix $) address in memory + * E.g: + * ADDR + * $200 + * + * or + * + * ADDR + * 512 + * + * changes the default start address (256) to 512. + * + * ORG + * 49152 + * + * moves address counter to address 49152, following data will be + * loaded from that address forward + * + * data - the multi-line stream of decimal of hexadecimal ($xx) values + * of size unsigned char (byte: 0-255) separated with spaces + * or commas. + * E.g.: + * $00 $00 $00 $00 + * $00 $00 $00 $00 + * + * or + * + * $00,$00,$00,$00 + * + * or + * + * 0 0 0 0 + * + * or + * + * 0,0,0,0 + * 0 0 0 0 + *-------------------------------------------------------------------- + */ +void VMachine::LoadMEM(string memfname, Memory *pmem) +{ + FILE *fp = NULL; + char line[256] = "\0"; + int lc = 0, errc = 0; + unsigned short addr = 0, rombegin = 0, romend = 0; + unsigned int nAddr; + bool enrom = false, enio = false, runset = false; + bool ioset = false, execset = false, rombegset = false; + bool romendset = false; + Memory *pm = pmem; + + if ((fp = fopen(memfname.c_str(), "r")) != NULL) { + while (0 == feof(fp) && 0 == ferror(fp)) + { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + // change run address (can be done only once) + if (0 == strncmp(line, "ADDR", 4)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!runset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + addr = nAddr; + } else { + addr = (unsigned short) atoi(line); + } + mRunAddr = addr; + runset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: Run address was already set. Ignoring..." << endl; + } + continue; + } + // change address counter + if (0 == strncmp(line, "ORG", 3)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + addr = nAddr; + } else { + addr = (unsigned short) atoi(line); + } + continue; + } + // define I/O emulation address (once) + if (0 == strncmp(line, "IOADDR", 6)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!ioset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + mCharIOAddr = nAddr; + } else { + mCharIOAddr = (unsigned short) atoi(line); + } + ioset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: I/O address was already set. Ignoring..." << endl; + } + continue; + } + // enable character I/O emulation + if (0 == strncmp(line, "ENIO", 4)) { + enio = true; + continue; + } + // enable ROM emulation + if (0 == strncmp(line, "ENROM", 5)) { + enrom = true; + continue; + } + // auto execute from address + if (0 == strncmp(line, "EXEC", 4)) { + mAutoExec = true; + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!execset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + mRunAddr = nAddr; + } else { + mRunAddr = (unsigned short) atoi(line); + } + execset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: auto-exec address was already set. Ignoring..." << endl; + } + continue; + } + // define ROM begin address + if (0 == strncmp(line, "ROMBEGIN", 8)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!rombegset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + rombegin = nAddr; + } else { + rombegin = (unsigned short) atoi(line); + } + rombegset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: ROM-begin address was already set. Ignoring..." << endl; + } + continue; + } + // define ROM end address + if (0 == strncmp(line, "ROMEND", 6)) { + line[0] = '\0'; + fgets(line, 256, fp); + lc++; + if (!romendset) { + if (*line == '$') { + sscanf(line+1, "%04x", &nAddr); + romend = nAddr; + } else { + romend = (unsigned short) atoi(line); + } + romendset = true; + } else { + errc++; + cout << "LINE #" << dec << lc << " WARNING: ROM-end address was already set. Ignoring..." << endl; + } + continue; + } + if (';' == *line) continue; // skip comment lines + char *s = strtok (line, " ,"); + while (NULL != s) { + unsigned int nVal; + if (*s == '$') { + sscanf(s+1, "%02x", &nVal); + pm->Poke8bit(addr++, (unsigned short)nVal); + } else { + pm->Poke8bit(addr++, (unsigned short)atoi(s)); + } + s = strtok(NULL, " ,"); + } + } + fclose(fp); + if (rombegin > MIN_ROM_BEGIN && romend > rombegin) { + if (enrom) + pm->EnableROM(rombegin, romend); + else + pm->SetROM(rombegin, romend); + } else { + if (enrom) pm->EnableROM(); + } + if (enio) { + SetCharIO(mCharIOAddr, false); + } + } + else { + cout << "WARNING: Unable to open memory definition file: " << memfname << endl; + errc++; + } + if (errc) { + cout << "Found " << dec << errc << ((errc > 1) ? " problems." : " problem.") << endl; + cout << "Press [ENTER] to continue..."; + getchar(); + } +} + +/* + *-------------------------------------------------------------------- + * Method: MemPeek8bit() + * Purpose: Read value from specified RAM address. + * Arguments: addr - RAM address (0..0xFFFF) + * Returns: unsigned short - value read from specified RAM address + *-------------------------------------------------------------------- + */ +unsigned short VMachine::MemPeek8bit(unsigned short addr) +{ + unsigned short ret = 0; + + ret = (unsigned short)mpRAM->Peek8bit(addr); + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: MemPoke8bit() + * Purpose: Write value to specified RAM address. + * Arguments: addr - RAM address (0..0xFFFF) + * v - 8-bit byte value + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::MemPoke8bit(unsigned short addr, unsigned char v) +{ + mpRAM->Poke8bit(addr, v); +} + +/* + *-------------------------------------------------------------------- + * Method: GetRegs() + * Purpose: Return pointer to CPU status register. + * Arguments: n/a + * Returns: pointer to status register + *-------------------------------------------------------------------- + */ +Regs *VMachine::GetRegs() +{ + return mpCPU->GetRegs(); +} + +/* + *-------------------------------------------------------------------- + * Method: SetCharIO() + * Purpose: Activates and sets an address of basic character I/O + * emulation (console). + * Arguments: addr - address of I/O area (0x0000..0xFFFF) + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::SetCharIO(unsigned short addr, bool echo) +{ + mCharIOAddr = addr; + mCharIOActive = true; + mpRAM->SetCharIO(addr, echo); + mpDisp->ClrScr(); +} + +/* + *-------------------------------------------------------------------- + * Method: DisableCharIO() + * Purpose: Deactivates basic character I/O emulation (console). + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::DisableCharIO() +{ + mCharIOActive = false; + mpRAM->DisableCharIO(); +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIOAddr() + * Purpose: Returns current address of basic character I/O area. + * Arguments: n/a + * Returns: address of I/O area + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetCharIOAddr() +{ + return mCharIOAddr; +} + +/* + *-------------------------------------------------------------------- + * Method: GetCharIOActive() + * Purpose: Returns status of character I/O emulation. + * Arguments: n/a + * Returns: true if I/O emulation active + *-------------------------------------------------------------------- + */ +bool VMachine::GetCharIOActive() +{ + return mCharIOActive; +} + +/* + *-------------------------------------------------------------------- + * Method: ShowIO() + * Purpose: Show contents of emulated char I/O. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::ShowIO() +{ + if (mCharIOActive) + mpDisp->ShowScr(); +} + +/* + *-------------------------------------------------------------------- + * Method: IsAutoExec() + * Purpose: Return status of auto-execute flag. + * Arguments: n/a + * Returns: bool - true if auto-exec flag is enabled. + *-------------------------------------------------------------------- + */ +bool VMachine::IsAutoExec() +{ + return mAutoExec; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::EnableROM() +{ + mpRAM->EnableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::DisableROM() +{ + mpRAM->DisableROM(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::SetROM(unsigned short start, unsigned short end) +{ + mpRAM->SetROM(start, end); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void VMachine::EnableROM(unsigned short start, unsigned short end) +{ + mpRAM->EnableROM(start, end); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetROMBegin() +{ + return mpRAM->GetROMBegin(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetROMEnd() +{ + return mpRAM->GetROMEnd(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +bool VMachine::IsROMEnabled() +{ + return mpRAM->IsROMEnabled(); +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +unsigned short VMachine::GetRunAddr() +{ + return mRunAddr; +} + +/* + *-------------------------------------------------------------------- + * Method: SetOpInterrupt() + * Purpose: Set the flag indicating operator interrupt. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void VMachine::SetOpInterrupt() +{ + mOpInterrupt = true; +} + +/* + *-------------------------------------------------------------------- + * Method: GetExecHistory() + * Purpose: Return history of executed opcodes (last 20). + * Arguments: n/a + * Returns: queue + *-------------------------------------------------------------------- + */ +queue VMachine::GetExecHistory() +{ + return mpCPU->GetExecHistory(); +} + +/* + *-------------------------------------------------------------------- + * Method: Disassemble() + * Purpose: Disassemble code in memory. Return next instruction + * address. + * Arguments: addr - address in memory + * buf - character buffer for disassembled instruction + * Returns: unsigned short - address of next instruction + *-------------------------------------------------------------------- + */ +unsigned short VMachine::Disassemble(unsigned short addr, char *buf) +{ + return mpCPU->Disassemble(addr, buf); +} + +} // namespace MKBasic diff --git a/VMachine.h b/VMachine.h index d18d793..8281a34 100644 --- a/VMachine.h +++ b/VMachine.h @@ -1,65 +1,84 @@ -#ifndef VMACHINE_H -#define VMACHINE_H - -#include -#include "MKCpu.h" -#include "Memory.h" -#include "Display.h" - -#define WINDOWS 1 -#if defined (WINDOWS) -#include -#endif -#define IOREFRESH 32 - -using namespace std; - -namespace MKBasic { - -class VMachine -{ - public: - VMachine(); - VMachine(string romfname, string ramfname); - ~VMachine(); - - void InitVM(); - Regs *Run(); - Regs *Run(unsigned short addr); - Regs *Exec(); - Regs *Exec(unsigned short addr); - Regs *Step(); - Regs *Step(unsigned short addr); - void LoadROM(string romfname); - void LoadRAM(string ramfname); - unsigned short MemPeek8bit(unsigned short addr); - void MemPoke8bit(unsigned short addr, unsigned char v); - Regs *GetRegs(); - void SetCharIO(unsigned short addr, bool echo); - void DisableCharIO(); - unsigned short GetCharIOAddr(); - bool GetCharIOActive(); - void ShowIO(); - void ClearScreen(); - void ScrHome(); - - protected: - - private: - - MKCpu *mpCPU; - Memory *mpROM; - Memory *mpRAM; - Display *mpDisp; - unsigned short mRunAddr; - unsigned short mCharIOAddr; - bool mCharIOActive; - bool mCharIO; - - void LoadMEM(string memfname, Memory *pmem); - void ShowDisp(); -}; - -} // namespace MKBasic - -#endif +#ifndef VMACHINE_H +#define VMACHINE_H + +#include +#include +#include "system.h" +#include "MKCpu.h" +#include "Memory.h" +#include "Display.h" + +//#define WINDOWS 1 +#if defined (WINDOWS) +#include +#endif + +#define IOREFRESH 32 +#define OPINTERRUPT 25 // operator interrupt code (CTRL-Y) + +using namespace std; + +namespace MKBasic { + +class VMachine +{ + public: + VMachine(); + VMachine(string romfname, string ramfname); + ~VMachine(); + + void InitVM(); + Regs *Run(); + Regs *Run(unsigned short addr); + Regs *Exec(); + Regs *Exec(unsigned short addr); + Regs *Step(); + Regs *Step(unsigned short addr); + void LoadROM(string romfname); + void LoadRAM(string ramfname); + void LoadRAMBin(string ramfname); + unsigned short MemPeek8bit(unsigned short addr); + void MemPoke8bit(unsigned short addr, unsigned char v); + Regs *GetRegs(); + void SetCharIO(unsigned short addr, bool echo); + void DisableCharIO(); + unsigned short GetCharIOAddr(); + bool GetCharIOActive(); + void ShowIO(); + void ClearScreen(); + void ScrHome(); + bool IsAutoExec(); + void EnableROM(); + void DisableROM(); + void SetROM(unsigned short start, unsigned short end); + void EnableROM(unsigned short start, unsigned short end); + unsigned short GetROMBegin(); + unsigned short GetROMEnd(); + bool IsROMEnabled(); + unsigned short GetRunAddr(); + void SetOpInterrupt(); + queue GetExecHistory(); + unsigned short Disassemble(unsigned short addr, char *buf); + + protected: + + private: + + MKCpu *mpCPU; + Memory *mpROM; + Memory *mpRAM; + Display *mpDisp; + unsigned short mRunAddr; + unsigned short mCharIOAddr; + bool mCharIOActive; + bool mCharIO; + bool mOpInterrupt; // operator interrupt from console + bool mAutoExec; + + void LoadMEM(string memfname, Memory *pmem); + void ShowDisp(); +}; + +} // namespace MKBasic + +#endif diff --git a/bcd.c b/bcd.c index 9dc76eb..e9bd058 100644 --- a/bcd.c +++ b/bcd.c @@ -1,56 +1,56 @@ - -#include -#include -#include - - -unsigned char conv2bcd(unsigned short v) -{ - unsigned char arg8 = 0; - arg8 = (unsigned char)((v/10) << 4); - arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; - return arg8; -} - -char *conv24bitbin(unsigned char v) -{ - static char retbuf[5]; - int i=3; - - memset(retbuf, '0', 4); - retbuf[4]=0; - if (v == 0) return retbuf; - while (v > 0 && i >= 0) { - int r = v % 2; - retbuf[i] = ((r==0) ? '0' : '1'); - v = v/2; - i--; - } - - return retbuf; -} - -/* run this program using the console pauser or add your own getch, system("pause") or input loop */ - -int main(int argc, char *argv[]) -{ - unsigned short v = 0; - - for (v = 0; v < 100; v++) { - unsigned char cv = conv2bcd(v), hinyb, lonyb; - hinyb = (cv & 0xF0) >> 4; - lonyb = cv & 0x0F; - char buf_hinyb[5], buf_lonyb[5]; - strcpy(buf_hinyb, conv24bitbin(hinyb)); - strcpy(buf_lonyb, conv24bitbin(lonyb)); - printf("%d (dec) \t= %4s(%d) %4s(%d) (BCD, dec:%d)\n", v, - buf_hinyb, - hinyb, - buf_lonyb, - lonyb, - cv); - } - - return 0; -} - + +#include +#include +#include + + +unsigned char conv2bcd(unsigned short v) +{ + unsigned char arg8 = 0; + arg8 = (unsigned char)((v/10) << 4); + arg8 |= ((unsigned char)(v - (v/10)*10)) & 0x0F; + return arg8; +} + +char *conv24bitbin(unsigned char v) +{ + static char retbuf[5]; + int i=3; + + memset(retbuf, '0', 4); + retbuf[4]=0; + if (v == 0) return retbuf; + while (v > 0 && i >= 0) { + int r = v % 2; + retbuf[i] = ((r==0) ? '0' : '1'); + v = v/2; + i--; + } + + return retbuf; +} + +/* run this program using the console pauser or add your own getch, system("pause") or input loop */ + +int main(int argc, char *argv[]) +{ + unsigned short v = 0; + + for (v = 0; v < 100; v++) { + unsigned char cv = conv2bcd(v), hinyb, lonyb; + hinyb = (cv & 0xF0) >> 4; + lonyb = cv & 0x0F; + char buf_hinyb[5], buf_lonyb[5]; + strcpy(buf_hinyb, conv24bitbin(hinyb)); + strcpy(buf_lonyb, conv24bitbin(lonyb)); + printf("%d (dec) \t= %4s(%d) %4s(%d) (BCD, dec:%d)\n", v, + buf_hinyb, + hinyb, + buf_lonyb, + lonyb, + cv); + } + + return 0; +} + diff --git a/bin2hex.c b/bin2hex.c new file mode 100644 index 0000000..5d5cd5f --- /dev/null +++ b/bin2hex.c @@ -0,0 +1,187 @@ +/* + *---------------------------------------------------------------------------- + * File: bin2hex.c + * + * Author: Marek Karcz + * + * Date created: 3/8/2016 + * + * Purpose: Convert binary file to memory image definition (plain text) file. + *---------------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +const int DEBUG = 0; +const char *hdr1 = "; Created with BIN2HEX (C) Marek Karcz 2016. All rights reserved.\n"; + +char g_szInputFileName[256] = {0}; +char g_szHexFileName[256] = {0}; +int g_nStartAddr = 2048; /* $0800 */ +int g_nExecAddr = 2048; /* $0800 */ +int g_nSuppressAutoExec = 1; +int g_nSuppressAllZeroRows = 0; + +void ScanArgs(int argc, char *argv[]); +void ConvertFile(void); + +void Usage(char *prgn) +{ + printf("\nProgram: %s\n Convert binary file to memory image definition for MKBASIC (VM65) emulator.\n\n", prgn); + printf("Copyright: Marek Karcz 2016. All rights reserved.\n"); + printf("Free for personal and educational use.\n\n"); + printf("Usage:\n\n"); + printf(" %s -f input_fname -o output_fname [-w load_addr] [-x exec_addr] [-s] [-z]\n\n", prgn); + printf("Where:\n\n"); + printf(" input_fname - binary file name\n"); + printf(" output_fname - output file name\n"); + printf(" load_addr - starting address to load data (default: %d)\n", g_nStartAddr); + printf(" exec_addr - address to auto-execute code from (default: %d)\n", g_nExecAddr); + printf(" -s - suppress auto-execute statement in output\n"); + printf(" -z - suppress data blocks with 0-s only\n"); + printf("\n"); +} + +/* + * bin2hex -f InputFile -o OutputFile -w StartAddr + */ +void ScanArgs(int argc, char *argv[]) +{ + int n = 1; + + while (n < argc) + { + if (strcmp(argv[n], "-f") == 0) + { + n++; + strcpy(g_szInputFileName,argv[n]); + } + else if (strcmp(argv[n],"-o") == 0) + { + n++; + strcpy(g_szHexFileName,argv[n]); + } + else if (strcmp(argv[n],"-w") == 0) + { + n++; + g_nStartAddr = atoi(argv[n]); + g_nExecAddr = g_nStartAddr; + g_nSuppressAutoExec = 0; + } + else if (strcmp(argv[n],"-x") == 0) + { + n++; + g_nExecAddr = atoi(argv[n]); + g_nSuppressAutoExec = 0; + } + else if (strcmp(argv[n],"-s") == 0) + { + g_nSuppressAutoExec = 1; + } + else if (strcmp(argv[n],"-z") == 0) + { + g_nSuppressAllZeroRows = 1; + } + + n++; + } +} + +void ConvertFile(void) +{ + FILE *fpi = NULL; + FILE *fpo = NULL; + unsigned char bt[17]; + char hex[80]; + int i, addr, allzero, prev_allzero; + + addr = g_nStartAddr; + printf("Processing...\n"); + printf("Start address: $%04x\n", addr); + if (NULL != (fpi = fopen(g_szInputFileName,"rb"))) + { + if (NULL != (fpo = fopen(g_szHexFileName,"w"))) + { + time_t t = time(NULL); + struct tm *tm = localtime(&t); + char s[64] = {0}; + strftime(s, sizeof(s), "; %c\n", tm); + + fputs(hdr1, fpo); + fputs(s, fpo); + sprintf(hex, "ADDR\n$%04x\nORG\n$%04x\n", g_nExecAddr, addr); + if (DEBUG) printf("Adding line:\n%s\n", hex); + fputs(hex,fpo); + prev_allzero = 1; + while(0 == feof(fpi) && addr <= 0xFFFF) + { + memset(bt, 0, 17); + memset(hex, 0, 80); + if (DEBUG) printf("Reading input file..."); + fread(bt, sizeof(char), 16, fpi); + if (DEBUG) printf("done.\n"); + if (DEBUG) printf("Preparing hex string...\n"); + allzero = 1; + for(i=0; i<16; i++) + { + if (DEBUG) printf("Code: %d\n", bt[i]); + if (*hex == 0) sprintf(hex, "$%02x", bt[i]); + else sprintf(hex, "%s $%02x", hex, bt[i]); + if (allzero && bt[i] > 0) + allzero = 0; + } + if (g_nSuppressAllZeroRows && prev_allzero && 0 == allzero) { + char buff[20]; + sprintf (buff, "ORG\n$%04x\n", addr); + fputs(buff, fpo); + } + if (0 == g_nSuppressAllZeroRows + || + (g_nSuppressAllZeroRows && 0 == allzero) + ) + { + sprintf(hex, "%s\n", hex); + if (DEBUG) printf("Adding line: %s", hex); + fputs(hex, fpo); + } + addr += 16; + prev_allzero = allzero; + } + if (0 == g_nSuppressAutoExec) + { + memset(hex, 80, sizeof(char)); + sprintf(hex, "EXEC\n$%04x\n", g_nExecAddr); + if (DEBUG) printf("Adding line: %s", hex); + fputs(hex, fpo); + } + fclose(fpi); + fclose(fpo); + printf("Done.\n"); + printf("End address: $%04x\n", (addr <= 0xFFFF) ? addr : 0xFFFF); + printf("Run address: $%04x\n", g_nExecAddr); + } + else + printf("ERROR: Unable to create output file.\n"); + } + else + printf("ERROR: Unable to open input file.\n"); +} + +int main(int argc, char *argv[]) +{ + if (argc == 1) + Usage(argv[0]); + else { + ScanArgs(argc, argv); + if (*g_szInputFileName == 0 || *g_szHexFileName == 0) + Usage(argv[0]); + else + ConvertFile(); + } + return 0; +} + + diff --git a/dummy.ram b/dummy.ram index 9ce490e..43eaabb 100644 --- a/dummy.ram +++ b/dummy.ram @@ -1,315 +1,315 @@ -; -; test program #1 -; address: $0200 -; load Acc with value 12 -; write Acc to address $c000 (49152) -; -; nop -; nop -; lda #$0c -; sta $c000 -; brk -; -$EA $EA $A9 $0c $8D $00 $c0 $00 $00 -; -; test program #2 -; address: $0400 -; copy 0-terminated string from -; address $d000 to $0200 -; "Hello World!" -; -; ORG=$0400 -; hello: -; ldx #0 -; loop: -; lda $d000,x -; beq $06 ;branch to end (+6) if A=0 -; sta $0200,x -; inx -; bne $f5 ; branch to loop (-11) if X<>0 -; end: -; brk -ORG -$0400 -$A2 $00 -$BD $00 $d0 -$F0 $06 -$9D $00 $02 -$E8 -$D0 $F5 -$00 $00 -; data -; address: $d000 -ORG -$D000 -;DEC: 53248 -; "Hello World!" -72 101 108 108 111 32 87 111 114 108 100 33 0 -; -; test program #3 - copy Hello World! string to $0300 -; using different assembly instructions -; address: $0500 -; -; ORG=$0500 ;dec: 1280 -; hello: -; lda #0 -; sta $05 -; ldx $05 -; loop: -; lda $d000,x -; sta $0300,x -; beq end ;(+6) -; inx -; beq end ;(+3) -; jmp loop -; end: -; brk -ORG -$0500 -;DEC: 1280 -$A9 $00 -$85 $05 -$A6 $05 -$BD $00 $d0 -$9D $00 $03 -$F0 $06 -$E8 -$F0 $03 -$4C $06 $05 -$00 $00 -; -; test program #4 -; left-shift memory location $05 at zero page, -; then location $06 using zero page indexed addressing, -; then memory location $c001 (outside zero page) using absolute addressing -; then location $c002 using indexed absolute addressing -; and finally left-shift Acc. -; stop after each step for debugging -; exit loop when Acc=0 -; -; start: -; lda #$ff -; ldx #$01 -; sta $05 -; sta $05,x -; sta $c000,x -; inx -; sta $c000,x -; ldx #$01 -; loop2: -; brk -; asl $05 -; asl $05,x -; asl $c001 -; asl $c001,x -; asl -; bne loop2 ;(-15 or $f1) -; brk -ORG -$0600 -$A9 $FF -$A2 $01 -$85 $05 -$95 $05 -$9D $00 $C0 -$E8 -$9D $00 $C0 -$A2 $01 -$00 $00 -$06 $05 -$16 $05 -$0E $01 $C0 -$1E $01 $C0 -$0A -$D0 $F1 -$00 $00 -; -; test program #5 -; Test ORA opcode with various arguments and addressing modes. -; At each break, the contents of Acc should equal $AA. -; -; start: -; lda #$aa ;%10101010 -; sta $05 -; sta $aa -; lda #$00 -; tax -; ora ($05,x) -; brk -; lda #$00 -; ora $05 -; brk -; lda #$00 -; ora #$aa -; brk -; lda #$00 -; ora $0005 -; brk -; lda #$05 -; sta $06 -; lda #$00 -; sta $07 -; tay -; ora ($06),y -; brk -; lda #$00 -; tax -; ora $05,x -; brk -; lda #$00 -; tay -; ora $0005,y -; brk -; lda #$00 -; tax -; ora $0005,x -; brk -ORG -$0700 -$A9 $AA -$85 $05 -$85 $AA -$A9 $00 -$AA -$01 $05 -$00 $00 -$A9 $00 -$05 $05 -$00 $00 -$A9 $00 -$09 $AA -$00 $00 -$A9 $00 -$0D $05 $00 -$00 $00 -$A9 $05 -$85 $06 -$A9 $00 -$85 $07 -$A8 -$11 $06 -$00 $00 -$A9 $00 -$AA -$15 $05 -$00 $00 -$A9 $00 -$A8 -$19 $05 $00 -$00 $00 -$A9 $00 -$AA -$1D $05 $00 -$00 $00 -; -; test program #6 -; Test JSR opcode. -; After each break examine memory at $c000 and $c001. -; After 1-st break, $c000 should equal $dd. -; Return address-1 ($0802) should be on stack. -; After 2-nd break, PC counter should be at $0805. -; After 3-rd break, $c000 should equal $ee. -; Return address-1 ($0807) should be on stack. -; After 4-th break, PC counter should be at $080a. -; -; start: -; jsr sub1 -; brk -; jsr sub2 -; brk -; brk -; brk -; sub1: -; lda #$dd -; sta $c000 -; brk -; rts -; sub2: -; lda #$ee -; sta $c000 -; brk -; rts -; -ORG -$0800 -$20 $0B $08 -$00 $00 -$20 $13 $08 -$00 -$00 -$00 -$A9 $DD -$8D $00 $C0 -$00 $00 -$60 -$A9 $EE -$8D $00 $C0 -$00 $00 -$60 -; -; test program #7 -; Test ADC opcode. -; Expected results: -; First break: Acc=$01, Carry=1 -; 2-nd break: Acc=$02, Carry=1 -; 3-rd break: Acc=$22, Carry=0 -; 4-th break: Acc=$23, Carry=0 -; -; start: -; clc -; lda #$ff -; adc #$02 -; brk -; sec -; lda #$ff -; adc #$02 -; brk -; clc -; lda #$20 -; adc #$02 -; brk -; sec -; lda #$20 -; adc #$02 -; brk -; -ORG -$0900 -$18 -$A9 $FF -$69 $02 -$00 $00 -$38 -$A9 $FF -$69 $02 -$00 $00 -$18 -$A9 $20 -$69 $02 -$00 $00 -$38 -$A9 $20 -$69 $02 -$00 $00 -; -; test program #8 -; Test ROR opcode. -; -; start: -; sec -; lda #$00 -; loop: -; ror -; brk -; bcc loop ;(-5 -> $FB) -; brk -; -ORG -$0920 -$38 -$A9 $00 -$6A -$00 $00 -$90 $FB -$00 $00 +; +; test program #1 +; address: $0200 +; load Acc with value 12 +; write Acc to address $c000 (49152) +; +; nop +; nop +; lda #$0c +; sta $c000 +; brk +; +$EA $EA $A9 $0c $8D $00 $c0 $00 $00 +; +; test program #2 +; address: $0400 +; copy 0-terminated string from +; address $d000 to $0200 +; "Hello World!" +; +; ORG=$0400 +; hello: +; ldx #0 +; loop: +; lda $d000,x +; beq $06 ;branch to end (+6) if A=0 +; sta $0200,x +; inx +; bne $f5 ; branch to loop (-11) if X<>0 +; end: +; brk +ORG +$0400 +$A2 $00 +$BD $00 $d0 +$F0 $06 +$9D $00 $02 +$E8 +$D0 $F5 +$00 $00 +; data +; address: $d000 +ORG +$D000 +;DEC: 53248 +; "Hello World!" +72 101 108 108 111 32 87 111 114 108 100 33 0 +; +; test program #3 - copy Hello World! string to $0300 +; using different assembly instructions +; address: $0500 +; +; ORG=$0500 ;dec: 1280 +; hello: +; lda #0 +; sta $05 +; ldx $05 +; loop: +; lda $d000,x +; sta $0300,x +; beq end ;(+6) +; inx +; beq end ;(+3) +; jmp loop +; end: +; brk +ORG +$0500 +;DEC: 1280 +$A9 $00 +$85 $05 +$A6 $05 +$BD $00 $d0 +$9D $00 $03 +$F0 $06 +$E8 +$F0 $03 +$4C $06 $05 +$00 $00 +; +; test program #4 +; left-shift memory location $05 at zero page, +; then location $06 using zero page indexed addressing, +; then memory location $c001 (outside zero page) using absolute addressing +; then location $c002 using indexed absolute addressing +; and finally left-shift Acc. +; stop after each step for debugging +; exit loop when Acc=0 +; +; start: +; lda #$ff +; ldx #$01 +; sta $05 +; sta $05,x +; sta $c000,x +; inx +; sta $c000,x +; ldx #$01 +; loop2: +; brk +; asl $05 +; asl $05,x +; asl $c001 +; asl $c001,x +; asl +; bne loop2 ;(-15 or $f1) +; brk +ORG +$0600 +$A9 $FF +$A2 $01 +$85 $05 +$95 $05 +$9D $00 $C0 +$E8 +$9D $00 $C0 +$A2 $01 +$00 $00 +$06 $05 +$16 $05 +$0E $01 $C0 +$1E $01 $C0 +$0A +$D0 $F1 +$00 $00 +; +; test program #5 +; Test ORA opcode with various arguments and addressing modes. +; At each break, the contents of Acc should equal $AA. +; +; start: +; lda #$aa ;%10101010 +; sta $05 +; sta $aa +; lda #$00 +; tax +; ora ($05,x) +; brk +; lda #$00 +; ora $05 +; brk +; lda #$00 +; ora #$aa +; brk +; lda #$00 +; ora $0005 +; brk +; lda #$05 +; sta $06 +; lda #$00 +; sta $07 +; tay +; ora ($06),y +; brk +; lda #$00 +; tax +; ora $05,x +; brk +; lda #$00 +; tay +; ora $0005,y +; brk +; lda #$00 +; tax +; ora $0005,x +; brk +ORG +$0700 +$A9 $AA +$85 $05 +$85 $AA +$A9 $00 +$AA +$01 $05 +$00 $00 +$A9 $00 +$05 $05 +$00 $00 +$A9 $00 +$09 $AA +$00 $00 +$A9 $00 +$0D $05 $00 +$00 $00 +$A9 $05 +$85 $06 +$A9 $00 +$85 $07 +$A8 +$11 $06 +$00 $00 +$A9 $00 +$AA +$15 $05 +$00 $00 +$A9 $00 +$A8 +$19 $05 $00 +$00 $00 +$A9 $00 +$AA +$1D $05 $00 +$00 $00 +; +; test program #6 +; Test JSR opcode. +; After each break examine memory at $c000 and $c001. +; After 1-st break, $c000 should equal $dd. +; Return address-1 ($0802) should be on stack. +; After 2-nd break, PC counter should be at $0805. +; After 3-rd break, $c000 should equal $ee. +; Return address-1 ($0807) should be on stack. +; After 4-th break, PC counter should be at $080a. +; +; start: +; jsr sub1 +; brk +; jsr sub2 +; brk +; brk +; brk +; sub1: +; lda #$dd +; sta $c000 +; brk +; rts +; sub2: +; lda #$ee +; sta $c000 +; brk +; rts +; +ORG +$0800 +$20 $0B $08 +$00 $00 +$20 $13 $08 +$00 +$00 +$00 +$A9 $DD +$8D $00 $C0 +$00 $00 +$60 +$A9 $EE +$8D $00 $C0 +$00 $00 +$60 +; +; test program #7 +; Test ADC opcode. +; Expected results: +; First break: Acc=$01, Carry=1 +; 2-nd break: Acc=$02, Carry=1 +; 3-rd break: Acc=$22, Carry=0 +; 4-th break: Acc=$23, Carry=0 +; +; start: +; clc +; lda #$ff +; adc #$02 +; brk +; sec +; lda #$ff +; adc #$02 +; brk +; clc +; lda #$20 +; adc #$02 +; brk +; sec +; lda #$20 +; adc #$02 +; brk +; +ORG +$0900 +$18 +$A9 $FF +$69 $02 +$00 $00 +$38 +$A9 $FF +$69 $02 +$00 $00 +$18 +$A9 $20 +$69 $02 +$00 $00 +$38 +$A9 $20 +$69 $02 +$00 $00 +; +; test program #8 +; Test ROR opcode. +; +; start: +; sec +; lda #$00 +; loop: +; ror +; brk +; bcc loop ;(-5 -> $FB) +; brk +; +ORG +$0920 +$38 +$A9 $00 +$6A +$00 $00 +$90 $FB +$00 $00 ; \ No newline at end of file diff --git a/dummy.rom b/dummy.rom index 9ce490e..43eaabb 100644 --- a/dummy.rom +++ b/dummy.rom @@ -1,315 +1,315 @@ -; -; test program #1 -; address: $0200 -; load Acc with value 12 -; write Acc to address $c000 (49152) -; -; nop -; nop -; lda #$0c -; sta $c000 -; brk -; -$EA $EA $A9 $0c $8D $00 $c0 $00 $00 -; -; test program #2 -; address: $0400 -; copy 0-terminated string from -; address $d000 to $0200 -; "Hello World!" -; -; ORG=$0400 -; hello: -; ldx #0 -; loop: -; lda $d000,x -; beq $06 ;branch to end (+6) if A=0 -; sta $0200,x -; inx -; bne $f5 ; branch to loop (-11) if X<>0 -; end: -; brk -ORG -$0400 -$A2 $00 -$BD $00 $d0 -$F0 $06 -$9D $00 $02 -$E8 -$D0 $F5 -$00 $00 -; data -; address: $d000 -ORG -$D000 -;DEC: 53248 -; "Hello World!" -72 101 108 108 111 32 87 111 114 108 100 33 0 -; -; test program #3 - copy Hello World! string to $0300 -; using different assembly instructions -; address: $0500 -; -; ORG=$0500 ;dec: 1280 -; hello: -; lda #0 -; sta $05 -; ldx $05 -; loop: -; lda $d000,x -; sta $0300,x -; beq end ;(+6) -; inx -; beq end ;(+3) -; jmp loop -; end: -; brk -ORG -$0500 -;DEC: 1280 -$A9 $00 -$85 $05 -$A6 $05 -$BD $00 $d0 -$9D $00 $03 -$F0 $06 -$E8 -$F0 $03 -$4C $06 $05 -$00 $00 -; -; test program #4 -; left-shift memory location $05 at zero page, -; then location $06 using zero page indexed addressing, -; then memory location $c001 (outside zero page) using absolute addressing -; then location $c002 using indexed absolute addressing -; and finally left-shift Acc. -; stop after each step for debugging -; exit loop when Acc=0 -; -; start: -; lda #$ff -; ldx #$01 -; sta $05 -; sta $05,x -; sta $c000,x -; inx -; sta $c000,x -; ldx #$01 -; loop2: -; brk -; asl $05 -; asl $05,x -; asl $c001 -; asl $c001,x -; asl -; bne loop2 ;(-15 or $f1) -; brk -ORG -$0600 -$A9 $FF -$A2 $01 -$85 $05 -$95 $05 -$9D $00 $C0 -$E8 -$9D $00 $C0 -$A2 $01 -$00 $00 -$06 $05 -$16 $05 -$0E $01 $C0 -$1E $01 $C0 -$0A -$D0 $F1 -$00 $00 -; -; test program #5 -; Test ORA opcode with various arguments and addressing modes. -; At each break, the contents of Acc should equal $AA. -; -; start: -; lda #$aa ;%10101010 -; sta $05 -; sta $aa -; lda #$00 -; tax -; ora ($05,x) -; brk -; lda #$00 -; ora $05 -; brk -; lda #$00 -; ora #$aa -; brk -; lda #$00 -; ora $0005 -; brk -; lda #$05 -; sta $06 -; lda #$00 -; sta $07 -; tay -; ora ($06),y -; brk -; lda #$00 -; tax -; ora $05,x -; brk -; lda #$00 -; tay -; ora $0005,y -; brk -; lda #$00 -; tax -; ora $0005,x -; brk -ORG -$0700 -$A9 $AA -$85 $05 -$85 $AA -$A9 $00 -$AA -$01 $05 -$00 $00 -$A9 $00 -$05 $05 -$00 $00 -$A9 $00 -$09 $AA -$00 $00 -$A9 $00 -$0D $05 $00 -$00 $00 -$A9 $05 -$85 $06 -$A9 $00 -$85 $07 -$A8 -$11 $06 -$00 $00 -$A9 $00 -$AA -$15 $05 -$00 $00 -$A9 $00 -$A8 -$19 $05 $00 -$00 $00 -$A9 $00 -$AA -$1D $05 $00 -$00 $00 -; -; test program #6 -; Test JSR opcode. -; After each break examine memory at $c000 and $c001. -; After 1-st break, $c000 should equal $dd. -; Return address-1 ($0802) should be on stack. -; After 2-nd break, PC counter should be at $0805. -; After 3-rd break, $c000 should equal $ee. -; Return address-1 ($0807) should be on stack. -; After 4-th break, PC counter should be at $080a. -; -; start: -; jsr sub1 -; brk -; jsr sub2 -; brk -; brk -; brk -; sub1: -; lda #$dd -; sta $c000 -; brk -; rts -; sub2: -; lda #$ee -; sta $c000 -; brk -; rts -; -ORG -$0800 -$20 $0B $08 -$00 $00 -$20 $13 $08 -$00 -$00 -$00 -$A9 $DD -$8D $00 $C0 -$00 $00 -$60 -$A9 $EE -$8D $00 $C0 -$00 $00 -$60 -; -; test program #7 -; Test ADC opcode. -; Expected results: -; First break: Acc=$01, Carry=1 -; 2-nd break: Acc=$02, Carry=1 -; 3-rd break: Acc=$22, Carry=0 -; 4-th break: Acc=$23, Carry=0 -; -; start: -; clc -; lda #$ff -; adc #$02 -; brk -; sec -; lda #$ff -; adc #$02 -; brk -; clc -; lda #$20 -; adc #$02 -; brk -; sec -; lda #$20 -; adc #$02 -; brk -; -ORG -$0900 -$18 -$A9 $FF -$69 $02 -$00 $00 -$38 -$A9 $FF -$69 $02 -$00 $00 -$18 -$A9 $20 -$69 $02 -$00 $00 -$38 -$A9 $20 -$69 $02 -$00 $00 -; -; test program #8 -; Test ROR opcode. -; -; start: -; sec -; lda #$00 -; loop: -; ror -; brk -; bcc loop ;(-5 -> $FB) -; brk -; -ORG -$0920 -$38 -$A9 $00 -$6A -$00 $00 -$90 $FB -$00 $00 +; +; test program #1 +; address: $0200 +; load Acc with value 12 +; write Acc to address $c000 (49152) +; +; nop +; nop +; lda #$0c +; sta $c000 +; brk +; +$EA $EA $A9 $0c $8D $00 $c0 $00 $00 +; +; test program #2 +; address: $0400 +; copy 0-terminated string from +; address $d000 to $0200 +; "Hello World!" +; +; ORG=$0400 +; hello: +; ldx #0 +; loop: +; lda $d000,x +; beq $06 ;branch to end (+6) if A=0 +; sta $0200,x +; inx +; bne $f5 ; branch to loop (-11) if X<>0 +; end: +; brk +ORG +$0400 +$A2 $00 +$BD $00 $d0 +$F0 $06 +$9D $00 $02 +$E8 +$D0 $F5 +$00 $00 +; data +; address: $d000 +ORG +$D000 +;DEC: 53248 +; "Hello World!" +72 101 108 108 111 32 87 111 114 108 100 33 0 +; +; test program #3 - copy Hello World! string to $0300 +; using different assembly instructions +; address: $0500 +; +; ORG=$0500 ;dec: 1280 +; hello: +; lda #0 +; sta $05 +; ldx $05 +; loop: +; lda $d000,x +; sta $0300,x +; beq end ;(+6) +; inx +; beq end ;(+3) +; jmp loop +; end: +; brk +ORG +$0500 +;DEC: 1280 +$A9 $00 +$85 $05 +$A6 $05 +$BD $00 $d0 +$9D $00 $03 +$F0 $06 +$E8 +$F0 $03 +$4C $06 $05 +$00 $00 +; +; test program #4 +; left-shift memory location $05 at zero page, +; then location $06 using zero page indexed addressing, +; then memory location $c001 (outside zero page) using absolute addressing +; then location $c002 using indexed absolute addressing +; and finally left-shift Acc. +; stop after each step for debugging +; exit loop when Acc=0 +; +; start: +; lda #$ff +; ldx #$01 +; sta $05 +; sta $05,x +; sta $c000,x +; inx +; sta $c000,x +; ldx #$01 +; loop2: +; brk +; asl $05 +; asl $05,x +; asl $c001 +; asl $c001,x +; asl +; bne loop2 ;(-15 or $f1) +; brk +ORG +$0600 +$A9 $FF +$A2 $01 +$85 $05 +$95 $05 +$9D $00 $C0 +$E8 +$9D $00 $C0 +$A2 $01 +$00 $00 +$06 $05 +$16 $05 +$0E $01 $C0 +$1E $01 $C0 +$0A +$D0 $F1 +$00 $00 +; +; test program #5 +; Test ORA opcode with various arguments and addressing modes. +; At each break, the contents of Acc should equal $AA. +; +; start: +; lda #$aa ;%10101010 +; sta $05 +; sta $aa +; lda #$00 +; tax +; ora ($05,x) +; brk +; lda #$00 +; ora $05 +; brk +; lda #$00 +; ora #$aa +; brk +; lda #$00 +; ora $0005 +; brk +; lda #$05 +; sta $06 +; lda #$00 +; sta $07 +; tay +; ora ($06),y +; brk +; lda #$00 +; tax +; ora $05,x +; brk +; lda #$00 +; tay +; ora $0005,y +; brk +; lda #$00 +; tax +; ora $0005,x +; brk +ORG +$0700 +$A9 $AA +$85 $05 +$85 $AA +$A9 $00 +$AA +$01 $05 +$00 $00 +$A9 $00 +$05 $05 +$00 $00 +$A9 $00 +$09 $AA +$00 $00 +$A9 $00 +$0D $05 $00 +$00 $00 +$A9 $05 +$85 $06 +$A9 $00 +$85 $07 +$A8 +$11 $06 +$00 $00 +$A9 $00 +$AA +$15 $05 +$00 $00 +$A9 $00 +$A8 +$19 $05 $00 +$00 $00 +$A9 $00 +$AA +$1D $05 $00 +$00 $00 +; +; test program #6 +; Test JSR opcode. +; After each break examine memory at $c000 and $c001. +; After 1-st break, $c000 should equal $dd. +; Return address-1 ($0802) should be on stack. +; After 2-nd break, PC counter should be at $0805. +; After 3-rd break, $c000 should equal $ee. +; Return address-1 ($0807) should be on stack. +; After 4-th break, PC counter should be at $080a. +; +; start: +; jsr sub1 +; brk +; jsr sub2 +; brk +; brk +; brk +; sub1: +; lda #$dd +; sta $c000 +; brk +; rts +; sub2: +; lda #$ee +; sta $c000 +; brk +; rts +; +ORG +$0800 +$20 $0B $08 +$00 $00 +$20 $13 $08 +$00 +$00 +$00 +$A9 $DD +$8D $00 $C0 +$00 $00 +$60 +$A9 $EE +$8D $00 $C0 +$00 $00 +$60 +; +; test program #7 +; Test ADC opcode. +; Expected results: +; First break: Acc=$01, Carry=1 +; 2-nd break: Acc=$02, Carry=1 +; 3-rd break: Acc=$22, Carry=0 +; 4-th break: Acc=$23, Carry=0 +; +; start: +; clc +; lda #$ff +; adc #$02 +; brk +; sec +; lda #$ff +; adc #$02 +; brk +; clc +; lda #$20 +; adc #$02 +; brk +; sec +; lda #$20 +; adc #$02 +; brk +; +ORG +$0900 +$18 +$A9 $FF +$69 $02 +$00 $00 +$38 +$A9 $FF +$69 $02 +$00 $00 +$18 +$A9 $20 +$69 $02 +$00 $00 +$38 +$A9 $20 +$69 $02 +$00 $00 +; +; test program #8 +; Test ROR opcode. +; +; start: +; sec +; lda #$00 +; loop: +; ror +; brk +; bcc loop ;(-5 -> $FB) +; brk +; +ORG +$0920 +$38 +$A9 $00 +$6A +$00 $00 +$90 $FB +$00 $00 ; \ No newline at end of file diff --git a/eh_basic.asm b/eh_basic.asm new file mode 100644 index 0000000..b8796ad --- /dev/null +++ b/eh_basic.asm @@ -0,0 +1,8723 @@ +; The code below was copied and adapted from Lee Davison’s +; code of EhBasic to be ran in MKBASIC (VM65) 6502 emulator. +; Original comments and credits follow: +; +; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 + +; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 + +; 2.00 new revision numbers start here +; 2.01 fixed LCASE$() and UCASE$() +; 2.02 new get value routine done +; 2.03 changed RND() to galoise method +; 2.04 fixed SPC() +; 2.05 new get value routine fixed +; 2.06 changed USR() code +; 2.07 fixed STR$() +; 2.08 changed INPUT and READ to remove need for $00 start to input buffer +; 2.09 fixed RND() +; 2.10 integrated missed changes from an earlier version +; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error +; 2.21 fixed IF .. THEN RETURN to not cause error +; 2.22 fixed RND() breaking the get byte routine + +; zero page use .. + +LAB_WARM = $00 ; BASIC warm start entry point +Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte +Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte + +Usrjmp = $0A ; USR function JMP address +Usrjpl = Usrjmp+1 ; USR function JMP vector low byte +Usrjph = Usrjmp+2 ; USR function JMP vector high byte +Nullct = $0D ; nulls output after each line +TPos = $0E ; BASIC terminal position byte +TWidth = $0F ; BASIC terminal width byte +Iclim = $10 ; input column limit +Itempl = $11 ; temporary integer low byte +Itemph = Itempl+1 ; temporary integer high byte + +nums_1 = Itempl ; number to bin/hex string convert MSB +nums_2 = nums_1+1 ; number to bin/hex string convert +nums_3 = nums_1+2 ; number to bin/hex string convert LSB + +Srchc = $5B ; search character +Temp3 = Srchc ; temp byte used in number routines +Scnquo = $5C ; scan-between-quotes flag +Asrch = Scnquo ; alt search character + +XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte +XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte + +Ibptr = $5D ; input buffer pointer +Dimcnt = Ibptr ; # of dimensions +Tindx = Ibptr ; token index + +Defdim = $5E ; default DIM flag +Dtypef = $5F ; data type flag, $FF=string, $00=numeric +Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) +Gclctd = $60 ; garbage collected flag +Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) +Imode = $62 ; input mode flag, $00=INPUT, $80=READ + +Cflag = $63 ; comparison evaluation flag + +TabSiz = $64 ; TAB step size (was input flag) + +next_s = $65 ; next descriptor stack address + + ; these two bytes form a word pointer to the item + ; currently on top of the descriptor stack +last_sl = $66 ; last descriptor stack address low byte +last_sh = $67 ; last descriptor stack address high byte (always $00) + +des_sk = $68 ; descriptor stack start address (temp strings) + +; = $70 ; End of descriptor stack + +ut1_pl = $71 ; utility pointer 1 low byte +ut1_ph = ut1_pl+1 ; utility pointer 1 high byte +ut2_pl = $73 ; utility pointer 2 low byte +ut2_ph = ut2_pl+1 ; utility pointer 2 high byte + +Temp_2 = ut1_pl ; temp byte for block move + +FACt_1 = $75 ; FAC temp mantissa1 +FACt_2 = FACt_1+1 ; FAC temp mantissa2 +FACt_3 = FACt_2+1 ; FAC temp mantissa3 + +dims_l = FACt_2 ; array dimension size low byte +dims_h = FACt_3 ; array dimension size high byte + +TempB = $78 ; temp page 0 byte + +Smeml = $79 ; start of mem low byte (Start-of-Basic) +Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) +Svarl = $7B ; start of vars low byte (Start-of-Variables) +Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) +Sarryl = $7D ; var mem end low byte (Start-of-Arrays) +Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) +Earryl = $7F ; array mem end low byte (End-of-Arrays) +Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) +Sstorl = $81 ; string storage low byte (String storage (moving down)) +Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) +Sutill = $83 ; string utility ptr low byte +Sutilh = Sutill+1 ; string utility ptr high byte +Ememl = $85 ; end of mem low byte (Limit-of-memory) +Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) +Clinel = $87 ; current line low byte (Basic line number) +Clineh = Clinel+1 ; current line high byte (Basic line number) +Blinel = $89 ; break line low byte (Previous Basic line number) +Blineh = Blinel+1 ; break line high byte (Previous Basic line number) + +Cpntrl = $8B ; continue pointer low byte +Cpntrh = Cpntrl+1 ; continue pointer high byte + +Dlinel = $8D ; current DATA line low byte +Dlineh = Dlinel+1 ; current DATA line high byte + +Dptrl = $8F ; DATA pointer low byte +Dptrh = Dptrl+1 ; DATA pointer high byte + +Rdptrl = $91 ; read pointer low byte +Rdptrh = Rdptrl+1 ; read pointer high byte + +Varnm1 = $93 ; current var name 1st byte +Varnm2 = Varnm1+1 ; current var name 2nd byte + +Cvaral = $95 ; current var address low byte +Cvarah = Cvaral+1 ; current var address high byte + +Frnxtl = $97 ; var pointer for FOR/NEXT low byte +Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte + +Tidx1 = Frnxtl ; temp line index + +Lvarpl = Frnxtl ; let var pointer low byte +Lvarph = Frnxth ; let var pointer high byte + +prstk = $99 ; precedence stacked flag + +comp_f = $9B ; compare function flag, bits 0,1 and 2 used + ; bit 2 set if > + ; bit 1 set if = + ; bit 0 set if < + +func_l = $9C ; function pointer low byte +func_h = func_l+1 ; function pointer high byte + +garb_l = func_l ; garbage collection working pointer low byte +garb_h = func_h ; garbage collection working pointer high byte + +des_2l = $9E ; string descriptor_2 pointer low byte +des_2h = des_2l+1 ; string descriptor_2 pointer high byte + +g_step = $A0 ; garbage collect step size + +Fnxjmp = $A1 ; jump vector for functions +Fnxjpl = Fnxjmp+1 ; functions jump vector low byte +Fnxjph = Fnxjmp+2 ; functions jump vector high byte + +g_indx = Fnxjpl ; garbage collect temp index + +FAC2_r = $A3 ; FAC2 rounding byte + +Adatal = $A4 ; array data pointer low byte +Adatah = Adatal+1 ; array data pointer high byte + +Nbendl = Adatal ; new block end pointer low byte +Nbendh = Adatah ; new block end pointer high byte + +Obendl = $A6 ; old block end pointer low byte +Obendh = Obendl+1 ; old block end pointer high byte + +numexp = $A8 ; string to float number exponent count +expcnt = $A9 ; string to float exponent count + +numbit = numexp ; bit count for array element calculations + +numdpf = $AA ; string to float decimal point flag +expneg = $AB ; string to float eval exponent -ve flag + +Astrtl = numdpf ; array start pointer low byte +Astrth = expneg ; array start pointer high byte + +Histrl = numdpf ; highest string low byte +Histrh = expneg ; highest string high byte + +Baslnl = numdpf ; BASIC search line pointer low byte +Baslnh = expneg ; BASIC search line pointer high byte + +Fvar_l = numdpf ; find/found variable pointer low byte +Fvar_h = expneg ; find/found variable pointer high byte + +Ostrtl = numdpf ; old block start pointer low byte +Ostrth = expneg ; old block start pointer high byte + +Vrschl = numdpf ; variable search pointer low byte +Vrschh = expneg ; variable search pointer high byte + +FAC1_e = $AC ; FAC1 exponent +FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 +FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 +FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 +FAC1_s = FAC1_e+4 ; FAC1 sign (b7) + +str_ln = FAC1_e ; string length +str_pl = FAC1_1 ; string pointer low byte +str_ph = FAC1_2 ; string pointer high byte + +des_pl = FAC1_2 ; string descriptor pointer low byte +des_ph = FAC1_3 ; string descriptor pointer high byte + +mids_l = FAC1_3 ; MID$ string temp length byte + +negnum = $B1 ; string to float eval -ve flag +numcon = $B1 ; series evaluation constant count + +FAC1_o = $B2 ; FAC1 overflow byte + +FAC2_e = $B3 ; FAC2 exponent +FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 +FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 +FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 +FAC2_s = FAC2_e+4 ; FAC2 sign (b7) + +FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 +FAC1_r = $B9 ; FAC1 rounding byte + +ssptr_l = FAC_sc ; string start pointer low byte +ssptr_h = FAC1_r ; string start pointer high byte + +sdescr = FAC_sc ; string descriptor pointer + +csidx = $BA ; line crunch save index +Asptl = csidx ; array size/pointer low byte +Aspth = $BB ; array size/pointer high byte + +Btmpl = Asptl ; BASIC pointer temp low byte +Btmph = Aspth ; BASIC pointer temp low byte + +Cptrl = Asptl ; BASIC pointer temp low byte +Cptrh = Aspth ; BASIC pointer temp low byte + +Sendl = Asptl ; BASIC pointer temp low byte +Sendh = Aspth ; BASIC pointer temp low byte + +LAB_IGBY = $BC ; get next BASIC byte subroutine + +LAB_GBYT = $C2 ; get current BASIC byte subroutine +Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte +Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte + +; = $D7 ; end of get BASIC char subroutine + +Rbyte4 = $D8 ; extra PRNG byte +Rbyte1 = Rbyte4+1 ; most significant PRNG byte +Rbyte2 = Rbyte4+2 ; middle PRNG byte +Rbyte3 = Rbyte4+3 ; least significant PRNG byte + +NmiBase = $DC ; NMI handler enabled/setup/triggered flags + ; bit function + ; === ======== + ; 7 interrupt enabled + ; 6 interrupt setup + ; 5 interrupt happened +; = $DD ; NMI handler addr low byte +; = $DE ; NMI handler addr high byte +IrqBase = $DF ; IRQ handler enabled/setup/triggered flags +; = $E0 ; IRQ handler addr low byte +; = $E1 ; IRQ handler addr high byte + +; = $DE ; unused +; = $DF ; unused +; = $E0 ; unused +; = $E1 ; unused +; = $E2 ; unused +; = $E3 ; unused +; = $E4 ; unused +; = $E5 ; unused +; = $E6 ; unused +; = $E7 ; unused +; = $E8 ; unused +; = $E9 ; unused +; = $EA ; unused +; = $EB ; unused +; = $EC ; unused +; = $ED ; unused +; = $EE ; unused + +Decss = $EF ; number to decimal string start +Decssp1 = Decss+1 ; number to decimal string start + +; = $FF ; decimal string end + +; token values needed for BASIC + +; primary command tokens (can start a statement) + +TK_END = $80 ; END token +TK_FOR = TK_END+1 ; FOR token +TK_NEXT = TK_FOR+1 ; NEXT token +TK_DATA = TK_NEXT+1 ; DATA token +TK_INPUT = TK_DATA+1 ; INPUT token +TK_DIM = TK_INPUT+1 ; DIM token +TK_READ = TK_DIM+1 ; READ token +TK_LET = TK_READ+1 ; LET token +TK_DEC = TK_LET+1 ; DEC token +TK_GOTO = TK_DEC+1 ; GOTO token +TK_RUN = TK_GOTO+1 ; RUN token +TK_IF = TK_RUN+1 ; IF token +TK_RESTORE = TK_IF+1 ; RESTORE token +TK_GOSUB = TK_RESTORE+1 ; GOSUB token +TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token +TK_RETNMI = TK_RETIRQ+1 ; RETNMI token +TK_RETURN = TK_RETNMI+1 ; RETURN token +TK_REM = TK_RETURN+1 ; REM token +TK_STOP = TK_REM+1 ; STOP token +TK_ON = TK_STOP+1 ; ON token +TK_NULL = TK_ON+1 ; NULL token +TK_INC = TK_NULL+1 ; INC token +TK_WAIT = TK_INC+1 ; WAIT token +TK_LOAD = TK_WAIT+1 ; LOAD token +TK_SAVE = TK_LOAD+1 ; SAVE token +TK_DEF = TK_SAVE+1 ; DEF token +TK_POKE = TK_DEF+1 ; POKE token +TK_DOKE = TK_POKE+1 ; DOKE token +TK_CALL = TK_DOKE+1 ; CALL token +TK_DO = TK_CALL+1 ; DO token +TK_LOOP = TK_DO+1 ; LOOP token +TK_PRINT = TK_LOOP+1 ; PRINT token +TK_CONT = TK_PRINT+1 ; CONT token +TK_LIST = TK_CONT+1 ; LIST token +TK_CLEAR = TK_LIST+1 ; CLEAR token +TK_NEW = TK_CLEAR+1 ; NEW token +TK_WIDTH = TK_NEW+1 ; WIDTH token +TK_GET = TK_WIDTH+1 ; GET token +TK_SWAP = TK_GET+1 ; SWAP token +TK_BITSET = TK_SWAP+1 ; BITSET token +TK_BITCLR = TK_BITSET+1 ; BITCLR token +TK_IRQ = TK_BITCLR+1 ; IRQ token +TK_NMI = TK_IRQ+1 ; NMI token + +; secondary command tokens, can't start a statement + +TK_TAB = TK_NMI+1 ; TAB token +TK_ELSE = TK_TAB+1 ; ELSE token +TK_TO = TK_ELSE+1 ; TO token +TK_FN = TK_TO+1 ; FN token +TK_SPC = TK_FN+1 ; SPC token +TK_THEN = TK_SPC+1 ; THEN token +TK_NOT = TK_THEN+1 ; NOT token +TK_STEP = TK_NOT+1 ; STEP token +TK_UNTIL = TK_STEP+1 ; UNTIL token +TK_WHILE = TK_UNTIL+1 ; WHILE token +TK_OFF = TK_WHILE+1 ; OFF token + +; opperator tokens + +TK_PLUS = TK_OFF+1 ; + token +TK_MINUS = TK_PLUS+1 ; - token +TK_MUL = TK_MINUS+1 ; * token +TK_DIV = TK_MUL+1 ; / token +TK_POWER = TK_DIV+1 ; ^ token +TK_AND = TK_POWER+1 ; AND token +TK_EOR = TK_AND+1 ; EOR token +TK_OR = TK_EOR+1 ; OR token +TK_RSHIFT = TK_OR+1 ; RSHIFT token +TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token +TK_GT = TK_LSHIFT+1 ; > token +TK_EQUAL = TK_GT+1 ; = token +TK_LT = TK_EQUAL+1 ; < token + +; functions tokens + +TK_SGN = TK_LT+1 ; SGN token +TK_INT = TK_SGN+1 ; INT token +TK_ABS = TK_INT+1 ; ABS token +TK_USR = TK_ABS+1 ; USR token +TK_FRE = TK_USR+1 ; FRE token +TK_POS = TK_FRE+1 ; POS token +TK_SQR = TK_POS+1 ; SQR token +TK_RND = TK_SQR+1 ; RND token +TK_LOG = TK_RND+1 ; LOG token +TK_EXP = TK_LOG+1 ; EXP token +TK_COS = TK_EXP+1 ; COS token +TK_SIN = TK_COS+1 ; SIN token +TK_TAN = TK_SIN+1 ; TAN token +TK_ATN = TK_TAN+1 ; ATN token +TK_PEEK = TK_ATN+1 ; PEEK token +TK_DEEK = TK_PEEK+1 ; DEEK token +TK_SADD = TK_DEEK+1 ; SADD token +TK_LEN = TK_SADD+1 ; LEN token +TK_STRS = TK_LEN+1 ; STR$ token +TK_VAL = TK_STRS+1 ; VAL token +TK_ASC = TK_VAL+1 ; ASC token +TK_UCASES = TK_ASC+1 ; UCASE$ token +TK_LCASES = TK_UCASES+1 ; LCASE$ token +TK_CHRS = TK_LCASES+1 ; CHR$ token +TK_HEXS = TK_CHRS+1 ; HEX$ token +TK_BINS = TK_HEXS+1 ; BIN$ token +TK_BITTST = TK_BINS+1 ; BITTST token +TK_MAX = TK_BITTST+1 ; MAX token +TK_MIN = TK_MAX+1 ; MIN token +TK_PI = TK_MIN+1 ; PI token +TK_TWOPI = TK_PI+1 ; TWOPI token +TK_VPTR = TK_TWOPI+1 ; VARPTR token +TK_LEFTS = TK_VPTR+1 ; LEFT$ token +TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token +TK_MIDS = TK_RIGHTS+1 ; MID$ token + +; offsets from a base of X or Y + +PLUS_0 = $00 ; X or Y plus 0 +PLUS_1 = $01 ; X or Y plus 1 +PLUS_2 = $02 ; X or Y plus 2 +PLUS_3 = $03 ; X or Y plus 3 + +LAB_STAK = $0100 ; stack bottom, no offset + +LAB_SKFE = LAB_STAK+$FE + ; flushed stack address +LAB_SKFF = LAB_STAK+$FF + ; flushed stack address + +ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis +ccbyte = ccflag+1 ; BASIC CTRL-C byte +ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout + +VEC_CC = ccnull+1 ; ctrl c check vector + +VEC_IN = VEC_CC+2 ; input vector +VEC_OUT = VEC_IN+2 ; output vector +VEC_LD = VEC_OUT+2 ; load vector +VEC_SV = VEC_LD+2 ; save vector + +; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 + +IRQ_vec = VEC_SV+2 + +Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code +Ibuffe = Ibuffs+$47 ; end of input buffer + + .ORG $FFC0 + +; I/O routines for MKBASIC (V65) emulator. + +CHRIN + LDA $FFE1 ; Read from char IO address, non-blocking + BEQ ECHRIN ; if null, assume no character in buffer + CMP #'a' ; < 'a'? + BCC DCHRIN ; yes, done + CMP #'{' ; >= '{'? + BCS DCHRIN ; yes, done + AND #$5F ; no, convert to upper case +DCHRIN + SEC ; These is character waiting, set CARRY flag + RTS +ECHRIN + CLC ; no character in buffer, clear CARRY + RTS + +CHROUT + STA $FFE0 ; write to char IO address + AND #$FF ; set flags + RTS + + +Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) +Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned) + +; This start can be changed to suit your system + + *= $C000 + +; BASIC cold start entry point + +; new page 2 initialisation, copy block to ccflag on + +LAB_COLD + CLD + LDY #PG2_TABE-PG2_TABS-1 + ; byte count-1 +LAB_2D13 + LDA PG2_TABS,Y ; get byte + STA ccflag,Y ; store in page 2 + DEY ; decrement count + BPL LAB_2D13 ; loop if not done + + LDX #$FF ; set byte + STX Ibuffs + STX Clineh ; set current line high byte (set immediate mode) + TXS ; reset stack pointer + + LDA #$4C ; code for JMP + STA Fnxjmp ; save for jump vector for functions + +; copy block from LAB_2CEE to $00BC - $00D3 + + LDX #StrTab-LAB_2CEE ; set byte count +LAB_2D4E + LDA LAB_2CEE-1,X ; get byte from table + STA LAB_IGBY-1,X ; save byte in page zero + DEX ; decrement count + BNE LAB_2D4E ; loop if not all done + +; copy block from StrTab to $0000 - $0012 + +LAB_GMEM + LDX #EndTab-StrTab-1 ; set byte count-1 +TabLoop + LDA StrTab,X ; get byte from table + STA PLUS_0,X ; save byte in page zero + DEX ; decrement count + BPL TabLoop ; loop if not all done + +; set-up start values + + LDA #$00 ; clear A + STA NmiBase ; clear NMI handler enabled flag + STA IrqBase ; clear IRQ handler enabled flag + STA FAC1_o ; clear FAC1 overflow byte + STA last_sh ; clear descriptor stack top item pointer high byte + + LDA #$0E ; set default tab size + STA TabSiz ; save it + LDA #$03 ; set garbage collect step size for descriptor stack + STA g_step ; save it + LDX #des_sk ; descriptor stack start + STX next_s ; set descriptor stack pointer + JSR LAB_CRLF ; print CR/LF + LDA #LAB_MSZM ; point to memory size message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; get last byte back + + BNE LAB_2DAA ; branch if not null (user typed something) + + LDY #$00 ; else clear Y + ; character was null so get memory size the hard way + ; we get here with Y=0 and Itempl/h = Ram_base +LAB_2D93 + INC Itempl ; increment temporary integer low byte + BNE LAB_2D99 ; branch if no overflow + + INC Itemph ; increment temporary integer high byte + LDA Itemph ; get high byte + CMP #>Ram_top ; compare with top of RAM+1 + BEQ LAB_2DB6 ; branch if match (end of user RAM) + +LAB_2D99 + LDA #$55 ; set test byte + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BNE LAB_2DB6 ; branch if fail + + ASL ; shift test byte left (now $AA) + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BEQ LAB_2D93 ; if ok go do next byte + + BNE LAB_2DB6 ; branch if fail + +LAB_2DAA + JSR LAB_2887 ; get FAC1 from string + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_GMEM ; if too large go try again + + JSR LAB_F2FU ; save integer part of FAC1 in temporary integer + ; (no range check) + +LAB_2DB6 + LDA Itempl ; get temporary integer low byte + LDY Itemph ; get temporary integer high byte + CPY #Ram_top ; compare with top of RAM high byte +; BCC MEM_OK ; branch if < RAM top + +; BNE LAB_GMEM ; if too large go try again + ; else was = so compare low bytes +; CMP #Ram_base ; set start addr high byte + STY Smeml ; save start of mem low byte + STX Smemh ; save start of mem high byte + +; this line is only needed if Ram_base is not $xx00 + +; LDY #$00 ; clear Y + TYA ; clear A + STA (Smeml),Y ; clear first byte + INC Smeml ; increment start of mem low byte + +; these two lines are only needed if Ram_base is $xxFF + +; BNE LAB_2E05 ; branch if no rollover + +; INC Smemh ; increment start of mem high byte +LAB_2E05 + JSR LAB_CRLF ; print CR/LF + JSR LAB_1463 ; do "NEW" and "CLEAR" + LDA Ememl ; get end of mem low byte + SEC ; set carry for subtract + SBC Smeml ; subtract start of mem low byte + TAX ; copy to X + LDA Ememh ; get end of mem high byte + SBC Smemh ; subtract start of mem high byte + JSR LAB_295E ; print XA as unsigned integer (bytes free) + LDA #LAB_SMSG ; point to sign-on message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA #LAB_1274 ; warm start vector high byte + STA Wrmjpl ; save warm start vector low byte + STY Wrmjph ; save warm start vector high byte + JMP (Wrmjpl) ; go do warm start + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) + +; Nbendl,Nbendh - new block end address (A/Y) +; Obendl,Obendh - old block end address +; Ostrtl,Ostrth - old block start address + +; returns with .. + +; Nbendl,Nbendh - new block start address (high byte - $100) +; Obendl,Obendh - old block start address (high byte - $100) +; Ostrtl,Ostrth - old block start address (unchanged) + +LAB_11CF + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save new array mem end low byte + STY Earryh ; save new array mem end high byte + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) +; don't set array end + +LAB_11D6 + SEC ; set carry for subtract + LDA Obendl ; get block end low byte + SBC Ostrtl ; subtract block start low byte + TAY ; copy MOD(block length/$100) byte to Y + LDA Obendh ; get block end high byte + SBC Ostrth ; subtract block start high byte + TAX ; copy block length high byte to X + INX ; +1 to allow for count=0 exit + TYA ; copy block length low byte to A + BEQ LAB_120A ; branch if length low byte=0 + + ; block is (X-1)*256+Y bytes, do the Y bytes first + + SEC ; set carry for add + 1, two's complement + EOR #$FF ; invert low byte for subtract + ADC Obendl ; add block end low byte + + STA Obendl ; save corrected old block end low byte + BCS LAB_11F3 ; branch if no underflow + + DEC Obendh ; else decrement block end high byte + SEC ; set carry for add + 1, two's complement +LAB_11F3 + TYA ; get MOD(block length/$100) byte + EOR #$FF ; invert low byte for subtract + ADC Nbendl ; add destination end low byte + STA Nbendl ; save modified new block end low byte + BCS LAB_1203 ; branch if no underflow + + DEC Nbendh ; else decrement block end high byte + BCC LAB_1203 ; branch always + +LAB_11FF + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; copy byte to destination +LAB_1203 + DEY ; decrement index + BNE LAB_11FF ; loop until Y=0 + + ; now do Y=0 indexed byte + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; save byte to destination +LAB_120A + DEC Obendh ; decrement source pointer high byte + DEC Nbendh ; decrement destination pointer high byte + DEX ; decrement block count + BNE LAB_1203 ; loop until count = $0 + + RTS + +; check room on stack for A bytes +; stack too deep? do OM error + +LAB_1212 + STA TempB ; save result in temp byte + TSX ; copy stack + CPX TempB ; compare new "limit" with stack + BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start + + RTS + +; check available memory, "Out of memory" error if no room +; addr to check is in AY (low/high) + +LAB_121F + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_1229 ; skip next test if greater (tested <) + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCC LAB_124B ; if less then exit (is ok) + + ; addr is > string storage ptr (oops!) +LAB_1229 + PHA ; push addr low byte + LDX #$08 ; set index to save Adatal to expneg inclusive + TYA ; copy addr high byte (to push on stack) + + ; save misc numeric work area +LAB_122D + PHA ; push byte + LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) + DEX ; decrement index + BPL LAB_122D ; loop until all done + + JSR LAB_GARB ; garbage collection routine + + ; restore misc numeric work area + LDX #$00 ; clear the index to restore bytes +LAB_1238 + PLA ; pop byte + STA Adatal,X ; save byte to Adatal to expneg + INX ; increment index + CPX #$08 ; compare with end + 1 + BMI LAB_1238 ; loop if more to do + + PLA ; pop addr high byte + TAY ; copy back to Y + PLA ; pop addr low byte + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_OMER ; if greater do "Out of memory" error then warm start + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCS LAB_OMER ; if >= do "Out of memory" error then warm start + + ; ok exit, carry clear +LAB_124B + RTS + +; do "Out of memory" error then warm start + +LAB_OMER + LDX #$0C ; error code $0C ("Out of memory" error) + +; do error #X, then warm start + +LAB_XERR + JSR LAB_CRLF ; print CR/LF + + LDA LAB_BAER,X ; get error message pointer low byte + LDY LAB_BAER+1,X ; get error message pointer high byte + JSR LAB_18C3 ; print null terminated string from memory + + JSR LAB_1491 ; flush stack and clear continue flag + LDA #LAB_EMSG ; point to " Error" high addr +LAB_1269 + JSR LAB_18C3 ; print null terminated string from memory + LDY Clineh ; get current line high byte + INY ; increment it + BEQ LAB_1274 ; go do warm start (was immediate mode) + + ; else print line number + JSR LAB_2953 ; print " in line [LINE #]" + +; BASIC warm start entry point +; wait for Basic command + +LAB_1274 + ; clear ON IRQ/NMI bytes + LDA #$00 ; clear A + STA IrqBase ; clear enabled byte + STA NmiBase ; clear enabled byte + LDA #LAB_RMSG ; point to "Ready" message high byte + + JSR LAB_18C3 ; go do print string + CLC + +; wait for Basic command (no "Ready") + +LAB_127D + JSR LAB_1357 ; call for BASIC input +LAB_1280 + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_127D ; loop while null + +; got to interpret input line now .. + + LDX #$FF ; current line to null value + STX Clineh ; set current line high byte + BCC LAB_1295 ; branch if numeric character (handle new BASIC line) + + ; no line number .. immediate mode + JSR LAB_13A6 ; crunch keywords into Basic tokens + JMP LAB_15F6 ; go scan and interpret code + +; handle new BASIC line + +LAB_1295 + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_13A6 ; crunch keywords into Basic tokens + STY Ibptr ; save index pointer to end of crunched line + JSR LAB_SSLN ; search BASIC for temp integer line number + BCC LAB_12E6 ; branch if not found + + ; aroooogah! line # already exists! delete it + LDY #$01 ; set index to next line pointer high byte + LDA (Baslnl),Y ; get next line pointer high byte + STA ut1_ph ; save it + LDA Svarl ; get start of vars low byte + STA ut1_pl ; save it + LDA Baslnh ; get found line pointer high byte + STA ut2_ph ; save it + LDA Baslnl ; get found line pointer low byte + DEY ; decrement index + SBC (Baslnl),Y ; subtract next line pointer low byte + CLC ; clear carry for add + ADC Svarl ; add start of vars low byte + STA Svarl ; save new start of vars low byte + STA ut2_pl ; save destination pointer low byte + LDA Svarh ; get start of vars high byte + ADC #$FF ; -1 + carry + STA Svarh ; save start of vars high byte + SBC Baslnh ; subtract found line pointer high byte + TAX ; copy to block count + SEC ; set carry for subtract + LDA Baslnl ; get found line pointer low byte + SBC Svarl ; subtract start of vars low byte + TAY ; copy to bytes in first block count + BCS LAB_12D0 ; branch if overflow + + INX ; increment block count (correct for =0 loop exit) + DEC ut2_ph ; decrement destination high byte +LAB_12D0 + CLC ; clear carry for add + ADC ut1_pl ; add source pointer low byte + BCC LAB_12D8 ; branch if no overflow + + DEC ut1_ph ; else decrement source pointer high byte + CLC ; clear carry + + ; close up memory to delete old line +LAB_12D8 + LDA (ut1_pl),Y ; get byte from source + STA (ut2_pl),Y ; copy to destination + INY ; increment index + BNE LAB_12D8 ; while <> 0 do this block + + INC ut1_ph ; increment source pointer high byte + INC ut2_ph ; increment destination pointer high byte + DEX ; decrement block count + BNE LAB_12D8 ; loop until all done + + ; got new line in buffer and no existing same # +LAB_12E6 + LDA Ibuffs ; get byte from start of input buffer + BEQ LAB_1319 ; if null line just go flush stack/vars and exit + + ; got new line and it isn't empty line + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte (end of BASIC) + STA Obendl ; save old block end low byte + LDY Svarh ; get start of vars high byte (end of BASIC) + STY Obendh ; save old block end high byte + ADC Ibptr ; add input buffer pointer (also buffer length) + BCC LAB_1301 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1301 + STA Nbendl ; save new block end low byte (move to, low byte) + STY Nbendh ; save new block end high byte + JSR LAB_11CF ; open up space in memory + ; old start pointer Ostrtl,Ostrth set by the find line call + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Svarl ; save start of vars low byte + STY Svarh ; save start of vars high byte + LDY Ibptr ; get input buffer pointer (also buffer length) + DEY ; adjust for loop type +LAB_1311 + LDA Ibuffs-4,Y ; get byte from crunched line + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + CPY #$03 ; compare with first byte-1 + BNE LAB_1311 ; continue while count <> 3 + + LDA Itemph ; get line # high byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA Itempl ; get line # low byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA #$FF ; set byte to allow chain rebuild. if you didn't set this + ; byte then a zero already here would stop the chain rebuild + ; as it would think it was the [EOT] marker. + STA (Baslnl),Y ; save it to program memory + +LAB_1319 + JSR LAB_1477 ; reset execution to start, clear vars and flush stack + LDX Smeml ; get start of mem low byte + LDA Smemh ; get start of mem high byte + LDY #$01 ; index to high byte of next line pointer +LAB_1325 + STX ut1_pl ; set line start pointer low byte + STA ut1_ph ; set line start pointer high byte + LDA (ut1_pl),Y ; get it + BEQ LAB_133E ; exit if end of program + +; rebuild chaining of Basic lines + + LDY #$04 ; point to first code byte of line + ; there is always 1 byte + [EOL] as null entries are deleted +LAB_1330 + INY ; next code byte + LDA (ut1_pl),Y ; get byte + BNE LAB_1330 ; loop if not [EOL] + + SEC ; set carry for add + 1 + TYA ; copy end index + ADC ut1_pl ; add to line start pointer low byte + TAX ; copy to X + LDY #$00 ; clear index, point to this line's next line pointer + STA (ut1_pl),Y ; set next line pointer low byte + TYA ; clear A + ADC ut1_ph ; add line start pointer high byte + carry + INY ; increment index to high byte + STA (ut1_pl),Y ; save next line pointer low byte + BCC LAB_1325 ; go do next line, branch always, carry clear + + +LAB_133E + JMP LAB_127D ; else we just wait for Basic command, no "Ready" + +; print "? " and get BASIC input + +LAB_INLN + JSR LAB_18E3 ; print "?" character + JSR LAB_18E0 ; print " " + BNE LAB_1357 ; call for BASIC input and return + +; receive line from keyboard + + ; $08 as delete key (BACKSPACE on standard keyboard) +LAB_134B + JSR LAB_PRNA ; go print the character + DEX ; decrement the buffer counter (delete) + .byte $2C ; make LDX into BIT abs + +; call for BASIC input (main entry point) + +LAB_1357 + LDX #$00 ; clear BASIC line buffer pointer +LAB_1359 + JSR V_INPT ; call scan input device + BCC LAB_1359 ; loop if no byte + + BEQ LAB_1359 ; loop until valid input (ignore NULLs) + + CMP #$07 ; compare with [BELL] + BEQ LAB_1378 ; branch if [BELL] + + CMP #$0D ; compare with [CR] + BEQ LAB_1384 ; do CR/LF exit if [CR] + + CPX #$00 ; compare pointer with $00 + BNE LAB_1374 ; branch if not empty + +; next two lines ignore any non print character and [SPACE] if input buffer empty + + CMP #$21 ; compare with [SP]+1 + BCC LAB_1359 ; if < ignore character + +LAB_1374 + CMP #$08 ; compare with [BACKSPACE] (delete last character) + BEQ LAB_134B ; go delete last character + +LAB_1378 + CPX #Ibuffe-Ibuffs ; compare character count with max + BCS LAB_138E ; skip store and do [BELL] if buffer full + + STA Ibuffs,X ; else store in buffer + INX ; increment pointer +LAB_137F + JSR LAB_PRNA ; go print the character + BNE LAB_1359 ; always loop for next character + +LAB_1384 + JMP LAB_1866 ; do CR/LF exit to BASIC + +; announce buffer full + +LAB_138E + LDA #$07 ; [BELL] character into A + BNE LAB_137F ; go print the [BELL] but ignore input character + ; branch always + +; crunch keywords into Basic tokens +; position independent buffer version .. +; faster, dictionary search version .... + +LAB_13A6 + LDY #$FF ; set save index (makes for easy math later) + + SEC ; set carry for subtract + LDA Bpntrl ; get basic execute pointer low byte + SBC #= go save byte then continue crunching + + CMP #'<' ; compare with "<" + BCS LAB_13CC ; if >= go crunch now + + CMP #'0' ; compare with "0" + BCS LAB_13EC ; if >= go save byte then continue crunching + + STA Scnquo ; save buffer byte as search character + CMP #$22 ; is it quote character? + BEQ LAB_1410 ; branch if so (copy quoted string) + + CMP #'*' ; compare with "*" + BCC LAB_13EC ; if < go save byte then continue crunching + + ; else crunch now +LAB_13CC + BIT Oquote ; get open quote/DATA token flag + BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) + ; go save byte then continue crunching + + STX TempB ; save buffer read index + STY csidx ; copy buffer save index + LDY #TAB_1STC ; get keyword first character table high address + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear table pointer + +LAB_13D0 + CMP (ut2_pl),Y ; compare with keyword first character table byte + BEQ LAB_13D1 ; go do word_table_chr if match + + BCC LAB_13EA ; if < keyword first character table byte go restore + ; Y and save to crunched + + INY ; else increment pointer + BNE LAB_13D0 ; and loop (branch always) + +; have matched first character of some keyword + +LAB_13D1 + TYA ; copy matching index + ASL ; *2 (bytes per pointer) + TAX ; copy to new index + LDA TAB_CHRT,X ; get keyword table pointer low byte + STA ut2_pl ; save pointer low byte + LDA TAB_CHRT+1,X ; get keyword table pointer high byte + STA ut2_ph ; save pointer high byte + + LDY #$FF ; clear table pointer (make -1 for start) + + LDX TempB ; restore buffer read index + +LAB_13D6 + INY ; next table byte + LDA (ut2_pl),Y ; get byte from table +LAB_13D8 + BMI LAB_13EA ; all bytes matched so go save token + + INX ; next buffer byte + CMP Ibuffs,X ; compare with byte from input buffer + BEQ LAB_13D6 ; go compare next if match + + BNE LAB_1417 ; branch if >< (not found keyword) + +LAB_13EA + LDY csidx ; restore save index + + ; save crunched to output +LAB_13EC + INX ; increment buffer index (to next input byte) + INY ; increment save index (to next output byte) + STA Ibuffs,Y ; save byte to output + CMP #$00 ; set the flags, set carry + BEQ LAB_142A ; do exit if was null [EOL] + + ; A holds token or byte here + SBC #':' ; subtract ":" (carry set by CMP #00) + BEQ LAB_13FF ; branch if it was ":" (is now $00) + + ; A now holds token-$3A + CMP #TK_DATA-$3A ; compare with DATA token - $3A + BNE LAB_1401 ; branch if not DATA + + ; token was : or DATA +LAB_13FF + STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) +LAB_1401 + EOR #TK_REM-$3A ; effectively subtract REM token offset + BNE LAB_13AC ; If wasn't REM then go crunch rest of line + + STA Asrch ; else was REM so set search for [EOL] + + ; loop for REM, "..." etc. +LAB_1408 + LDA Ibuffs,X ; get byte from input buffer + BEQ LAB_13EC ; branch if null [EOL] + + CMP Asrch ; compare with stored character + BEQ LAB_13EC ; branch if match (end quote) + + ; entry for copy string in quotes, don't crunch +LAB_1410 + INY ; increment buffer save index + STA Ibuffs,Y ; save byte to output + INX ; increment buffer read index + BNE LAB_1408 ; loop while <> 0 (should never be 0!) + + ; not found keyword this go +LAB_1417 + LDX TempB ; compare has failed, restore buffer index (start byte!) + + ; now find the end of this word in the table +LAB_141B + LDA (ut2_pl),Y ; get table byte + PHP ; save status + INY ; increment table index + PLP ; restore byte status + BPL LAB_141B ; if not end of keyword go do next + + LDA (ut2_pl),Y ; get byte from keyword table + BNE LAB_13D8 ; go test next word if not zero byte (end of table) + + ; reached end of table with no match + LDA Ibuffs,X ; restore byte from input buffer + BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) + ; go save byte in output and continue crunching + + ; reached [EOL] +LAB_142A + INY ; increment pointer + INY ; increment pointer (makes it next line pointer high byte) + STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) + INY ; adjust for line copy + INY ; adjust for line copy + INY ; adjust for line copy + DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) + RTS + +; search Basic for temp integer line number from start of mem + +LAB_SSLN + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search Basic for temp integer line number from AX +; returns carry set if found +; returns Baslnl/Baslnh pointer to found or next higher (not found) line + +; old 541 new 507 + +LAB_SHLN + LDY #$01 ; set index + STA Baslnl ; save low byte as current + STX Baslnh ; save high byte as current + LDA (Baslnl),Y ; get pointer high byte from addr + BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit + + LDY #$03 ; set index to line # high byte + LDA (Baslnl),Y ; get line # high byte + DEY ; decrement index (point to low byte) + CMP Itemph ; compare with temporary integer high byte + BNE LAB_1455 ; if <> skip low byte check + + LDA (Baslnl),Y ; get line # low byte + CMP Itempl ; compare with temporary integer low byte +LAB_1455 + BCS LAB_145E ; else if temp < this line, exit (passed line#) + +LAB_1456 + DEY ; decrement index to next line ptr high byte + LDA (Baslnl),Y ; get next line pointer high byte + TAX ; copy to X + DEY ; decrement index to next line ptr low byte + LDA (Baslnl),Y ; get next line pointer low byte + BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX + ; (carry always clear) + +LAB_145E + BEQ LAB_1460 ; exit if temp = found line #, carry is set + +LAB_145F + CLC ; clear found flag +LAB_1460 + RTS + +; perform NEW + +LAB_NEW + BNE LAB_1460 ; exit if not end of statement (to do syntax error) + +LAB_1463 + LDA #$00 ; clear A + TAY ; clear Y + STA (Smeml),Y ; clear first line, next line pointer, low byte + INY ; increment index + STA (Smeml),Y ; clear first line, next line pointer, high byte + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$02 ; calculate end of BASIC low byte + STA Svarl ; save start of vars low byte + LDA Smemh ; get start of mem high byte + ADC #$00 ; add any carry + STA Svarh ; save start of vars high byte + +; reset execution to start, clear vars and flush stack + +LAB_1477 + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$FF ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Smemh ; get start of mem high byte + ADC #$FF ; -1+carry + STA Bpntrh ; save BASIC execute pointer high byte + +; "CLEAR" command gets here + +LAB_147A + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte + LDY Svarh ; get start of vars high byte + STA Sarryl ; save var mem end low byte + STY Sarryh ; save var mem end high byte + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + JSR LAB_161A ; perform RESTORE command + +; flush stack and clear continue flag + +LAB_1491 + LDX #des_sk ; set descriptor stack pointer + STX next_s ; save descriptor stack pointer + PLA ; pull return address low byte + TAX ; copy return address low byte + PLA ; pull return address high byte + STX LAB_SKFE ; save to cleared stack + STA LAB_SKFF ; save to cleared stack + LDX #$FD ; new stack pointer + TXS ; reset stack + LDA #$00 ; clear byte + STA Cpntrh ; clear continue pointer high byte + STA Sufnxf ; clear subscript/FNX flag +LAB_14A6 + RTS + +; perform CLEAR + +LAB_CLEAR + BEQ LAB_147A ; if no following token go do "CLEAR" + + ; else there was a following token (go do syntax error) + RTS + +; perform LIST [n][-m] +; bigger, faster version (a _lot_ faster) + +LAB_LIST + BCC LAB_14BD ; branch if next character numeric (LIST n..) + + BEQ LAB_14BD ; branch if next character [NULL] (LIST) + + CMP #TK_MINUS ; compare with token for - + BNE LAB_14A6 ; exit if not - (LIST -m) + + ; LIST [[n][-m]] + ; this bit sets the n , if present, as the start and end +LAB_14BD + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SSLN ; search BASIC for temp integer line number + ; (pointer in Baslnl/Baslnh) + JSR LAB_GBYT ; scan memory + BEQ LAB_14D4 ; branch if no more characters + + ; this bit checks the - is present + CMP #TK_MINUS ; compare with token for - + BNE LAB_1460 ; return if not "-" (will be Syntax error) + + ; LIST [n]-m + ; the - was there so set m as the end value + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer + BNE LAB_1460 ; exit if not ok + +LAB_14D4 + LDA Itempl ; get temporary integer low byte + ORA Itemph ; OR temporary integer high byte + BNE LAB_14E2 ; branch if start set + + LDA #$FF ; set for -1 + STA Itempl ; set temporary integer low byte + STA Itemph ; set temporary integer high byte +LAB_14E2 + LDY #$01 ; set index for line + STY Oquote ; clear open quote flag + JSR LAB_CRLF ; print CR/LF + LDA (Baslnl),Y ; get next line pointer high byte + ; pointer initially set by search at LAB_14BD + BEQ LAB_152B ; if null all done so exit + JSR LAB_1629 ; do CRTL-C check vector + + INY ; increment index for line + LDA (Baslnl),Y ; get line # low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get line # high byte + CMP Itemph ; compare with temporary integer high byte + BNE LAB_14FF ; branch if no high byte match + + CPX Itempl ; compare with temporary integer low byte + BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) + +LAB_14FF ; else .. + BCS LAB_152B ; if greater all done so exit + +LAB_1501 + STY Tidx1 ; save index for line + JSR LAB_295E ; print XA as unsigned integer + LDA #$20 ; space is the next character +LAB_1508 + LDY Tidx1 ; get index for line + AND #$7F ; mask top out bit of character +LAB_150C + JSR LAB_PRNA ; go print the character + CMP #$22 ; was it " character + BNE LAB_1519 ; branch if not + + ; we are either entering or leaving a pair of quotes + LDA Oquote ; get open quote flag + EOR #$FF ; toggle it + STA Oquote ; save it back +LAB_1519 + INY ; increment index + LDA (Baslnl),Y ; get next byte + BNE LAB_152E ; branch if not [EOL] (go print character) + TAY ; else clear index + LDA (Baslnl),Y ; get next line pointer low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get next line pointer high byte + STX Baslnl ; set pointer to line low byte + STA Baslnh ; set pointer to line high byte + BNE LAB_14E2 ; go do next line if not [EOT] + ; else .. +LAB_152B + RTS + +LAB_152E + BPL LAB_150C ; just go print it if not token byte + + ; else was token byte so uncrunch it (maybe) + BIT Oquote ; test the open quote flag + BMI LAB_150C ; just go print character if open quote set + + LDX #>LAB_KEYT ; get table address high byte + ASL ; *2 + ASL ; *4 + BCC LAB_152F ; branch if no carry + + INX ; else increment high byte + CLC ; clear carry for add +LAB_152F + ADC #LAB_159F ; set return address high byte + STA ut1_pl ; save return address low byte + STY ut1_ph ; save return address high byte + JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) + +LAB_159F + LDA #LAB_259C ; set 1 pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JSR LAB_GBYT ; scan memory + CMP #TK_STEP ; compare with STEP token + BNE LAB_15B3 ; jump if not "STEP" + + ;.was step so .. + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch +LAB_15B3 + JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve + STA FAC1_s ; set FAC1 sign (b7) + ; this is +1 for +ve step and -1 for -ve step, in NEXT we + ; compare the FOR value and the TO value and return +1 if + ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value + ; here (+/-1) is then compared to that result and if they + ; are the same (+ve and FOR > TO or -ve and FOR < TO) then + ; the loop is done + JSR LAB_1B5B ; push sign, round FAC1 and put on stack + LDA Frnxth ; get var pointer for FOR/NEXT high byte + PHA ; push on stack + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + PHA ; push on stack + LDA #TK_FOR ; get FOR token + PHA ; push on stack + +; interpreter inner loop + +LAB_15C2 + JSR LAB_1629 ; do CRTL-C check vector + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + LDX Clineh ; continue line is $FFxx for immediate mode + ; ($00xx for RUN from immediate mode) + INX ; increment it (now $00 if immediate mode) + BEQ LAB_15D1 ; branch if null (immediate mode) + + STA Cpntrl ; save continue pointer low byte + STY Cpntrh ; save continue pointer high byte +LAB_15D1 + LDY #$00 ; clear index + LDA (Bpntrl),Y ; get next byte + BEQ LAB_15DC ; branch if null [EOL] + + CMP #':' ; compare with ":" + BEQ LAB_15F6 ; branch if = (statement separator) + +LAB_15D9 + JMP LAB_SNER ; else syntax error then warm start + + ; have reached [EOL] +LAB_15DC + LDY #$02 ; set index + LDA (Bpntrl),Y ; get next line pointer high byte + CLC ; clear carry for no "BREAK" message + BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] + ; marker) + + INY ; increment index + LDA (Bpntrl),Y ; get line # low byte + STA Clinel ; save current line low byte + INY ; increment index + LDA (Bpntrl),Y ; get line # high byte + STA Clineh ; save current line high byte + TYA ; A now = 4 + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_15F6 ; branch if no overflow + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_15F6 + JSR LAB_IGBY ; increment and scan memory + +LAB_15F9 + JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) + +LAB_15FC + JMP LAB_15C2 ; loop + +; interpret BASIC code from (Bpntrl) + +LAB_15FF + BEQ LAB_1628 ; exit if zero [EOL] + +LAB_1602 + ASL ; *2 bytes per vector and normalise token + BCS LAB_1609 ; branch if was token + + JMP LAB_LET ; else go do implied LET + +LAB_1609 + CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB + BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) + ; only tokens before TAB can start a line + TAY ; copy to index + LDA LAB_CTBL+1,Y ; get vector high byte + PHA ; onto stack + LDA LAB_CTBL,Y ; get vector low byte + PHA ; onto stack + JMP LAB_IGBY ; jump to increment and scan memory + ; then "return" to vector + +; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a +; key press is detected. + +LAB_1629 + JMP (VEC_CC) ; ctrl c check vector + +; if there was a key press it gets back here .. + +LAB_1636 + CMP #$03 ; compare with CTRL-C + +; perform STOP + +LAB_STOP + BCS LAB_163B ; branch if token follows STOP + ; else just END +; END + +LAB_END + CLC ; clear the carry, indicate a normal program end +LAB_163B + BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return + + LDA Bpntrh ; get the BASIC execute pointer high byte + EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) + BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer + ; (can't continue in immediate mode) + + ; else .. + EOR #>Ibuffs ; correct the bits + LDY Bpntrl ; get BASIC execute pointer low byte + STY Cpntrl ; save continue pointer low byte + STA Cpntrh ; save continue pointer high byte +LAB_1647 + LDA Clinel ; get current line low byte + LDY Clineh ; get current line high byte + STA Blinel ; save break line low byte + STY Blineh ; save break line high byte +LAB_164F + PLA ; pull return address low + PLA ; pull return address high +LAB_1651 + BCC LAB_165E ; if was program end just do warm start + + ; else .. + LDA #LAB_BMSG ; point to "Break" high byte + JMP LAB_1269 ; print "Break" and do warm start + +LAB_165E + JMP LAB_1274 ; go do warm start + +; perform RESTORE + +LAB_RESTORE + BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) + +LAB_161A + SEC ; set carry for subtract + LDA Smeml ; get start of mem low byte + SBC #$01 ; -1 + LDY Smemh ; get start of mem high byte + BCS LAB_1624 ; branch if no underflow + +LAB_uflow + DEY ; else decrement high byte +LAB_1624 + STA Dptrl ; save DATA pointer low byte + STY Dptrh ; save DATA pointer high byte +LAB_1628 + RTS + + ; is RESTORE n +LAB_RESTOREn + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_reset_search ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_go_search ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_go_search ; branch always (can never be carry clear) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_reset_search + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_go_search + + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_line_found ; if carry set go set pointer + + JMP LAB_16F7 ; else go do "Undefined statement" error + +LAB_line_found + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + LDY Baslnh ; get pointer high byte + BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) + + BCC LAB_uflow ; else decrement high byte then save DATA pointer and + ; return (branch always) + +; perform NULL + +LAB_NULL + JSR LAB_GTBY ; get byte parameter + STX Nullct ; save new NULL count +LAB_167A + RTS + +; perform CONT + +LAB_CONT + BNE LAB_167A ; if following byte exit to do syntax error + + LDY Cpntrh ; get continue pointer high byte + BNE LAB_166C ; go do continue if we can + + LDX #$1E ; error code $1E ("Can't continue" error) + JMP LAB_XERR ; do error #X, then warm start + + ; we can continue so .. +LAB_166C + LDA #TK_ON ; set token for ON + JSR LAB_IRQ ; set IRQ flags + LDA #TK_ON ; set token for ON + JSR LAB_NMI ; set NMI flags + + STY Bpntrh ; save BASIC execute pointer high byte + LDA Cpntrl ; get continue pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA Blinel ; get break line low byte + LDY Blineh ; get break line high byte + STA Clinel ; set current line low byte + STY Clineh ; set current line high byte + RTS + +; perform RUN + +LAB_RUN + BNE LAB_1696 ; branch if RUN n + JMP LAB_1477 ; reset execution to start, clear variables, flush stack and + ; return + +; does RUN n + +LAB_1696 + JSR LAB_147A ; go do "CLEAR" + BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) + +; perform DO + +LAB_DO + LDA #$05 ; need 5 bytes for DO + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_DO ; token for DO + PHA ; push on stack + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + +; perform GOSUB + +LAB_GOSUB + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack +LAB_16B0 + JSR LAB_GBYT ; scan memory + JSR LAB_GOTO ; perform GOTO n + JMP LAB_15C2 ; go do interpreter inner loop + ; (can't RTS, we used the stack!) + +; perform GOTO + +LAB_GOTO + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_16D0 ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_16D4 ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_16D4 ; branch always (can never be carry) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_16D0 + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_16D4 + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCC LAB_16F7 ; if carry clear go do "Undefined statement" error + ; (unspecified statement) + + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA Bpntrh ; save BASIC execute pointer high byte +LAB_16E5 + RTS + +LAB_DONOK + LDX #$22 ; error code $22 ("LOOP without DO" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform LOOP + +LAB_LOOP + TAY ; save following token + TSX ; copy stack pointer + LDA LAB_STAK+3,X ; get token byte from stack + CMP #TK_DO ; compare with DO token + BNE LAB_DONOK ; branch if no matching DO + + INX ; dump calling routine return address + INX ; dump calling routine return address + TXS ; correct stack + TYA ; get saved following token back + BEQ LoopAlways ; if no following token loop forever + ; (stack pointer in X) + + CMP #':' ; could be ':' + BEQ LoopAlways ; if :... loop forever + + SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here + TAX ; copy to X (if it was UNTIL then Y will be correct) + BEQ DoRest ; branch if was UNTIL + + DEX ; decrement result + BNE LAB_16FC ; if not WHILE go do syntax error and warm start + ; only if the token was WHILE will this fail + + DEX ; set invert result byte +DoRest + STX Frnxth ; save invert result byte + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVEX ; evaluate expression + LDA FAC1_e ; get FAC1 exponent + BEQ DoCmp ; if =0 go do straight compare + + LDA #$FF ; else set all bits +DoCmp + TSX ; copy stack pointer + EOR Frnxth ; EOR with invert byte + BNE LoopDone ; if <> 0 clear stack and back to interpreter loop + + ; loop condition wasn't met so do it again +LoopAlways + LDA LAB_STAK+2,X ; get current line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+3,X ; get current line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+4,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+5,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + + ; clear stack and back to interpreter loop +LoopDone + INX ; dump DO token + INX ; dump current line low byte + INX ; dump current line high byte + INX ; dump BASIC execute pointer low byte + INX ; dump BASIC execute pointer high byte + TXS ; correct stack + JMP LAB_DATA ; go perform DATA (find : or [EOL]) + +; do the return without gosub error + +LAB_16F4 + LDX #$04 ; error code $04 ("RETURN without GOSUB" error) + .byte $2C ; makes next line BIT LAB_0EA2 + +LAB_16F7 ; do undefined statement error + LDX #$0E ; error code $0E ("Undefined statement" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform RETURN + +LAB_RETURN + BNE LAB_16E5 ; exit if following token (to allow syntax error) + +LAB_16E8 + PLA ; dump calling routine return address + PLA ; dump calling routine return address + PLA ; pull token + CMP #TK_GOSUB ; compare with GOSUB token + BNE LAB_16F4 ; branch if no matching GOSUB + +LAB_16FF + PLA ; pull current line low byte + STA Clinel ; save current line low byte + PLA ; pull current line high byte + STA Clineh ; save current line high byte + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + + ; now do the DATA statement as we could be returning into + ; the middle of an ON GOSUB n,m,p,q line + ; (the return address used by the DATA statement is the one + ; pushed before the GOSUB was executed!) + +; perform DATA + +LAB_DATA + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + + ; set BASIC execute pointer +LAB_170F + TYA ; copy index to A + CLC ; clear carry for add + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_1719 ; skip next if no carry + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_1719 + RTS + +LAB_16FC + JMP LAB_SNER ; do syntax error then warm start + +; scan for next BASIC statement ([:] or [EOL]) +; returns Y as index to [:] or [EOL] + +LAB_SNBS + LDX #':' ; set look for character = ":" + .byte $2C ; makes next line BIT $00A2 + +; scan for next BASIC line +; returns Y as index to [EOL] + +LAB_SNBL + LDX #$00 ; set alt search character = [EOL] + LDY #$00 ; set search character = [EOL] + STY Asrch ; store search character +LAB_1725 + TXA ; get alt search character + EOR Asrch ; toggle search character, effectively swap with $00 + STA Asrch ; save swapped search character +LAB_172D + LDA (Bpntrl),Y ; get next byte + BEQ LAB_1719 ; exit if null [EOL] + + CMP Asrch ; compare with search character + BEQ LAB_1719 ; exit if found + + INY ; increment index + CMP #$22 ; compare current character with open quote + BNE LAB_172D ; if not open quote go get next character + + BEQ LAB_1725 ; if found go swap search character for alt search character + +; perform IF + +LAB_IF + JSR LAB_EVEX ; evaluate the expression + JSR LAB_GBYT ; scan memory + CMP #TK_THEN ; compare with THEN token + BEQ LAB_174B ; if it was THEN go do IF + + ; wasn't IF .. THEN so must be IF .. GOTO + CMP #TK_GOTO ; compare with GOTO token + BNE LAB_16FC ; if it wasn't GOTO go do syntax error + + LDX Bpntrl ; save the basic pointer low byte + LDY Bpntrh ; save the basic pointer high byte + JSR LAB_IGBY ; increment and scan memory + BCS LAB_16FC ; if not numeric go do syntax error + + STX Bpntrl ; restore the basic pointer low byte + STY Bpntrh ; restore the basic pointer high byte +LAB_174B + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_174E ; if the result was zero go look for an ELSE + + JSR LAB_IGBY ; else increment and scan memory + BCS LAB_174D ; if not numeric go do var or keyword + +LAB_174C + JMP LAB_GOTO ; else was numeric so do GOTO n + + ; is var or keyword +LAB_174D + CMP #TK_RETURN ; compare the byte with the token for RETURN + BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) + ; and return to this code to process any following code + + JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) + ; but don't return here + +LAB_174G + JSR LAB_15FF ; interpret BASIC code from (Bpntrl) + +; the IF was executed and there may be a following ELSE so the code needs to return +; here to check and ignore the ELSE if present + + LDY #$00 ; clear the index + LDA (Bpntrl),Y ; get the next BASIC byte + CMP #TK_ELSE ; compare it with the token for ELSE + BEQ LAB_DATA ; if ELSE ignore the following statement + +; there was no ELSE so continue execution of IF THEN [: ]. any +; following ELSE will, correctly, cause a syntax error + + RTS ; else return to the interpreter inner loop + +; perform ELSE after IF + +LAB_174E + LDY #$00 ; clear the BASIC byte index + LDX #$01 ; clear the nesting depth +LAB_1750 + INY ; increment the BASIC byte index + LDA (Bpntrl),Y ; get the next BASIC byte + BEQ LAB_1753 ; if EOL go add the pointer and return + + CMP #TK_IF ; compare the byte with the token for IF + BNE LAB_1752 ; if not IF token skip the depth increment + + INX ; else increment the nesting depth .. + BNE LAB_1750 ; .. and continue looking + +LAB_1752 + CMP #TK_ELSE ; compare the byte with the token for ELSE + BNE LAB_1750 ; if not ELSE token continue looking + + DEX ; was ELSE so decrement the nesting depth + BNE LAB_1750 ; loop if still nested + + INY ; increment the BASIC byte index past the ELSE + +; found the matching ELSE, now do <{n|statement}> + +LAB_1753 + TYA ; else copy line index to A + CLC ; clear carry for add + ADC Bpntrl ; add the BASIC execute pointer low byte + STA Bpntrl ; save the BASIC execute pointer low byte + BCC LAB_1754 ; branch if no overflow to high byte + + INC Bpntrh ; else increment the BASIC execute pointer high byte +LAB_1754 + JSR LAB_GBYT ; scan memory + BCC LAB_174C ; if numeric do GOTO n + ; the code will return to the interpreter loop at the + ; tail end of the GOTO + + JMP LAB_15FF ; interpret BASIC code from (Bpntrl) + ; the code will return to the interpreter loop at the + ; tail end of the + +; perform REM, skip (rest of) line + +LAB_REM + JSR LAB_SNBL ; scan for next BASIC line + JMP LAB_170F ; go set BASIC execute pointer and return, branch always + +LAB_16FD + JMP LAB_SNER ; do syntax error then warm start + +; perform ON + +LAB_ON + CMP #TK_IRQ ; was it IRQ token ? + BNE LAB_NOIN ; if not go check NMI + + JMP LAB_SIRQ ; else go set-up IRQ + +LAB_NOIN + CMP #TK_NMI ; was it NMI token ? + BNE LAB_NONM ; if not go do normal ON command + + JMP LAB_SNMI ; else go set-up NMI + +LAB_NONM + JSR LAB_GTBY ; get byte parameter + PHA ; push GOTO/GOSUB token + CMP #TK_GOSUB ; compare with GOSUB token + BEQ LAB_176B ; branch if GOSUB + + CMP #TK_GOTO ; compare with GOTO token +LAB_1767 + BNE LAB_16FD ; if not GOTO do syntax error then warm start + + +; next character was GOTO or GOSUB + +LAB_176B + DEC FAC1_3 ; decrement index (byte value) + BNE LAB_1773 ; branch if not zero + + PLA ; pull GOTO/GOSUB token + JMP LAB_1602 ; go execute it + +LAB_1773 + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) + ; (we could LDX #',' and JSR LAB_SNBL+2, then we + ; just BNE LAB_176B for the loop. should be quicker .. + ; no we can't, what if we meet a colon or [EOL]?) + CMP #$2C ; compare next character with "," + BEQ LAB_176B ; loop if "," + +LAB_177E + PLA ; else pull keyword token (run out of options) + ; also dump +/-1 pointer low byte and exit +LAB_177F + RTS + +; takes n * 106 + 11 cycles where n is the number of digits + +; get fixed-point number into temp integer + +LAB_GFPN + LDX #$00 ; clear reg + STX Itempl ; clear temporary integer low byte +LAB_1785 + STX Itemph ; save temporary integer high byte + BCS LAB_177F ; return if carry set, end of scan, character was + ; not 0-9 + + CPX #$19 ; compare high byte with $19 + TAY ; ensure Zb = 0 if the branch is taken + BCS LAB_1767 ; branch if >=, makes max line # 63999 because next + ; bit does *$0A, = 64000, compare at target will fail + ; and do syntax error + + SBC #'0'-1 ; subtract "0", $2F + carry, from byte + TAY ; copy binary digit + LDA Itempl ; get temporary integer low byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte, *4 + ADC Itempl ; + low byte, *5 + STA Itempl ; save it + TXA ; get high byte copy to A + ADC Itemph ; + high byte, *5 + ASL Itempl ; *2 low byte, *10d + ROL ; *2 high byte, *10d + TAX ; copy high byte back to X + TYA ; get binary digit back + ADC Itempl ; add number low byte + STA Itempl ; save number low byte + BCC LAB_17B3 ; if no overflow to high byte get next character + + INX ; else increment high byte +LAB_17B3 + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1785 ; loop for next character + +; perform DEC + +LAB_DEC + LDA #LAB_259C ; set +/-1 pointer high byte (both the same) + JSR LAB_246C ; add (AY) to FAC1 + JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) + + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_177E ; exit if not "," (either end or error) + + ; was "," so another INCR variable to do + JSR LAB_IGBY ; increment and scan memory + JMP LAB_17B7 ; go do next var + +IncrErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform LET + +LAB_LET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push data type flag + JSR LAB_EVEX ; evaluate expression + PLA ; pop data type flag + ROL ; set carry if type = string + JSR LAB_CKTM ; type match check, set C for string + BNE LAB_17D5 ; branch if string + + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +; string LET + +LAB_17D5 + LDY #$02 ; set index to pointer high byte + LDA (des_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + BNE LAB_17E6 ; branch if > + ; else was equal so compare low bytes + DEY ; decrement index + LDA (des_pl),Y ; get pointer low byte + CMP Sstorl ; compare bottom of string space low byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + ; pointer was >= to bottom of string space pointer +LAB_17E6 + LDY des_ph ; get descriptor pointer high byte + CPY Svarh ; compare start of vars high byte + BCC LAB_17F4 ; branch if less (descriptor is on stack) + + BNE LAB_17FB ; branch if greater (descriptor is not on stack) + + ; else high bytes were equal so .. + LDA des_pl ; get descriptor pointer low byte + CMP Svarl ; compare start of vars low byte + BCS LAB_17FB ; branch if >= (descriptor is not on stack) + +LAB_17F4 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + JMP LAB_1811 ; clean stack, copy descriptor to variable and return + + ; make space and copy string +LAB_17FB + LDY #$00 ; index to length + LDA (des_pl),Y ; get string length + JSR LAB_209C ; copy string + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + STA ssptr_l ; save descriptor pointer low byte + STY ssptr_h ; save descriptor pointer high byte + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA #FAC1_e ; get descriptor pointer high byte + + ; clean stack and assign value to string variable +LAB_1811 + STA des_2l ; save descriptor_2 pointer low byte + STY des_2h ; save descriptor_2 pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + LDY #$00 ; index to length + LDA (des_2l),Y ; get string length + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer low byte + LDA (des_2l),Y ; get string pointer low byte + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer high byte + LDA (des_2l),Y ; get string pointer high byte + STA (Lvarpl),Y ; copy to let string variable + RTS + +; perform GET + +LAB_GET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + JSR INGET ; get input byte + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_GETS ; go get string character + + ; was numeric get + TAY ; copy character to Y + JSR LAB_1FD0 ; convert Y to byte in FAC1 + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +LAB_GETS + PHA ; save character + LDA #$01 ; string is single byte + BCS LAB_IsByte ; branch if byte received + + PLA ; string is null +LAB_IsByte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + BEQ LAB_NoSt ; skip store if null string + + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) +LAB_NoSt + JSR LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + + JMP LAB_17D5 ; do string LET and return + +; perform PRINT + +LAB_1829 + JSR LAB_18C6 ; print string from Sutill/Sutilh +LAB_182C + JSR LAB_GBYT ; scan memory + +; PRINT + +LAB_PRINT + BEQ LAB_CRLF ; if nothing following just print CR/LF + +LAB_1831 + CMP #TK_TAB ; compare with TAB( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #TK_SPC ; compare with SPC( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #',' ; compare with "," + BEQ LAB_188B ; go do move to next TAB mark + + CMP #';' ; compare with ";" + BEQ LAB_18BD ; if ";" continue with PRINT processing + + JSR LAB_EVEX ; evaluate expression + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1829 ; branch if string + + JSR LAB_296E ; convert FAC1 to string + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + LDY #$00 ; clear index + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width byte + BEQ LAB_185E ; skip check if zero + + SEC ; set carry for subtract + SBC TPos ; subtract terminal position + SBC (des_pl),Y ; subtract string length + BCS LAB_185E ; branch if less than terminal width + + JSR LAB_CRLF ; else print CR/LF +LAB_185E + JSR LAB_18C6 ; print string from Sutill/Sutilh + BEQ LAB_182C ; always go continue processing line + +; CR/LF return to BASIC from BASIC input handler + +LAB_1866 + LDA #$00 ; clear byte + STA Ibuffs,X ; null terminate input + LDX #Ibuffs ; set Y to buffer start-1 high byte + +; print CR/LF + +LAB_CRLF + LDA #$0D ; load [CR] + JSR LAB_PRNA ; go print the character + LDA #$0A ; load [LF] + BNE LAB_PRNA ; go print the character and return, branch always + +LAB_188B + LDA TPos ; get terminal position + CMP Iclim ; compare with input column limit + BCC LAB_1897 ; branch if less + + JSR LAB_CRLF ; else print CR/LF (next line) + BNE LAB_18BD ; continue with PRINT processing (branch always) + +LAB_1897 + SEC ; set carry for subtract +LAB_1898 + SBC TabSiz ; subtract TAB size + BCS LAB_1898 ; loop if result was +ve + + EOR #$FF ; complement it + ADC #$01 ; +1 (twos complement) + BNE LAB_18B6 ; always print A spaces (result is never $00) + + ; do TAB/SPC +LAB_18A2 + PHA ; save token + JSR LAB_SGBY ; scan and get byte parameter + CMP #$29 ; is next character ) + BNE LAB_1910 ; if not do syntax error then warm start + + PLA ; get token back + CMP #TK_TAB ; was it TAB ? + BNE LAB_18B7 ; if not go do SPC + + ; calculate TAB offset + TXA ; copy integer value to A + SBC TPos ; subtract terminal position + BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) + + ; print A spaces +LAB_18B6 + TAX ; copy result to X +LAB_18B7 + TXA ; set flags on size for SPC + BEQ LAB_18BD ; branch if result was = $0, already here + + ; print X spaces +LAB_18BA + JSR LAB_18E0 ; print " " + DEX ; decrement count + BNE LAB_18BA ; loop if not all done + + ; continue with PRINT processing +LAB_18BD + JSR LAB_IGBY ; increment and scan memory + BNE LAB_1831 ; if more to print go do it + + RTS + +; print null terminated string from memory + +LAB_18C3 + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + +; print string from Sutill/Sutilh + +LAB_18C6 + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + LDY #$00 ; reset index + TAX ; copy length to X + BEQ LAB_188C ; exit (RTS) if null string + +LAB_18CD + + LDA (ut1_pl),Y ; get next byte + JSR LAB_PRNA ; go print the character + INY ; increment index + DEX ; decrement count + BNE LAB_18CD ; loop if not done yet + + RTS + + ; Print single format character +; print " " + +LAB_18E0 + LDA #$20 ; load " " + .byte $2C ; change next line to BIT LAB_3FA9 + +; print "?" character + +LAB_18E3 + LDA #$3F ; load "?" character + +; print character in A +; now includes the null handler +; also includes infinite line length code +; note! some routines expect this one to exit with Zb=0 + +LAB_PRNA + CMP #' ' ; compare with " " + BCC LAB_18F9 ; branch if less (non printing) + + ; else printable character + PHA ; save the character + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width + BNE LAB_18F0 ; branch if not zero (not infinite length) + +; is "infinite line" so check TAB position + + LDA TPos ; get position + SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above + BNE LAB_18F7 ; skip reset if different + + STA TPos ; else reset position + BEQ LAB_18F7 ; go print character + +LAB_18F0 + CMP TPos ; compare with terminal character position + BNE LAB_18F7 ; branch if not at end of line + + JSR LAB_CRLF ; else print CR/LF +LAB_18F7 + INC TPos ; increment terminal position + PLA ; get character back +LAB_18F9 + JSR V_OUTP ; output byte via output vector + CMP #$0D ; compare with [CR] + BNE LAB_188A ; branch if not [CR] + + ; else print nullct nulls after the [CR] + STX TempB ; save buffer index + LDX Nullct ; get null count + BEQ LAB_1886 ; branch if no nulls + + LDA #$00 ; load [NULL] +LAB_1880 + JSR LAB_PRNA ; go print the character + DEX ; decrement count + BNE LAB_1880 ; loop if not all done + + LDA #$0D ; restore the character (and set the flags) +LAB_1886 + STX TPos ; clear terminal position (X always = zero when we get here) + LDX TempB ; restore buffer index +LAB_188A + AND #$FF ; set the flags +LAB_188C + RTS + +; handle bad input data + +LAB_1904 + LDA Imode ; get input mode flag, $00=INPUT, $00=READ + BPL LAB_1913 ; branch if INPUT (go do redo) + + LDA Dlinel ; get current DATA line low byte + LDY Dlineh ; get current DATA line high byte + STA Clinel ; save current line low byte + STY Clineh ; save current line high byte +LAB_1910 + JMP LAB_SNER ; do syntax error then warm start + + ; mode was INPUT +LAB_1913 + LDA #LAB_REDO ; point to redo message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA Cpntrl ; get continue pointer low byte + LDY Cpntrh ; get continue pointer high byte + STA Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; perform INPUT + +LAB_INPUT + CMP #$22 ; compare next byte with open quote + BNE LAB_1934 ; branch if no prompt string + + JSR LAB_1BC1 ; print "..." string + LDA #$3B ; load A with ";" + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + JSR LAB_18C6 ; print string from Sutill/Sutilh + + ; done with prompt, now get data +LAB_1934 + JSR LAB_CKRN ; check not Direct, back here if ok + JSR LAB_INLN ; print "? " and get BASIC input + LDA #$00 ; set mode = INPUT + CMP Ibuffs ; test first byte in buffer + BNE LAB_1953 ; branch if not null input + + CLC ; was null input so clear carry to exit program + JMP LAB_1647 ; go do BREAK exit + +; perform READ + +LAB_READ + LDX Dptrl ; get DATA pointer low byte + LDY Dptrh ; get DATA pointer high byte + LDA #$80 ; set mode = READ + +LAB_1953 + STA Imode ; set input mode flag, $00=INPUT, $80=READ + STX Rdptrl ; save READ pointer low byte + STY Rdptrh ; save READ pointer high byte + + ; READ or INPUT next variable from list +LAB_195B + JSR LAB_GVAR ; get (var) address + STA Lvarpl ; save address low byte + STY Lvarph ; save address high byte + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STA Itempl ; save as temporary integer low byte + STY Itemph ; save as temporary integer high byte + LDX Rdptrl ; get READ pointer low byte + LDY Rdptrh ; get READ pointer high byte + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BNE LAB_1988 ; branch if not null + + ; pointer was to null entry + BIT Imode ; test input mode flag, $00=INPUT, $80=READ + BMI LAB_19DD ; branch if READ + + ; mode was INPUT + JSR LAB_18E3 ; print "?" character (double ? for extended input) + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte +LAB_1985 + JSR LAB_GBYT ; scan memory +LAB_1988 + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_19B0 ; branch if numeric + + ; else get string + STA Srchc ; save search character + CMP #$22 ; was it " ? + BEQ LAB_1999 ; branch if so + + LDA #':' ; else search character is ":" + STA Srchc ; set new search character + LDA #',' ; other search character is "," + CLC ; clear carry for add +LAB_1999 + STA Asrch ; set second search character + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 + BCC LAB_19A4 ; branch if no execute pointer low byte rollover + + INY ; else increment high byte +LAB_19A4 + JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh + JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) + JSR LAB_17D5 ; go do string LET + JMP LAB_19B6 ; go check string terminator + + ; get numeric INPUT +LAB_19B0 + JSR LAB_2887 ; get FAC1 from string + JSR LAB_PFAC ; pack FAC1 into (Lvarpl) +LAB_19B6 + JSR LAB_GBYT ; scan memory + BEQ LAB_19C5 ; branch if null (last entry) + + CMP #',' ; else compare with "," + BEQ LAB_19C2 ; branch if "," + + JMP LAB_1904 ; else go handle bad input data + + ; got good input data +LAB_19C2 + JSR LAB_IGBY ; increment and scan memory +LAB_19C5 + LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) + LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) + STA Rdptrl ; save for now + STY Rdptrh ; save for now + LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) + LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) + STA Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_1A03 ; if null go do extra ignored message + + JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start + JMP LAB_195B ; go INPUT next variable from list + + ; find next DATA statement or do "Out of DATA" error +LAB_19DD + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + INY ; increment index + TAX ; copy character ([:] or [EOL]) + BNE LAB_19F6 ; branch if [:] + + LDX #$06 ; set for "Out of DATA" error + INY ; increment index, now points to next line pointer high byte + LDA (Bpntrl),Y ; get next line pointer high byte + BEQ LAB_1A54 ; branch if end (eventually does error X) + + INY ; increment index + LDA (Bpntrl),Y ; get next line # low byte + STA Dlinel ; save current DATA line low byte + INY ; increment index + LDA (Bpntrl),Y ; get next line # high byte + INY ; increment index + STA Dlineh ; save current DATA line high byte +LAB_19F6 + LDA (Bpntrl),Y ; get byte + INY ; increment index + TAX ; copy to X + JSR LAB_170F ; set BASIC execute pointer + CPX #TK_DATA ; compare with "DATA" token + BEQ LAB_1985 ; was "DATA" so go do next READ + + BNE LAB_19DD ; go find next statement if not "DATA" + +; end of INPUT/READ routine + +LAB_1A03 + LDA Rdptrl ; get temp READ pointer low byte + LDY Rdptrh ; get temp READ pointer high byte + LDX Imode ; get input mode flag, $00=INPUT, $80=READ + BPL LAB_1A0E ; branch if INPUT + + JMP LAB_1624 ; save AY as DATA pointer and return + + ; we were getting INPUT +LAB_1A0E + LDY #$00 ; clear index + LDA (Rdptrl),Y ; get next byte + BNE LAB_1A1B ; error if not end of INPUT + + RTS + + ; user typed too much +LAB_1A1B + LDA #LAB_IMSG ; point to extra ignored message (high addr) + JMP LAB_18C3 ; print null terminated string from memory and return + +; search the stack for FOR activity +; exit with z=1 if FOR else exit with z=0 + +LAB_11A1 + TSX ; copy stack pointer + INX ; +1 pass return address + INX ; +2 pass return address + INX ; +3 pass calling routine return address + INX ; +4 pass calling routine return address +LAB_11A6 + LDA LAB_STAK+1,X ; get token byte from stack + CMP #TK_FOR ; is it FOR token + BNE LAB_11CE ; exit if not FOR token + + ; was FOR token + LDA Frnxth ; get var pointer for FOR/NEXT high byte + BNE LAB_11BB ; branch if not null + + LDA LAB_STAK+2,X ; get FOR variable pointer low byte + STA Frnxtl ; save var pointer for FOR/NEXT low byte + LDA LAB_STAK+3,X ; get FOR variable pointer high byte + STA Frnxth ; save var pointer for FOR/NEXT high byte +LAB_11BB + CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) + BNE LAB_11C7 ; branch if no match + + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) + BEQ LAB_11CE ; exit if match found + +LAB_11C7 + TXA ; copy index + CLC ; clear carry for add + ADC #$10 ; add FOR stack use size + TAX ; copy back to index + BNE LAB_11A6 ; loop if not at start of stack + +LAB_11CE + RTS + +; perform NEXT + +LAB_NEXT + BNE LAB_1A46 ; branch if NEXT var + + LDY #$00 ; else clear Y + BEQ LAB_1A49 ; branch always (no variable to search for) + +; NEXT var + +LAB_1A46 + JSR LAB_GVAR ; get variable address +LAB_1A49 + STA Frnxtl ; store variable pointer low byte + STY Frnxth ; store variable pointer high byte + ; (both cleared if no variable defined) + JSR LAB_11A1 ; search the stack for FOR activity + BEQ LAB_1A56 ; branch if found + + LDX #$00 ; else set error $00 ("NEXT without FOR" error) +LAB_1A54 + BEQ LAB_1ABE ; do error #X, then warm start + +LAB_1A56 + TXS ; set stack pointer, X set by search, dumps return addresses + + TXA ; copy stack pointer + SEC ; set carry for subtract + SBC #$F7 ; point to TO var + STA ut2_pl ; save pointer to TO var for compare + ADC #$FB ; point to STEP var + + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 + TSX ; get stack pointer back + LDA LAB_STAK+8,X ; get step sign + STA FAC1_s ; save FAC1 sign (b7) + LDA Frnxtl ; get FOR variable pointer low byte + LDY Frnxth ; get FOR variable pointer high byte + JSR LAB_246C ; add (FOR variable) to FAC1 + JSR LAB_PFAC ; pack FAC1 into (FOR variable) + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) + TSX ; get stack pointer back + CMP LAB_STAK+8,X ; compare step sign + BEQ LAB_1A9B ; branch if = (loop complete) + + ; loop back and do it all again + LDA LAB_STAK+$0D,X ; get FOR line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+$0E,X ; get FOR line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte +LAB_1A98 + JMP LAB_15C2 ; go do interpreter inner loop + + ; loop complete so carry on +LAB_1A9B + TXA ; stack copy to A + ADC #$0F ; add $10 ($0F+carry) to dump FOR structure + TAX ; copy back to index + TXS ; copy to stack pointer + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) + + ; was "," so another NEXT variable to do + JSR LAB_IGBY ; else increment and scan memory + JSR LAB_1A46 ; do NEXT (var) + +; evaluate expression and check is numeric, else do type mismatch + +LAB_EVNM + JSR LAB_EVEX ; evaluate expression + +; check if source is numeric, else do type mismatch + +LAB_CTNM + CLC ; destination is numeric + .byte $24 ; makes next line BIT $38 + +; check if source is string, else do type mismatch + +LAB_CTST + SEC ; required type is string + +; type match check, set C for string, clear C for numeric + +LAB_CKTM + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1ABA ; branch if data type is string + + ; else data type was numeric + BCS LAB_1ABC ; if required type is string do type mismatch error +LAB_1AB9 + RTS + + ; data type was string, now check required type +LAB_1ABA + BCS LAB_1AB9 ; exit if required type is string + + ; else do type mismatch error +LAB_1ABC + LDX #$18 ; error code $18 ("Type mismatch" error) +LAB_1ABE + JMP LAB_XERR ; do error #X, then warm start + +; evaluate expression + +LAB_EVEX + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1AC7 ; skip next if not zero + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1AC7 + DEC Bpntrl ; decrement BASIC execute pointer low byte + +LAB_EVEZ + LDA #$00 ; set null precedence (flag done) +LAB_1ACC + PHA ; push precedence byte + LDA #$02 ; 2 bytes + JSR LAB_1212 ; check room on stack for A bytes + JSR LAB_GVAL ; get value from line + LDA #$00 ; clear A + STA comp_f ; clear compare function flag +LAB_1ADB + JSR LAB_GBYT ; scan memory +LAB_1ADE + SEC ; set carry for subtract + SBC #TK_GT ; subtract token for > (lowest comparison function) + BCC LAB_1AFA ; branch if < TK_GT + + CMP #$03 ; compare with ">" to "<" tokens + BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) + + ; was token for > = or < (A = 0, 1 or 2) + CMP #$01 ; compare with token for = + ROL ; *2, b0 = carry (=1 if token was = or <) + ; (A = 0, 3 or 5) + EOR #$01 ; toggle b0 + ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) + EOR comp_f ; EOR with compare function flag bits + CMP comp_f ; compare with compare function flag + BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start + ; was more than one <, = or >) + + STA comp_f ; save new compare function flag + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1ADE ; go do next character + + ; token is < ">" or > "<" tokens +LAB_1AFA + LDX comp_f ; get compare function flag + BNE LAB_1B2A ; branch if compare function + + BCS LAB_1B78 ; go do functions + + ; else was < TK_GT so is operator or lower + ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) + BCC LAB_1B78 ; branch if < + operator + + ; carry was set so token was +, -, *, /, ^, AND, OR or EOR + BNE LAB_1B0B ; branch if not + token + + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_1B0B ; branch if not string + + ; will only be $00 if type is string and token was + + JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 + ; is in line, and return + +LAB_1B0B + STA ut1_pl ; save it + ASL ; *2 + ADC ut1_pl ; *3 + TAY ; copy to index +LAB_1B13 + PLA ; pull previous precedence + CMP LAB_OPPT,Y ; compare with precedence byte + BCS LAB_1B7D ; branch if A >= + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B1C + PHA ; save precedence +LAB_1B1D + JSR LAB_1B43 ; get vector, execute function then continue evaluation + PLA ; restore precedence + LDY prstk ; get precedence stacked flag + BPL LAB_1B3C ; branch if stacked values + + TAX ; copy precedence (set flags) + BEQ LAB_1B9D ; exit if done + + BNE LAB_1B86 ; else pop FAC2 and return, branch always + +LAB_1B2A + ROL Dtypef ; shift data type flag into Cb + TXA ; copy compare function flag + STA Dtypef ; clear data type flag, X is 0xxx xxxx + ROL ; shift data type into compare function byte b0 + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1B34 ; branch if no underflow + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1B34 + DEC Bpntrl ; decrement BASIC execute pointer low byte +TK_LT_PLUS = TK_LT-TK_PLUS + LDY #TK_LT_PLUS*3 ; set offset to last operator entry + STA comp_f ; save new compare function flag + BNE LAB_1B13 ; branch always + +LAB_1B3C + CMP LAB_OPPT,Y ;.compare with stacked function precedence + BCS LAB_1B86 ; branch if A >=, pop FAC2 and return + + BCC LAB_1B1C ; branch always + +;.get vector, execute function then continue evaluation + +LAB_1B43 + LDA LAB_OPPT+2,Y ; get function vector high byte + PHA ; onto stack + LDA LAB_OPPT+1,Y ; get function vector low byte + PHA ; onto stack + ; now push sign, round FAC1 and put on stack + JSR LAB_1B5B ; function will return here, then the next RTS will call + ; the function + LDA comp_f ; get compare function flag + PHA ; push compare evaluation byte + LDA LAB_OPPT,Y ; get precedence byte + JMP LAB_1ACC ; continue evaluating expression + +LAB_1B53 + JMP LAB_SNER ; do syntax error then warm start + +; push sign, round FAC1 and put on stack + +LAB_1B5B + PLA ; get return addr low byte + STA ut1_pl ; save it + INC ut1_pl ; increment it (was ret-1 pushed? yes!) + ; note! no check is made on the high byte! if the calling + ; routine assembles to a page edge then this all goes + ; horribly wrong !!! + PLA ; get return addr high byte + STA ut1_ph ; save it + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; push sign + +; round FAC1 and put on stack + +LAB_1B66 + JSR LAB_27BA ; round FAC1 + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_1 ; get FAC1 mantissa1 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + JMP (ut1_pl) ; return, sort of + +; do functions + +LAB_1B78 + LDY #$FF ; flag function + PLA ; pull precedence byte +LAB_1B7B + BEQ LAB_1B9D ; exit if done + +LAB_1B7D + CMP #$64 ; compare previous precedence with $64 + BEQ LAB_1B84 ; branch if was $64 (< function) + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B84 + STY prstk ; save precedence stacked flag + + ; pop FAC2 and return +LAB_1B86 + PLA ; pop byte + LSR ; shift out comparison evaluation lowest bit + STA Cflag ; save comparison evaluation flag + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + PLA ; pop mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) +LAB_1B9D + LDA FAC1_e ; get FAC1 exponent + RTS + +; print "..." string to string util area + +LAB_1BC1 + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + ADC #$00 ; add carry to low byte + BCC LAB_1BCA ; branch if no overflow + + INY ; increment high byte +LAB_1BCA + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + JMP LAB_23F3 ; restore BASIC execute pointer from temp and return + +; get value from line + +LAB_GVAL + JSR LAB_IGBY ; increment and scan memory + BCS LAB_1BAC ; branch if not numeric character + + ; else numeric string found (e.g. 123) +LAB_1BA9 + JMP LAB_2887 ; get FAC1 from string and return + +; get value from line .. continued + + ; wasn't a number so .. +LAB_1BAC + TAX ; set the flags + BMI LAB_1BD0 ; if -ve go test token values + + ; else it is either a string, number, variable or () + CMP #'$' ; compare with "$" + BEQ LAB_1BA9 ; branch if "$", hex number + + CMP #'%' ; else compare with "%" + BEQ LAB_1BA9 ; branch if "%", binary number + + CMP #'.' ; compare with "." + BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) + + ; it wasn't any sort of number so .. + CMP #$22 ; compare with " + BEQ LAB_1BC1 ; branch if open quote + + ; wasn't any sort of number so .. + +; evaluate expression within parentheses + + CMP #'(' ; compare with "(" + BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag + +LAB_1BF7 + JSR LAB_EVEZ ; evaluate expression, no decrement + +; all the 'scan for' routines return the character after the sought character + +; scan for ")" , else do syntax error then warm start + +LAB_1BFB + LDA #$29 ; load A with ")" + +; scan for CHR$(A) , else do syntax error then warm start + +LAB_SCCA + LDY #$00 ; clear index + CMP (Bpntrl),Y ; check next byte is = A + BNE LAB_SNER ; if not do syntax error then warm start + + JMP LAB_IGBY ; increment and scan memory then return + +; scan for "(" , else do syntax error then warm start + +LAB_1BFE + LDA #$28 ; load A with "(" + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; scan for "," , else do syntax error then warm start + +LAB_1C01 + LDA #$2C ; load A with "," + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; syntax error then warm start + +LAB_SNER + LDX #$02 ; error code $02 ("Syntax" error) + JMP LAB_XERR ; do error #X, then warm start + +; get value from line .. continued +; do tokens + +LAB_1BD0 + CMP #TK_MINUS ; compare with token for - + BEQ LAB_1C11 ; branch if - token (do set-up for functions) + + ; wasn't -n so .. + CMP #TK_PLUS ; compare with token for + + BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) + + CMP #TK_NOT ; compare with token for NOT + BNE LAB_1BE7 ; branch if not token for NOT + + ; was NOT token +TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS + LDY #TK_EQUAL_PLUS*3 ; offset to NOT function + BNE LAB_1C13 ; do set-up for function then execute (branch always) + +; do = compare + +LAB_EQUAL + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; invert it + TAY ; copy it + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; invert it + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get value from line .. continued + + ; wasn't +, -, or NOT so .. +LAB_1BE7 + CMP #TK_FN ; compare with token for FN + BNE LAB_1BEE ; branch if not token for FN + + JMP LAB_201E ; go evaluate FNx + +; get value from line .. continued + + ; wasn't +, -, NOT or FN so .. +LAB_1BEE + SBC #TK_SGN ; subtract with token for SGN + BCS LAB_1C27 ; if a function token go do it + + JMP LAB_SNER ; else do syntax error + +; set-up for functions + +LAB_1C11 +TK_GT_PLUS = TK_GT-TK_PLUS + LDY #TK_GT_PLUS*3 ; set offset from base to > operator +LAB_1C13 + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_1B1D ; execute function then continue evaluation + +; variable name set-up +; get (var), return value in FAC_1 and $ flag + +LAB_1C18 + JSR LAB_GVAR ; get (var) address + STA FAC1_2 ; save address low byte in FAC1 mantissa2 + STY FAC1_3 ; save address high byte in FAC1 mantissa3 + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_1C25 ; if string then return (does RTS) + +LAB_1C24 + JMP LAB_UFAC ; unpack memory (AY) into FAC1 + +LAB_1C25 + RTS + +; get value from line .. continued +; only functions left so .. + +; set up function references + +; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed +; to process function calls. now the function vector is computed and pushed on the stack +; and the preprocess offset is read. if the preprocess offset is non zero then the vector +; is calculated and the routine called, if not this routine just does RTS. whichever +; happens the RTS at the end of this routine, or the end of the preprocess routine, calls +; the function code + +; this also removes some less than elegant code that was used to bypass type checking +; for functions that returned strings + +LAB_1C27 + ASL ; *2 (2 bytes per function address) + TAY ; copy to index + + LDA LAB_FTBM,Y ; get function jump vector high byte + PHA ; push functions jump vector high byte + LDA LAB_FTBL,Y ; get function jump vector low byte + PHA ; push functions jump vector low byte + + LDA LAB_FTPM,Y ; get function pre process vector high byte + BEQ LAB_1C56 ; skip pre process if null vector + + PHA ; push functions pre process vector high byte + LDA LAB_FTPL,Y ; get function pre process vector low byte + PHA ; push functions pre process vector low byte + +LAB_1C56 + RTS ; do function, or pre process, call + +; process string expression in parenthesis + +LAB_PPFS + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTST ; check if source is string then do function, + ; else do type mismatch + +; process numeric expression in parenthesis + +LAB_PPFN + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTNM ; check if source is numeric then do function, + ; else do type mismatch + +; set numeric data type and increment BASIC execute pointer + +LAB_PPBI + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + JMP LAB_IGBY ; increment and scan memory then do function + +; process string for LEFT$, RIGHT$ or MID$ + +LAB_LRMS + JSR LAB_EVEZ ; evaluate (should be string) expression + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + PLA ; get function jump vector low byte + TAX ; save functions jump vector low byte + PLA ; get function jump vector high byte + TAY ; save functions jump vector high byte + LDA des_ph ; get descriptor pointer high byte + PHA ; push string pointer high byte + LDA des_pl ; get descriptor pointer low byte + PHA ; push string pointer low byte + TYA ; get function jump vector high byte back + PHA ; save functions jump vector high byte + TXA ; get function jump vector low byte back + PHA ; save functions jump vector low byte + JSR LAB_GTBY ; get byte parameter + TXA ; copy byte parameter to A + RTS ; go do function + +; process numeric expression(s) for BIN$ or HEX$ + +LAB_BHSS + JSR LAB_EVEZ ; process expression + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_BHER ; branch if n>=2^24 (is too big) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$02 ; 3 bytes to do +LAB_CFAC + LDA FAC1_1,X ; get byte from FAC1 + STA nums_1,X ; save byte to temp + DEX ; decrement index + BPL LAB_CFAC ; copy FAC1 mantissa to temp + + JSR LAB_GBYT ; get next BASIC byte + LDX #$00 ; set default to no leading "0"s + CMP #')' ; compare with close bracket + BEQ LAB_1C54 ; if ")" go do rest of function + + JSR LAB_SCGB ; scan for "," and get byte + JSR LAB_GBYT ; get last byte back + CMP #')' ; is next character ) + BNE LAB_BHER ; if not ")" go do error + +LAB_1C54 + RTS ; else do function + +LAB_BHER + JMP LAB_FCER ; do function call error then warm start + +; perform EOR + +; added operator format is the same as AND or OR, precedence is the same as OR + +; this bit worked first time but it took a while to sort out the operator table +; pointers and offsets afterwards! + +LAB_EOR + JSR GetFirst ; get first integer expression (no sign check) + EOR XOAw_l ; EOR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + EOR XOAw_h ; EOR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform OR + +LAB_OR + JSR GetFirst ; get first integer expression (no sign check) + ORA XOAw_l ; OR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + ORA XOAw_h ; OR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform AND + +LAB_AND + JSR GetFirst ; get first integer expression (no sign check) + AND XOAw_l ; AND with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + AND XOAw_h ; AND with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get first value for OR, AND or EOR + +GetFirst + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_2 ; get FAC1 mantissa2 + STA XOAw_h ; save it + LDA FAC1_3 ; get FAC1 mantissa3 + STA XOAw_l ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 +LAB_1C95 + RTS + +; perform comparisons + +; do < compare + +LAB_LTHAN + JSR LAB_CKTM ; type match check, set C for string + BCS LAB_1CAE ; branch if string + + ; do numeric < compare + LDA FAC2_s ; get FAC2 sign (b7) + ORA #$7F ; set all non sign bits + AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) + STA FAC2_1 ; save FAC2 mantissa1 + LDA #FAC2_e ; set pointer high byte to FAC2 + JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) + TAX ; copy result + JMP LAB_1CE1 ; go evaluate result + + ; do string < compare +LAB_1CAE + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + DEC comp_f ; clear < bit in compare function flag + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STA str_ln ; save length + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDA FAC2_2 ; get descriptor pointer low byte + LDY FAC2_3 ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STX FAC2_2 ; save string pointer low byte + STY FAC2_3 ; save string pointer high byte + TAX ; copy length + SEC ; set carry for subtract + SBC str_ln ; subtract string 1 length + BEQ LAB_1CD6 ; branch if str 1 length = string 2 length + + LDA #$01 ; set str 1 length > string 2 length + BCC LAB_1CD6 ; branch if so + + LDX str_ln ; get string 1 length + LDA #$FF ; set str 1 length < string 2 length +LAB_1CD6 + STA FAC1_s ; save length compare + LDY #$FF ; set index + INX ; adjust for loop +LAB_1CDB + INY ; increment index + DEX ; decrement count + BNE LAB_1CE6 ; branch if still bytes to do + + LDX FAC1_s ; get length compare back +LAB_1CE1 + BMI LAB_1CF2 ; branch if str 1 < str 2 + + CLC ; flag str 1 <= str 2 + BCC LAB_1CF2 ; go evaluate result + +LAB_1CE6 + LDA (FAC2_2),Y ; get string 2 byte + CMP (FAC1_1),Y ; compare with string 1 byte + BEQ LAB_1CDB ; loop if bytes = + + LDX #$FF ; set str 1 < string 2 + BCS LAB_1CF2 ; branch if so + + LDX #$01 ; set str 1 > string 2 +LAB_1CF2 + INX ; x = 0, 1 or 2 + TXA ; copy to A + ROL ; *2 (1, 2 or 4) + AND Cflag ; AND with comparison evaluation flag + BEQ LAB_1CFB ; branch if 0 (compare is false) + + LDA #$FF ; else set result true +LAB_1CFB + JMP LAB_27DB ; save A as integer byte and return + +LAB_1CFE + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + +; perform DIM + +LAB_DIM + TAX ; copy "DIM" flag to X + JSR LAB_1D10 ; search for variable + JSR LAB_GBYT ; scan memory + BNE LAB_1CFE ; scan for "," and loop if not null + + RTS + +; perform << (left shift) + +LAB_LSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Ls_loop + ASL FAC1_3 ; shift low byte + ROL ; shift high byte + DEX ; decrement bit count + BNE Ls_loop ; loop if shift not complete + + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform >> (right shift) + +LAB_RSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Rs_loop + LSR ; shift high byte + ROR FAC1_3 ; shift low byte + DEX ; decrement bit count + BNE Rs_loop ; loop if shift not complete + +NoShift + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +TooBig + LDA #$00 ; clear high byte + TAY ; copy to low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +GetPair + JSR LAB_EVBY ; evaluate byte expression, result in X + STX TempB ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JMP LAB_EVIR ; evaluate integer expression (no sign check) + +; search for variable + +; return pointer to variable in Cvaral/Cvarah + +LAB_GVAR + LDX #$00 ; set DIM flag = $00 + JSR LAB_GBYT ; scan memory (1st character) +LAB_1D10 + STX Defdim ; save DIM flag +LAB_1D12 + STA Varnm1 ; save 1st character + AND #$7F ; clear FN flag bit + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D1F ; branch if ok + + JMP LAB_SNER ; else syntax error then warm start + + ; was variable name so .. +LAB_1D1F + LDX #$00 ; clear 2nd character temp + STX Dtypef ; clear data type flag, $FF=string, $00=numeric + JSR LAB_IGBY ; increment and scan memory (2nd character) + BCC LAB_1D2D ; branch if character = "0"-"9" (ok) + + ; 2nd character wasn't "0" to "9" so .. + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) + +LAB_1D2D + TAX ; copy 2nd character + + ; ignore further (valid) characters in the variable name +LAB_1D2E + JSR LAB_IGBY ; increment and scan memory (3rd character) + BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) + + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) + + ; check if string variable +LAB_1D38 + CMP #'$' ; compare with "$" + BNE LAB_1D47 ; branch if not string + +; to introduce a new variable type (% suffix for integers say) then this branch +; will need to go to that check and then that branch, if it fails, go to LAB_1D47 + + ; type is string + LDA #$FF ; set data type = string + STA Dtypef ; set data type flag, $FF=string, $00=numeric + TXA ; get 2nd character back + ORA #$80 ; set top bit (indicate string var) + TAX ; copy back to 2nd character temp + JSR LAB_IGBY ; increment and scan memory + +; after we have determined the variable type we need to come back here to determine +; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely + + +LAB_1D47 ; gets here with character after var name in A + STX Varnm2 ; save 2nd character + ORA Sufnxf ; or with subscript/FNX flag (or FN name) + CMP #'(' ; compare with "(" + BNE LAB_1D53 ; branch if not "(" + + JMP LAB_1E17 ; go find, or make, array + +; either find or create var +; var name (1st two characters only!) is in Varnm1,Varnm2 + + ; variable name wasn't var(... so look for plain var +LAB_1D53 + LDA #$00 ; clear A + STA Sufnxf ; clear subscript/FNX flag + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + LDY #$00 ; clear index +LAB_1D5D + STX Vrschh ; save search address high byte +LAB_1D5F + STA Vrschl ; save search address low byte + CPX Sarryh ; compare high address with var space end + BNE LAB_1D69 ; skip next compare if <> + + ; high addresses were = so compare low addresses + CMP Sarryl ; compare low address with var space end + BEQ LAB_1D8B ; if not found go make new var + +LAB_1D69 + LDA Varnm1 ; get 1st character of var to find + CMP (Vrschl),Y ; compare with variable name 1st character + BNE LAB_1D77 ; branch if no match + + ; 1st characters match so compare 2nd characters + LDA Varnm2 ; get 2nd character of var to find + INY ; index to point to variable name 2nd character + CMP (Vrschl),Y ; compare with variable name 2nd character + BEQ LAB_1DD7 ; branch if match (found var) + + DEY ; else decrement index (now = $00) +LAB_1D77 + CLC ; clear carry for add + LDA Vrschl ; get search address low byte + ADC #$06 ; +6 (offset to next var name) + BCC LAB_1D5F ; loop if no overflow to high byte + + INX ; else increment high byte + BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) + +; check byte, return C=0 if<"A" or >"Z" or "a" to "z" + +LAB_CASC + CMP #'a' ; compare with "a" + BCS LAB_1D83 ; go check <"z"+1 + +; check byte, return C=0 if<"A" or >"Z" + +LAB_1D82 + CMP #'A' ; compare with "A" + BCC LAB_1D8A ; exit if less + + ; carry is set + SBC #$5B ; subtract "Z"+1 + SEC ; set carry + SBC #$A5 ; subtract $A5 (restore byte) + ; carry clear if byte>$5A +LAB_1D8A + RTS + +LAB_1D83 + SBC #$7B ; subtract "z"+1 + SEC ; set carry + SBC #$85 ; subtract $85 (restore byte) + ; carry clear if byte>$7A + RTS + + ; reached end of variable mem without match + ; .. so create new variable +LAB_1D8B + PLA ; pop return address low byte + PHA ; push return address low byte +LAB_1C18p2 = LAB_1C18+2 + CMP #LAB_1D96 ; high byte point to $00,$00 + RTS + + ; create new numeric variable +LAB_1D98 + LDA Sarryl ; get var mem end low byte + LDY Sarryh ; get var mem end high byte + STA Ostrtl ; save old block start low byte + STY Ostrth ; save old block start high byte + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Obendl ; save old block end low byte + STY Obendh ; save old block end high byte + CLC ; clear carry for add + ADC #$06 ; +6 (space for one var) + BCC LAB_1DAE ; branch if no overflow to high byte + + INY ; else increment high byte +LAB_1DAE + STA Nbendl ; set new block end low byte + STY Nbendh ; set new block end high byte + JSR LAB_11CF ; open up space in memory + LDA Nbendl ; get new start low byte + LDY Nbendh ; get new start high byte (-$100) + INY ; correct high byte + STA Sarryl ; save new var mem end low byte + STY Sarryh ; save new var mem end high byte + LDY #$00 ; clear index + LDA Varnm1 ; get var name 1st character + STA (Vrschl),Y ; save var name 1st character + INY ; increment index + LDA Varnm2 ; get var name 2nd character + STA (Vrschl),Y ; save var name 2nd character + LDA #$00 ; clear A + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + + ; found a match for var ((Vrschl) = ptr) +LAB_1DD7 + LDA Vrschl ; get var address low byte + CLC ; clear carry for add + ADC #$02 ; +2 (offset past var name bytes) + LDY Vrschh ; get var address high byte + BCC LAB_1DE1 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1DE1 + STA Cvaral ; save current var address low byte + STY Cvarah ; save current var address high byte + RTS + +; set-up array pointer (Adatal/h) to first element in array +; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 + +LAB_1DE6 + LDA Dimcnt ; get # of dimensions (1, 2 or 3) + ASL ; *2 (also clears the carry !) + ADC #$05 ; +5 (result is 7, 9 or 11 here) + ADC Astrtl ; add array start pointer low byte + LDY Astrth ; get array pointer high byte + BCC LAB_1DF2 ; branch if no overflow + + INY ; else increment high byte +LAB_1DF2 + STA Adatal ; save array data pointer low byte + STY Adatah ; save array data pointer high byte + RTS + +; evaluate integer expression + +LAB_EVIN + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate integer expression (no check) + +LAB_EVPI + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_1E12 ; do function call error if -ve + +; evaluate integer expression (no sign check) + +LAB_EVIR + LDA FAC1_e ; get FAC1 exponent + CMP #$90 ; compare with exponent = 2^16 (n>2^15) + BCC LAB_1E14 ; branch if n<2^16 (is ok) + + LDA #LAB_1DF7 ; set pointer high byte to -32768 + JSR LAB_27F8 ; compare FAC1 with (AY) +LAB_1E12 + BNE LAB_FCER ; if <> do function call error then warm start + +LAB_1E14 + JMP LAB_2831 ; convert FAC1 floating-to-fixed and return + +; find or make array + +LAB_1E17 + LDA Defdim ; get DIM flag + PHA ; push it + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push it + LDY #$00 ; clear dimensions count + +; now get the array dimension(s) and stack it (them) before the data type and DIM flag + +LAB_1E1F + TYA ; copy dimensions count + PHA ; save it + LDA Varnm2 ; get array name 2nd byte + PHA ; save it + LDA Varnm1 ; get array name 1st byte + PHA ; save it + JSR LAB_EVIN ; evaluate integer expression + PLA ; pull array name 1st byte + STA Varnm1 ; restore array name 1st byte + PLA ; pull array name 2nd byte + STA Varnm2 ; restore array name 2nd byte + PLA ; pull dimensions count + TAY ; restore it + TSX ; copy stack pointer + LDA LAB_STAK+2,X ; get DIM flag + PHA ; push it + LDA LAB_STAK+1,X ; get data type flag + PHA ; push it + LDA FAC1_2 ; get this dimension size high byte + STA LAB_STAK+2,X ; stack before flag bytes + LDA FAC1_3 ; get this dimension size low byte + STA LAB_STAK+1,X ; stack before flag bytes + INY ; increment dimensions count + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BEQ LAB_1E1F ; if found go do next dimension + + STY Dimcnt ; store dimensions count + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull data type flag + STA Dtypef ; restore data type flag, $FF=string, $00=numeric + PLA ; pull DIM flag + STA Defdim ; restore DIM flag + LDX Sarryl ; get array mem start low byte + LDA Sarryh ; get array mem start high byte + +; now check to see if we are at the end of array memory (we would be if there were +; no arrays). + +LAB_1E5C + STX Astrtl ; save as array start pointer low byte + STA Astrth ; save as array start pointer high byte + CMP Earryh ; compare with array mem end high byte + BNE LAB_1E68 ; branch if not reached array mem end + + CPX Earryl ; else compare with array mem end low byte + BEQ LAB_1EA1 ; go build array if not found + + ; search for array +LAB_1E68 + LDY #$00 ; clear index + LDA (Astrtl),Y ; get array name first byte + INY ; increment index to second name byte + CMP Varnm1 ; compare with this array name first byte + BNE LAB_1E77 ; branch if no match + + LDA Varnm2 ; else get this array name second byte + CMP (Astrtl),Y ; compare with array name second byte + BEQ LAB_1E8D ; array found so branch + + ; no match +LAB_1E77 + INY ; increment index + LDA (Astrtl),Y ; get array size low byte + CLC ; clear carry for add + ADC Astrtl ; add array start pointer low byte + TAX ; copy low byte to X + INY ; increment index + LDA (Astrtl),Y ; get array size high byte + ADC Astrth ; add array mem pointer high byte + BCC LAB_1E5C ; if no overflow go check next array + +; do array bounds error + +LAB_1E85 + LDX #$10 ; error code $10 ("Array bounds" error) + .byte $2C ; makes next bit BIT LAB_08A2 + +; do function call error + +LAB_FCER + LDX #$08 ; error code $08 ("Function call" error) +LAB_1E8A + JMP LAB_XERR ; do error #X, then warm start + + ; found array, are we trying to dimension it? +LAB_1E8D + LDX #$12 ; set error $12 ("Double dimension" error) + LDA Defdim ; get DIM flag + BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm + ; start + +; found the array and we're not dimensioning it so we must find an element in it + + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + LDA Dimcnt ; get dimensions count + LDY #$04 ; set index to array's # of dimensions + CMP (Astrtl),Y ; compare with no of dimensions + BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong + ; dimensions" error here .. if we want a different + ; error message + + JMP LAB_1F28 ; found array so go get element + ; (could jump to LAB_1F28 as all LAB_1F24 does is take + ; Dimcnt and save it at (Astrtl),Y which is already the + ; same or we would have taken the BNE) + + ; array not found, so build it +LAB_1EA1 + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + LDY #$00 ; clear Y (don't need to clear A) + STY Aspth ; clear array data size high byte + LDA Varnm1 ; get variable name 1st byte + STA (Astrtl),Y ; save array name 1st byte + INY ; increment index + LDA Varnm2 ; get variable name 2nd byte + STA (Astrtl),Y ; save array name 2nd byte + LDA Dimcnt ; get dimensions count + LDY #$04 ; index to dimension count + STY Asptl ; set array data size low byte (four bytes per element) + STA (Astrtl),Y ; set array's dimensions count + + ; now calculate the size of the data space for the array + CLC ; clear carry for add (clear on subsequent loops) +LAB_1EC0 + LDX #$0B ; set default dimension value low byte + LDA #$00 ; set default dimension value high byte + BIT Defdim ; test default DIM flag + BVC LAB_1ED0 ; branch if b6 of Defdim is clear + + PLA ; else pull dimension value low byte + ADC #$01 ; +1 (allow for zeroeth element) + TAX ; copy low byte to X + PLA ; pull dimension value high byte + ADC #$00 ; add carry from low byte + +LAB_1ED0 + INY ; index to dimension value high byte + STA (Astrtl),Y ; save dimension value high byte + INY ; index to dimension value high byte + TXA ; get dimension value low byte + STA (Astrtl),Y ; save dimension value low byte + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + STX Asptl ; save array data size low byte + STA Aspth ; save array data size high byte + LDY ut1_pl ; restore index (saved by subroutine) + DEC Dimcnt ; decrement dimensions count + BNE LAB_1EC0 ; loop while not = 0 + + ADC Adatah ; add size high byte to first element high byte + ; (carry is always clear here) + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + STA Adatah ; save end of array high byte + TAY ; copy end high byte to Y + TXA ; get array size low byte + ADC Adatal ; add array start low byte + BCC LAB_1EF3 ; branch if no carry + + INY ; else increment end of array high byte + BEQ LAB_1F45 ; if overflow go do "Out of memory" error + + ; set-up mostly complete, now zero the array +LAB_1EF3 + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + LDA #$00 ; clear byte for array clear + INC Aspth ; increment array size high byte (now block count) + LDY Asptl ; get array size low byte (now index to block) + BEQ LAB_1F07 ; branch if low byte = $00 + +LAB_1F02 + DEY ; decrement index (do 0 to n-1) + STA (Adatal),Y ; zero byte + BNE LAB_1F02 ; loop until this block done + +LAB_1F07 + DEC Adatah ; decrement array pointer high byte + DEC Aspth ; decrement block count high byte + BNE LAB_1F02 ; loop until all blocks done + + INC Adatah ; correct for last loop + SEC ; set carry for subtract + LDY #$02 ; index to array size low byte + LDA Earryl ; get array mem end low byte + SBC Astrtl ; subtract array start low byte + STA (Astrtl),Y ; save array size low byte + INY ; index to array size high byte + LDA Earryh ; get array mem end high byte + SBC Astrth ; subtract array start high byte + STA (Astrtl),Y ; save array size high byte + LDA Defdim ; get default DIM flag + BNE LAB_1F7B ; exit (RET) if this was a DIM command + + ; else, find element + INY ; index to # of dimensions + +LAB_1F24 + LDA (Astrtl),Y ; get array's dimension count + STA Dimcnt ; save it + +; we have found, or built, the array. now we need to find the element + +LAB_1F28 + LDA #$00 ; clear byte + STA Asptl ; clear array data pointer low byte +LAB_1F2C + STA Aspth ; save array data pointer high byte + INY ; increment index (point to array bound high byte) + PLA ; pull array index low byte + TAX ; copy to X + STA FAC1_2 ; save index low byte to FAC1 mantissa2 + PLA ; pull array index high byte + STA FAC1_3 ; save index high byte to FAC1 mantissa3 + CMP (Astrtl),Y ; compare with array bound high byte + BCC LAB_1F48 ; branch if within bounds + + BNE LAB_1F42 ; if outside bounds do array bounds error + + ; else high byte was = so test low bytes + INY ; index to array bound low byte + TXA ; get array index low byte + CMP (Astrtl),Y ; compare with array bound low byte + BCC LAB_1F49 ; branch if within bounds + +LAB_1F42 + JMP LAB_1E85 ; else do array bounds error + +LAB_1F45 + JMP LAB_OMER ; do "Out of memory" error then warm start + +LAB_1F48 + INY ; index to array bound low byte +LAB_1F49 + LDA Aspth ; get array data pointer high byte + ORA Asptl ; OR with array data pointer low byte + BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) + + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + TXA ; get result low byte + ADC FAC1_2 ; add index low byte from FAC1 mantissa2 + TAX ; save result low byte + TYA ; get result high byte + LDY ut1_pl ; restore index +LAB_1F5A + ADC FAC1_3 ; add index high byte from FAC1 mantissa3 + STX Asptl ; save array data pointer low byte + DEC Dimcnt ; decrement dimensions count + BNE LAB_1F2C ; loop if dimensions still to do + + ASL Asptl ; array data pointer low byte * 2 + ROL ; array data pointer high byte * 2 + ASL Asptl ; array data pointer low byte * 4 + ROL ; array data pointer high byte * 4 + TAY ; copy high byte + LDA Asptl ; get low byte + ADC Adatal ; add array data start pointer low byte + STA Cvaral ; save as current var address low byte + TYA ; get high byte back + ADC Adatah ; add array data start pointer high byte + STA Cvarah ; save as current var address high byte + TAY ; copy high byte to Y + LDA Cvaral ; get current var address low byte +LAB_1F7B + RTS + +; does XY = (Astrtl),Y * (Asptl) + +LAB_1F7C + STY ut1_pl ; save index + LDA (Astrtl),Y ; get dimension size low byte + STA dims_l ; save dimension size low byte + DEY ; decrement index + LDA (Astrtl),Y ; get dimension size high byte + STA dims_h ; save dimension size high byte + + LDA #$10 ; count = $10 (16 bit multiply) + STA numbit ; save bit count + LDX #$00 ; clear result low byte + LDY #$00 ; clear result high byte +LAB_1F8F + TXA ; get result low byte + ASL ; *2 + TAX ; save result low byte + TYA ; get result high byte + ROL ; *2 + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + ASL Asptl ; shift multiplier low byte + ROL Aspth ; shift multiplier high byte + BCC LAB_1FA8 ; skip add if no carry + + CLC ; else clear carry for add + TXA ; get result low byte + ADC dims_l ; add dimension size low byte + TAX ; save result low byte + TYA ; get result high byte + ADC dims_h ; add dimension size high byte + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + +LAB_1FA8 + DEC numbit ; decrement bit count + BNE LAB_1F8F ; loop until all done + + RTS + +; perform FRE() + +LAB_FRE + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + BPL LAB_1FB4 ; branch if numeric + + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + + ; FRE(n) was numeric so do this +LAB_1FB4 + JSR LAB_GARB ; go do garbage collection + SEC ; set carry for subtract + LDA Sstorl ; get bottom of string space low byte + SBC Earryl ; subtract array mem end low byte + TAY ; copy result to Y + LDA Sstorh ; get bottom of string space high byte + SBC Earryh ; subtract array mem end high byte + +; save and convert integer AY to FAC1 + +LAB_AYFC + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + STA FAC1_1 ; save FAC1 mantissa1 + STY FAC1_2 ; save FAC1 mantissa2 + LDX #$90 ; set exponent=2^16 (integer) + JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return + +; perform POS() + +LAB_POS + LDY TPos ; get terminal position + +; convert Y to byte in FAC1 + +LAB_1FD0 + LDA #$00 ; clear high byte + BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return + +; check not Direct (used by DEF and INPUT) + +LAB_CKRN + LDX Clineh ; get current line high byte + INX ; increment it + BNE LAB_1F7B ; return if can continue not direct mode + + ; else do illegal direct error +LAB_1FD9 + LDX #$16 ; error code $16 ("Illegal direct" error) +LAB_1FDB + JMP LAB_XERR ; go do error #X, then warm start + +; perform DEF + +LAB_DEF + JSR LAB_200B ; check FNx syntax + STA func_l ; save function pointer low byte + STY func_h ; save function pointer high byte + JSR LAB_CKRN ; check not Direct (back here if ok) + JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start + LDA #$80 ; set flag for FNx + STA Sufnxf ; save subscript/FNx flag + JSR LAB_GVAR ; get (var) address + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Cvarah ; get current var address high byte + PHA ; push it + LDA Cvaral ; get current var address low byte + PHA ; push it + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + JSR LAB_DATA ; go perform DATA + JMP LAB_207A ; put execute pointer and variable pointer into function + ; and return + +; check FNx syntax + +LAB_200B + LDA #TK_FN ; get FN" token + JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start + ; return character after A + ORA #$80 ; set FN flag bit + STA Sufnxf ; save FN flag so array variable test fails + JSR LAB_1D12 ; search for FN variable + JMP LAB_CTNM ; check if source is numeric and return, else do type + ; mismatch + + ; Evaluate FNx +LAB_201E + JSR LAB_200B ; check FNx syntax + PHA ; push function pointer low byte + TYA ; copy function pointer high byte + PHA ; push function pointer high byte + JSR LAB_1BFE ; scan for "(", else do syntax error then warm start + JSR LAB_EVEX ; evaluate expression + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + PLA ; pop function pointer high byte + STA func_h ; restore it + PLA ; pop function pointer low byte + STA func_l ; restore it + LDX #$20 ; error code $20 ("Undefined function" error) + LDY #$03 ; index to variable pointer high byte + LDA (func_l),Y ; get variable pointer high byte + BEQ LAB_1FDB ; if zero go do undefined function error + + STA Cvarah ; save variable address high byte + DEY ; index to variable address low byte + LDA (func_l),Y ; get variable address low byte + STA Cvaral ; save variable address low byte + TAX ; copy address low byte + + ; now stack the function variable value before use + INY ; index to mantissa_3 +LAB_2043 + LDA (Cvaral),Y ; get byte from variable + PHA ; stack it + DEY ; decrement index + BPL LAB_2043 ; loop until variable stacked + + LDY Cvarah ; get variable address high byte + JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) + ; (function variable), return Y=0, always + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + LDA (func_l),Y ; get function execute pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + INY ; index to high byte + LDA (func_l),Y ; get function execute pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + LDA Cvarah ; get variable address high byte + PHA ; push it + LDA Cvaral ; get variable address low byte + PHA ; push it + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + PLA ; pull variable address low byte + STA func_l ; save variable address low byte + PLA ; pull variable address high byte + STA func_h ; save variable address high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_2074 ; branch if null (should be [EOL] marker) + + JMP LAB_SNER ; else syntax error then warm start + +; restore Bpntrl,Bpntrh and function variable from stack + +LAB_2074 + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; restore BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; restore BASIC execute pointer high byte + +; put execute pointer and variable pointer into function + +LAB_207A + LDY #$00 ; clear index + PLA ; pull BASIC execute pointer low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull BASIC execute pointer high byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address high byte + STA (func_l),Y ; save to function + RTS + +; perform STR$() + +LAB_STRS + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_296E ; convert FAC1 to string + LDA #Decssp1 ; set result string high pointer + BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh + +; Do string vector +; copy des_pl/h to des_2l/h and make string space A bytes long + +LAB_209C + LDX des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + STX des_2l ; save descriptor pointer low byte + STY des_2h ; save descriptor pointer high byte + +; make string space A bytes long +; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + +LAB_MSSP + JSR LAB_2115 ; make space in string memory for string A long + ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + STA str_ln ; save length + RTS + +; Scan, set up string +; print " terminated string to Sutill/Sutilh + +LAB_20AE + LDX #$22 ; set terminator to " + STX Srchc ; set search character (terminator 1) + STX Asrch ; set terminator 2 + +; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh +; source is AY + +LAB_20B4 + STA ssptr_l ; store string start low byte + STY ssptr_h ; store string start high byte + STA str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDY #$FF ; set length to -1 +LAB_20BE + INY ; increment length + LDA (ssptr_l),Y ; get byte from string + BEQ LAB_20CF ; exit loop if null byte [EOS] + + CMP Srchc ; compare with search character (terminator 1) + BEQ LAB_20CB ; branch if terminator + + CMP Asrch ; compare with terminator 2 + BNE LAB_20BE ; loop if not terminator 2 + +LAB_20CB + CMP #$22 ; compare with " + BEQ LAB_20D0 ; branch if " (carry set if = !) + +LAB_20CF + CLC ; clear carry for add (only if [EOL] terminated string) +LAB_20D0 + STY str_ln ; save length in FAC1 exponent + TYA ; copy length to A + ADC ssptr_l ; add string start low byte + STA Sendl ; save string end low byte + LDX ssptr_h ; get string start high byte + BCC LAB_20DC ; branch if no low byte overflow + + INX ; else increment high byte +LAB_20DC + STX Sendh ; save string end high byte + LDA ssptr_h ; get string start high byte + CMP #>Ram_base ; compare with start of program memory + BCS LAB_RTST ; branch if not in utility area + + ; string in utility area, move to string memory + TYA ; copy length to A + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + LDX ssptr_l ; get string start low byte + LDY ssptr_h ; get string start high byte + JSR LAB_2298 ; store string A bytes long from XY to (Sutill) + +; check for space on descriptor stack then .. +; put string address and length on descriptor stack and update stack pointers + +LAB_RTST + LDX next_s ; get string stack pointer + CPX #des_sk+$09 ; compare with max+1 + BNE LAB_20F8 ; branch if space on string stack + + ; else do string too complex error + LDX #$1C ; error code $1C ("String too complex" error) +LAB_20F5 + JMP LAB_XERR ; do error #X, then warm start + +; put string address and length on descriptor stack and update stack pointers + +LAB_20F8 + LDA str_ln ; get string length + STA PLUS_0,X ; put on string stack + LDA str_pl ; get string pointer low byte + STA PLUS_1,X ; put on string stack + LDA str_ph ; get string pointer high byte + STA PLUS_2,X ; put on string stack + LDY #$00 ; clear Y + STX des_pl ; save string descriptor pointer low byte + STY des_ph ; save string descriptor pointer high byte (always $00) + DEY ; Y = $FF + STY Dtypef ; save data type flag, $FF=string + STX last_sl ; save old stack pointer (current top item) + INX ; update stack pointer + INX ; update stack pointer + INX ; update stack pointer + STX next_s ; save new top item value + RTS + +; Build descriptor +; make space in string memory for string A long +; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte + +LAB_2115 + LSR Gclctd ; clear garbage collected flag (b7) + + ; make space for string A long +LAB_2117 + PHA ; save string length + EOR #$FF ; complement it + SEC ; set carry for subtract (twos comp add) + ADC Sstorl ; add bottom of string space low byte (subtract length) + LDY Sstorh ; get bottom of string space high byte + BCS LAB_2122 ; skip decrement if no underflow + + DEY ; decrement bottom of string space high byte +LAB_2122 + CPY Earryh ; compare with array mem end high byte + BCC LAB_2137 ; do out of memory error if less + + BNE LAB_212C ; if not = skip next test + + CMP Earryl ; compare with array mem end low byte + BCC LAB_2137 ; do out of memory error if less + +LAB_212C + STA Sstorl ; save bottom of string space low byte + STY Sstorh ; save bottom of string space high byte + STA Sutill ; save string utility ptr low byte + STY Sutilh ; save string utility ptr high byte + TAX ; copy low byte to X + PLA ; get string length back + RTS + +LAB_2137 + LDX #$0C ; error code $0C ("Out of memory" error) + LDA Gclctd ; get garbage collected flag + BMI LAB_20F5 ; if set then do error code X + + JSR LAB_GARB ; else go do garbage collection + LDA #$80 ; flag for garbage collected + STA Gclctd ; set garbage collected flag + PLA ; pull length + BNE LAB_2117 ; go try again (loop always, length should never be = $00) + +; garbage collection routine + +LAB_GARB + LDX Ememl ; get end of mem low byte + LDA Ememh ; get end of mem high byte + +; re-run routine from last ending + +LAB_214B + STX Sstorl ; set string storage low byte + STA Sstorh ; set string storage high byte + LDY #$00 ; clear index + STY garb_h ; clear working pointer high byte (flag no strings to move) + LDA Earryl ; get array mem end low byte + LDX Earryh ; get array mem end high byte + STA Histrl ; save as highest string low byte + STX Histrh ; save as highest string high byte + LDA #des_sk ; set descriptor stack pointer + STA ut1_pl ; save descriptor stack pointer low byte + STY ut1_ph ; save descriptor stack pointer high byte ($00) +LAB_2161 + CMP next_s ; compare with descriptor stack pointer + BEQ LAB_216A ; branch if = + + JSR LAB_21D7 ; go garbage collect descriptor stack + BEQ LAB_2161 ; loop always + + ; done stacked strings, now do string vars +LAB_216A + ASL g_step ; set step size = $06 + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + STA ut1_pl ; save as pointer low byte + STX ut1_ph ; save as pointer high byte +LAB_2176 + CPX Sarryh ; compare start of arrays high byte + BNE LAB_217E ; branch if no high byte match + + CMP Sarryl ; else compare start of arrays low byte + BEQ LAB_2183 ; branch if = var mem end + +LAB_217E + JSR LAB_21D1 ; go garbage collect strings + BEQ LAB_2176 ; loop always + + ; done string vars, now do string arrays +LAB_2183 + STA Nbendl ; save start of arrays low byte as working pointer + STX Nbendh ; save start of arrays high byte as working pointer + LDA #$04 ; set step size + STA g_step ; save step size +LAB_218B + LDA Nbendl ; get pointer low byte + LDX Nbendh ; get pointer high byte +LAB_218F + CPX Earryh ; compare with array mem end high byte + BNE LAB_219A ; branch if not at end + + CMP Earryl ; else compare with array mem end low byte + BEQ LAB_2216 ; tidy up and exit if at end + +LAB_219A + STA ut1_pl ; save pointer low byte + STX ut1_ph ; save pointer high byte + LDY #$02 ; set index + LDA (ut1_pl),Y ; get array size low byte + ADC Nbendl ; add start of this array low byte + STA Nbendl ; save start of next array low byte + INY ; increment index + LDA (ut1_pl),Y ; get array size high byte + ADC Nbendh ; add start of this array high byte + STA Nbendh ; save start of next array high byte + LDY #$01 ; set index + LDA (ut1_pl),Y ; get name second byte + BPL LAB_218B ; skip if not string array + +; was string array so .. + + LDY #$04 ; set index + LDA (ut1_pl),Y ; get # of dimensions + ASL ; *2 + ADC #$05 ; +5 (array header size) + JSR LAB_2208 ; go set up for first element +LAB_21C4 + CPX Nbendh ; compare with start of next array high byte + BNE LAB_21CC ; branch if <> (go do this array) + + CMP Nbendl ; else compare element pointer low byte with next array + ; low byte + BEQ LAB_218F ; if equal then go do next array + +LAB_21CC + JSR LAB_21D7 ; go defrag array strings + BEQ LAB_21C4 ; go do next array string (loop always) + +; defrag string variables +; enter with XA = variable pointer +; return with XA = next variable pointer + +LAB_21D1 + INY ; increment index (Y was $00) + LDA (ut1_pl),Y ; get var name byte 2 + BPL LAB_2206 ; if not string, step pointer to next var and return + + INY ; else increment index +LAB_21D7 + LDA (ut1_pl),Y ; get string length + BEQ LAB_2206 ; if null, step pointer to next string and return + + INY ; else increment index + LDA (ut1_pl),Y ; get string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_21EC ; branch if less + + BNE LAB_2206 ; if greater, step pointer to next string and return + + ; high bytes were = so compare low bytes + CPX Sstorl ; compare bottom of string space low byte + BCS LAB_2206 ; if >=, step pointer to next string and return + + ; string pointer is < string storage pointer (pos in mem) +LAB_21EC + CMP Histrh ; compare to highest string high byte + BCC LAB_2207 ; if <, step pointer to next string and return + + BNE LAB_21F6 ; if > update pointers, step to next and return + + ; high bytes were = so compare low bytes + CPX Histrl ; compare to highest string low byte + BCC LAB_2207 ; if <, step pointer to next string and return + + ; string is in string memory space +LAB_21F6 + STX Histrl ; save as new highest string low byte + STA Histrh ; save as new highest string high byte + LDA ut1_pl ; get start of vars(descriptors) low byte + LDX ut1_ph ; get start of vars(descriptors) high byte + STA garb_l ; save as working pointer low byte + STX garb_h ; save as working pointer high byte + DEY ; decrement index DIFFERS + DEY ; decrement index (should point to descriptor start) + STY g_indx ; save index pointer + + ; step pointer to next string +LAB_2206 + CLC ; clear carry for add +LAB_2207 + LDA g_step ; get step size +LAB_2208 + ADC ut1_pl ; add pointer low byte + STA ut1_pl ; save pointer low byte + BCC LAB_2211 ; branch if no overflow + + INC ut1_ph ; else increment high byte +LAB_2211 + LDX ut1_ph ; get pointer high byte + LDY #$00 ; clear Y + RTS + +; search complete, now either exit or set-up and move string + +LAB_2216 + DEC g_step ; decrement step size (now $03 for descriptor stack) + LDX garb_h ; get string to move high byte + BEQ LAB_2211 ; exit if nothing to move + + LDY g_indx ; get index byte back (points to descriptor) + CLC ; clear carry for add + LDA (garb_l),Y ; get string length + ADC Histrl ; add highest string low byte + STA Obendl ; save old block end low pointer + LDA Histrh ; get highest string high byte + ADC #$00 ; add any carry + STA Obendh ; save old block end high byte + LDA Sstorl ; get bottom of string space low byte + LDX Sstorh ; get bottom of string space high byte + STA Nbendl ; save new block end low byte + STX Nbendh ; save new block end high byte + JSR LAB_11D6 ; open up space in memory, don't set array end + LDY g_indx ; get index byte + INY ; point to descriptor low byte + LDA Nbendl ; get string pointer low byte + STA (garb_l),Y ; save new string pointer low byte + TAX ; copy string pointer low byte + INC Nbendh ; correct high byte (move sets high byte -1) + LDA Nbendh ; get new string pointer high byte + INY ; point to descriptor high byte + STA (garb_l),Y ; save new string pointer high byte + JMP LAB_214B ; re-run routine from last ending + ; (but don't collect this string) + +; concatenate +; add strings, string 1 is in descriptor des_pl, string 2 is in line + +LAB_224D + LDA des_ph ; get descriptor pointer high byte + PHA ; put on stack + LDA des_pl ; get descriptor pointer low byte + PHA ; put on stack + JSR LAB_GVAL ; get value from line + JSR LAB_CTST ; check if source is string, else do type mismatch + PLA ; get descriptor pointer low byte back + STA ssptr_l ; set pointer low byte + PLA ; get descriptor pointer high byte back + STA ssptr_h ; set pointer high byte + LDY #$00 ; clear index + LDA (ssptr_l),Y ; get length_1 from descriptor + CLC ; clear carry for add + ADC (des_pl),Y ; add length_2 + BCC LAB_226D ; branch if no overflow + + LDX #$1A ; else set error code $1A ("String too long" error) + JMP LAB_XERR ; do error #X, then warm start + +LAB_226D + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, ut1_pl = pointer low byte, + ; ut1_ph = pointer high byte + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + LDA ssptr_l ;.set descriptor pointer low byte + LDY ssptr_h ;.set descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + JSR LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + JMP LAB_1ADB ;.continue evaluation + +; copy string from descriptor (sdescr) to (Sutill) + +LAB_228A + LDY #$00 ; clear index + LDA (sdescr),Y ; get string length + PHA ; save on stack + INY ; increment index + LDA (sdescr),Y ; get source string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (sdescr),Y ; get source string pointer high byte + TAY ; copy to Y + PLA ; get length back + +; store string A bytes long from YX to (Sutill) + +LAB_2298 + STX ut1_pl ; save source string pointer low byte + STY ut1_ph ; save source string pointer high byte + +; store string A bytes long from (ut1_pl) to (Sutill) + +LAB_229C + TAX ; copy length to index (don't count with Y) + BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length + + LDY #$00 ; zero pointer (copy forward) +LAB_22A0 + LDA (ut1_pl),Y ; get source byte + STA (Sutill),Y ; save destination byte + + INY ; increment index + DEX ; decrement counter + BNE LAB_22A0 ; loop while <> 0 + + TYA ; restore length from Y +LAB_22A9 + CLC ; clear carry for add + ADC Sutill ; add string utility ptr low byte + STA Sutill ; save string utility ptr low byte + BCC LAB_22B2 ; branch if no carry + + INC Sutilh ; else increment string utility ptr high byte +LAB_22B2 + RTS + +; evaluate string + +LAB_EVST + JSR LAB_CTST ; check if source is string, else do type mismatch + +; pop string off descriptor stack, or from top of string space +; returns with A = length, X=pointer low byte, Y=pointer high byte + +LAB_22B6 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + +; pop (YA) descriptor off stack or from top of string space +; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte + +LAB_22BA + STA ut1_pl ; save descriptor pointer low byte + STY ut1_ph ; save descriptor pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + PHP ; save status flags + LDY #$00 ; clear index + LDA (ut1_pl),Y ; get length from string descriptor + PHA ; put on stack + INY ; increment index + LDA (ut1_pl),Y ; get string pointer low byte from descriptor + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte from descriptor + TAY ; copy to Y + PLA ; get string length back + PLP ; restore status + BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh + + CPY Sstorh ; compare bottom of string space high byte + BNE LAB_22E6 ; branch if <> + + CPX Sstorl ; else compare bottom of string space low byte + BNE LAB_22E6 ; branch if <> + + PHA ; save string length + CLC ; clear carry for add + ADC Sstorl ; add bottom of string space low byte + STA Sstorl ; save bottom of string space low byte + BCC LAB_22E5 ; skip increment if no overflow + + INC Sstorh ; increment bottom of string space high byte +LAB_22E5 + PLA ; restore string length +LAB_22E6 + STX ut1_pl ; save string pointer low byte + STY ut1_ph ; save string pointer high byte + RTS + +; clean descriptor stack, YA = pointer +; checks if AY is on the descriptor stack, if so does a stack discard + +LAB_22EB + CPY last_sh ; compare pointer high byte + BNE LAB_22FB ; exit if <> + + CMP last_sl ; compare pointer low byte + BNE LAB_22FB ; exit if <> + + STA next_s ; save descriptor stack pointer + SBC #$03 ; -3 + STA last_sl ; save low byte -3 + LDY #$00 ; clear high byte +LAB_22FB + RTS + +; perform CHR$() + +LAB_CHRS + JSR LAB_EVBY ; evaluate byte expression, result in X + TXA ; copy to A + PHA ; save character + LDA #$01 ; string is single byte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform LEFT$() + +LAB_LEFT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CMP (des_2l),Y ; compare byte parameter with string length + TYA ; clear A + BEQ LAB_2316 ; go do string copy (branch always) + +; perform RIGHT$() + +LAB_RIGHT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CLC ; clear carry for add-1 + SBC (des_2l),Y ; subtract string length + EOR #$FF ; invert it (A=LEN(expression$)-l) + +LAB_2316 + BCC LAB_231C ; branch if string length > byte parameter + + LDA (des_2l),Y ; else make parameter = length + TAX ; copy to byte parameter copy + TYA ; clear string start offset +LAB_231C + PHA ; save string start offset +LAB_231D + TXA ; copy byte parameter (or string length if <) +LAB_231E + PHA ; save string length + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + PLA ; get string length back + TAY ; copy length to Y + PLA ; get string start offset back + CLC ; clear carry for add + ADC ut1_pl ; add start offset to string start pointer low byte + STA ut1_pl ; save string start pointer low byte + BCC LAB_2335 ; branch if no overflow + + INC ut1_ph ; else increment string start pointer high byte +LAB_2335 + TYA ; copy length to A + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform MID$() + +LAB_MIDS + PHA ; push byte parameter + LDA #$FF ; set default length = 255 + STA mids_l ; save default length + JSR LAB_GBYT ; scan memory + CMP #')' ; compare with ")" + BEQ LAB_2358 ; branch if = ")" (skip second byte get) + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GTBY ; get byte parameter (use copy in mids_l) +LAB_2358 + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + DEX ; decrement start index + TXA ; copy to A + PHA ; save string start offset + CLC ; clear carry for sub-1 + LDX #$00 ; clear output string length + SBC (des_2l),Y ; subtract string length + BCS LAB_231D ; if start>string length go do null string + + EOR #$FF ; complement -length + CMP mids_l ; compare byte parameter + BCC LAB_231E ; if length>remaining string go do RIGHT$ + + LDA mids_l ; get length byte + BCS LAB_231E ; go do string copy (branch always) + +; pull string data and byte parameter from stack +; return pointer in des_2l/h, byte in A (and X), Y=0 + +LAB_236F + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull return address low byte (return address) + STA Fnxjpl ; save functions jump vector low byte + PLA ; pull return address high byte (return address) + STA Fnxjph ; save functions jump vector high byte + PLA ; pull byte parameter + TAX ; copy byte parameter to X + PLA ; pull string pointer low byte + STA des_2l ; save it + PLA ; pull string pointer high byte + STA des_2h ; save it + LDY #$00 ; clear index + TXA ; copy byte parameter + BEQ LAB_23A8 ; if null do function call error then warm start + + INC Fnxjpl ; increment function jump vector low byte + ; (JSR pushes return addr-1. this is all very nice + ; but will go tits up if either call is on a page + ; boundary!) + JMP (Fnxjpl) ; in effect, RTS + +; perform LCASE$() + +LAB_LCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +LC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_1D82 ; is character "A" to "Z" + BCC NoUcase ; branch if not upper case alpha + + ORA #$20 ; convert upper to lower case +NoUcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE LC_loop ; loop if not all done + + BEQ NoString ; tidy up and exit, branch always + +; perform UCASE$() + +LAB_UCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +UC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") + BCC NoLcase ; branch if not alpha + + AND #$DF ; convert lower to upper case +NoLcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE UC_loop ; loop if not all done + +NoString + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform SADD() + +LAB_SADD + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + LDY #$02 ; index to string pointer high byte + LDA (Cvaral),Y ; get string pointer high byte + TAX ; copy string pointer high byte to X + DEY ; index to string pointer low byte + LDA (Cvaral),Y ; get string pointer low byte + TAY ; copy string pointer low byte to Y + TXA ; copy string pointer high byte to A + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform LEN() + +LAB_LENS + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; evaluate string, get length in Y + +LAB_ESGL + JSR LAB_EVST ; evaluate string + TAY ; copy length to Y + RTS + +; perform ASC() + +LAB_ASC + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BEQ LAB_23A8 ; if null do function call error then warm start + + LDY #$00 ; set index to first character + LDA (ut1_pl),Y ; get byte + TAY ; copy to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; do function call error then warm start + +LAB_23A8 + JMP LAB_FCER ; do function call error then warm start + +; scan and get byte parameter + +LAB_SGBY + JSR LAB_IGBY ; increment and scan memory + +; get byte parameter + +LAB_GTBY + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate byte expression, result in X + +LAB_EVBY + JSR LAB_EVPI ; evaluate integer expression (no check) + + LDY FAC1_2 ; get FAC1 mantissa2 + BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start + + LDX FAC1_3 ; get FAC1 mantissa3 + JMP LAB_GBYT ; scan memory and return + +; perform VAL() + +LAB_VAL + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BNE LAB_23C5 ; branch if not null string + + ; string was null so set result = $00 + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +LAB_23C5 + LDX Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STX Btmpl ; save BASIC execute pointer low byte + STY Btmph ; save BASIC execute pointer high byte + LDX ut1_pl ; get string pointer low byte + STX Bpntrl ; save as BASIC execute pointer low byte + CLC ; clear carry + ADC ut1_pl ; add string length + STA ut2_pl ; save string end low byte + LDA ut1_ph ; get string pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + ADC #$00 ; add carry to high byte + STA ut2_ph ; save string end high byte + LDY #$00 ; set index to $00 + LDA (ut2_pl),Y ; get string end +1 byte + PHA ; push it + TYA ; clear A + STA (ut2_pl),Y ; terminate string with $00 + JSR LAB_GBYT ; scan memory + JSR LAB_2887 ; get FAC1 from string + PLA ; restore string end +1 byte + LDY #$00 ; set index to zero + STA (ut2_pl),Y ; put string end byte back + +; restore BASIC execute pointer from temp (Btmpl/Btmph) + +LAB_23F3 + LDX Btmpl ; get BASIC execute pointer low byte back + LDY Btmph ; get BASIC execute pointer high byte back + STX Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; get two parameters for POKE or WAIT + +LAB_GADB + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + +; scan for "," and get byte, else do Syntax error then warm start + +LAB_SCGB + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + LDA Itemph ; save temporary integer high byte + PHA ; on stack + LDA Itempl ; save temporary integer low byte + PHA ; on stack + JSR LAB_GTBY ; get byte parameter + PLA ; pull low byte + STA Itempl ; restore temporary integer low byte + PLA ; pull high byte + STA Itemph ; restore temporary integer high byte + RTS + +; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or +; -ve and converts it into a right truncated integer in Itempl and Itemph + +; save unsigned 16 bit integer part of FAC1 in temporary integer + +LAB_F2FX + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_23A8 ; if >= do function call error then warm start + +LAB_F2FU + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDA FAC1_2 ; get FAC1 mantissa2 + LDY FAC1_3 ; get FAC1 mantissa3 + STY Itempl ; save temporary integer low byte + STA Itemph ; save temporary integer high byte + RTS + +; perform PEEK() + +LAB_PEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; get byte via temporary integer (addr) + TAY ; copy byte to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; perform POKE + +LAB_POKE + JSR LAB_GADB ; get two parameters for POKE or WAIT + TXA ; copy byte argument to A + LDX #$00 ; clear index + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +; perform DEEK() + +LAB_DEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; PEEK low byte + TAY ; copy to Y + INC Itempl ; increment pointer low byte + BNE Deekh ; skip high increment if no rollover + + INC Itemph ; increment pointer high byte +Deekh + LDA (Itempl,X) ; PEEK high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform DOKE + +LAB_DOKE + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) + STA Frnxth ; save pointer high byte + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + TYA ; copy value low byte (float to fixed returns word in AY) + LDX #$00 ; clear index + STA (Frnxtl,X) ; POKE low byte + INC Frnxtl ; increment pointer low byte + BNE Dokeh ; skip high increment if no rollover + + INC Frnxth ; increment pointer high byte +Dokeh + LDA Itemph ; get value high byte + STA (Frnxtl,X) ; POKE high byte + JMP LAB_GBYT ; scan memory and return + +; perform SWAP + +LAB_SWAP + JSR LAB_GVAR ; get var1 address + STA Lvarpl ; save var1 address low byte + STY Lvarph ; save var1 address high byte + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; save data type flag + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) + PLA ; pull var1 data type flag + EOR Dtypef ; compare with var2 data type + BPL SwapErr ; exit if not both the same type + + LDY #$03 ; four bytes to swap (either value or descriptor+1) +SwapLp + LDA (Lvarpl),Y ; get byte from var1 + TAX ; save var1 byte + LDA (Cvaral),Y ; get byte from var2 + STA (Lvarpl),Y ; save byte to var1 + TXA ; restore var1 byte + STA (Cvaral),Y ; save byte to var2 + DEY ; decrement index + BPL SwapLp ; loop until done + + RTS + +SwapErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform CALL + +LAB_CALL + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + LDA #>CallExit ; set return address high byte + PHA ; put on stack + LDA #8 shifts) + BCC LAB_24A8 ;.go subtract mantissas + +; add 0.5 to FAC1 + +LAB_244E + LDA #LAB_2A96 ; set 0.5 pointer high byte + +; add (AY) to FAC1 + +LAB_246C + JSR LAB_264D ; unpack memory (AY) into FAC2 + +; add FAC2 to FAC1 + +LAB_ADD + BNE LAB_2474 ; branch if FAC1 was not zero + +; copy FAC2 to FAC1 + +LAB_279B + LDA FAC2_s ; get FAC2 sign (b7) + +; save FAC1 sign and copy ABS(FAC2) to FAC1 + +LAB_279D + STA FAC1_s ; save FAC1 sign (b7) + LDX #$04 ; 4 bytes to copy +LAB_27A1 + LDA FAC1_o,X ; get byte from FAC2,X + STA FAC1_e-1,X ; save byte at FAC1,X + DEX ; decrement count + BNE LAB_27A1 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte + RTS + + ; FAC1 is non zero +LAB_2474 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC2_r ; save as FAC2 rounding byte + LDX #FAC2_e ; set index to FAC2 exponent addr + LDA FAC2_e ; get FAC2 exponent +LAB_247C + TAY ; copy exponent + BEQ LAB_244D ; exit if zero + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BEQ LAB_24A8 ; branch if = (go add mantissa) + + BCC LAB_2498 ; branch if < + + ; FAC2>FAC1 + STY FAC1_e ; save FAC1 exponent + LDY FAC2_s ; get FAC2 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$FF ; complement A + ADC #$00 ; +1 (twos complement, carry is set) + LDY #$00 ; clear Y + STY FAC2_r ; clear FAC2 rounding byte + LDX #FAC1_e ; set index to FAC1 exponent addr + BNE LAB_249C ; branch always + +LAB_2498 + LDY #$00 ; clear Y + STY FAC1_r ; clear FAC1 rounding byte +LAB_249C + CMP #$F9 ; compare exponent diff with $F9 + BMI LAB_2467 ; branch if range $79-$F8 + + TAY ; copy exponent difference to Y + LDA FAC1_r ; get FAC1 rounding byte + LSR PLUS_1,X ; shift FAC? mantissa1 + JSR LAB_2592 ; shift FACX Y times right + + ; exponents are equal now do mantissa subtract +LAB_24A8 + BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) + BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return + + LDY #FAC1_e ; set index to FAC1 exponent addr + CPX #FAC2_e ; compare X to FAC2 exponent addr + BEQ LAB_24B4 ; branch if = + + LDY #FAC2_e ; else set index to FAC2 exponent addr + + ; subtract smaller from bigger (take sign of bigger) +LAB_24B4 + SEC ; set carry for subtract + EOR #$FF ; ones complement A + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA PLUS_3,Y ; get FACY mantissa3 + SBC PLUS_3,X ; subtract FACX mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA PLUS_2,Y ; get FACY mantissa2 + SBC PLUS_2,X ; subtract FACX mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA PLUS_1,Y ; get FACY mantissa1 + SBC PLUS_1,X ; subtract FACX mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + +; do ABS and normalise FAC1 + +LAB_24D0 + BCS LAB_24D5 ; branch if number is +ve + + JSR LAB_2537 ; negate FAC1 + +; normalise FAC1 + +LAB_24D5 + LDY #$00 ; clear Y + TYA ; clear A + CLC ; clear carry for add +LAB_24D9 + LDX FAC1_1 ; get FAC1 mantissa1 + BNE LAB_251B ; if not zero normalise FAC1 + + LDX FAC1_2 ; get FAC1 mantissa2 + STX FAC1_1 ; save FAC1 mantissa1 + LDX FAC1_3 ; get FAC1 mantissa3 + STX FAC1_2 ; save FAC1 mantissa2 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC1_3 ; save FAC1 mantissa3 + STY FAC1_r ; clear FAC1 rounding byte + ADC #$08 ; add x to exponent offset + CMP #$18 ; compare with $18 (max offset, all bits would be =0) + BNE LAB_24D9 ; loop if not max + +; clear FAC1 exponent and sign + +LAB_24F1 + LDA #$00 ; clear A +LAB_24F3 + STA FAC1_e ; set FAC1 exponent + +; save FAC1 sign + +LAB_24F5 + STA FAC1_s ; save FAC1 sign (b7) + RTS + +; add FAC2 mantissa to FAC1 mantissa + +LAB_24F8 + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA FAC1_3 ; get FAC1 mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + BCS LAB_252A ; if carry then normalise FAC1 for C=1 + + RTS ; else just exit + +LAB_2511 + ADC #$01 ; add 1 to exponent offset + ASL FAC1_r ; shift FAC1 rounding byte + ROL FAC1_3 ; shift FAC1 mantissa3 + ROL FAC1_2 ; shift FAC1 mantissa2 + ROL FAC1_1 ; shift FAC1 mantissa1 + +; normalise FAC1 + +LAB_251B + BPL LAB_2511 ; loop if not normalised + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BCS LAB_24F1 ; branch if underflow (set result = $0) + + EOR #$FF ; complement exponent + ADC #$01 ; +1 (twos complement) + STA FAC1_e ; save FAC1 exponent + +; test and normalise FAC1 for C=0/1 + +LAB_2528 + BCC LAB_2536 ; exit if no overflow + +; normalise FAC1 for C=1 + +LAB_252A + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_2564 ; if zero do overflow error and warm start + + ROR FAC1_1 ; shift FAC1 mantissa1 + ROR FAC1_2 ; shift FAC1 mantissa2 + ROR FAC1_3 ; shift FAC1 mantissa3 + ROR FAC1_r ; shift FAC1 rounding byte +LAB_2536 + RTS + +; negate FAC1 + +LAB_2537 + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) + +; twos complement FAC1 mantissa + +LAB_253D + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + STA FAC1_1 ; save FAC1 mantissa1 + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; complement it + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; complement it + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + EOR #$FF ; complement it + STA FAC1_r ; save FAC1 rounding byte + INC FAC1_r ; increment FAC1 rounding byte + BNE LAB_2563 ; exit if no overflow + +; increment FAC1 mantissa + +LAB_2559 + INC FAC1_3 ; increment FAC1 mantissa3 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_2 ; increment FAC1 mantissa2 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_1 ; increment FAC1 mantissa1 +LAB_2563 + RTS + +; do overflow error (overflow exit) + +LAB_2564 + LDX #$0A ; error code $0A ("Overflow" error) + JMP LAB_XERR ; do error #X, then warm start + +; shift FCAtemp << A+8 times + +LAB_2569 + LDX #FACt_1-1 ; set offset to FACtemp +LAB_256B + LDY PLUS_3,X ; get FACX mantissa3 + STY FAC1_r ; save as FAC1 rounding byte + LDY PLUS_2,X ; get FACX mantissa2 + STY PLUS_3,X ; save FACX mantissa3 + LDY PLUS_1,X ; get FACX mantissa1 + STY PLUS_2,X ; save FACX mantissa2 + LDY FAC1_o ; get FAC1 overflow byte + STY PLUS_1,X ; save FACX mantissa1 + +; shift FACX -A times right (> 8 shifts) + +LAB_257B + ADC #$08 ; add 8 to shift count + BMI LAB_256B ; go do 8 shift if still -ve + + BEQ LAB_256B ; go do 8 shift if zero + + SBC #$08 ; else subtract 8 again + TAY ; save count to Y + LDA FAC1_r ; get FAC1 rounding byte + BCS LAB_259A ;. + +LAB_2588 + ASL PLUS_1,X ; shift FACX mantissa1 + BCC LAB_258E ; branch if +ve + + INC PLUS_1,X ; this sets b7 eventually +LAB_258E + ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) + ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) + +; shift FACX Y times right + +LAB_2592 + ROR PLUS_2,X ; shift FACX mantissa2 + ROR PLUS_3,X ; shift FACX mantissa3 + ROR ; shift FACX rounding byte + INY ; increment exponent diff + BNE LAB_2588 ; branch if range adjust not complete + +LAB_259A + CLC ; just clear it + RTS + +; perform LOG() + +LAB_LOG + JSR LAB_27CA ; test sign and zero + BEQ LAB_25C4 ; if zero do function call error then warm start + + BPL LAB_25C7 ; skip error if +ve + +LAB_25C4 + JMP LAB_FCER ; do function call error then warm start (-ve) + +LAB_25C7 + LDA FAC1_e ; get FAC1 exponent + SBC #$7F ; normalise it + PHA ; save it + LDA #$80 ; set exponent to zero + STA FAC1_e ; save FAC1 exponent + LDA #LAB_25AD ; set 1/root2 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 (1/root2) + LDA #LAB_25B1 ; set root2 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) + LDA #LAB_25A0 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + LDA #LAB_25B5 ; set -0.5 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 exponent + JSR LAB_2912 ; evaluate new ASCII digit + LDA #LAB_25B9 ; set LOG(2) pointer high byte + +; do convert AY, FCA1*(AY) + +LAB_25FB + JSR LAB_264D ; unpack memory (AY) into FAC2 +LAB_MULTIPLY + BEQ LAB_264C ; exit if zero + + JSR LAB_2673 ; test and adjust accumulators + LDA #$00 ; clear A + STA FACt_1 ; clear temp mantissa1 + STA FACt_2 ; clear temp mantissa2 + STA FACt_3 ; clear temp mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_3 ; get FAC1 mantissa3 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_2 ; get FAC1 mantissa2 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_1 ; get FAC1 mantissa1 + JSR LAB_2627 ; go do shift/add FAC2 + JMP LAB_273C ; copy temp to FAC1, normalise and return + +LAB_2622 + BNE LAB_2627 ; branch if byte <> zero + + JMP LAB_2569 ; shift FCAtemp << A+8 times + + ; else do shift and add +LAB_2627 + LSR ; shift byte + ORA #$80 ; set top bit (mark for 8 times) +LAB_262A + TAY ; copy result + BCC LAB_2640 ; skip next if bit was zero + + CLC ; clear carry for add + LDA FACt_3 ; get temp mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FACt_3 ; save temp mantissa3 + LDA FACt_2 ; get temp mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FACt_2 ; save temp mantissa2 + LDA FACt_1 ; get temp mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FACt_1 ; save temp mantissa1 +LAB_2640 + ROR FACt_1 ; shift temp mantissa1 + ROR FACt_2 ; shift temp mantissa2 + ROR FACt_3 ; shift temp mantissa3 + ROR FAC1_r ; shift temp rounding byte + TYA ; get byte back + LSR ; shift byte + BNE LAB_262A ; loop if all bits not done + +LAB_264C + RTS + +; unpack memory (AY) into FAC2 + +LAB_264D + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to get (0-3) + LDA (ut1_pl),Y ; get mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa1+sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDA FAC2_s ; recover FAC2 sign (b7) + ORA #$80 ; set 1xxx xxx (set normal bit) + STA FAC2_1 ; save FAC2 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get exponent byte + STA FAC2_e ; save FAC2 exponent + LDA FAC1_e ; get FAC1 exponent + RTS + +; test and adjust accumulators + +LAB_2673 + LDA FAC2_e ; get FAC2 exponent +LAB_2675 + BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) + + CLC ; clear carry for add + ADC FAC1_e ; add FAC1 exponent + BCC LAB_2680 ; branch if sum of exponents <$0100 + + BMI LAB_269B ; do overflow error + + CLC ; clear carry for the add + .byte $2C ; makes next line BIT $1410 +LAB_2680 + BPL LAB_2696 ; if +ve go handle underflow + + ADC #$80 ; adjust exponent + STA FAC1_e ; save FAC1 exponent + BNE LAB_268B ; branch if not zero + + JMP LAB_24F5 ; save FAC1 sign and return + +LAB_268B + LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) + STA FAC1_s ; save FAC1 sign (b7) +LAB_268F + RTS + +; handle overflow and underflow + +LAB_2690 + LDA FAC1_s ; get FAC1 sign (b7) + BPL LAB_269B ; do overflow error + + ; handle underflow +LAB_2696 + PLA ; pop return address low byte + PLA ; pop return address high byte + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +; multiply by 10 + +LAB_269E + JSR LAB_27AB ; round and copy FAC1 to FAC2 + TAX ; copy exponent (set the flags) + BEQ LAB_268F ; exit if zero + + CLC ; clear carry for add + ADC #$02 ; add two to exponent (*4) + BCS LAB_269B ; do overflow error if > $FF + + LDX #$00 ; clear byte + STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_247C ; add FAC2 to FAC1 (*5) + INC FAC1_e ; increment FAC1 exponent (*10) + BNE LAB_268F ; if non zero just do RTS + +LAB_269B + JMP LAB_2564 ; do overflow error and warm start + +; divide by 10 + +LAB_26B9 + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_26B5 ; set pointer to 10d high addr + LDX #$00 ; clear sign + +; divide by (AY) (X=sign) + +LAB_26C2 + STX FAC_sc ; save sign compare (FAC1 EOR FAC2) + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JMP LAB_DIVIDE ; do FAC2/FAC1 + + ; Perform divide-by +; convert AY and do (AY)/FAC1 + +LAB_26CA + JSR LAB_264D ; unpack memory (AY) into FAC2 + + ; Perform divide-into +LAB_DIVIDE + BEQ LAB_2737 ; if zero go do /0 error + + JSR LAB_27BA ; round FAC1 + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent (2s complement) + STA FAC1_e ; save FAC1 exponent + JSR LAB_2673 ; test and adjust accumulators + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_269B ; if zero do overflow error + + LDX #$FF ; set index for pre increment + LDA #$01 ; set bit to flag byte save +LAB_26E4 + LDY FAC2_1 ; get FAC2 mantissa1 + CPY FAC1_1 ; compare FAC1 mantissa1 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_2 ; get FAC2 mantissa2 + CPY FAC1_2 ; compare FAC1 mantissa2 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_3 ; get FAC2 mantissa3 + CPY FAC1_3 ; compare FAC1 mantissa3 +LAB_26F4 + PHP ; save FAC2-FAC1 compare status + ROL ; shift the result byte + BCC LAB_2702 ; if no carry skip the byte save + + LDY #$01 ; set bit to flag byte save + INX ; else increment the index to FACt + CPX #$02 ; compare with the index to FACt_3 + BMI LAB_2701 ; if not last byte just go save it + + BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and + ; return + + LDY #$40 ; set bit to flag byte save for the rounding byte +LAB_2701 + STA FACt_1,X ; write result byte to FACt_1 + index + TYA ; copy the next save byte flag +LAB_2702 + PLP ; restore FAC2-FAC1 compare status + BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract + + TAY ; save FAC2-FAC1 compare status + LDA FAC2_3 ; get FAC2 mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + LDA FAC2_2 ; get FAC2 mantissa2 + SBC FAC1_2 ; subtract FAC1 mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + LDA FAC2_1 ; get FAC2 mantissa1 + SBC FAC1_1 ; subtract FAC1 mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + TYA ; restore FAC2-FAC1 compare status + + ; FAC2 = FAC2*2 +LAB_2704 + ASL FAC2_3 ; shift FAC2 mantissa3 + ROL FAC2_2 ; shift FAC2 mantissa2 + ROL FAC2_1 ; shift FAC2 mantissa1 + BCS LAB_26F4 ; loop with no compare + + BMI LAB_26E4 ; loop with compare + + BPL LAB_26F4 ; loop always with no compare + +; do A<<6, save as FAC1 rounding byte, normalise and return + +LAB_272B + LSR ; shift b1 - b0 .. + ROR ; .. + ROR ; .. to b7 - b6 + STA FAC1_r ; save FAC1 rounding byte + PLP ; dump FAC2-FAC1 compare status + JMP LAB_273C ; copy temp to FAC1, normalise and return + +; do "Divide by zero" error + +LAB_2737 + LDX #$14 ; error code $14 ("Divide by zero" error) + JMP LAB_XERR ; do error #X, then warm start + +; copy temp to FAC1 and normalise + +LAB_273C + LDA FACt_1 ; get temp mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + LDA FACt_2 ; get temp mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FACt_3 ; get temp mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + JMP LAB_24D5 ; normalise FAC1 and return + +; unpack memory (AY) into FAC1 + +LAB_UFAC + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to do + LDA (ut1_pl),Y ; get last byte + STA FAC1_3 ; save FAC1 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get last-1 byte + STA FAC1_2 ; save FAC1 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get second byte + STA FAC1_s ; save FAC1 sign (b7) + ORA #$80 ; set 1xxx xxxx (add normal bit) + STA FAC1_1 ; save FAC1 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get first byte (exponent) + STA FAC1_e ; save FAC1 exponent + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; pack FAC1 into Adatal + +LAB_276E + LDX #Adatal ; set pointer high byte + BEQ LAB_2778 ; pack FAC1 into (XY) and return + +; pack FAC1 into (Lvarpl) + +LAB_PFAC + LDX Lvarpl ; get destination pointer low byte + LDY Lvarph ; get destination pointer high byte + +; pack FAC1 into (XY) + +LAB_2778 + JSR LAB_27BA ; round FAC1 + STX ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; set index + LDA FAC1_3 ; get FAC1 mantissa3 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_2 ; get FAC1 mantissa2 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_s ; get FAC1 sign (b7) + ORA #$7F ; set bits x111 1111 + AND FAC1_1 ; AND in FAC1 mantissa1 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_e ; get FAC1 exponent + STA (ut1_pl),Y ; store in destination + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; round and copy FAC1 to FAC2 + +LAB_27AB + JSR LAB_27BA ; round FAC1 + +; copy FAC1 to FAC2 + +LAB_27AE + LDX #$05 ; 5 bytes to copy +LAB_27B0 + LDA FAC1_e-1,X ; get byte from FAC1,X + STA FAC1_o,X ; save byte at FAC2,X + DEX ; decrement count + BNE LAB_27B0 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte +LAB_27B9 + RTS + +; round FAC1 + +LAB_27BA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27B9 ; exit if zero + + ASL FAC1_r ; shift FAC1 rounding byte + BCC LAB_27B9 ; exit if no overflow + +; round FAC1 (no check) + +LAB_27C2 + JSR LAB_2559 ; increment FAC1 mantissa + BNE LAB_27B9 ; branch if no overflow + + JMP LAB_252A ; normalise FAC1 for C=1 and return + +; get FAC1 sign +; return A=FF,C=1/-ve A=01,C=0/+ve + +LAB_27CA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check + +LAB_27CE + LDA FAC1_s ; else get FAC1 sign (b7) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check, sign in A + +LAB_27D0 + ROL ; move sign bit to carry + LDA #$FF ; set byte for -ve result + BCS LAB_27D7 ; return if sign was set (-ve) + + LDA #$01 ; else set byte for +ve result +LAB_27D7 + RTS + +; perform SGN() + +LAB_SGN + JSR LAB_27CA ; get FAC1 sign + ; return A=$FF/-ve A=$01/+ve +; save A as integer byte + +LAB_27DB + STA FAC1_1 ; save FAC1 mantissa1 + LDA #$00 ; clear A + STA FAC1_2 ; clear FAC1 mantissa2 + LDX #$88 ; set exponent + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_27E3 + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + ROL ; sign bit into carry + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_STFA + LDA #$00 ; clear A + STA FAC1_3 ; clear FAC1 mantissa3 + STX FAC1_e ; set FAC1 exponent + STA FAC1_r ; clear FAC1 rounding byte + STA FAC1_s ; clear FAC1 sign (b7) + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; perform ABS() + +LAB_ABS + LSR FAC1_s ; clear FAC1 sign (put zero in b7) + RTS + +; compare FAC1 with (AY) +; returns A=$00 if FAC1 = (AY) +; returns A=$01 if FAC1 > (AY) +; returns A=$FF if FAC1 < (AY) + +LAB_27F8 + STA ut2_pl ; save pointer low byte +LAB_27FA + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear index + LDA (ut2_pl),Y ; get exponent + INY ; increment index + TAX ; copy (AY) exponent to X + BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign + ; A=FF,C=1/-ve A=01,C=0/+ve + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + EOR FAC1_s ; EOR FAC1 sign (b7) + BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve + ; A=01,C=0/+ve and return + + CPX FAC1_e ; compare (AY) exponent with FAC1 exponent + BNE LAB_2828 ; branch if different + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + ORA #$80 ; normalise top bit + CMP FAC1_1 ; compare with FAC1 mantissa1 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA (ut2_pl),Y ; get mantissa2 + CMP FAC1_2 ; compare with FAC1 mantissa2 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA #$7F ; set for 1/2 value rounding byte + CMP FAC1_r ; compare with FAC1 rounding byte (set carry) + LDA (ut2_pl),Y ; get mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + BEQ LAB_2850 ; exit if mantissa3 equal + +; gets here if number <> FAC1 + +LAB_2828 + LDA FAC1_s ; get FAC1 sign (b7) + BCC LAB_282E ; branch if FAC1 > (AY) + + EOR #$FF ; else toggle FAC1 sign +LAB_282E + JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve + +; convert FAC1 floating-to-fixed + +LAB_2831 + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_287F ; if zero go clear FAC1 and return + + SEC ; set carry for subtract + SBC #$98 ; subtract maximum integer range exponent + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2845 ; branch if FAC1 +ve + + ; FAC1 was -ve + TAX ; copy subtracted exponent + LDA #$FF ; overflow for -ve number + STA FAC1_o ; set FAC1 overflow byte + JSR LAB_253D ; twos complement FAC1 mantissa + TXA ; restore subtracted exponent +LAB_2845 + LDX #FAC1_e ; set index to FAC1 + CMP #$F9 ; compare exponent result + BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return + + JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) + STY FAC1_o ; clear FAC1 overflow byte +LAB_2850 + RTS + +; shift FAC1 A times right + +LAB_2851 + TAY ; copy shift count + LDA FAC1_s ; get FAC1 sign (b7) + AND #$80 ; mask sign bit only (x000 0000) + LSR FAC1_1 ; shift FAC1 mantissa1 + ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + JSR LAB_2592 ; shift FAC1 Y times right + STY FAC1_o ; clear FAC1 overflow byte + RTS + +; perform INT() + +LAB_INT + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with max int + BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + STY FAC1_r ; save FAC1 rounding byte + LDA FAC1_s ; get FAC1 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$80 ; toggle FAC1 sign + ROL ; shift into carry + LDA #$98 ; set new exponent + STA FAC1_e ; save FAC1 exponent + LDA FAC1_3 ; get FAC1 mantissa3 + STA Temp3 ; save for EXP() function + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; clear FAC1 and return + +LAB_287F + STA FAC1_1 ; clear FAC1 mantissa1 + STA FAC1_2 ; clear FAC1 mantissa2 + STA FAC1_3 ; clear FAC1 mantissa3 + TAY ; clear Y +LAB_2886 + RTS + +; get FAC1 from string +; this routine now handles hex and binary values from strings +; starting with "$" and "%" respectively + +LAB_2887 + LDY #$00 ; clear Y + STY Dtypef ; clear data type flag, $FF=string, $00=numeric + LDX #$09 ; set index +LAB_288B + STY numexp,X ; clear byte + DEX ; decrement index + BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 + + BCC LAB_28FE ; branch if 1st character numeric + +; get FAC1 from string .. first character wasn't numeric + + CMP #'-' ; else compare with "-" + BNE LAB_289A ; branch if not "-" + + STX negnum ; set flag for -ve number (X = $FF) + BEQ LAB_289C ; branch always (go scan and check for hex/bin) + +; get FAC1 from string .. first character wasn't numeric or - + +LAB_289A + CMP #'+' ; else compare with "+" + BNE LAB_289D ; branch if not "+" (go check for hex/bin) + +; was "+" or "-" to start, so get next character + +LAB_289C + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28FE ; branch if numeric character + +; code here for hex and binary numbers + +LAB_289D + CMP #'$' ; else compare with "$" + BNE LAB_NHEX ; branch if not "$" + + JMP LAB_CHEX ; branch if "$" + +LAB_NHEX + CMP #'%' ; else compare with "%" + BNE LAB_28A3 ; branch if not "%" (continue original code) + + JMP LAB_CBIN ; branch if "%" + +LAB_289E + JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) +LAB_28A1 + BCC LAB_28FE ; branch if numeric character + +; get FAC1 from string .. character wasn't numeric, -, +, hex or binary + +LAB_28A3 + CMP #'.' ; else compare with "." + BEQ LAB_28D5 ; branch if "." + +; get FAC1 from string .. character wasn't numeric, -, + or . + + CMP #'E' ; else compare with "E" + BNE LAB_28DB ; branch if not "E" + + ; was "E" so evaluate exponential part + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28C7 ; branch if numeric character + + CMP #TK_MINUS ; else compare with token for - + BEQ LAB_28C2 ; branch if token for - + + CMP #'-' ; else compare with "-" + BEQ LAB_28C2 ; branch if "-" + + CMP #TK_PLUS ; else compare with token for + + BEQ LAB_28C4 ; branch if token for + + + CMP #'+' ; else compare with "+" + BEQ LAB_28C4 ; branch if "+" + + BNE LAB_28C9 ; branch always + +LAB_28C2 + ROR expneg ; set exponent -ve flag (C, which=1, into b7) +LAB_28C4 + JSR LAB_IGBY ; increment and scan memory +LAB_28C7 + BCC LAB_2925 ; branch if numeric character + +LAB_28C9 + BIT expneg ; test exponent -ve flag + BPL LAB_28DB ; if +ve go evaluate exponent + + ; else do exponent = -exponent + LDA #$00 ; clear result + SEC ; set carry for subtract + SBC expcnt ; subtract exponent byte + JMP LAB_28DD ; go evaluate exponent + +LAB_28D5 + ROR numdpf ; set decimal point flag + BIT numdpf ; test decimal point flag + BVC LAB_289E ; branch if only one decimal point so far + + ; evaluate exponent +LAB_28DB + LDA expcnt ; get exponent count byte +LAB_28DD + SEC ; set carry for subtract + SBC numexp ; subtract numerator exponent + STA expcnt ; save exponent count byte + BEQ LAB_28F6 ; branch if no adjustment + + BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt + + ; else go do FAC1/10^(0-expcnt) +LAB_28E6 + JSR LAB_26B9 ; divide by 10 + INC expcnt ; increment exponent count byte + BNE LAB_28E6 ; loop until all done + + BEQ LAB_28F6 ; branch always + +LAB_28EF + JSR LAB_269E ; multiply by 10 + DEC expcnt ; decrement exponent count byte + BNE LAB_28EF ; loop until all done + +LAB_28F6 + LDA negnum ; get -ve flag + BMI LAB_28FB ; if -ve do - FAC1 and return + + RTS + +; do - FAC1 and return + +LAB_28FB + JMP LAB_GTHAN ; do - FAC1 and return + +; do unsigned FAC1*10+number + +LAB_28FE + PHA ; save character + BIT numdpf ; test decimal point flag + BPL LAB_2905 ; skip exponent increment if not set + + INC numexp ; else increment number exponent +LAB_2905 + JSR LAB_269E ; multiply FAC1 by 10 + PLA ; restore character + AND #$0F ; convert to binary + JSR LAB_2912 ; evaluate new ASCII digit + JMP LAB_289E ; go do next character + +; evaluate new ASCII digit + +LAB_2912 + PHA ; save digit + JSR LAB_27AB ; round and copy FAC1 to FAC2 + PLA ; restore digit + JSR LAB_27DB ; save A as integer byte + LDA FAC2_s ; get FAC2 sign (b7) + EOR FAC1_s ; toggle with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDX FAC1_e ; get FAC1 exponent + JMP LAB_ADD ; add FAC2 to FAC1 and return + +; evaluate next character of exponential part of number + +LAB_2925 + LDA expcnt ; get exponent count byte + CMP #$0A ; compare with 10 decimal + BCC LAB_2934 ; branch if less + + LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) + BIT expneg ; test exponent -ve flag + BMI LAB_2942 ; branch if -ve + + JMP LAB_2564 ; else do overflow error + +LAB_2934 + ASL ; * 2 + ASL ; * 4 + ADC expcnt ; * 5 + ASL ; * 10 + LDY #$00 ; set index + ADC (Bpntrl),Y ; add character (will be $30 too much!) + SBC #'0'-1 ; convert character to binary +LAB_2942 + STA expcnt ; save exponent count byte + JMP LAB_28C4 ; go get next character + +; print " in line [LINE #]" + +LAB_2953 + LDA #LAB_LMSG ; point to " in line " message high byte + JSR LAB_18C3 ; print null terminated string from memory + + ; print Basic line # + LDA Clineh ; get current line high byte + LDX Clinel ; get current line low byte + +; print XA as unsigned integer + +LAB_295E + STA FAC1_1 ; save low byte as FAC1 mantissa1 + STX FAC1_2 ; save high byte as FAC1 mantissa2 + LDX #$90 ; set exponent to 16d bits + SEC ; set integer is +ve flag + JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise + LDY #$00 ; clear index + TYA ; clear A + JSR LAB_297B ; convert FAC1 to string, skip sign character save + JMP LAB_18C3 ; print null terminated string from memory and return + +; convert FAC1 to ASCII string result in (AY) +; not any more, moved scratchpad to page 0 + +LAB_296E + LDY #$01 ; set index = 1 + LDA #$20 ; character = " " (assume +ve) + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2978 ; branch if +ve + + LDA #$2D ; else character = "-" +LAB_2978 + STA Decss,Y ; save leading character (" " or "-") +LAB_297B + STA FAC1_s ; clear FAC1 sign (b7) + STY Sendl ; save index + INY ; increment index + LDX FAC1_e ; get FAC1 exponent + BNE LAB_2989 ; branch if FAC1<>0 + + ; exponent was $00 so FAC1 is 0 + LDA #'0' ; set character = "0" + JMP LAB_2A89 ; save last character, [EOT] and exit + + ; FAC1 is some non zero value +LAB_2989 + LDA #$00 ; clear (number exponent count) + CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) + + BCS LAB_299A ; branch if FAC1=>1 + + ; FAC1<1 + LDA #LAB_294F ; set pointer high byte to 1,000,000 + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA #$FA ; set number exponent count (-6) +LAB_299A + STA numexp ; save number exponent count +LAB_299C + LDA #LAB_294B ; set pointer high byte to 999999.4375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29C3 ; exit if FAC1 = (AY) + + BPL LAB_29B9 ; go do /10 if FAC1 > (AY) + + ; FAC1 < (AY) +LAB_29A7 + LDA #LAB_2947 ; set pointer high byte to 99999.9375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) + + BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) + + ; FAC1 <= (AY) +LAB_29B2 + JSR LAB_269E ; multiply by 10 + DEC numexp ; decrement number exponent count + BNE LAB_29A7 ; go test again (branch always) + +LAB_29B9 + JSR LAB_26B9 ; divide by 10 + INC numexp ; increment number exponent count + BNE LAB_299C ; go test again (branch always) + +; now we have just the digits to do + +LAB_29C0 + JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) +LAB_29C3 + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$01 ; set default digits before dp = 1 + LDA numexp ; get number exponent count + CLC ; clear carry for add + ADC #$07 ; up to 6 digits before point + BMI LAB_29D8 ; if -ve then 1 digit before dp + + CMP #$08 ; A>=8 if n>=1E6 + BCS LAB_29D9 ; branch if >= $08 + + ; carry is clear + ADC #$FF ; take 1 from digit count + TAX ; copy to A + LDA #$02 ;.set exponent adjust +LAB_29D8 + SEC ; set carry for subtract +LAB_29D9 + SBC #$02 ; -2 + STA expcnt ;.save exponent adjust + STX numexp ; save digits before dp count + TXA ; copy to A + BEQ LAB_29E4 ; branch if no digits before dp + + BPL LAB_29F7 ; branch if digits before dp + +LAB_29E4 + LDY Sendl ; get output string index + LDA #$2E ; character "." + INY ; increment index + STA Decss,Y ; save to output string + TXA ;. + BEQ LAB_29F5 ;. + + LDA #'0' ; character "0" + INY ; increment index + STA Decss,Y ; save to output string +LAB_29F5 + STY Sendl ; save output string index +LAB_29F7 + LDY #$00 ; clear index (point to 100,000) + LDX #$80 ; +LAB_29FB + LDA FAC1_3 ; get FAC1 mantissa3 + CLC ; clear carry for add + ADC LAB_2A9C,Y ; add -ve LSB + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC LAB_2A9B,Y ; add -ve NMSB + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC LAB_2A9A,Y ; add -ve MSB + STA FAC1_1 ; save FAC1 mantissa1 + INX ; + BCS LAB_2A18 ; + + BPL LAB_29FB ; not -ve so try again + + BMI LAB_2A1A ; + +LAB_2A18 + BMI LAB_29FB ; + +LAB_2A1A + TXA ; + BCC LAB_2A21 ; + + EOR #$FF ; + ADC #$0A ; +LAB_2A21 + ADC #'0'-1 ; add "0"-1 to result + INY ; increment index .. + INY ; .. to next less .. + INY ; .. power of ten + STY Cvaral ; save as current var address low byte + LDY Sendl ; get output string index + INY ; increment output string index + TAX ; copy character to X + AND #$7F ; mask out top bit + STA Decss,Y ; save to output string + DEC numexp ; decrement # of characters before the dp + BNE LAB_2A3B ; branch if still characters to do + + ; else output the point + LDA #$2E ; character "." + INY ; increment output string index + STA Decss,Y ; save to output string +LAB_2A3B + STY Sendl ; save output string index + LDY Cvaral ; get current var address low byte + TXA ; get character back + EOR #$FF ; + AND #$80 ; + TAX ; + CPY #$12 ; compare index with max + BNE LAB_29FB ; loop if not max + + ; now remove trailing zeroes + LDY Sendl ; get output string index +LAB_2A4B + LDA Decss,Y ; get character from output string + DEY ; decrement output string index + CMP #'0' ; compare with "0" + BEQ LAB_2A4B ; loop until non "0" character found + + CMP #'.' ; compare with "." + BEQ LAB_2A58 ; branch if was dp + + ; restore last character + INY ; increment output string index +LAB_2A58 + LDA #$2B ; character "+" + LDX expcnt ; get exponent count + BEQ LAB_2A8C ; if zero go set null terminator and exit + + ; exponent isn't zero so write exponent + BPL LAB_2A68 ; branch if exponent count +ve + + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) + TAX ; copy exponent count to X + LDA #'-' ; character "-" +LAB_2A68 + STA Decss+2,Y ; save to output string + LDA #$45 ; character "E" + STA Decss+1,Y ; save exponent sign to output string + TXA ; get exponent count back + LDX #'0'-1 ; one less than "0" character + SEC ; set carry for subtract +LAB_2A74 + INX ; increment 10's character + SBC #$0A ;.subtract 10 from exponent count + BCS LAB_2A74 ; loop while still >= 0 + + ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) + STA Decss+4,Y ; save to output string + TXA ; copy 10's character + STA Decss+3,Y ; save to output string + LDA #$00 ; set null terminator + STA Decss+5,Y ; save to output string + BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) + + ; save last character, [EOT] and exit +LAB_2A89 + STA Decss,Y ; save last character to output string + + ; set null terminator and exit +LAB_2A8C + LDA #$00 ; set null terminator + STA Decss+1,Y ; save after last character + + ; set string pointer (AY) and exit +LAB_2A91 + LDA #Decssp1 ; set result string high pointer + RTS + +; perform power function + +LAB_POWER + BEQ LAB_EXP ; go do EXP() + + LDA FAC2_e ; get FAC2 exponent + BNE LAB_2ABF ; branch if FAC2<>0 + + JMP LAB_24F3 ; clear FAC1 exponent and sign and return + +LAB_2ABF + LDX #func_l ; set destination pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA FAC2_s ; get FAC2 sign (b7) + BPL LAB_2AD9 ; branch if FAC2>0 + + ; else FAC2 is -ve and can only be raised to an + ; integer power which gives an x +j0 result + JSR LAB_INT ; perform INT + LDA #func_l ; set source pointer high byte + JSR LAB_27F8 ; compare FAC1 with (AY) + BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error + ; this will leave FAC1 -ve and cause a Function Call + ; error when LOG() is called + + TYA ; clear sign b7 + LDY Temp3 ; save mantissa 3 from INT() function as sign in Y + ; for possible later negation, b0 +LAB_2AD9 + JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 + TYA ; copy sign back .. + PHA ; .. and save it + JSR LAB_LOG ; do LOG(n) + LDA #garb_l ; set pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) + JSR LAB_EXP ; go do EXP(n) + PLA ; pull sign from stack + LSR ; b0 is to be tested, shift to Cb + BCC LAB_2AF9 ; if no bit then exit + + ; Perform negation +; do - FAC1 + +LAB_GTHAN + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_2AF9 ; exit if FAC1_e = $00 + + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) +LAB_2AF9 + RTS + +; perform EXP() (x^e) + +LAB_EXP + LDA #LAB_2AFA ; set 1.443 pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA FAC1_r ; get FAC1 rounding byte + ADC #$50 ; +$50/$100 + BCC LAB_2B2B ; skip rounding if no carry + + JSR LAB_27C2 ; round FAC1 (no check) +LAB_2B2B + STA FAC2_r ; save FAC2 rounding byte + JSR LAB_27AE ; copy FAC1 to FAC2 + LDA FAC1_e ; get FAC1 exponent + CMP #$88 ; compare with EXP limit (256d) + BCC LAB_2B39 ; branch if less + +LAB_2B36 + JSR LAB_2690 ; handle overflow and underflow +LAB_2B39 + JSR LAB_INT ; perform INT + LDA Temp3 ; get mantissa 3 from INT() function + CLC ; clear carry for add + ADC #$81 ; normalise +1 + BEQ LAB_2B36 ; if $00 go handle overflow + + SEC ; set carry for subtract + SBC #$01 ; now correct for exponent + PHA ; save FAC2 exponent + + ; swap FAC1 and FAC2 + LDX #$04 ; 4 bytes to do +LAB_2B49 + LDA FAC2_e,X ; get FAC2,X + LDY FAC1_e,X ; get FAC1,X + STA FAC1_e,X ; save FAC1,X + STY FAC2_e,X ; save FAC2,X + DEX ; decrement count/index + BPL LAB_2B49 ; loop if not all done + + LDA FAC2_r ; get FAC2 rounding byte + STA FAC1_r ; save as FAC1 rounding byte + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + JSR LAB_GTHAN ; do - FAC1 + LDA #LAB_2AFE ; set counter pointer high byte + JSR LAB_2B84 ; go do series evaluation + LDA #$00 ; clear A + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + PLA ;.get saved FAC2 exponent + JMP LAB_2675 ; test and adjust accumulators and return + +; ^2 then series evaluation + +LAB_2B6E + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte + JSR LAB_276E ; pack FAC1 into Adatal + LDA #Adatal ; pointer to original # high byte + JMP LAB_25FB ; do convert AY, FCA1*(AY) and return + +; series evaluation + +LAB_2B84 + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte +LAB_2B88 + LDX #numexp ; set pointer high byte to partial @ numexp + DEC numcon ; decrement constants count + BNE LAB_2B9B ; loop until all done + + RTS + +; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 +; to get 19th next number in sequence after seed n. This version of the PRNG uses +; the Galois method and a sample of 65536 bytes produced gives the following values. + +; Entropy = 7.997442 bits per byte +; Optimum compression would reduce these 65536 bytes by 0 percent + +; Chi square distribution for 65536 samples is 232.01, and +; randomly would exceed this value 75.00 percent of the time + +; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random +; Monte Carlo value for Pi is 3.122871269, error 0.60 percent +; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 + +LAB_RND + LDA FAC1_e ; get FAC1 exponent + BEQ NextPRN ; do next random # if zero + + ; else get seed into random number store + LDX #Rbyte4 ; set PRNG pointer low byte + LDY #$00 ; set PRNG pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) +NextPRN + LDX #$AF ; set EOR byte + LDY #$13 ; do this nineteen times +LoopPRN + ASL Rbyte1 ; shift PRNG most significant byte + ROL Rbyte2 ; shift PRNG middle byte + ROL Rbyte3 ; shift PRNG least significant byte + ROL Rbyte4 ; shift PRNG extra byte + BCC Ninc1 ; branch if bit 32 clear + + TXA ; set EOR byte + EOR Rbyte1 ; EOR PRNG extra byte + STA Rbyte1 ; save new PRNG extra byte +Ninc1 + DEY ; decrement loop count + BNE LoopPRN ; loop if not all done + + LDX #$02 ; three bytes to copy +CopyPRNG + LDA Rbyte1,X ; get PRNG byte + STA FAC1_1,X ; save FAC1 byte + DEX + BPL CopyPRNG ; loop if not complete + + LDA #$80 ; set the exponent + STA FAC1_e ; save FAC1 exponent + + ASL ; clear A + STA FAC1_s ; save FAC1 sign + + JMP LAB_24D5 ; normalise FAC1 and return + +; perform COS() + +LAB_COS + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + +; perform SIN() + +LAB_SIN + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_2C7C ; set (2*pi) pointer high byte + LDX FAC2_s ; get FAC2 sign (b7) + JSR LAB_26C2 ; divide by (AY) (X=sign) + JSR LAB_27AB ; round and copy FAC1 to FAC2 + JSR LAB_INT ; perform INT + LDA #$00 ; clear byte + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save FAC1 sign + BPL LAB_2C35 ; branch if +ve + + ; FAC1 sign was -ve + JSR LAB_244E ; add 0.5 to FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_2C38 ; branch if -ve + + LDA Cflag ; get comparison evaluation flag + EOR #$FF ; toggle flag + STA Cflag ; save comparison evaluation flag +LAB_2C35 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C38 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 sign + BPL LAB_2C45 ; branch if was +ve + + ; else correct FAC1 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C45 + LDA #LAB_2C84 ; set pointer high byte to counter + JMP LAB_2B6E ; ^2 then series evaluation and return + +; perform TAN() + +LAB_TAN + JSR LAB_276E ; pack FAC1 into Adatal + LDA #$00 ; clear byte + STA Cflag ; clear comparison evaluation flag + JSR LAB_SIN ; go do SIN(n) + LDX #func_l ; set sin(n) pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA #Adatal ; set n pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + LDA #$00 ; clear byte + STA FAC1_s ; clear FAC1 sign (b7) + LDA Cflag ; get comparison evaluation flag + JSR LAB_2C74 ; save flag and go do series evaluation + + LDA #func_l ; set sin(n) pointer high byte + JMP LAB_26CA ; convert AY and do (AY)/FAC1 + +LAB_2C74 + PHA ; save comparison evaluation flag + JMP LAB_2C35 ; go do series evaluation + +; perform USR() + +LAB_USR + JSR Usrjmp ; call user code + JMP LAB_1BFB ; scan for ")", else do syntax error then warm start + +; perform ATN() + +LAB_ATN + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save sign + BPL LAB_2CA1 ; branch if +ve + + JSR LAB_GTHAN ; else do - FAC1 +LAB_2CA1 + LDA FAC1_e ; get FAC1 exponent + PHA ; push exponent + CMP #$81 ; compare with 1 + BCC LAB_2CAF ; branch if FAC1<1 + + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 +LAB_2CAF + LDA #LAB_2CC9 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + PLA ; restore old FAC1 exponent + CMP #$81 ; compare with 1 + BCC LAB_2CC2 ; branch if FAC1<1 + + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 +LAB_2CC2 + PLA ; restore FAC1 sign + BPL LAB_2D04 ; exit if was +ve + + JMP LAB_GTHAN ; else do - FAC1 and return + +; perform BITSET + +LAB_BITSET + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$00 ; clear A + SEC ; set the carry +S_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bits ; loop if still +ve + + INX ; make X = $00 + ORA (Itempl,X) ; or with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) +LAB_2D04 + RTS + +; perform BITCLR + +LAB_BITCLR + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$FF ; set A +S_Bitc + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bitc ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; and with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +FCError + JMP LAB_FCER ; do function call error then warm start + +; perform BITTST() + +LAB_BTST + JSR LAB_IGBY ; increment BASIC pointer + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + JSR LAB_GBYT ; get next BASIC byte + CMP #')' ; is next character ")" + BEQ TST_OK ; if ")" go do rest of function + + JMP LAB_SNER ; do syntax error then warm start + +TST_OK + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + LDA #$00 ; clear A + SEC ; set the carry +T_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL T_Bits ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; AND with byte via temporary integer (addr) + BEQ LAB_NOTT ; branch if zero (already correct) + + LDA #$FF ; set for -1 result +LAB_NOTT + JMP LAB_27DB ; go do SGN tail + +; perform BIN$() + +LAB_BINS + CPX #$19 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters ($00 = leading zero remove) + LDA #$18 ; need A byte long space + JSR LAB_MSSP ; make string space A bytes long + LDY #$17 ; set index + LDX #$18 ; character count +NextB1 + LSR nums_1 ; shift highest byte + ROR nums_2 ; shift middle byte + ROR nums_3 ; shift lowest byte bit 0 to carry + TXA ; load with "0"/2 + ROL ; shift in carry + STA (str_pl),Y ; save to temp string + index + DEY ; decrement index + BPL NextB1 ; loop if not done + + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$18 ; add 24d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string + +; this is the exit code and is also used by HEX$() +; truncate string to remove leading "0"s + +EndBHS + TAY ; clear index (A=0, X=length here) +NextB2 + LDA (str_pl),Y ; get character from string + CMP #'0' ; compare with "0" + BNE GoPr ; if not "0" then go print string from here + + DEX ; decrement character count + BEQ GoPr3 ; if zero then end of string so go print it + + INY ; else increment index + BPL NextB2 ; loop always + +; make fixed length output string - ignore overflows! + +GoPr3 + INX ; need at least 1 character +GoPr + TYA ; copy result +GoPr1 + CLC ; clear carry for add + ADC str_pl ; add low address + STA str_pl ; save low address + LDA #$00 ; do high byte + ADC str_ph ; add high address + STA str_ph ; save high address +GoPr2 + STX str_ln ; X holds string length + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + JMP LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + +BinFErr + JMP LAB_FCER ; do function call error then warm start + +; perform HEX$() + +LAB_HEXS + CPX #$07 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters + + LDA #$06 ; need 6 bytes for string + JSR LAB_MSSP ; make string space A bytes long + LDY #$05 ; set string index + + SED ; need decimal mode for nibble convert + LDA nums_3 ; get lowest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_2 ; get middle byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_1 ; get highest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + CLD ; back to binary + + LDX #$06 ; character count + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$06 ; add 6d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string (branch always) + +; convert A to ASCII hex byte and output .. note set decimal mode before calling + +LAB_A2HX + TAX ; save byte + AND #$0F ; mask off top bits + JSR LAB_AL2X ; convert low nibble to ASCII and output + TXA ; get byte back + LSR ; /2 shift high nibble to low nibble + LSR ; /4 + LSR ; /8 + LSR ; /16 +LAB_AL2X + CMP #$0A ; set carry for +1 if >9 + ADC #'0' ; add ASCII "0" + STA (str_pl),Y ; save to temp string + DEY ; decrement counter + RTS + +LAB_NLTO + STA FAC1_e ; save FAC1 exponent + LDA #$00 ; clear sign compare +LAB_MLTE + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore character + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "$" for hex +; get hex number + +LAB_CHEX + JSR LAB_IGBY ; increment and scan memory + BCC LAB_ISHN ; branch if numeric character + + ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" + SBC #'a' ; subtract "a" (carry set here) + CMP #$06 ; compare normalised with $06 (max+1) + BCS LAB_EXCH ; exit if >"f" or <"0" + + ADC #$0A ; convert to nibble +LAB_ISHN + AND #$0F ; convert to binary + TAX ; save nibble + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLTE ; skip multiply if zero + + ADC #$04 ; add four to exponent (*16 - carry clear here) + BCC LAB_NLTO ; if no overflow do evaluate digit + +LAB_MLTO + JMP LAB_2564 ; do overflow error and warm start + +LAB_NXCH + TAX ; save bit + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLBT ; skip multiply if zero + + INC FAC1_e ; increment FAC1 exponent (*2) + BEQ LAB_MLTO ; do overflow error if = $00 + + LDA #$00 ; clear sign compare +LAB_MLBT + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore bit + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "%" for binary +; get binary number + +LAB_CBIN + JSR LAB_IGBY ; increment and scan memory + EOR #'0' ; convert "0" to 0 etc. + CMP #$02 ; compare with max+1 + BCC LAB_NXCH ; branch exit if < 2 + +LAB_EXCH + JMP LAB_28F6 ; evaluate -ve flag and return + +; ctrl-c check routine. includes limited "life" byte save for INGET routine +; now also the code that checks to see if an interrupt has occurred + +CTRLC + LDA ccflag ; get [CTRL-C] check flag + BNE LAB_FBA2 ; exit if inhibited + + JSR V_INPT ; scan input device + BCC LAB_FBA0 ; exit if buffer empty + + STA ccbyte ; save received byte + LDX #$20 ; "life" timer for bytes + STX ccnull ; set countdown + JMP LAB_1636 ; return to BASIC + +LAB_FBA0 + LDX ccnull ; get countdown byte + BEQ LAB_FBA2 ; exit if finished + + DEC ccnull ; else decrement countdown +LAB_FBA2 + LDX #NmiBase ; set pointer to NMI values + JSR LAB_CKIN ; go check interrupt + LDX #IrqBase ; set pointer to IRQ values + JSR LAB_CKIN ; go check interrupt +LAB_CRTS + RTS + +; check whichever interrupt is indexed by X + +LAB_CKIN + LDA PLUS_0,X ; get interrupt flag byte + BPL LAB_CRTS ; branch if interrupt not enabled + +; we disable the interrupt here and make two new commands RETIRQ and RETNMI to +; automatically enable the interrupt when we exit + + ASL ; move happened bit to setup bit + AND #$40 ; mask happened bits + BEQ LAB_CRTS ; if no interrupt then exit + + STA PLUS_0,X ; save interrupt flag byte + + TXA ; copy index .. + TAY ; .. to Y + + PLA ; dump return address low byte, call from CTRL-C + PLA ; dump return address high byte + + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack + + LDA PLUS_1,Y ; get interrupt code pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + LDA PLUS_2,Y ; get interrupt code pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + + JMP LAB_15C2 ; go do interpreter inner loop + ; can't RTS, we used the stack! the RTS from the ctrl-c + ; check will be taken when the RETIRQ/RETNMI/RETURN is + ; executed at the end of the subroutine + +; get byte from input device, no waiting +; returns with carry set if byte in A + +INGET + JSR V_INPT ; call scan input device + BCS LAB_FB95 ; if byte go reset timer + + LDA ccnull ; get countdown + BEQ LAB_FB96 ; exit if empty + + LDA ccbyte ; get last received byte + SEC ; flag we got a byte +LAB_FB95 + LDX #$00 ; clear X + STX ccnull ; clear timer because we got a byte +LAB_FB96 + RTS + +; these routines only enable the interrupts if the set-up flag is set +; if not they have no effect + +; perform IRQ {ON|OFF|CLEAR} + +LAB_IRQ + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform NMI {ON|OFF|CLEAR} + +LAB_NMI + LDX #NmiBase ; set pointer to NMI values + CMP #TK_ON ; compare with token for ON + BEQ LAB_INON ; go turn on interrupt + + CMP #TK_OFF ; compare with token for OFF + BEQ LAB_IOFF ; go turn off interrupt + + EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR + BEQ LAB_INEX ; go clear interrupt flags and return + + JMP LAB_SNER ; do syntax error then warm start + +LAB_IOFF + LDA #$7F ; clear A + AND PLUS_0,X ; AND with interrupt setup flag + BPL LAB_INEX ; go clear interrupt enabled flag and return + +LAB_INON + LDA PLUS_0,X ; get interrupt setup flag + ASL ; Shift bit to enabled flag + ORA PLUS_0,X ; OR with flag byte +LAB_INEX + STA PLUS_0,X ; save interrupt flag byte + JMP LAB_IGBY ; update BASIC execute pointer and return + +; these routines set up the pointers and flags for the interrupt routines +; note that the interrupts are also enabled by these commands + +; perform ON IRQ + +LAB_SIRQ + CLI ; enable interrupts + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform ON NMI + +LAB_SNMI + LDX #NmiBase ; set pointer to NMI values + + STX TempB ; save interrupt pointer + JSR LAB_IGBY ; increment and scan memory (past token) + JSR LAB_GFPN ; get fixed-point number into temp integer + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_LFND ; if carry set go set-up interrupt + + JMP LAB_16F7 ; else go do "Undefined statement" error and warm start + +LAB_LFND + LDX TempB ; get interrupt pointer + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 (carry already set for subtract) + STA PLUS_1,X ; save as interrupt pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA PLUS_2,X ; save as interrupt pointer high byte + + LDA #$C0 ; set interrupt enabled/setup bits + STA PLUS_0,X ; set interrupt flags +LAB_IRTS + RTS + +; return from IRQ service, restores the enabled flag. + +; perform RETIRQ + +LAB_RETIRQ + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA IrqBase ; get interrupt flags + ASL ; copy setup to enabled (b7) + ORA IrqBase ; OR in setup flag + STA IrqBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; return from NMI service, restores the enabled flag. + +; perform RETNMI + +LAB_RETNMI + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA NmiBase ; get set-up flag + ASL ; copy setup to enabled (b7) + ORA NmiBase ; OR in setup flag + STA NmiBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; MAX() MIN() pre process + +LAB_MMPP + JSR LAB_EVEZ ; process expression + JMP LAB_CTNM ; check if source is numeric, else do type mismatch + +; perform MAX() + +LAB_MAX + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BPL LAB_MAX ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MAX ; go do next (branch always) + +; perform MIN() + +LAB_MIN + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BMI LAB_MIN ; branch if no swap to do + + BEQ LAB_MIN ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MIN ; go do next (branch always) + +; exit routine. don't bother returning to the loop code +; check for correct exit, else so syntax error + +LAB_MMEC + CMP #')' ; is it end of function? + BNE LAB_MMSE ; if not do MAX MIN syntax error + + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") + +LAB_MMSE + JMP LAB_SNER ; do syntax error then warm start + +; check for next, evaluate and return or exit +; this is the routine that does most of the work + +LAB_PHFA + JSR LAB_GBYT ; get next BASIC byte + CMP #',' ; is there more ? + BNE LAB_MMEC ; if not go do end check + + ; push FAC1 + JSR LAB_27BA ; round FAC1 + LDA FAC1_s ; get FAC1 sign + ORA #$7F ; set all non sign bits + AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + + JSR LAB_IGBY ; scan and get next BASIC byte (after ",") + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + + ; pop FAC2 (MAX/MIN expression so far) + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop mantissa1 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop sign/mantissa1 + STA FAC2_1 ; save FAC2 sign/mantissa1 + STA FAC2_s ; save FAC2 sign + + ; compare FAC1 with (packed) FAC2 + LDA #FAC2_e ; set pointer high byte to FAC2 + JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return + ; returns A=$00 if FAC1 = (AY) + ; returns A=$01 if FAC1 > (AY) + ; returns A=$FF if FAC1 < (AY) + +; perform WIDTH + +LAB_WDTH + CMP #',' ; is next byte "," + BEQ LAB_TBSZ ; if so do tab size + + JSR LAB_GTBY ; get byte parameter + TXA ; copy width to A + BEQ LAB_NSTT ; branch if set for infinite line + + CPX #$10 ; else make min width = 16d + BCC TabErr ; if less do function call error and exit + +; this next compare ensures that we can't exit WIDTH via an error leaving the +; tab size greater than the line length. + + CPX TabSiz ; compare with tab size + BCS LAB_NSTT ; branch if >= tab size + + STX TabSiz ; else make tab size = terminal width +LAB_NSTT + STX TWidth ; set the terminal width + JSR LAB_GBYT ; get BASIC byte back + BEQ WExit ; exit if no following + + CMP #',' ; else is it "," + BNE LAB_MMSE ; if not do syntax error + +LAB_TBSZ + JSR LAB_SGBY ; scan and get byte parameter + TXA ; copy TAB size + BMI TabErr ; if >127 do function call error and exit + + CPX #$01 ; compare with min-1 + BCC TabErr ; if <=1 do function call error and exit + + LDA TWidth ; set flags for width + BEQ LAB_SVTB ; skip check if infinite line + + CPX TWidth ; compare TAB with width + BEQ LAB_SVTB ; ok if = + + BCS TabErr ; branch if too big + +LAB_SVTB + STX TabSiz ; save TAB size + +; calculate tab column limit from TAB size. The Iclim is set to the last tab +; position on a line that still has at least one whole tab width between it +; and the end of the line. + +WExit + LDA TWidth ; get width + BEQ LAB_SULP ; branch if infinite line + + CMP TabSiz ; compare with tab size + BCS LAB_WDLP ; branch if >= tab size + + STA TabSiz ; else make tab size = terminal width +LAB_SULP + SEC ; set carry for subtract +LAB_WDLP + SBC TabSiz ; subtract tab size + BCS LAB_WDLP ; loop while no borrow + + ADC TabSiz ; add tab size back + CLC ; clear carry for add + ADC TabSiz ; add tab size back again + STA Iclim ; save for now + LDA TWidth ; get width back + SEC ; set carry for subtract + SBC Iclim ; subtract remainder + STA Iclim ; save tab column limit +LAB_NOSQ + RTS + +TabErr + JMP LAB_FCER ; do function call error then warm start + +; perform SQR() + +LAB_SQR + LDA FAC1_s ; get FAC1 sign + BMI TabErr ; if -ve do function call error + + LDA FAC1_e ; get exponent + BEQ LAB_NOSQ ; if zero just return + + ; else do root + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #$00 ; clear A + + STA FACt_3 ; clear remainder + STA FACt_2 ; .. + STA FACt_1 ; .. + STA TempB ; .. + + STA FAC1_3 ; clear root + STA FAC1_2 ; .. + STA FAC1_1 ; .. + + LDX #$18 ; 24 pairs of bits to do + LDA FAC2_e ; get exponent + LSR ; check odd/even + BCS LAB_SQE2 ; if odd only 1 shift first time + +LAB_SQE1 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows +LAB_SQE2 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows + + ASL FAC1_3 ; root = root * 2 + ROL FAC1_2 ; .. + ROL FAC1_1 ; .. never overflows + + LDA FAC1_3 ; get root low byte + ROL ; *2 + STA Temp3 ; save partial low byte + LDA FAC1_2 ; get root low mid byte + ROL ; *2 + STA Temp3+1 ; save partial low mid byte + LDA FAC1_1 ; get root high mid byte + ROL ; *2 + STA Temp3+2 ; save partial high mid byte + LDA #$00 ; get root high byte (always $00) + ROL ; *2 + STA Temp3+3 ; save partial high byte + + ; carry clear for subtract +1 + LDA FACt_3 ; get remainder low byte + SBC Temp3 ; subtract partial low byte + STA Temp3 ; save partial low byte + + LDA FACt_2 ; get remainder low mid byte + SBC Temp3+1 ; subtract partial low mid byte + STA Temp3+1 ; save partial low mid byte + + LDA FACt_1 ; get remainder high mid byte + SBC Temp3+2 ; subtract partial high mid byte + TAY ; copy partial high mid byte + + LDA TempB ; get remainder high byte + SBC Temp3+3 ; subtract partial high byte + BCC LAB_SQNS ; skip sub if remainder smaller + + STA TempB ; save remainder high byte + + STY FACt_1 ; save remainder high mid byte + + LDA Temp3+1 ; get remainder low mid byte + STA FACt_2 ; save remainder low mid byte + + LDA Temp3 ; get partial low byte + STA FACt_3 ; save remainder low byte + + INC FAC1_3 ; increment root low byte (never any rollover) +LAB_SQNS + DEX ; decrement bit pair count + BNE LAB_SQE1 ; loop if not all done + + SEC ; set carry for subtract + LDA FAC2_e ; get exponent + SBC #$80 ; normalise + ROR ; /2 and re-bias to $80 + ADC #$00 ; add bit zero back in (allow for half shift) + STA FAC1_e ; save it + JMP LAB_24D5 ; normalise FAC1 and return + +; perform VARPTR() + +LAB_VARPTR + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDY Cvaral ; get var address low byte + LDA Cvarah ; get var address high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform PI + +LAB_PI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + DEC FAC1_e ; make result = PI + RTS + +; perform TWOPI + +LAB_TWOPI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return + +; system dependant i/o vectors +; these are in RAM and are set by the monitor at start-up + +V_INPT + JMP (VEC_IN) ; non halting scan input device +V_OUTP + JMP (VEC_OUT) ; send byte to output device +V_LOAD + JMP (VEC_LD) ; load BASIC program +V_SAVE + JMP (VEC_SV) ; save BASIC program + +; The rest are tables messages and code for RAM + +; the rest of the code is tables and BASIC start-up code + +PG2_TABS + .byte $FF ; ctrl-c flag - $00 = enabled + .byte $00 ; ctrl-c byte - GET needs this + .byte $00 ; ctrl-c byte timeout - GET needs this + .word CTRLC ; ctrl c check vector + .word CHRIN ; non halting key input - monitor to set this + .word CHROUT ; output vector - monitor to set this +; .word xxxx ; load vector - monitor to set this +; .word xxxx ; save vector - monitor to set this +PG2_TABE + +; character get subroutine for zero page + +; For a 1.8432MHz 6502 including the JSR and RTS +; fastest (>=":") = 29 cycles = 15.7uS +; slowest (<":") = 40 cycles = 21.7uS +; space skip = +21 cycles = +11.4uS +; inc across page = +4 cycles = +2.2uS + +; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the +; block is copied to it's destination, any non zero page address will do at assembly +; time, to assemble a three byte instruction. + +; page 0 initialisation table from $BC +; increment and scan memory + +LAB_2CEE + INC Bpntrl ; increment BASIC execute pointer low byte + BNE LAB_2CF4 ; branch if no carry + ; else + INC Bpntrh ; increment BASIC execute pointer high byte + +; page 0 initialisation table from $C2 +; scan memory + +LAB_2CF4 + LDA $FFFF ; get byte to scan (addr set by call routine) + CMP #TK_ELSE ; compare with the token for ELSE + BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set + + CMP #':' ; compare with ":" + BCS LAB_2D05 ; exit if >= ":", not numeric, carry set + + CMP #' ' ; compare with " " + BEQ LAB_2CEE ; if " " go do next + + SEC ; set carry for SBC + SBC #'0' ; subtract "0" + SEC ; set carry for SBC + SBC #$D0 ; subtract -"0" + ; clear carry if byte = "0"-"9" +LAB_2D05 + RTS + +; page zero initialisation table $00-$12 inclusive + +StrTab + .byte $4C ; JMP opcode + .word LAB_COLD ; initial warm start vector (cold start) + + .byte $00 ; these bytes are not used by BASIC + .word $0000 ; + .word $0000 ; + .word $0000 ; + + .byte $4C ; JMP opcode + .word LAB_FCER ; initial user function vector ("Function call" error) + .byte $00 ; default NULL count + .byte $00 ; clear terminal position + .byte $00 ; default terminal width byte + .byte $F2 ; default limit for TAB = 14 + .word Ram_base ; start of user RAM +EndTab + +LAB_MSZM + .byte $0D,$0A,"Memory size ",$00 + +LAB_SMSG + .byte " Bytes free",$0D,$0A,$0A + .byte "Enhanced BASIC 2.22",$0A,$00 + +; numeric constants and series + + ; constants and series for LOG(n) +LAB_25A0 + .byte $02 ; counter + .byte $80,$19,$56,$62 ; 0.59898 + .byte $80,$76,$22,$F3 ; 0.96147 +;## .byte $80,$76,$22,$F1 ; 0.96147 + .byte $82,$38,$AA,$40 ; 2.88539 +;## .byte $82,$38,$AA,$45 ; 2.88539 + +LAB_25AD + .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 +LAB_25B1 + .byte $81,$35,$04,$F3 ; 1.41421 root 2 +LAB_25B5 + .byte $80,$80,$00,$00 ; -0.5 +LAB_25B9 + .byte $80,$31,$72,$18 ; 0.69315 LOG(2) + + ; numeric PRINT constants +LAB_2947 + .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) +LAB_294B + .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) +LAB_294F + .byte $94,$74,$24,$00 ; 1000000 + + ; EXP(n) constants and series +LAB_2AFA + .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) +LAB_2AFE + .byte $06 ; counter + .byte $74,$63,$90,$8C ; 2.17023e-4 + .byte $77,$23,$0C,$AB ; 0.00124 + .byte $7A,$1E,$94,$00 ; 0.00968 + .byte $7C,$63,$42,$80 ; 0.05548 + .byte $7E,$75,$FE,$D0 ; 0.24023 + .byte $80,$31,$72,$15 ; 0.69315 + .byte $81,$00,$00,$00 ; 1.00000 + +;## .byte $07 ; counter +;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) +;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) +;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) +;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) +;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) +;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) +;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) +;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) + + ; trigonometric constants and series +LAB_2C78 + .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # +LAB_2C84 + .byte $04 ; counter + .byte $86,$1E,$D7,$FB ; 39.7109 +;## .byte $86,$1E,$D7,$BA ; 39.7109 + .byte $87,$99,$26,$65 ;-76.575 +;## .byte $87,$99,$26,$64 ;-76.575 + .byte $87,$23,$34,$58 ; 81.6022 + .byte $86,$A5,$5D,$E1 ;-41.3417 +;## .byte $86,$A5,$5D,$E0 ;-41.3417 +LAB_2C7C + .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # +;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # + +LAB_2CC9 + .byte $08 ; counter + .byte $78,$3A,$C5,$37 ; 0.00285 + .byte $7B,$83,$A2,$5C ;-0.0160686 + .byte $7C,$2E,$DD,$4D ; 0.0426915 + .byte $7D,$99,$B0,$1E ;-0.0750429 + .byte $7D,$59,$ED,$24 ; 0.106409 + .byte $7E,$91,$72,$00 ;-0.142036 + .byte $7E,$4C,$B9,$73 ; 0.199926 + .byte $7F,$AA,$AA,$53 ;-0.333331 + +;## .byte $08 ; counter +;## .byte $78,$3B,$D7,$4A ; 1/17 +;## .byte $7B,$84,$6E,$02 ;-1/15 +;## .byte $7C,$2F,$C1,$FE ; 1/13 +;## .byte $7D,$9A,$31,$74 ;-1/11 +;## .byte $7D,$5A,$3D,$84 ; 1/9 +;## .byte $7E,$91,$7F,$C8 ;-1/7 +;## .byte $7E,$4C,$BB,$E4 ; 1/5 +;## .byte $7F,$AA,$AA,$6C ;-1/3 + +LAB_1D96 = *+1 ; $00,$00 used for undefined variables +LAB_259C + .byte $81,$00,$00,$00 ; 1.000000, used for INC +LAB_2AFD + .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 + + ; misc constants +LAB_1DF7 + .byte $90 ;-32768 (uses first three bytes from 0.5) +LAB_2A96 + .byte $80,$00,$00,$00 ; 0.5 +LAB_2C80 + .byte $7F,$00,$00,$00 ; 0.25 +LAB_26B5 + .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant + +; This table is used in converting numbers to ASCII. + +LAB_2A9A +LAB_2A9B = LAB_2A9A+1 +LAB_2A9C = LAB_2A9B+1 + .byte $FE,$79,$60 ; -100000 + .byte $00,$27,$10 ; 10000 + .byte $FF,$FC,$18 ; -1000 + .byte $00,$00,$64 ; 100 + .byte $FF,$FF,$F6 ; -10 + .byte $00,$00,$01 ; 1 + +LAB_CTBL + .word LAB_END-1 ; END + .word LAB_FOR-1 ; FOR + .word LAB_NEXT-1 ; NEXT + .word LAB_DATA-1 ; DATA + .word LAB_INPUT-1 ; INPUT + .word LAB_DIM-1 ; DIM + .word LAB_READ-1 ; READ + .word LAB_LET-1 ; LET + .word LAB_DEC-1 ; DEC new command + .word LAB_GOTO-1 ; GOTO + .word LAB_RUN-1 ; RUN + .word LAB_IF-1 ; IF + .word LAB_RESTORE-1 ; RESTORE modified command + .word LAB_GOSUB-1 ; GOSUB + .word LAB_RETIRQ-1 ; RETIRQ new command + .word LAB_RETNMI-1 ; RETNMI new command + .word LAB_RETURN-1 ; RETURN + .word LAB_REM-1 ; REM + .word LAB_STOP-1 ; STOP + .word LAB_ON-1 ; ON modified command + .word LAB_NULL-1 ; NULL modified command + .word LAB_INC-1 ; INC new command + .word LAB_WAIT-1 ; WAIT + .word V_LOAD-1 ; LOAD + .word V_SAVE-1 ; SAVE + .word LAB_DEF-1 ; DEF + .word LAB_POKE-1 ; POKE + .word LAB_DOKE-1 ; DOKE new command + .word LAB_CALL-1 ; CALL new command + .word LAB_DO-1 ; DO new command + .word LAB_LOOP-1 ; LOOP new command + .word LAB_PRINT-1 ; PRINT + .word LAB_CONT-1 ; CONT + .word LAB_LIST-1 ; LIST + .word LAB_CLEAR-1 ; CLEAR + .word LAB_NEW-1 ; NEW + .word LAB_WDTH-1 ; WIDTH new command + .word LAB_GET-1 ; GET new command + .word LAB_SWAP-1 ; SWAP new command + .word LAB_BITSET-1 ; BITSET new command + .word LAB_BITCLR-1 ; BITCLR new command + .word LAB_IRQ-1 ; IRQ new command + .word LAB_NMI-1 ; NMI new command + +; function pre process routine table + +LAB_FTPL +LAB_FTPM = LAB_FTPL+$01 + .word LAB_PPFN-1 ; SGN(n) process numeric expression in () + .word LAB_PPFN-1 ; INT(n) " + .word LAB_PPFN-1 ; ABS(n) " + .word LAB_EVEZ-1 ; USR(x) process any expression + .word LAB_1BF7-1 ; FRE(x) " + .word LAB_1BF7-1 ; POS(x) " + .word LAB_PPFN-1 ; SQR(n) process numeric expression in () + .word LAB_PPFN-1 ; RND(n) " + .word LAB_PPFN-1 ; LOG(n) " + .word LAB_PPFN-1 ; EXP(n) " + .word LAB_PPFN-1 ; COS(n) " + .word LAB_PPFN-1 ; SIN(n) " + .word LAB_PPFN-1 ; TAN(n) " + .word LAB_PPFN-1 ; ATN(n) " + .word LAB_PPFN-1 ; PEEK(n) " + .word LAB_PPFN-1 ; DEEK(n) " + .word $0000 ; SADD() none + .word LAB_PPFS-1 ; LEN($) process string expression in () + .word LAB_PPFN-1 ; STR$(n) process numeric expression in () + .word LAB_PPFS-1 ; VAL($) process string expression in () + .word LAB_PPFS-1 ; ASC($) " + .word LAB_PPFS-1 ; UCASE$($) " + .word LAB_PPFS-1 ; LCASE$($) " + .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () + .word LAB_BHSS-1 ; HEX$(n) " + .word LAB_BHSS-1 ; BIN$(n) " + .word $0000 ; BITTST() none + .word LAB_MMPP-1 ; MAX() process numeric expression + .word LAB_MMPP-1 ; MIN() " + .word LAB_PPBI-1 ; PI advance pointer + .word LAB_PPBI-1 ; TWOPI " + .word $0000 ; VARPTR() none + .word LAB_LRMS-1 ; LEFT$() process string expression + .word LAB_LRMS-1 ; RIGHT$() " + .word LAB_LRMS-1 ; MID$() " + +; action addresses for functions + +LAB_FTBL +LAB_FTBM = LAB_FTBL+$01 + .word LAB_SGN-1 ; SGN() + .word LAB_INT-1 ; INT() + .word LAB_ABS-1 ; ABS() + .word LAB_USR-1 ; USR() + .word LAB_FRE-1 ; FRE() + .word LAB_POS-1 ; POS() + .word LAB_SQR-1 ; SQR() + .word LAB_RND-1 ; RND() modified function + .word LAB_LOG-1 ; LOG() + .word LAB_EXP-1 ; EXP() + .word LAB_COS-1 ; COS() + .word LAB_SIN-1 ; SIN() + .word LAB_TAN-1 ; TAN() + .word LAB_ATN-1 ; ATN() + .word LAB_PEEK-1 ; PEEK() + .word LAB_DEEK-1 ; DEEK() new function + .word LAB_SADD-1 ; SADD() new function + .word LAB_LENS-1 ; LEN() + .word LAB_STRS-1 ; STR$() + .word LAB_VAL-1 ; VAL() + .word LAB_ASC-1 ; ASC() + .word LAB_UCASE-1 ; UCASE$() new function + .word LAB_LCASE-1 ; LCASE$() new function + .word LAB_CHRS-1 ; CHR$() + .word LAB_HEXS-1 ; HEX$() new function + .word LAB_BINS-1 ; BIN$() new function + .word LAB_BTST-1 ; BITTST() new function + .word LAB_MAX-1 ; MAX() new function + .word LAB_MIN-1 ; MIN() new function + .word LAB_PI-1 ; PI new function + .word LAB_TWOPI-1 ; TWOPI new function + .word LAB_VARPTR-1 ; VARPTR() new function + .word LAB_LEFT-1 ; LEFT$() + .word LAB_RIGHT-1 ; RIGHT$() + .word LAB_MIDS-1 ; MID$() + +; hierarchy and action addresses for operator + +LAB_OPPT + .byte $79 ; + + .word LAB_ADD-1 + .byte $79 ; - + .word LAB_SUBTRACT-1 + .byte $7B ; * + .word LAB_MULTIPLY-1 + .byte $7B ; / + .word LAB_DIVIDE-1 + .byte $7F ; ^ + .word LAB_POWER-1 + .byte $50 ; AND + .word LAB_AND-1 + .byte $46 ; EOR new operator + .word LAB_EOR-1 + .byte $46 ; OR + .word LAB_OR-1 + .byte $56 ; >> new operator + .word LAB_RSHIFT-1 + .byte $56 ; << new operator + .word LAB_LSHIFT-1 + .byte $7D ; > + .word LAB_GTHAN-1 + .byte $5A ; = + .word LAB_EQUAL-1 + .byte $64 ; < + .word LAB_LTHAN-1 + +; keywords start with .. +; this is the first character table and must be in alphabetic order + +TAB_1STC + .byte "*" + .byte "+" + .byte "-" + .byte "/" + .byte "<" + .byte "=" + .byte ">" + .byte "?" + .byte "A" + .byte "B" + .byte "C" + .byte "D" + .byte "E" + .byte "F" + .byte "G" + .byte "H" + .byte "I" + .byte "L" + .byte "M" + .byte "N" + .byte "O" + .byte "P" + .byte "R" + .byte "S" + .byte "T" + .byte "U" + .byte "V" + .byte "W" + .byte "^" + .byte $00 ; table terminator + +; pointers to keyword tables + +TAB_CHRT + .word TAB_STAR ; table for "*" + .word TAB_PLUS ; table for "+" + .word TAB_MNUS ; table for "-" + .word TAB_SLAS ; table for "/" + .word TAB_LESS ; table for "<" + .word TAB_EQUL ; table for "=" + .word TAB_MORE ; table for ">" + .word TAB_QEST ; table for "?" + .word TAB_ASCA ; table for "A" + .word TAB_ASCB ; table for "B" + .word TAB_ASCC ; table for "C" + .word TAB_ASCD ; table for "D" + .word TAB_ASCE ; table for "E" + .word TAB_ASCF ; table for "F" + .word TAB_ASCG ; table for "G" + .word TAB_ASCH ; table for "H" + .word TAB_ASCI ; table for "I" + .word TAB_ASCL ; table for "L" + .word TAB_ASCM ; table for "M" + .word TAB_ASCN ; table for "N" + .word TAB_ASCO ; table for "O" + .word TAB_ASCP ; table for "P" + .word TAB_ASCR ; table for "R" + .word TAB_ASCS ; table for "S" + .word TAB_ASCT ; table for "T" + .word TAB_ASCU ; table for "U" + .word TAB_ASCV ; table for "V" + .word TAB_ASCW ; table for "W" + .word TAB_POWR ; table for "^" + +; tables for each start character, note if a longer keyword with the same start +; letters as a shorter one exists then it must come first, else the list is in +; alphabetical order as follows .. + +; [keyword,token +; [keyword,token]] +; end marker (#$00) + +TAB_STAR + .byte TK_MUL,$00 ; * +TAB_PLUS + .byte TK_PLUS,$00 ; + +TAB_MNUS + .byte TK_MINUS,$00 ; - +TAB_SLAS + .byte TK_DIV,$00 ; / +TAB_LESS +LBB_LSHIFT + .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" + .byte TK_LT ; < + .byte $00 +TAB_EQUL + .byte TK_EQUAL,$00 ; = +TAB_MORE +LBB_RSHIFT + .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" + .byte TK_GT ; > + .byte $00 +TAB_QEST + .byte TK_PRINT,$00 ; ? +TAB_ASCA +LBB_ABS + .byte "BS(",TK_ABS ; ABS( +LBB_AND + .byte "ND",TK_AND ; AND +LBB_ASC + .byte "SC(",TK_ASC ; ASC( +LBB_ATN + .byte "TN(",TK_ATN ; ATN( + .byte $00 +TAB_ASCB +LBB_BINS + .byte "IN$(",TK_BINS ; BIN$( +LBB_BITCLR + .byte "ITCLR",TK_BITCLR ; BITCLR +LBB_BITSET + .byte "ITSET",TK_BITSET ; BITSET +LBB_BITTST + .byte "ITTST(",TK_BITTST + ; BITTST( + .byte $00 +TAB_ASCC +LBB_CALL + .byte "ALL",TK_CALL ; CALL +LBB_CHRS + .byte "HR$(",TK_CHRS ; CHR$( +LBB_CLEAR + .byte "LEAR",TK_CLEAR ; CLEAR +LBB_CONT + .byte "ONT",TK_CONT ; CONT +LBB_COS + .byte "OS(",TK_COS ; COS( + .byte $00 +TAB_ASCD +LBB_DATA + .byte "ATA",TK_DATA ; DATA +LBB_DEC + .byte "EC",TK_DEC ; DEC +LBB_DEEK + .byte "EEK(",TK_DEEK ; DEEK( +LBB_DEF + .byte "EF",TK_DEF ; DEF +LBB_DIM + .byte "IM",TK_DIM ; DIM +LBB_DOKE + .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" +LBB_DO + .byte "O",TK_DO ; DO + .byte $00 +TAB_ASCE +LBB_ELSE + .byte "LSE",TK_ELSE ; ELSE +LBB_END + .byte "ND",TK_END ; END +LBB_EOR + .byte "OR",TK_EOR ; EOR +LBB_EXP + .byte "XP(",TK_EXP ; EXP( + .byte $00 +TAB_ASCF +LBB_FN + .byte "N",TK_FN ; FN +LBB_FOR + .byte "OR",TK_FOR ; FOR +LBB_FRE + .byte "RE(",TK_FRE ; FRE( + .byte $00 +TAB_ASCG +LBB_GET + .byte "ET",TK_GET ; GET +LBB_GOSUB + .byte "OSUB",TK_GOSUB ; GOSUB +LBB_GOTO + .byte "OTO",TK_GOTO ; GOTO + .byte $00 +TAB_ASCH +LBB_HEXS + .byte "EX$(",TK_HEXS ; HEX$( + .byte $00 +TAB_ASCI +LBB_IF + .byte "F",TK_IF ; IF +LBB_INC + .byte "NC",TK_INC ; INC +LBB_INPUT + .byte "NPUT",TK_INPUT ; INPUT +LBB_INT + .byte "NT(",TK_INT ; INT( +LBB_IRQ + .byte "RQ",TK_IRQ ; IRQ + .byte $00 +TAB_ASCL +LBB_LCASES + .byte "CASE$(",TK_LCASES + ; LCASE$( +LBB_LEFTS + .byte "EFT$(",TK_LEFTS ; LEFT$( +LBB_LEN + .byte "EN(",TK_LEN ; LEN( +LBB_LET + .byte "ET",TK_LET ; LET +LBB_LIST + .byte "IST",TK_LIST ; LIST +LBB_LOAD + .byte "OAD",TK_LOAD ; LOAD +LBB_LOG + .byte "OG(",TK_LOG ; LOG( +LBB_LOOP + .byte "OOP",TK_LOOP ; LOOP + .byte $00 +TAB_ASCM +LBB_MAX + .byte "AX(",TK_MAX ; MAX( +LBB_MIDS + .byte "ID$(",TK_MIDS ; MID$( +LBB_MIN + .byte "IN(",TK_MIN ; MIN( + .byte $00 +TAB_ASCN +LBB_NEW + .byte "EW",TK_NEW ; NEW +LBB_NEXT + .byte "EXT",TK_NEXT ; NEXT +LBB_NMI + .byte "MI",TK_NMI ; NMI +LBB_NOT + .byte "OT",TK_NOT ; NOT +LBB_NULL + .byte "ULL",TK_NULL ; NULL + .byte $00 +TAB_ASCO +LBB_OFF + .byte "FF",TK_OFF ; OFF +LBB_ON + .byte "N",TK_ON ; ON +LBB_OR + .byte "R",TK_OR ; OR + .byte $00 +TAB_ASCP +LBB_PEEK + .byte "EEK(",TK_PEEK ; PEEK( +LBB_PI + .byte "I",TK_PI ; PI +LBB_POKE + .byte "OKE",TK_POKE ; POKE +LBB_POS + .byte "OS(",TK_POS ; POS( +LBB_PRINT + .byte "RINT",TK_PRINT ; PRINT + .byte $00 +TAB_ASCR +LBB_READ + .byte "EAD",TK_READ ; READ +LBB_REM + .byte "EM",TK_REM ; REM +LBB_RESTORE + .byte "ESTORE",TK_RESTORE + ; RESTORE +LBB_RETIRQ + .byte "ETIRQ",TK_RETIRQ ; RETIRQ +LBB_RETNMI + .byte "ETNMI",TK_RETNMI ; RETNMI +LBB_RETURN + .byte "ETURN",TK_RETURN ; RETURN +LBB_RIGHTS + .byte "IGHT$(",TK_RIGHTS + ; RIGHT$( +LBB_RND + .byte "ND(",TK_RND ; RND( +LBB_RUN + .byte "UN",TK_RUN ; RUN + .byte $00 +TAB_ASCS +LBB_SADD + .byte "ADD(",TK_SADD ; SADD( +LBB_SAVE + .byte "AVE",TK_SAVE ; SAVE +LBB_SGN + .byte "GN(",TK_SGN ; SGN( +LBB_SIN + .byte "IN(",TK_SIN ; SIN( +LBB_SPC + .byte "PC(",TK_SPC ; SPC( +LBB_SQR + .byte "QR(",TK_SQR ; SQR( +LBB_STEP + .byte "TEP",TK_STEP ; STEP +LBB_STOP + .byte "TOP",TK_STOP ; STOP +LBB_STRS + .byte "TR$(",TK_STRS ; STR$( +LBB_SWAP + .byte "WAP",TK_SWAP ; SWAP + .byte $00 +TAB_ASCT +LBB_TAB + .byte "AB(",TK_TAB ; TAB( +LBB_TAN + .byte "AN(",TK_TAN ; TAN( +LBB_THEN + .byte "HEN",TK_THEN ; THEN +LBB_TO + .byte "O",TK_TO ; TO +LBB_TWOPI + .byte "WOPI",TK_TWOPI ; TWOPI + .byte $00 +TAB_ASCU +LBB_UCASES + .byte "CASE$(",TK_UCASES + ; UCASE$( +LBB_UNTIL + .byte "NTIL",TK_UNTIL ; UNTIL +LBB_USR + .byte "SR(",TK_USR ; USR( + .byte $00 +TAB_ASCV +LBB_VAL + .byte "AL(",TK_VAL ; VAL( +LBB_VPTR + .byte "ARPTR(",TK_VPTR ; VARPTR( + .byte $00 +TAB_ASCW +LBB_WAIT + .byte "AIT",TK_WAIT ; WAIT +LBB_WHILE + .byte "HILE",TK_WHILE ; WHILE +LBB_WIDTH + .byte "IDTH",TK_WIDTH ; WIDTH + .byte $00 +TAB_POWR + .byte TK_POWER,$00 ; ^ + +; new decode table for LIST +; Table is .. +; byte - keyword length, keyword first character +; word - pointer to rest of keyword from dictionary + +; note if length is 1 then the pointer is ignored + +LAB_KEYT + .byte 3,'E' + .word LBB_END ; END + .byte 3,'F' + .word LBB_FOR ; FOR + .byte 4,'N' + .word LBB_NEXT ; NEXT + .byte 4,'D' + .word LBB_DATA ; DATA + .byte 5,'I' + .word LBB_INPUT ; INPUT + .byte 3,'D' + .word LBB_DIM ; DIM + .byte 4,'R' + .word LBB_READ ; READ + .byte 3,'L' + .word LBB_LET ; LET + .byte 3,'D' + .word LBB_DEC ; DEC + .byte 4,'G' + .word LBB_GOTO ; GOTO + .byte 3,'R' + .word LBB_RUN ; RUN + .byte 2,'I' + .word LBB_IF ; IF + .byte 7,'R' + .word LBB_RESTORE ; RESTORE + .byte 5,'G' + .word LBB_GOSUB ; GOSUB + .byte 6,'R' + .word LBB_RETIRQ ; RETIRQ + .byte 6,'R' + .word LBB_RETNMI ; RETNMI + .byte 6,'R' + .word LBB_RETURN ; RETURN + .byte 3,'R' + .word LBB_REM ; REM + .byte 4,'S' + .word LBB_STOP ; STOP + .byte 2,'O' + .word LBB_ON ; ON + .byte 4,'N' + .word LBB_NULL ; NULL + .byte 3,'I' + .word LBB_INC ; INC + .byte 4,'W' + .word LBB_WAIT ; WAIT + .byte 4,'L' + .word LBB_LOAD ; LOAD + .byte 4,'S' + .word LBB_SAVE ; SAVE + .byte 3,'D' + .word LBB_DEF ; DEF + .byte 4,'P' + .word LBB_POKE ; POKE + .byte 4,'D' + .word LBB_DOKE ; DOKE + .byte 4,'C' + .word LBB_CALL ; CALL + .byte 2,'D' + .word LBB_DO ; DO + .byte 4,'L' + .word LBB_LOOP ; LOOP + .byte 5,'P' + .word LBB_PRINT ; PRINT + .byte 4,'C' + .word LBB_CONT ; CONT + .byte 4,'L' + .word LBB_LIST ; LIST + .byte 5,'C' + .word LBB_CLEAR ; CLEAR + .byte 3,'N' + .word LBB_NEW ; NEW + .byte 5,'W' + .word LBB_WIDTH ; WIDTH + .byte 3,'G' + .word LBB_GET ; GET + .byte 4,'S' + .word LBB_SWAP ; SWAP + .byte 6,'B' + .word LBB_BITSET ; BITSET + .byte 6,'B' + .word LBB_BITCLR ; BITCLR + .byte 3,'I' + .word LBB_IRQ ; IRQ + .byte 3,'N' + .word LBB_NMI ; NMI + +; secondary commands (can't start a statement) + + .byte 4,'T' + .word LBB_TAB ; TAB + .byte 4,'E' + .word LBB_ELSE ; ELSE + .byte 2,'T' + .word LBB_TO ; TO + .byte 2,'F' + .word LBB_FN ; FN + .byte 4,'S' + .word LBB_SPC ; SPC + .byte 4,'T' + .word LBB_THEN ; THEN + .byte 3,'N' + .word LBB_NOT ; NOT + .byte 4,'S' + .word LBB_STEP ; STEP + .byte 5,'U' + .word LBB_UNTIL ; UNTIL + .byte 5,'W' + .word LBB_WHILE ; WHILE + .byte 3,'O' + .word LBB_OFF ; OFF + +; opperators + + .byte 1,'+' + .word $0000 ; + + .byte 1,'-' + .word $0000 ; - + .byte 1,'*' + .word $0000 ; * + .byte 1,'/' + .word $0000 ; / + .byte 1,'^' + .word $0000 ; ^ + .byte 3,'A' + .word LBB_AND ; AND + .byte 3,'E' + .word LBB_EOR ; EOR + .byte 2,'O' + .word LBB_OR ; OR + .byte 2,'>' + .word LBB_RSHIFT ; >> + .byte 2,'<' + .word LBB_LSHIFT ; << + .byte 1,'>' + .word $0000 ; > + .byte 1,'=' + .word $0000 ; = + .byte 1,'<' + .word $0000 ; < + +; functions + + .byte 4,'S' ; + .word LBB_SGN ; SGN + .byte 4,'I' ; + .word LBB_INT ; INT + .byte 4,'A' ; + .word LBB_ABS ; ABS + .byte 4,'U' ; + .word LBB_USR ; USR + .byte 4,'F' ; + .word LBB_FRE ; FRE + .byte 4,'P' ; + .word LBB_POS ; POS + .byte 4,'S' ; + .word LBB_SQR ; SQR + .byte 4,'R' ; + .word LBB_RND ; RND + .byte 4,'L' ; + .word LBB_LOG ; LOG + .byte 4,'E' ; + .word LBB_EXP ; EXP + .byte 4,'C' ; + .word LBB_COS ; COS + .byte 4,'S' ; + .word LBB_SIN ; SIN + .byte 4,'T' ; + .word LBB_TAN ; TAN + .byte 4,'A' ; + .word LBB_ATN ; ATN + .byte 5,'P' ; + .word LBB_PEEK ; PEEK + .byte 5,'D' ; + .word LBB_DEEK ; DEEK + .byte 5,'S' ; + .word LBB_SADD ; SADD + .byte 4,'L' ; + .word LBB_LEN ; LEN + .byte 5,'S' ; + .word LBB_STRS ; STR$ + .byte 4,'V' ; + .word LBB_VAL ; VAL + .byte 4,'A' ; + .word LBB_ASC ; ASC + .byte 7,'U' ; + .word LBB_UCASES ; UCASE$ + .byte 7,'L' ; + .word LBB_LCASES ; LCASE$ + .byte 5,'C' ; + .word LBB_CHRS ; CHR$ + .byte 5,'H' ; + .word LBB_HEXS ; HEX$ + .byte 5,'B' ; + .word LBB_BINS ; BIN$ + .byte 7,'B' ; + .word LBB_BITTST ; BITTST + .byte 4,'M' ; + .word LBB_MAX ; MAX + .byte 4,'M' ; + .word LBB_MIN ; MIN + .byte 2,'P' ; + .word LBB_PI ; PI + .byte 5,'T' ; + .word LBB_TWOPI ; TWOPI + .byte 7,'V' ; + .word LBB_VPTR ; VARPTR + .byte 6,'L' ; + .word LBB_LEFTS ; LEFT$ + .byte 7,'R' ; + .word LBB_RIGHTS ; RIGHT$ + .byte 5,'M' ; + .word LBB_MIDS ; MID$ + +; BASIC messages, mostly error messages + +LAB_BAER + .word ERR_NF ;$00 NEXT without FOR + .word ERR_SN ;$02 syntax + .word ERR_RG ;$04 RETURN without GOSUB + .word ERR_OD ;$06 out of data + .word ERR_FC ;$08 function call + .word ERR_OV ;$0A overflow + .word ERR_OM ;$0C out of memory + .word ERR_US ;$0E undefined statement + .word ERR_BS ;$10 array bounds + .word ERR_DD ;$12 double dimension array + .word ERR_D0 ;$14 divide by 0 + .word ERR_ID ;$16 illegal direct + .word ERR_TM ;$18 type mismatch + .word ERR_LS ;$1A long string + .word ERR_ST ;$1C string too complex + .word ERR_CN ;$1E continue error + .word ERR_UF ;$20 undefined function + .word ERR_LD ;$22 LOOP without DO + +; I may implement these two errors to force definition of variables and +; dimensioning of arrays before use. + +; .word ERR_UV ;$24 undefined variable + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +; .word ERR_UA ;$26 undimensioned array + +ERR_NF .byte "NEXT without FOR",$00 +ERR_SN .byte "Syntax",$00 +ERR_RG .byte "RETURN without GOSUB",$00 +ERR_OD .byte "Out of DATA",$00 +ERR_FC .byte "Function call",$00 +ERR_OV .byte "Overflow",$00 +ERR_OM .byte "Out of memory",$00 +ERR_US .byte "Undefined statement",$00 +ERR_BS .byte "Array bounds",$00 +ERR_DD .byte "Double dimension",$00 +ERR_D0 .byte "Divide by zero",$00 +ERR_ID .byte "Illegal direct",$00 +ERR_TM .byte "Type mismatch",$00 +ERR_LS .byte "String too long",$00 +ERR_ST .byte "String too complex",$00 +ERR_CN .byte "Can't continue",$00 +ERR_UF .byte "Undefined function",$00 +ERR_LD .byte "LOOP without DO",$00 + +;ERR_UV .byte "Undefined variable",$00 + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +;ERR_UA .byte "Undimensioned array",$00 + +LAB_BMSG .byte $0D,$0A,"Break",$00 +LAB_EMSG .byte " Error",$00 +LAB_LMSG .byte " in line ",$00 +LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 + +LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 +LAB_REDO .byte " Redo from start",$0D,$0A,$00 + +AA_end_basic diff --git a/eh_basic_kow.asm b/eh_basic_kow.asm new file mode 100644 index 0000000..382b368 --- /dev/null +++ b/eh_basic_kow.asm @@ -0,0 +1,8724 @@ + +; The code below was copied and adapted from Lee Davison’s +; code of EhBasic to be ran in Michal Kowalski's 6502 emulator. +; Original comments and credits follow: +; +; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22 + +; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825 + +; 2.00 new revision numbers start here +; 2.01 fixed LCASE$() and UCASE$() +; 2.02 new get value routine done +; 2.03 changed RND() to galoise method +; 2.04 fixed SPC() +; 2.05 new get value routine fixed +; 2.06 changed USR() code +; 2.07 fixed STR$() +; 2.08 changed INPUT and READ to remove need for $00 start to input buffer +; 2.09 fixed RND() +; 2.10 integrated missed changes from an earlier version +; 2.20 added ELSE to IF .. THEN and fixed IF .. GOTO to cause error +; 2.21 fixed IF .. THEN RETURN to not cause error +; 2.22 fixed RND() breaking the get byte routine + +; zero page use .. + +LAB_WARM = $00 ; BASIC warm start entry point +Wrmjpl = LAB_WARM+1; BASIC warm start vector jump low byte +Wrmjph = LAB_WARM+2; BASIC warm start vector jump high byte + +Usrjmp = $0A ; USR function JMP address +Usrjpl = Usrjmp+1 ; USR function JMP vector low byte +Usrjph = Usrjmp+2 ; USR function JMP vector high byte +Nullct = $0D ; nulls output after each line +TPos = $0E ; BASIC terminal position byte +TWidth = $0F ; BASIC terminal width byte +Iclim = $10 ; input column limit +Itempl = $11 ; temporary integer low byte +Itemph = Itempl+1 ; temporary integer high byte + +nums_1 = Itempl ; number to bin/hex string convert MSB +nums_2 = nums_1+1 ; number to bin/hex string convert +nums_3 = nums_1+2 ; number to bin/hex string convert LSB + +Srchc = $5B ; search character +Temp3 = Srchc ; temp byte used in number routines +Scnquo = $5C ; scan-between-quotes flag +Asrch = Scnquo ; alt search character + +XOAw_l = Srchc ; eXclusive OR, OR and AND word low byte +XOAw_h = Scnquo ; eXclusive OR, OR and AND word high byte + +Ibptr = $5D ; input buffer pointer +Dimcnt = Ibptr ; # of dimensions +Tindx = Ibptr ; token index + +Defdim = $5E ; default DIM flag +Dtypef = $5F ; data type flag, $FF=string, $00=numeric +Oquote = $60 ; open quote flag (b7) (Flag: DATA scan; LIST quote; memory) +Gclctd = $60 ; garbage collected flag +Sufnxf = $61 ; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx) +Imode = $62 ; input mode flag, $00=INPUT, $80=READ + +Cflag = $63 ; comparison evaluation flag + +TabSiz = $64 ; TAB step size (was input flag) + +next_s = $65 ; next descriptor stack address + + ; these two bytes form a word pointer to the item + ; currently on top of the descriptor stack +last_sl = $66 ; last descriptor stack address low byte +last_sh = $67 ; last descriptor stack address high byte (always $00) + +des_sk = $68 ; descriptor stack start address (temp strings) + +; = $70 ; End of descriptor stack + +ut1_pl = $71 ; utility pointer 1 low byte +ut1_ph = ut1_pl+1 ; utility pointer 1 high byte +ut2_pl = $73 ; utility pointer 2 low byte +ut2_ph = ut2_pl+1 ; utility pointer 2 high byte + +Temp_2 = ut1_pl ; temp byte for block move + +FACt_1 = $75 ; FAC temp mantissa1 +FACt_2 = FACt_1+1 ; FAC temp mantissa2 +FACt_3 = FACt_2+1 ; FAC temp mantissa3 + +dims_l = FACt_2 ; array dimension size low byte +dims_h = FACt_3 ; array dimension size high byte + +TempB = $78 ; temp page 0 byte + +Smeml = $79 ; start of mem low byte (Start-of-Basic) +Smemh = Smeml+1 ; start of mem high byte (Start-of-Basic) +Svarl = $7B ; start of vars low byte (Start-of-Variables) +Svarh = Svarl+1 ; start of vars high byte (Start-of-Variables) +Sarryl = $7D ; var mem end low byte (Start-of-Arrays) +Sarryh = Sarryl+1 ; var mem end high byte (Start-of-Arrays) +Earryl = $7F ; array mem end low byte (End-of-Arrays) +Earryh = Earryl+1 ; array mem end high byte (End-of-Arrays) +Sstorl = $81 ; string storage low byte (String storage (moving down)) +Sstorh = Sstorl+1 ; string storage high byte (String storage (moving down)) +Sutill = $83 ; string utility ptr low byte +Sutilh = Sutill+1 ; string utility ptr high byte +Ememl = $85 ; end of mem low byte (Limit-of-memory) +Ememh = Ememl+1 ; end of mem high byte (Limit-of-memory) +Clinel = $87 ; current line low byte (Basic line number) +Clineh = Clinel+1 ; current line high byte (Basic line number) +Blinel = $89 ; break line low byte (Previous Basic line number) +Blineh = Blinel+1 ; break line high byte (Previous Basic line number) + +Cpntrl = $8B ; continue pointer low byte +Cpntrh = Cpntrl+1 ; continue pointer high byte + +Dlinel = $8D ; current DATA line low byte +Dlineh = Dlinel+1 ; current DATA line high byte + +Dptrl = $8F ; DATA pointer low byte +Dptrh = Dptrl+1 ; DATA pointer high byte + +Rdptrl = $91 ; read pointer low byte +Rdptrh = Rdptrl+1 ; read pointer high byte + +Varnm1 = $93 ; current var name 1st byte +Varnm2 = Varnm1+1 ; current var name 2nd byte + +Cvaral = $95 ; current var address low byte +Cvarah = Cvaral+1 ; current var address high byte + +Frnxtl = $97 ; var pointer for FOR/NEXT low byte +Frnxth = Frnxtl+1 ; var pointer for FOR/NEXT high byte + +Tidx1 = Frnxtl ; temp line index + +Lvarpl = Frnxtl ; let var pointer low byte +Lvarph = Frnxth ; let var pointer high byte + +prstk = $99 ; precedence stacked flag + +comp_f = $9B ; compare function flag, bits 0,1 and 2 used + ; bit 2 set if > + ; bit 1 set if = + ; bit 0 set if < + +func_l = $9C ; function pointer low byte +func_h = func_l+1 ; function pointer high byte + +garb_l = func_l ; garbage collection working pointer low byte +garb_h = func_h ; garbage collection working pointer high byte + +des_2l = $9E ; string descriptor_2 pointer low byte +des_2h = des_2l+1 ; string descriptor_2 pointer high byte + +g_step = $A0 ; garbage collect step size + +Fnxjmp = $A1 ; jump vector for functions +Fnxjpl = Fnxjmp+1 ; functions jump vector low byte +Fnxjph = Fnxjmp+2 ; functions jump vector high byte + +g_indx = Fnxjpl ; garbage collect temp index + +FAC2_r = $A3 ; FAC2 rounding byte + +Adatal = $A4 ; array data pointer low byte +Adatah = Adatal+1 ; array data pointer high byte + +Nbendl = Adatal ; new block end pointer low byte +Nbendh = Adatah ; new block end pointer high byte + +Obendl = $A6 ; old block end pointer low byte +Obendh = Obendl+1 ; old block end pointer high byte + +numexp = $A8 ; string to float number exponent count +expcnt = $A9 ; string to float exponent count + +numbit = numexp ; bit count for array element calculations + +numdpf = $AA ; string to float decimal point flag +expneg = $AB ; string to float eval exponent -ve flag + +Astrtl = numdpf ; array start pointer low byte +Astrth = expneg ; array start pointer high byte + +Histrl = numdpf ; highest string low byte +Histrh = expneg ; highest string high byte + +Baslnl = numdpf ; BASIC search line pointer low byte +Baslnh = expneg ; BASIC search line pointer high byte + +Fvar_l = numdpf ; find/found variable pointer low byte +Fvar_h = expneg ; find/found variable pointer high byte + +Ostrtl = numdpf ; old block start pointer low byte +Ostrth = expneg ; old block start pointer high byte + +Vrschl = numdpf ; variable search pointer low byte +Vrschh = expneg ; variable search pointer high byte + +FAC1_e = $AC ; FAC1 exponent +FAC1_1 = FAC1_e+1 ; FAC1 mantissa1 +FAC1_2 = FAC1_e+2 ; FAC1 mantissa2 +FAC1_3 = FAC1_e+3 ; FAC1 mantissa3 +FAC1_s = FAC1_e+4 ; FAC1 sign (b7) + +str_ln = FAC1_e ; string length +str_pl = FAC1_1 ; string pointer low byte +str_ph = FAC1_2 ; string pointer high byte + +des_pl = FAC1_2 ; string descriptor pointer low byte +des_ph = FAC1_3 ; string descriptor pointer high byte + +mids_l = FAC1_3 ; MID$ string temp length byte + +negnum = $B1 ; string to float eval -ve flag +numcon = $B1 ; series evaluation constant count + +FAC1_o = $B2 ; FAC1 overflow byte + +FAC2_e = $B3 ; FAC2 exponent +FAC2_1 = FAC2_e+1 ; FAC2 mantissa1 +FAC2_2 = FAC2_e+2 ; FAC2 mantissa2 +FAC2_3 = FAC2_e+3 ; FAC2 mantissa3 +FAC2_s = FAC2_e+4 ; FAC2 sign (b7) + +FAC_sc = $B8 ; FAC sign comparison, Acc#1 vs #2 +FAC1_r = $B9 ; FAC1 rounding byte + +ssptr_l = FAC_sc ; string start pointer low byte +ssptr_h = FAC1_r ; string start pointer high byte + +sdescr = FAC_sc ; string descriptor pointer + +csidx = $BA ; line crunch save index +Asptl = csidx ; array size/pointer low byte +Aspth = $BB ; array size/pointer high byte + +Btmpl = Asptl ; BASIC pointer temp low byte +Btmph = Aspth ; BASIC pointer temp low byte + +Cptrl = Asptl ; BASIC pointer temp low byte +Cptrh = Aspth ; BASIC pointer temp low byte + +Sendl = Asptl ; BASIC pointer temp low byte +Sendh = Aspth ; BASIC pointer temp low byte + +LAB_IGBY = $BC ; get next BASIC byte subroutine + +LAB_GBYT = $C2 ; get current BASIC byte subroutine +Bpntrl = $C3 ; BASIC execute (get byte) pointer low byte +Bpntrh = Bpntrl+1 ; BASIC execute (get byte) pointer high byte + +; = $D7 ; end of get BASIC char subroutine + +Rbyte4 = $D8 ; extra PRNG byte +Rbyte1 = Rbyte4+1 ; most significant PRNG byte +Rbyte2 = Rbyte4+2 ; middle PRNG byte +Rbyte3 = Rbyte4+3 ; least significant PRNG byte + +NmiBase = $DC ; NMI handler enabled/setup/triggered flags + ; bit function + ; === ======== + ; 7 interrupt enabled + ; 6 interrupt setup + ; 5 interrupt happened +; = $DD ; NMI handler addr low byte +; = $DE ; NMI handler addr high byte +IrqBase = $DF ; IRQ handler enabled/setup/triggered flags +; = $E0 ; IRQ handler addr low byte +; = $E1 ; IRQ handler addr high byte + +; = $DE ; unused +; = $DF ; unused +; = $E0 ; unused +; = $E1 ; unused +; = $E2 ; unused +; = $E3 ; unused +; = $E4 ; unused +; = $E5 ; unused +; = $E6 ; unused +; = $E7 ; unused +; = $E8 ; unused +; = $E9 ; unused +; = $EA ; unused +; = $EB ; unused +; = $EC ; unused +; = $ED ; unused +; = $EE ; unused + +Decss = $EF ; number to decimal string start +Decssp1 = Decss+1 ; number to decimal string start + +; = $FF ; decimal string end + +; token values needed for BASIC + +; primary command tokens (can start a statement) + +TK_END = $80 ; END token +TK_FOR = TK_END+1 ; FOR token +TK_NEXT = TK_FOR+1 ; NEXT token +TK_DATA = TK_NEXT+1 ; DATA token +TK_INPUT = TK_DATA+1 ; INPUT token +TK_DIM = TK_INPUT+1 ; DIM token +TK_READ = TK_DIM+1 ; READ token +TK_LET = TK_READ+1 ; LET token +TK_DEC = TK_LET+1 ; DEC token +TK_GOTO = TK_DEC+1 ; GOTO token +TK_RUN = TK_GOTO+1 ; RUN token +TK_IF = TK_RUN+1 ; IF token +TK_RESTORE = TK_IF+1 ; RESTORE token +TK_GOSUB = TK_RESTORE+1 ; GOSUB token +TK_RETIRQ = TK_GOSUB+1 ; RETIRQ token +TK_RETNMI = TK_RETIRQ+1 ; RETNMI token +TK_RETURN = TK_RETNMI+1 ; RETURN token +TK_REM = TK_RETURN+1 ; REM token +TK_STOP = TK_REM+1 ; STOP token +TK_ON = TK_STOP+1 ; ON token +TK_NULL = TK_ON+1 ; NULL token +TK_INC = TK_NULL+1 ; INC token +TK_WAIT = TK_INC+1 ; WAIT token +TK_LOAD = TK_WAIT+1 ; LOAD token +TK_SAVE = TK_LOAD+1 ; SAVE token +TK_DEF = TK_SAVE+1 ; DEF token +TK_POKE = TK_DEF+1 ; POKE token +TK_DOKE = TK_POKE+1 ; DOKE token +TK_CALL = TK_DOKE+1 ; CALL token +TK_DO = TK_CALL+1 ; DO token +TK_LOOP = TK_DO+1 ; LOOP token +TK_PRINT = TK_LOOP+1 ; PRINT token +TK_CONT = TK_PRINT+1 ; CONT token +TK_LIST = TK_CONT+1 ; LIST token +TK_CLEAR = TK_LIST+1 ; CLEAR token +TK_NEW = TK_CLEAR+1 ; NEW token +TK_WIDTH = TK_NEW+1 ; WIDTH token +TK_GET = TK_WIDTH+1 ; GET token +TK_SWAP = TK_GET+1 ; SWAP token +TK_BITSET = TK_SWAP+1 ; BITSET token +TK_BITCLR = TK_BITSET+1 ; BITCLR token +TK_IRQ = TK_BITCLR+1 ; IRQ token +TK_NMI = TK_IRQ+1 ; NMI token + +; secondary command tokens, can't start a statement + +TK_TAB = TK_NMI+1 ; TAB token +TK_ELSE = TK_TAB+1 ; ELSE token +TK_TO = TK_ELSE+1 ; TO token +TK_FN = TK_TO+1 ; FN token +TK_SPC = TK_FN+1 ; SPC token +TK_THEN = TK_SPC+1 ; THEN token +TK_NOT = TK_THEN+1 ; NOT token +TK_STEP = TK_NOT+1 ; STEP token +TK_UNTIL = TK_STEP+1 ; UNTIL token +TK_WHILE = TK_UNTIL+1 ; WHILE token +TK_OFF = TK_WHILE+1 ; OFF token + +; opperator tokens + +TK_PLUS = TK_OFF+1 ; + token +TK_MINUS = TK_PLUS+1 ; - token +TK_MUL = TK_MINUS+1 ; * token +TK_DIV = TK_MUL+1 ; / token +TK_POWER = TK_DIV+1 ; ^ token +TK_AND = TK_POWER+1 ; AND token +TK_EOR = TK_AND+1 ; EOR token +TK_OR = TK_EOR+1 ; OR token +TK_RSHIFT = TK_OR+1 ; RSHIFT token +TK_LSHIFT = TK_RSHIFT+1 ; LSHIFT token +TK_GT = TK_LSHIFT+1 ; > token +TK_EQUAL = TK_GT+1 ; = token +TK_LT = TK_EQUAL+1 ; < token + +; functions tokens + +TK_SGN = TK_LT+1 ; SGN token +TK_INT = TK_SGN+1 ; INT token +TK_ABS = TK_INT+1 ; ABS token +TK_USR = TK_ABS+1 ; USR token +TK_FRE = TK_USR+1 ; FRE token +TK_POS = TK_FRE+1 ; POS token +TK_SQR = TK_POS+1 ; SQR token +TK_RND = TK_SQR+1 ; RND token +TK_LOG = TK_RND+1 ; LOG token +TK_EXP = TK_LOG+1 ; EXP token +TK_COS = TK_EXP+1 ; COS token +TK_SIN = TK_COS+1 ; SIN token +TK_TAN = TK_SIN+1 ; TAN token +TK_ATN = TK_TAN+1 ; ATN token +TK_PEEK = TK_ATN+1 ; PEEK token +TK_DEEK = TK_PEEK+1 ; DEEK token +TK_SADD = TK_DEEK+1 ; SADD token +TK_LEN = TK_SADD+1 ; LEN token +TK_STRS = TK_LEN+1 ; STR$ token +TK_VAL = TK_STRS+1 ; VAL token +TK_ASC = TK_VAL+1 ; ASC token +TK_UCASES = TK_ASC+1 ; UCASE$ token +TK_LCASES = TK_UCASES+1 ; LCASE$ token +TK_CHRS = TK_LCASES+1 ; CHR$ token +TK_HEXS = TK_CHRS+1 ; HEX$ token +TK_BINS = TK_HEXS+1 ; BIN$ token +TK_BITTST = TK_BINS+1 ; BITTST token +TK_MAX = TK_BITTST+1 ; MAX token +TK_MIN = TK_MAX+1 ; MIN token +TK_PI = TK_MIN+1 ; PI token +TK_TWOPI = TK_PI+1 ; TWOPI token +TK_VPTR = TK_TWOPI+1 ; VARPTR token +TK_LEFTS = TK_VPTR+1 ; LEFT$ token +TK_RIGHTS = TK_LEFTS+1 ; RIGHT$ token +TK_MIDS = TK_RIGHTS+1 ; MID$ token + +; offsets from a base of X or Y + +PLUS_0 = $00 ; X or Y plus 0 +PLUS_1 = $01 ; X or Y plus 1 +PLUS_2 = $02 ; X or Y plus 2 +PLUS_3 = $03 ; X or Y plus 3 + +LAB_STAK = $0100 ; stack bottom, no offset + +LAB_SKFE = LAB_STAK+$FE + ; flushed stack address +LAB_SKFF = LAB_STAK+$FF + ; flushed stack address + +ccflag = $0200 ; BASIC CTRL-C flag, 00 = enabled, 01 = dis +ccbyte = ccflag+1 ; BASIC CTRL-C byte +ccnull = ccbyte+1 ; BASIC CTRL-C byte timeout + +VEC_CC = ccnull+1 ; ctrl c check vector + +VEC_IN = VEC_CC+2 ; input vector +VEC_OUT = VEC_IN+2 ; output vector +VEC_LD = VEC_OUT+2 ; load vector +VEC_SV = VEC_LD+2 ; save vector + +; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80 + +IRQ_vec = VEC_SV+2 + +Ibuffs = IRQ_vec+$14 ; start of input buffer after IRQ/NMI code +Ibuffe = Ibuffs+$47 ; end of input buffer + + .ORG $FFC0 + +; I/O routines for Michal Kowalski's 6502 emulator. + +CHRIN + LDA $E004 ; Read from char IO address, non-blocking + BEQ ECHRIN ; if null, assume no character in buffer + CMP #'a' ; < 'a'? + BCC DCHRIN ; yes, done + CMP #'{' ; >= '{'? + BCS DCHRIN ; yes, done + AND #$5F ; no, convert to upper case +DCHRIN + SEC ; These is character waiting, set CARRY flag + RTS +ECHRIN + CLC ; no character in buffer, clear CARRY + RTS + +CHROUT + STA $E001 ; write to char IO address + AND #$FF ; set flags + RTS + + +Ram_base = $0300 ; start of user RAM (set as needed, should be page aligned) +Ram_top = $C000 ; end of user RAM+1 (set as needed, should be page aligned) + +; This start can be changed to suit your system + + *= $C000 + +; BASIC cold start entry point + +; new page 2 initialisation, copy block to ccflag on + +LAB_COLD + CLD + LDY #PG2_TABE-PG2_TABS-1 + ; byte count-1 +LAB_2D13 + LDA PG2_TABS,Y ; get byte + STA ccflag,Y ; store in page 2 + DEY ; decrement count + BPL LAB_2D13 ; loop if not done + + LDX #$FF ; set byte + STX Ibuffs + STX Clineh ; set current line high byte (set immediate mode) + TXS ; reset stack pointer + + LDA #$4C ; code for JMP + STA Fnxjmp ; save for jump vector for functions + +; copy block from LAB_2CEE to $00BC - $00D3 + + LDX #StrTab-LAB_2CEE ; set byte count +LAB_2D4E + LDA LAB_2CEE-1,X ; get byte from table + STA LAB_IGBY-1,X ; save byte in page zero + DEX ; decrement count + BNE LAB_2D4E ; loop if not all done + +; copy block from StrTab to $0000 - $0012 + +LAB_GMEM + LDX #EndTab-StrTab-1 ; set byte count-1 +TabLoop + LDA StrTab,X ; get byte from table + STA PLUS_0,X ; save byte in page zero + DEX ; decrement count + BPL TabLoop ; loop if not all done + +; set-up start values + + LDA #$00 ; clear A + STA NmiBase ; clear NMI handler enabled flag + STA IrqBase ; clear IRQ handler enabled flag + STA FAC1_o ; clear FAC1 overflow byte + STA last_sh ; clear descriptor stack top item pointer high byte + + LDA #$0E ; set default tab size + STA TabSiz ; save it + LDA #$03 ; set garbage collect step size for descriptor stack + STA g_step ; save it + LDX #des_sk ; descriptor stack start + STX next_s ; set descriptor stack pointer + JSR LAB_CRLF ; print CR/LF + LDA #LAB_MSZM ; point to memory size message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; get last byte back + + BNE LAB_2DAA ; branch if not null (user typed something) + + LDY #$00 ; else clear Y + ; character was null so get memory size the hard way + ; we get here with Y=0 and Itempl/h = Ram_base +LAB_2D93 + INC Itempl ; increment temporary integer low byte + BNE LAB_2D99 ; branch if no overflow + + INC Itemph ; increment temporary integer high byte + LDA Itemph ; get high byte + CMP #>Ram_top ; compare with top of RAM+1 + BEQ LAB_2DB6 ; branch if match (end of user RAM) + +LAB_2D99 + LDA #$55 ; set test byte + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BNE LAB_2DB6 ; branch if fail + + ASL ; shift test byte left (now $AA) + STA (Itempl),Y ; save via temporary integer + CMP (Itempl),Y ; compare via temporary integer + BEQ LAB_2D93 ; if ok go do next byte + + BNE LAB_2DB6 ; branch if fail + +LAB_2DAA + JSR LAB_2887 ; get FAC1 from string + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_GMEM ; if too large go try again + + JSR LAB_F2FU ; save integer part of FAC1 in temporary integer + ; (no range check) + +LAB_2DB6 + LDA Itempl ; get temporary integer low byte + LDY Itemph ; get temporary integer high byte + CPY #Ram_top ; compare with top of RAM high byte +; BCC MEM_OK ; branch if < RAM top + +; BNE LAB_GMEM ; if too large go try again + ; else was = so compare low bytes +; CMP #Ram_base ; set start addr high byte + STY Smeml ; save start of mem low byte + STX Smemh ; save start of mem high byte + +; this line is only needed if Ram_base is not $xx00 + +; LDY #$00 ; clear Y + TYA ; clear A + STA (Smeml),Y ; clear first byte + INC Smeml ; increment start of mem low byte + +; these two lines are only needed if Ram_base is $xxFF + +; BNE LAB_2E05 ; branch if no rollover + +; INC Smemh ; increment start of mem high byte +LAB_2E05 + JSR LAB_CRLF ; print CR/LF + JSR LAB_1463 ; do "NEW" and "CLEAR" + LDA Ememl ; get end of mem low byte + SEC ; set carry for subtract + SBC Smeml ; subtract start of mem low byte + TAX ; copy to X + LDA Ememh ; get end of mem high byte + SBC Smemh ; subtract start of mem high byte + JSR LAB_295E ; print XA as unsigned integer (bytes free) + LDA #LAB_SMSG ; point to sign-on message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA #LAB_1274 ; warm start vector high byte + STA Wrmjpl ; save warm start vector low byte + STY Wrmjph ; save warm start vector high byte + JMP (Wrmjpl) ; go do warm start + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) + +; Nbendl,Nbendh - new block end address (A/Y) +; Obendl,Obendh - old block end address +; Ostrtl,Ostrth - old block start address + +; returns with .. + +; Nbendl,Nbendh - new block start address (high byte - $100) +; Obendl,Obendh - old block start address (high byte - $100) +; Ostrtl,Ostrth - old block start address (unchanged) + +LAB_11CF + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save new array mem end low byte + STY Earryh ; save new array mem end high byte + +; open up space in memory +; move (Ostrtl)-(Obendl) to new block ending at (Nbendl) +; don't set array end + +LAB_11D6 + SEC ; set carry for subtract + LDA Obendl ; get block end low byte + SBC Ostrtl ; subtract block start low byte + TAY ; copy MOD(block length/$100) byte to Y + LDA Obendh ; get block end high byte + SBC Ostrth ; subtract block start high byte + TAX ; copy block length high byte to X + INX ; +1 to allow for count=0 exit + TYA ; copy block length low byte to A + BEQ LAB_120A ; branch if length low byte=0 + + ; block is (X-1)*256+Y bytes, do the Y bytes first + + SEC ; set carry for add + 1, two's complement + EOR #$FF ; invert low byte for subtract + ADC Obendl ; add block end low byte + + STA Obendl ; save corrected old block end low byte + BCS LAB_11F3 ; branch if no underflow + + DEC Obendh ; else decrement block end high byte + SEC ; set carry for add + 1, two's complement +LAB_11F3 + TYA ; get MOD(block length/$100) byte + EOR #$FF ; invert low byte for subtract + ADC Nbendl ; add destination end low byte + STA Nbendl ; save modified new block end low byte + BCS LAB_1203 ; branch if no underflow + + DEC Nbendh ; else decrement block end high byte + BCC LAB_1203 ; branch always + +LAB_11FF + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; copy byte to destination +LAB_1203 + DEY ; decrement index + BNE LAB_11FF ; loop until Y=0 + + ; now do Y=0 indexed byte + LDA (Obendl),Y ; get byte from source + STA (Nbendl),Y ; save byte to destination +LAB_120A + DEC Obendh ; decrement source pointer high byte + DEC Nbendh ; decrement destination pointer high byte + DEX ; decrement block count + BNE LAB_1203 ; loop until count = $0 + + RTS + +; check room on stack for A bytes +; stack too deep? do OM error + +LAB_1212 + STA TempB ; save result in temp byte + TSX ; copy stack + CPX TempB ; compare new "limit" with stack + BCC LAB_OMER ; if stack < limit do "Out of memory" error then warm start + + RTS + +; check available memory, "Out of memory" error if no room +; addr to check is in AY (low/high) + +LAB_121F + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_1229 ; skip next test if greater (tested <) + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCC LAB_124B ; if less then exit (is ok) + + ; addr is > string storage ptr (oops!) +LAB_1229 + PHA ; push addr low byte + LDX #$08 ; set index to save Adatal to expneg inclusive + TYA ; copy addr high byte (to push on stack) + + ; save misc numeric work area +LAB_122D + PHA ; push byte + LDA Adatal-1,X ; get byte from Adatal to expneg ( ,$00 not pushed) + DEX ; decrement index + BPL LAB_122D ; loop until all done + + JSR LAB_GARB ; garbage collection routine + + ; restore misc numeric work area + LDX #$00 ; clear the index to restore bytes +LAB_1238 + PLA ; pop byte + STA Adatal,X ; save byte to Adatal to expneg + INX ; increment index + CPX #$08 ; compare with end + 1 + BMI LAB_1238 ; loop if more to do + + PLA ; pop addr high byte + TAY ; copy back to Y + PLA ; pop addr low byte + CPY Sstorh ; compare bottom of string mem high byte + BCC LAB_124B ; if less then exit (is ok) + + BNE LAB_OMER ; if greater do "Out of memory" error then warm start + + ; high byte was =, now do low byte + CMP Sstorl ; compare with bottom of string mem low byte + BCS LAB_OMER ; if >= do "Out of memory" error then warm start + + ; ok exit, carry clear +LAB_124B + RTS + +; do "Out of memory" error then warm start + +LAB_OMER + LDX #$0C ; error code $0C ("Out of memory" error) + +; do error #X, then warm start + +LAB_XERR + JSR LAB_CRLF ; print CR/LF + + LDA LAB_BAER,X ; get error message pointer low byte + LDY LAB_BAER+1,X ; get error message pointer high byte + JSR LAB_18C3 ; print null terminated string from memory + + JSR LAB_1491 ; flush stack and clear continue flag + LDA #LAB_EMSG ; point to " Error" high addr +LAB_1269 + JSR LAB_18C3 ; print null terminated string from memory + LDY Clineh ; get current line high byte + INY ; increment it + BEQ LAB_1274 ; go do warm start (was immediate mode) + + ; else print line number + JSR LAB_2953 ; print " in line [LINE #]" + +; BASIC warm start entry point +; wait for Basic command + +LAB_1274 + ; clear ON IRQ/NMI bytes + LDA #$00 ; clear A + STA IrqBase ; clear enabled byte + STA NmiBase ; clear enabled byte + LDA #LAB_RMSG ; point to "Ready" message high byte + + JSR LAB_18C3 ; go do print string + CLC + +; wait for Basic command (no "Ready") + +LAB_127D + JSR LAB_1357 ; call for BASIC input +LAB_1280 + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_127D ; loop while null + +; got to interpret input line now .. + + LDX #$FF ; current line to null value + STX Clineh ; set current line high byte + BCC LAB_1295 ; branch if numeric character (handle new BASIC line) + + ; no line number .. immediate mode + JSR LAB_13A6 ; crunch keywords into Basic tokens + JMP LAB_15F6 ; go scan and interpret code + +; handle new BASIC line + +LAB_1295 + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_13A6 ; crunch keywords into Basic tokens + STY Ibptr ; save index pointer to end of crunched line + JSR LAB_SSLN ; search BASIC for temp integer line number + BCC LAB_12E6 ; branch if not found + + ; aroooogah! line # already exists! delete it + LDY #$01 ; set index to next line pointer high byte + LDA (Baslnl),Y ; get next line pointer high byte + STA ut1_ph ; save it + LDA Svarl ; get start of vars low byte + STA ut1_pl ; save it + LDA Baslnh ; get found line pointer high byte + STA ut2_ph ; save it + LDA Baslnl ; get found line pointer low byte + DEY ; decrement index + SBC (Baslnl),Y ; subtract next line pointer low byte + CLC ; clear carry for add + ADC Svarl ; add start of vars low byte + STA Svarl ; save new start of vars low byte + STA ut2_pl ; save destination pointer low byte + LDA Svarh ; get start of vars high byte + ADC #$FF ; -1 + carry + STA Svarh ; save start of vars high byte + SBC Baslnh ; subtract found line pointer high byte + TAX ; copy to block count + SEC ; set carry for subtract + LDA Baslnl ; get found line pointer low byte + SBC Svarl ; subtract start of vars low byte + TAY ; copy to bytes in first block count + BCS LAB_12D0 ; branch if overflow + + INX ; increment block count (correct for =0 loop exit) + DEC ut2_ph ; decrement destination high byte +LAB_12D0 + CLC ; clear carry for add + ADC ut1_pl ; add source pointer low byte + BCC LAB_12D8 ; branch if no overflow + + DEC ut1_ph ; else decrement source pointer high byte + CLC ; clear carry + + ; close up memory to delete old line +LAB_12D8 + LDA (ut1_pl),Y ; get byte from source + STA (ut2_pl),Y ; copy to destination + INY ; increment index + BNE LAB_12D8 ; while <> 0 do this block + + INC ut1_ph ; increment source pointer high byte + INC ut2_ph ; increment destination pointer high byte + DEX ; decrement block count + BNE LAB_12D8 ; loop until all done + + ; got new line in buffer and no existing same # +LAB_12E6 + LDA Ibuffs ; get byte from start of input buffer + BEQ LAB_1319 ; if null line just go flush stack/vars and exit + + ; got new line and it isn't empty line + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte (end of BASIC) + STA Obendl ; save old block end low byte + LDY Svarh ; get start of vars high byte (end of BASIC) + STY Obendh ; save old block end high byte + ADC Ibptr ; add input buffer pointer (also buffer length) + BCC LAB_1301 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1301 + STA Nbendl ; save new block end low byte (move to, low byte) + STY Nbendh ; save new block end high byte + JSR LAB_11CF ; open up space in memory + ; old start pointer Ostrtl,Ostrth set by the find line call + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Svarl ; save start of vars low byte + STY Svarh ; save start of vars high byte + LDY Ibptr ; get input buffer pointer (also buffer length) + DEY ; adjust for loop type +LAB_1311 + LDA Ibuffs-4,Y ; get byte from crunched line + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + CPY #$03 ; compare with first byte-1 + BNE LAB_1311 ; continue while count <> 3 + + LDA Itemph ; get line # high byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA Itempl ; get line # low byte + STA (Baslnl),Y ; save it to program memory + DEY ; decrement count + LDA #$FF ; set byte to allow chain rebuild. if you didn't set this + ; byte then a zero already here would stop the chain rebuild + ; as it would think it was the [EOT] marker. + STA (Baslnl),Y ; save it to program memory + +LAB_1319 + JSR LAB_1477 ; reset execution to start, clear vars and flush stack + LDX Smeml ; get start of mem low byte + LDA Smemh ; get start of mem high byte + LDY #$01 ; index to high byte of next line pointer +LAB_1325 + STX ut1_pl ; set line start pointer low byte + STA ut1_ph ; set line start pointer high byte + LDA (ut1_pl),Y ; get it + BEQ LAB_133E ; exit if end of program + +; rebuild chaining of Basic lines + + LDY #$04 ; point to first code byte of line + ; there is always 1 byte + [EOL] as null entries are deleted +LAB_1330 + INY ; next code byte + LDA (ut1_pl),Y ; get byte + BNE LAB_1330 ; loop if not [EOL] + + SEC ; set carry for add + 1 + TYA ; copy end index + ADC ut1_pl ; add to line start pointer low byte + TAX ; copy to X + LDY #$00 ; clear index, point to this line's next line pointer + STA (ut1_pl),Y ; set next line pointer low byte + TYA ; clear A + ADC ut1_ph ; add line start pointer high byte + carry + INY ; increment index to high byte + STA (ut1_pl),Y ; save next line pointer low byte + BCC LAB_1325 ; go do next line, branch always, carry clear + + +LAB_133E + JMP LAB_127D ; else we just wait for Basic command, no "Ready" + +; print "? " and get BASIC input + +LAB_INLN + JSR LAB_18E3 ; print "?" character + JSR LAB_18E0 ; print " " + BNE LAB_1357 ; call for BASIC input and return + +; receive line from keyboard + + ; $08 as delete key (BACKSPACE on standard keyboard) +LAB_134B + JSR LAB_PRNA ; go print the character + DEX ; decrement the buffer counter (delete) + .byte $2C ; make LDX into BIT abs + +; call for BASIC input (main entry point) + +LAB_1357 + LDX #$00 ; clear BASIC line buffer pointer +LAB_1359 + JSR V_INPT ; call scan input device + BCC LAB_1359 ; loop if no byte + + BEQ LAB_1359 ; loop until valid input (ignore NULLs) + + CMP #$07 ; compare with [BELL] + BEQ LAB_1378 ; branch if [BELL] + + CMP #$0D ; compare with [CR] + BEQ LAB_1384 ; do CR/LF exit if [CR] + + CPX #$00 ; compare pointer with $00 + BNE LAB_1374 ; branch if not empty + +; next two lines ignore any non print character and [SPACE] if input buffer empty + + CMP #$21 ; compare with [SP]+1 + BCC LAB_1359 ; if < ignore character + +LAB_1374 + CMP #$08 ; compare with [BACKSPACE] (delete last character) + BEQ LAB_134B ; go delete last character + +LAB_1378 + CPX #Ibuffe-Ibuffs ; compare character count with max + BCS LAB_138E ; skip store and do [BELL] if buffer full + + STA Ibuffs,X ; else store in buffer + INX ; increment pointer +LAB_137F + JSR LAB_PRNA ; go print the character + BNE LAB_1359 ; always loop for next character + +LAB_1384 + JMP LAB_1866 ; do CR/LF exit to BASIC + +; announce buffer full + +LAB_138E + LDA #$07 ; [BELL] character into A + BNE LAB_137F ; go print the [BELL] but ignore input character + ; branch always + +; crunch keywords into Basic tokens +; position independent buffer version .. +; faster, dictionary search version .... + +LAB_13A6 + LDY #$FF ; set save index (makes for easy math later) + + SEC ; set carry for subtract + LDA Bpntrl ; get basic execute pointer low byte + SBC #= go save byte then continue crunching + + CMP #'<' ; compare with "<" + BCS LAB_13CC ; if >= go crunch now + + CMP #'0' ; compare with "0" + BCS LAB_13EC ; if >= go save byte then continue crunching + + STA Scnquo ; save buffer byte as search character + CMP #$22 ; is it quote character? + BEQ LAB_1410 ; branch if so (copy quoted string) + + CMP #'*' ; compare with "*" + BCC LAB_13EC ; if < go save byte then continue crunching + + ; else crunch now +LAB_13CC + BIT Oquote ; get open quote/DATA token flag + BVS LAB_13EC ; branch if b6 of Oquote set (was DATA) + ; go save byte then continue crunching + + STX TempB ; save buffer read index + STY csidx ; copy buffer save index + LDY #TAB_1STC ; get keyword first character table high address + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear table pointer + +LAB_13D0 + CMP (ut2_pl),Y ; compare with keyword first character table byte + BEQ LAB_13D1 ; go do word_table_chr if match + + BCC LAB_13EA ; if < keyword first character table byte go restore + ; Y and save to crunched + + INY ; else increment pointer + BNE LAB_13D0 ; and loop (branch always) + +; have matched first character of some keyword + +LAB_13D1 + TYA ; copy matching index + ASL ; *2 (bytes per pointer) + TAX ; copy to new index + LDA TAB_CHRT,X ; get keyword table pointer low byte + STA ut2_pl ; save pointer low byte + LDA TAB_CHRT+1,X ; get keyword table pointer high byte + STA ut2_ph ; save pointer high byte + + LDY #$FF ; clear table pointer (make -1 for start) + + LDX TempB ; restore buffer read index + +LAB_13D6 + INY ; next table byte + LDA (ut2_pl),Y ; get byte from table +LAB_13D8 + BMI LAB_13EA ; all bytes matched so go save token + + INX ; next buffer byte + CMP Ibuffs,X ; compare with byte from input buffer + BEQ LAB_13D6 ; go compare next if match + + BNE LAB_1417 ; branch if >< (not found keyword) + +LAB_13EA + LDY csidx ; restore save index + + ; save crunched to output +LAB_13EC + INX ; increment buffer index (to next input byte) + INY ; increment save index (to next output byte) + STA Ibuffs,Y ; save byte to output + CMP #$00 ; set the flags, set carry + BEQ LAB_142A ; do exit if was null [EOL] + + ; A holds token or byte here + SBC #':' ; subtract ":" (carry set by CMP #00) + BEQ LAB_13FF ; branch if it was ":" (is now $00) + + ; A now holds token-$3A + CMP #TK_DATA-$3A ; compare with DATA token - $3A + BNE LAB_1401 ; branch if not DATA + + ; token was : or DATA +LAB_13FF + STA Oquote ; save token-$3A (clear for ":", TK_DATA-$3A for DATA) +LAB_1401 + EOR #TK_REM-$3A ; effectively subtract REM token offset + BNE LAB_13AC ; If wasn't REM then go crunch rest of line + + STA Asrch ; else was REM so set search for [EOL] + + ; loop for REM, "..." etc. +LAB_1408 + LDA Ibuffs,X ; get byte from input buffer + BEQ LAB_13EC ; branch if null [EOL] + + CMP Asrch ; compare with stored character + BEQ LAB_13EC ; branch if match (end quote) + + ; entry for copy string in quotes, don't crunch +LAB_1410 + INY ; increment buffer save index + STA Ibuffs,Y ; save byte to output + INX ; increment buffer read index + BNE LAB_1408 ; loop while <> 0 (should never be 0!) + + ; not found keyword this go +LAB_1417 + LDX TempB ; compare has failed, restore buffer index (start byte!) + + ; now find the end of this word in the table +LAB_141B + LDA (ut2_pl),Y ; get table byte + PHP ; save status + INY ; increment table index + PLP ; restore byte status + BPL LAB_141B ; if not end of keyword go do next + + LDA (ut2_pl),Y ; get byte from keyword table + BNE LAB_13D8 ; go test next word if not zero byte (end of table) + + ; reached end of table with no match + LDA Ibuffs,X ; restore byte from input buffer + BPL LAB_13EA ; branch always (all bytes in buffer are $00-$7F) + ; go save byte in output and continue crunching + + ; reached [EOL] +LAB_142A + INY ; increment pointer + INY ; increment pointer (makes it next line pointer high byte) + STA Ibuffs,Y ; save [EOL] (marks [EOT] in immediate mode) + INY ; adjust for line copy + INY ; adjust for line copy + INY ; adjust for line copy + DEC Bpntrl ; allow for increment (change if buffer starts at $xxFF) + RTS + +; search Basic for temp integer line number from start of mem + +LAB_SSLN + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search Basic for temp integer line number from AX +; returns carry set if found +; returns Baslnl/Baslnh pointer to found or next higher (not found) line + +; old 541 new 507 + +LAB_SHLN + LDY #$01 ; set index + STA Baslnl ; save low byte as current + STX Baslnh ; save high byte as current + LDA (Baslnl),Y ; get pointer high byte from addr + BEQ LAB_145F ; pointer was zero so we're done, do 'not found' exit + + LDY #$03 ; set index to line # high byte + LDA (Baslnl),Y ; get line # high byte + DEY ; decrement index (point to low byte) + CMP Itemph ; compare with temporary integer high byte + BNE LAB_1455 ; if <> skip low byte check + + LDA (Baslnl),Y ; get line # low byte + CMP Itempl ; compare with temporary integer low byte +LAB_1455 + BCS LAB_145E ; else if temp < this line, exit (passed line#) + +LAB_1456 + DEY ; decrement index to next line ptr high byte + LDA (Baslnl),Y ; get next line pointer high byte + TAX ; copy to X + DEY ; decrement index to next line ptr low byte + LDA (Baslnl),Y ; get next line pointer low byte + BCC LAB_SHLN ; go search for line # in temp (Itempl/Itemph) from AX + ; (carry always clear) + +LAB_145E + BEQ LAB_1460 ; exit if temp = found line #, carry is set + +LAB_145F + CLC ; clear found flag +LAB_1460 + RTS + +; perform NEW + +LAB_NEW + BNE LAB_1460 ; exit if not end of statement (to do syntax error) + +LAB_1463 + LDA #$00 ; clear A + TAY ; clear Y + STA (Smeml),Y ; clear first line, next line pointer, low byte + INY ; increment index + STA (Smeml),Y ; clear first line, next line pointer, high byte + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$02 ; calculate end of BASIC low byte + STA Svarl ; save start of vars low byte + LDA Smemh ; get start of mem high byte + ADC #$00 ; add any carry + STA Svarh ; save start of vars high byte + +; reset execution to start, clear vars and flush stack + +LAB_1477 + CLC ; clear carry + LDA Smeml ; get start of mem low byte + ADC #$FF ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Smemh ; get start of mem high byte + ADC #$FF ; -1+carry + STA Bpntrh ; save BASIC execute pointer high byte + +; "CLEAR" command gets here + +LAB_147A + LDA Ememl ; get end of mem low byte + LDY Ememh ; get end of mem high byte + STA Sstorl ; set bottom of string space low byte + STY Sstorh ; set bottom of string space high byte + LDA Svarl ; get start of vars low byte + LDY Svarh ; get start of vars high byte + STA Sarryl ; save var mem end low byte + STY Sarryh ; save var mem end high byte + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + JSR LAB_161A ; perform RESTORE command + +; flush stack and clear continue flag + +LAB_1491 + LDX #des_sk ; set descriptor stack pointer + STX next_s ; save descriptor stack pointer + PLA ; pull return address low byte + TAX ; copy return address low byte + PLA ; pull return address high byte + STX LAB_SKFE ; save to cleared stack + STA LAB_SKFF ; save to cleared stack + LDX #$FD ; new stack pointer + TXS ; reset stack + LDA #$00 ; clear byte + STA Cpntrh ; clear continue pointer high byte + STA Sufnxf ; clear subscript/FNX flag +LAB_14A6 + RTS + +; perform CLEAR + +LAB_CLEAR + BEQ LAB_147A ; if no following token go do "CLEAR" + + ; else there was a following token (go do syntax error) + RTS + +; perform LIST [n][-m] +; bigger, faster version (a _lot_ faster) + +LAB_LIST + BCC LAB_14BD ; branch if next character numeric (LIST n..) + + BEQ LAB_14BD ; branch if next character [NULL] (LIST) + + CMP #TK_MINUS ; compare with token for - + BNE LAB_14A6 ; exit if not - (LIST -m) + + ; LIST [[n][-m]] + ; this bit sets the n , if present, as the start and end +LAB_14BD + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SSLN ; search BASIC for temp integer line number + ; (pointer in Baslnl/Baslnh) + JSR LAB_GBYT ; scan memory + BEQ LAB_14D4 ; branch if no more characters + + ; this bit checks the - is present + CMP #TK_MINUS ; compare with token for - + BNE LAB_1460 ; return if not "-" (will be Syntax error) + + ; LIST [n]-m + ; the - was there so set m as the end value + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer + BNE LAB_1460 ; exit if not ok + +LAB_14D4 + LDA Itempl ; get temporary integer low byte + ORA Itemph ; OR temporary integer high byte + BNE LAB_14E2 ; branch if start set + + LDA #$FF ; set for -1 + STA Itempl ; set temporary integer low byte + STA Itemph ; set temporary integer high byte +LAB_14E2 + LDY #$01 ; set index for line + STY Oquote ; clear open quote flag + JSR LAB_CRLF ; print CR/LF + LDA (Baslnl),Y ; get next line pointer high byte + ; pointer initially set by search at LAB_14BD + BEQ LAB_152B ; if null all done so exit + JSR LAB_1629 ; do CRTL-C check vector + + INY ; increment index for line + LDA (Baslnl),Y ; get line # low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get line # high byte + CMP Itemph ; compare with temporary integer high byte + BNE LAB_14FF ; branch if no high byte match + + CPX Itempl ; compare with temporary integer low byte + BEQ LAB_1501 ; branch if = last line to do (< will pass next branch) + +LAB_14FF ; else .. + BCS LAB_152B ; if greater all done so exit + +LAB_1501 + STY Tidx1 ; save index for line + JSR LAB_295E ; print XA as unsigned integer + LDA #$20 ; space is the next character +LAB_1508 + LDY Tidx1 ; get index for line + AND #$7F ; mask top out bit of character +LAB_150C + JSR LAB_PRNA ; go print the character + CMP #$22 ; was it " character + BNE LAB_1519 ; branch if not + + ; we are either entering or leaving a pair of quotes + LDA Oquote ; get open quote flag + EOR #$FF ; toggle it + STA Oquote ; save it back +LAB_1519 + INY ; increment index + LDA (Baslnl),Y ; get next byte + BNE LAB_152E ; branch if not [EOL] (go print character) + TAY ; else clear index + LDA (Baslnl),Y ; get next line pointer low byte + TAX ; copy to X + INY ; increment index + LDA (Baslnl),Y ; get next line pointer high byte + STX Baslnl ; set pointer to line low byte + STA Baslnh ; set pointer to line high byte + BNE LAB_14E2 ; go do next line if not [EOT] + ; else .. +LAB_152B + RTS + +LAB_152E + BPL LAB_150C ; just go print it if not token byte + + ; else was token byte so uncrunch it (maybe) + BIT Oquote ; test the open quote flag + BMI LAB_150C ; just go print character if open quote set + + LDX #>LAB_KEYT ; get table address high byte + ASL ; *2 + ASL ; *4 + BCC LAB_152F ; branch if no carry + + INX ; else increment high byte + CLC ; clear carry for add +LAB_152F + ADC #LAB_159F ; set return address high byte + STA ut1_pl ; save return address low byte + STY ut1_ph ; save return address high byte + JMP LAB_1B66 ; round FAC1 and put on stack (returns to next instruction) + +LAB_159F + LDA #LAB_259C ; set 1 pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JSR LAB_GBYT ; scan memory + CMP #TK_STEP ; compare with STEP token + BNE LAB_15B3 ; jump if not "STEP" + + ;.was step so .. + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch +LAB_15B3 + JSR LAB_27CA ; return A=FF,C=1/-ve A=01,C=0/+ve + STA FAC1_s ; set FAC1 sign (b7) + ; this is +1 for +ve step and -1 for -ve step, in NEXT we + ; compare the FOR value and the TO value and return +1 if + ; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value + ; here (+/-1) is then compared to that result and if they + ; are the same (+ve and FOR > TO or -ve and FOR < TO) then + ; the loop is done + JSR LAB_1B5B ; push sign, round FAC1 and put on stack + LDA Frnxth ; get var pointer for FOR/NEXT high byte + PHA ; push on stack + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + PHA ; push on stack + LDA #TK_FOR ; get FOR token + PHA ; push on stack + +; interpreter inner loop + +LAB_15C2 + JSR LAB_1629 ; do CRTL-C check vector + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + LDX Clineh ; continue line is $FFxx for immediate mode + ; ($00xx for RUN from immediate mode) + INX ; increment it (now $00 if immediate mode) + BEQ LAB_15D1 ; branch if null (immediate mode) + + STA Cpntrl ; save continue pointer low byte + STY Cpntrh ; save continue pointer high byte +LAB_15D1 + LDY #$00 ; clear index + LDA (Bpntrl),Y ; get next byte + BEQ LAB_15DC ; branch if null [EOL] + + CMP #':' ; compare with ":" + BEQ LAB_15F6 ; branch if = (statement separator) + +LAB_15D9 + JMP LAB_SNER ; else syntax error then warm start + + ; have reached [EOL] +LAB_15DC + LDY #$02 ; set index + LDA (Bpntrl),Y ; get next line pointer high byte + CLC ; clear carry for no "BREAK" message + BEQ LAB_1651 ; if null go to immediate mode (was immediate or [EOT] + ; marker) + + INY ; increment index + LDA (Bpntrl),Y ; get line # low byte + STA Clinel ; save current line low byte + INY ; increment index + LDA (Bpntrl),Y ; get line # high byte + STA Clineh ; save current line high byte + TYA ; A now = 4 + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_15F6 ; branch if no overflow + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_15F6 + JSR LAB_IGBY ; increment and scan memory + +LAB_15F9 + JSR LAB_15FF ; go interpret BASIC code from (Bpntrl) + +LAB_15FC + JMP LAB_15C2 ; loop + +; interpret BASIC code from (Bpntrl) + +LAB_15FF + BEQ LAB_1628 ; exit if zero [EOL] + +LAB_1602 + ASL ; *2 bytes per vector and normalise token + BCS LAB_1609 ; branch if was token + + JMP LAB_LET ; else go do implied LET + +LAB_1609 + CMP #[TK_TAB-$80]*2 ; compare normalised token * 2 with TAB + BCS LAB_15D9 ; branch if A>=TAB (do syntax error then warm start) + ; only tokens before TAB can start a line + TAY ; copy to index + LDA LAB_CTBL+1,Y ; get vector high byte + PHA ; onto stack + LDA LAB_CTBL,Y ; get vector low byte + PHA ; onto stack + JMP LAB_IGBY ; jump to increment and scan memory + ; then "return" to vector + +; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a +; key press is detected. + +LAB_1629 + JMP (VEC_CC) ; ctrl c check vector + +; if there was a key press it gets back here .. + +LAB_1636 + CMP #$03 ; compare with CTRL-C + +; perform STOP + +LAB_STOP + BCS LAB_163B ; branch if token follows STOP + ; else just END +; END + +LAB_END + CLC ; clear the carry, indicate a normal program end +LAB_163B + BNE LAB_167A ; if wasn't CTRL-C or there is a following byte return + + LDA Bpntrh ; get the BASIC execute pointer high byte + EOR #>Ibuffs ; compare with buffer address high byte (Cb unchanged) + BEQ LAB_164F ; branch if the BASIC pointer is in the input buffer + ; (can't continue in immediate mode) + + ; else .. + EOR #>Ibuffs ; correct the bits + LDY Bpntrl ; get BASIC execute pointer low byte + STY Cpntrl ; save continue pointer low byte + STA Cpntrh ; save continue pointer high byte +LAB_1647 + LDA Clinel ; get current line low byte + LDY Clineh ; get current line high byte + STA Blinel ; save break line low byte + STY Blineh ; save break line high byte +LAB_164F + PLA ; pull return address low + PLA ; pull return address high +LAB_1651 + BCC LAB_165E ; if was program end just do warm start + + ; else .. + LDA #LAB_BMSG ; point to "Break" high byte + JMP LAB_1269 ; print "Break" and do warm start + +LAB_165E + JMP LAB_1274 ; go do warm start + +; perform RESTORE + +LAB_RESTORE + BNE LAB_RESTOREn ; branch if next character not null (RESTORE n) + +LAB_161A + SEC ; set carry for subtract + LDA Smeml ; get start of mem low byte + SBC #$01 ; -1 + LDY Smemh ; get start of mem high byte + BCS LAB_1624 ; branch if no underflow + +LAB_uflow + DEY ; else decrement high byte +LAB_1624 + STA Dptrl ; save DATA pointer low byte + STY Dptrh ; save DATA pointer high byte +LAB_1628 + RTS + + ; is RESTORE n +LAB_RESTOREn + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_reset_search ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_go_search ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_go_search ; branch always (can never be carry clear) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_reset_search + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_go_search + + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_line_found ; if carry set go set pointer + + JMP LAB_16F7 ; else go do "Undefined statement" error + +LAB_line_found + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + LDY Baslnh ; get pointer high byte + BCS LAB_1624 ; branch if no underflow (save DATA pointer and return) + + BCC LAB_uflow ; else decrement high byte then save DATA pointer and + ; return (branch always) + +; perform NULL + +LAB_NULL + JSR LAB_GTBY ; get byte parameter + STX Nullct ; save new NULL count +LAB_167A + RTS + +; perform CONT + +LAB_CONT + BNE LAB_167A ; if following byte exit to do syntax error + + LDY Cpntrh ; get continue pointer high byte + BNE LAB_166C ; go do continue if we can + + LDX #$1E ; error code $1E ("Can't continue" error) + JMP LAB_XERR ; do error #X, then warm start + + ; we can continue so .. +LAB_166C + LDA #TK_ON ; set token for ON + JSR LAB_IRQ ; set IRQ flags + LDA #TK_ON ; set token for ON + JSR LAB_NMI ; set NMI flags + + STY Bpntrh ; save BASIC execute pointer high byte + LDA Cpntrl ; get continue pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA Blinel ; get break line low byte + LDY Blineh ; get break line high byte + STA Clinel ; set current line low byte + STY Clineh ; set current line high byte + RTS + +; perform RUN + +LAB_RUN + BNE LAB_1696 ; branch if RUN n + JMP LAB_1477 ; reset execution to start, clear variables, flush stack and + ; return + +; does RUN n + +LAB_1696 + JSR LAB_147A ; go do "CLEAR" + BEQ LAB_16B0 ; get n and do GOTO n (branch always as CLEAR sets Z=1) + +; perform DO + +LAB_DO + LDA #$05 ; need 5 bytes for DO + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_DO ; token for DO + PHA ; push on stack + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + +; perform GOSUB + +LAB_GOSUB + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack +LAB_16B0 + JSR LAB_GBYT ; scan memory + JSR LAB_GOTO ; perform GOTO n + JMP LAB_15C2 ; go do interpreter inner loop + ; (can't RTS, we used the stack!) + +; perform GOTO + +LAB_GOTO + JSR LAB_GFPN ; get fixed-point number into temp integer + JSR LAB_SNBL ; scan for next BASIC line + LDA Clineh ; get current line high byte + CMP Itemph ; compare with temporary integer high byte + BCS LAB_16D0 ; branch if >= (start search from beginning) + + TYA ; else copy line index to A + SEC ; set carry (+1) + ADC Bpntrl ; add BASIC execute pointer low byte + LDX Bpntrh ; get BASIC execute pointer high byte + BCC LAB_16D4 ; branch if no overflow to high byte + + INX ; increment high byte + BCS LAB_16D4 ; branch always (can never be carry) + +; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml) + +LAB_16D0 + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + +; search for line # in temp (Itempl/Itemph) from (AX) + +LAB_16D4 + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCC LAB_16F7 ; if carry clear go do "Undefined statement" error + ; (unspecified statement) + + ; carry already set for subtract + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 + STA Bpntrl ; save BASIC execute pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA Bpntrh ; save BASIC execute pointer high byte +LAB_16E5 + RTS + +LAB_DONOK + LDX #$22 ; error code $22 ("LOOP without DO" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform LOOP + +LAB_LOOP + TAY ; save following token + TSX ; copy stack pointer + LDA LAB_STAK+3,X ; get token byte from stack + CMP #TK_DO ; compare with DO token + BNE LAB_DONOK ; branch if no matching DO + + INX ; dump calling routine return address + INX ; dump calling routine return address + TXS ; correct stack + TYA ; get saved following token back + BEQ LoopAlways ; if no following token loop forever + ; (stack pointer in X) + + CMP #':' ; could be ':' + BEQ LoopAlways ; if :... loop forever + + SBC #TK_UNTIL ; subtract token for UNTIL, we know carry is set here + TAX ; copy to X (if it was UNTIL then Y will be correct) + BEQ DoRest ; branch if was UNTIL + + DEX ; decrement result + BNE LAB_16FC ; if not WHILE go do syntax error and warm start + ; only if the token was WHILE will this fail + + DEX ; set invert result byte +DoRest + STX Frnxth ; save invert result byte + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVEX ; evaluate expression + LDA FAC1_e ; get FAC1 exponent + BEQ DoCmp ; if =0 go do straight compare + + LDA #$FF ; else set all bits +DoCmp + TSX ; copy stack pointer + EOR Frnxth ; EOR with invert byte + BNE LoopDone ; if <> 0 clear stack and back to interpreter loop + + ; loop condition wasn't met so do it again +LoopAlways + LDA LAB_STAK+2,X ; get current line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+3,X ; get current line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+4,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+5,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + JMP LAB_15C2 ; go do interpreter inner loop + + ; clear stack and back to interpreter loop +LoopDone + INX ; dump DO token + INX ; dump current line low byte + INX ; dump current line high byte + INX ; dump BASIC execute pointer low byte + INX ; dump BASIC execute pointer high byte + TXS ; correct stack + JMP LAB_DATA ; go perform DATA (find : or [EOL]) + +; do the return without gosub error + +LAB_16F4 + LDX #$04 ; error code $04 ("RETURN without GOSUB" error) + .byte $2C ; makes next line BIT LAB_0EA2 + +LAB_16F7 ; do undefined statement error + LDX #$0E ; error code $0E ("Undefined statement" error) + JMP LAB_XERR ; do error #X, then warm start + +; perform RETURN + +LAB_RETURN + BNE LAB_16E5 ; exit if following token (to allow syntax error) + +LAB_16E8 + PLA ; dump calling routine return address + PLA ; dump calling routine return address + PLA ; pull token + CMP #TK_GOSUB ; compare with GOSUB token + BNE LAB_16F4 ; branch if no matching GOSUB + +LAB_16FF + PLA ; pull current line low byte + STA Clinel ; save current line low byte + PLA ; pull current line high byte + STA Clineh ; save current line high byte + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte + + ; now do the DATA statement as we could be returning into + ; the middle of an ON GOSUB n,m,p,q line + ; (the return address used by the DATA statement is the one + ; pushed before the GOSUB was executed!) + +; perform DATA + +LAB_DATA + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + + ; set BASIC execute pointer +LAB_170F + TYA ; copy index to A + CLC ; clear carry for add + ADC Bpntrl ; add BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + BCC LAB_1719 ; skip next if no carry + + INC Bpntrh ; else increment BASIC execute pointer high byte +LAB_1719 + RTS + +LAB_16FC + JMP LAB_SNER ; do syntax error then warm start + +; scan for next BASIC statement ([:] or [EOL]) +; returns Y as index to [:] or [EOL] + +LAB_SNBS + LDX #':' ; set look for character = ":" + .byte $2C ; makes next line BIT $00A2 + +; scan for next BASIC line +; returns Y as index to [EOL] + +LAB_SNBL + LDX #$00 ; set alt search character = [EOL] + LDY #$00 ; set search character = [EOL] + STY Asrch ; store search character +LAB_1725 + TXA ; get alt search character + EOR Asrch ; toggle search character, effectively swap with $00 + STA Asrch ; save swapped search character +LAB_172D + LDA (Bpntrl),Y ; get next byte + BEQ LAB_1719 ; exit if null [EOL] + + CMP Asrch ; compare with search character + BEQ LAB_1719 ; exit if found + + INY ; increment index + CMP #$22 ; compare current character with open quote + BNE LAB_172D ; if not open quote go get next character + + BEQ LAB_1725 ; if found go swap search character for alt search character + +; perform IF + +LAB_IF + JSR LAB_EVEX ; evaluate the expression + JSR LAB_GBYT ; scan memory + CMP #TK_THEN ; compare with THEN token + BEQ LAB_174B ; if it was THEN go do IF + + ; wasn't IF .. THEN so must be IF .. GOTO + CMP #TK_GOTO ; compare with GOTO token + BNE LAB_16FC ; if it wasn't GOTO go do syntax error + + LDX Bpntrl ; save the basic pointer low byte + LDY Bpntrh ; save the basic pointer high byte + JSR LAB_IGBY ; increment and scan memory + BCS LAB_16FC ; if not numeric go do syntax error + + STX Bpntrl ; restore the basic pointer low byte + STY Bpntrh ; restore the basic pointer high byte +LAB_174B + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_174E ; if the result was zero go look for an ELSE + + JSR LAB_IGBY ; else increment and scan memory + BCS LAB_174D ; if not numeric go do var or keyword + +LAB_174C + JMP LAB_GOTO ; else was numeric so do GOTO n + + ; is var or keyword +LAB_174D + CMP #TK_RETURN ; compare the byte with the token for RETURN + BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl) + ; and return to this code to process any following code + + JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl) + ; but don't return here + +LAB_174G + JSR LAB_15FF ; interpret BASIC code from (Bpntrl) + +; the IF was executed and there may be a following ELSE so the code needs to return +; here to check and ignore the ELSE if present + + LDY #$00 ; clear the index + LDA (Bpntrl),Y ; get the next BASIC byte + CMP #TK_ELSE ; compare it with the token for ELSE + BEQ LAB_DATA ; if ELSE ignore the following statement + +; there was no ELSE so continue execution of IF THEN [: ]. any +; following ELSE will, correctly, cause a syntax error + + RTS ; else return to the interpreter inner loop + +; perform ELSE after IF + +LAB_174E + LDY #$00 ; clear the BASIC byte index + LDX #$01 ; clear the nesting depth +LAB_1750 + INY ; increment the BASIC byte index + LDA (Bpntrl),Y ; get the next BASIC byte + BEQ LAB_1753 ; if EOL go add the pointer and return + + CMP #TK_IF ; compare the byte with the token for IF + BNE LAB_1752 ; if not IF token skip the depth increment + + INX ; else increment the nesting depth .. + BNE LAB_1750 ; .. and continue looking + +LAB_1752 + CMP #TK_ELSE ; compare the byte with the token for ELSE + BNE LAB_1750 ; if not ELSE token continue looking + + DEX ; was ELSE so decrement the nesting depth + BNE LAB_1750 ; loop if still nested + + INY ; increment the BASIC byte index past the ELSE + +; found the matching ELSE, now do <{n|statement}> + +LAB_1753 + TYA ; else copy line index to A + CLC ; clear carry for add + ADC Bpntrl ; add the BASIC execute pointer low byte + STA Bpntrl ; save the BASIC execute pointer low byte + BCC LAB_1754 ; branch if no overflow to high byte + + INC Bpntrh ; else increment the BASIC execute pointer high byte +LAB_1754 + JSR LAB_GBYT ; scan memory + BCC LAB_174C ; if numeric do GOTO n + ; the code will return to the interpreter loop at the + ; tail end of the GOTO + + JMP LAB_15FF ; interpret BASIC code from (Bpntrl) + ; the code will return to the interpreter loop at the + ; tail end of the + +; perform REM, skip (rest of) line + +LAB_REM + JSR LAB_SNBL ; scan for next BASIC line + JMP LAB_170F ; go set BASIC execute pointer and return, branch always + +LAB_16FD + JMP LAB_SNER ; do syntax error then warm start + +; perform ON + +LAB_ON + CMP #TK_IRQ ; was it IRQ token ? + BNE LAB_NOIN ; if not go check NMI + + JMP LAB_SIRQ ; else go set-up IRQ + +LAB_NOIN + CMP #TK_NMI ; was it NMI token ? + BNE LAB_NONM ; if not go do normal ON command + + JMP LAB_SNMI ; else go set-up NMI + +LAB_NONM + JSR LAB_GTBY ; get byte parameter + PHA ; push GOTO/GOSUB token + CMP #TK_GOSUB ; compare with GOSUB token + BEQ LAB_176B ; branch if GOSUB + + CMP #TK_GOTO ; compare with GOTO token +LAB_1767 + BNE LAB_16FD ; if not GOTO do syntax error then warm start + + +; next character was GOTO or GOSUB + +LAB_176B + DEC FAC1_3 ; decrement index (byte value) + BNE LAB_1773 ; branch if not zero + + PLA ; pull GOTO/GOSUB token + JMP LAB_1602 ; go execute it + +LAB_1773 + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GFPN ; get fixed-point number into temp integer (skip this n) + ; (we could LDX #',' and JSR LAB_SNBL+2, then we + ; just BNE LAB_176B for the loop. should be quicker .. + ; no we can't, what if we meet a colon or [EOL]?) + CMP #$2C ; compare next character with "," + BEQ LAB_176B ; loop if "," + +LAB_177E + PLA ; else pull keyword token (run out of options) + ; also dump +/-1 pointer low byte and exit +LAB_177F + RTS + +; takes n * 106 + 11 cycles where n is the number of digits + +; get fixed-point number into temp integer + +LAB_GFPN + LDX #$00 ; clear reg + STX Itempl ; clear temporary integer low byte +LAB_1785 + STX Itemph ; save temporary integer high byte + BCS LAB_177F ; return if carry set, end of scan, character was + ; not 0-9 + + CPX #$19 ; compare high byte with $19 + TAY ; ensure Zb = 0 if the branch is taken + BCS LAB_1767 ; branch if >=, makes max line # 63999 because next + ; bit does *$0A, = 64000, compare at target will fail + ; and do syntax error + + SBC #'0'-1 ; subtract "0", $2F + carry, from byte + TAY ; copy binary digit + LDA Itempl ; get temporary integer low byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte + ASL ; *2 low byte + ROL Itemph ; *2 high byte, *4 + ADC Itempl ; + low byte, *5 + STA Itempl ; save it + TXA ; get high byte copy to A + ADC Itemph ; + high byte, *5 + ASL Itempl ; *2 low byte, *10d + ROL ; *2 high byte, *10d + TAX ; copy high byte back to X + TYA ; get binary digit back + ADC Itempl ; add number low byte + STA Itempl ; save number low byte + BCC LAB_17B3 ; if no overflow to high byte get next character + + INX ; else increment high byte +LAB_17B3 + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1785 ; loop for next character + +; perform DEC + +LAB_DEC + LDA #LAB_259C ; set +/-1 pointer high byte (both the same) + JSR LAB_246C ; add (AY) to FAC1 + JSR LAB_PFAC ; pack FAC1 into variable (Lvarpl) + + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_177E ; exit if not "," (either end or error) + + ; was "," so another INCR variable to do + JSR LAB_IGBY ; increment and scan memory + JMP LAB_17B7 ; go do next var + +IncrErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform LET + +LAB_LET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push data type flag + JSR LAB_EVEX ; evaluate expression + PLA ; pop data type flag + ROL ; set carry if type = string + JSR LAB_CKTM ; type match check, set C for string + BNE LAB_17D5 ; branch if string + + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +; string LET + +LAB_17D5 + LDY #$02 ; set index to pointer high byte + LDA (des_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + BNE LAB_17E6 ; branch if > + ; else was equal so compare low bytes + DEY ; decrement index + LDA (des_pl),Y ; get pointer low byte + CMP Sstorl ; compare bottom of string space low byte + BCC LAB_17F4 ; if less assign value and exit (was in program memory) + + ; pointer was >= to bottom of string space pointer +LAB_17E6 + LDY des_ph ; get descriptor pointer high byte + CPY Svarh ; compare start of vars high byte + BCC LAB_17F4 ; branch if less (descriptor is on stack) + + BNE LAB_17FB ; branch if greater (descriptor is not on stack) + + ; else high bytes were equal so .. + LDA des_pl ; get descriptor pointer low byte + CMP Svarl ; compare start of vars low byte + BCS LAB_17FB ; branch if >= (descriptor is not on stack) + +LAB_17F4 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + JMP LAB_1811 ; clean stack, copy descriptor to variable and return + + ; make space and copy string +LAB_17FB + LDY #$00 ; index to length + LDA (des_pl),Y ; get string length + JSR LAB_209C ; copy string + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + STA ssptr_l ; save descriptor pointer low byte + STY ssptr_h ; save descriptor pointer high byte + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA #FAC1_e ; get descriptor pointer high byte + + ; clean stack and assign value to string variable +LAB_1811 + STA des_2l ; save descriptor_2 pointer low byte + STY des_2h ; save descriptor_2 pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + LDY #$00 ; index to length + LDA (des_2l),Y ; get string length + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer low byte + LDA (des_2l),Y ; get string pointer low byte + STA (Lvarpl),Y ; copy to let string variable + INY ; index to string pointer high byte + LDA (des_2l),Y ; get string pointer high byte + STA (Lvarpl),Y ; copy to let string variable + RTS + +; perform GET + +LAB_GET + JSR LAB_GVAR ; get var address + STA Lvarpl ; save var address low byte + STY Lvarph ; save var address high byte + JSR INGET ; get input byte + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_GETS ; go get string character + + ; was numeric get + TAY ; copy character to Y + JSR LAB_1FD0 ; convert Y to byte in FAC1 + JMP LAB_PFAC ; pack FAC1 into variable (Lvarpl) and return + +LAB_GETS + PHA ; save character + LDA #$01 ; string is single byte + BCS LAB_IsByte ; branch if byte received + + PLA ; string is null +LAB_IsByte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + BEQ LAB_NoSt ; skip store if null string + + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) +LAB_NoSt + JSR LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + + JMP LAB_17D5 ; do string LET and return + +; perform PRINT + +LAB_1829 + JSR LAB_18C6 ; print string from Sutill/Sutilh +LAB_182C + JSR LAB_GBYT ; scan memory + +; PRINT + +LAB_PRINT + BEQ LAB_CRLF ; if nothing following just print CR/LF + +LAB_1831 + CMP #TK_TAB ; compare with TAB( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #TK_SPC ; compare with SPC( token + BEQ LAB_18A2 ; go do TAB/SPC + + CMP #',' ; compare with "," + BEQ LAB_188B ; go do move to next TAB mark + + CMP #';' ; compare with ";" + BEQ LAB_18BD ; if ";" continue with PRINT processing + + JSR LAB_EVEX ; evaluate expression + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1829 ; branch if string + + JSR LAB_296E ; convert FAC1 to string + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + LDY #$00 ; clear index + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width byte + BEQ LAB_185E ; skip check if zero + + SEC ; set carry for subtract + SBC TPos ; subtract terminal position + SBC (des_pl),Y ; subtract string length + BCS LAB_185E ; branch if less than terminal width + + JSR LAB_CRLF ; else print CR/LF +LAB_185E + JSR LAB_18C6 ; print string from Sutill/Sutilh + BEQ LAB_182C ; always go continue processing line + +; CR/LF return to BASIC from BASIC input handler + +LAB_1866 + LDA #$00 ; clear byte + STA Ibuffs,X ; null terminate input + LDX #Ibuffs ; set Y to buffer start-1 high byte + +; print CR/LF + +LAB_CRLF + LDA #$0D ; load [CR] + JSR LAB_PRNA ; go print the character + LDA #$0A ; load [LF] + BNE LAB_PRNA ; go print the character and return, branch always + +LAB_188B + LDA TPos ; get terminal position + CMP Iclim ; compare with input column limit + BCC LAB_1897 ; branch if less + + JSR LAB_CRLF ; else print CR/LF (next line) + BNE LAB_18BD ; continue with PRINT processing (branch always) + +LAB_1897 + SEC ; set carry for subtract +LAB_1898 + SBC TabSiz ; subtract TAB size + BCS LAB_1898 ; loop if result was +ve + + EOR #$FF ; complement it + ADC #$01 ; +1 (twos complement) + BNE LAB_18B6 ; always print A spaces (result is never $00) + + ; do TAB/SPC +LAB_18A2 + PHA ; save token + JSR LAB_SGBY ; scan and get byte parameter + CMP #$29 ; is next character ) + BNE LAB_1910 ; if not do syntax error then warm start + + PLA ; get token back + CMP #TK_TAB ; was it TAB ? + BNE LAB_18B7 ; if not go do SPC + + ; calculate TAB offset + TXA ; copy integer value to A + SBC TPos ; subtract terminal position + BCC LAB_18BD ; branch if result was < 0 (can't TAB backwards) + + ; print A spaces +LAB_18B6 + TAX ; copy result to X +LAB_18B7 + TXA ; set flags on size for SPC + BEQ LAB_18BD ; branch if result was = $0, already here + + ; print X spaces +LAB_18BA + JSR LAB_18E0 ; print " " + DEX ; decrement count + BNE LAB_18BA ; loop if not all done + + ; continue with PRINT processing +LAB_18BD + JSR LAB_IGBY ; increment and scan memory + BNE LAB_1831 ; if more to print go do it + + RTS + +; print null terminated string from memory + +LAB_18C3 + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + +; print string from Sutill/Sutilh + +LAB_18C6 + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + LDY #$00 ; reset index + TAX ; copy length to X + BEQ LAB_188C ; exit (RTS) if null string + +LAB_18CD + + LDA (ut1_pl),Y ; get next byte + JSR LAB_PRNA ; go print the character + INY ; increment index + DEX ; decrement count + BNE LAB_18CD ; loop if not done yet + + RTS + + ; Print single format character +; print " " + +LAB_18E0 + LDA #$20 ; load " " + .byte $2C ; change next line to BIT LAB_3FA9 + +; print "?" character + +LAB_18E3 + LDA #$3F ; load "?" character + +; print character in A +; now includes the null handler +; also includes infinite line length code +; note! some routines expect this one to exit with Zb=0 + +LAB_PRNA + CMP #' ' ; compare with " " + BCC LAB_18F9 ; branch if less (non printing) + + ; else printable character + PHA ; save the character + +; don't check fit if terminal width byte is zero + + LDA TWidth ; get terminal width + BNE LAB_18F0 ; branch if not zero (not infinite length) + +; is "infinite line" so check TAB position + + LDA TPos ; get position + SBC TabSiz ; subtract TAB size, carry set by CMP #$20 above + BNE LAB_18F7 ; skip reset if different + + STA TPos ; else reset position + BEQ LAB_18F7 ; go print character + +LAB_18F0 + CMP TPos ; compare with terminal character position + BNE LAB_18F7 ; branch if not at end of line + + JSR LAB_CRLF ; else print CR/LF +LAB_18F7 + INC TPos ; increment terminal position + PLA ; get character back +LAB_18F9 + JSR V_OUTP ; output byte via output vector + CMP #$0D ; compare with [CR] + BNE LAB_188A ; branch if not [CR] + + ; else print nullct nulls after the [CR] + STX TempB ; save buffer index + LDX Nullct ; get null count + BEQ LAB_1886 ; branch if no nulls + + LDA #$00 ; load [NULL] +LAB_1880 + JSR LAB_PRNA ; go print the character + DEX ; decrement count + BNE LAB_1880 ; loop if not all done + + LDA #$0D ; restore the character (and set the flags) +LAB_1886 + STX TPos ; clear terminal position (X always = zero when we get here) + LDX TempB ; restore buffer index +LAB_188A + AND #$FF ; set the flags +LAB_188C + RTS + +; handle bad input data + +LAB_1904 + LDA Imode ; get input mode flag, $00=INPUT, $00=READ + BPL LAB_1913 ; branch if INPUT (go do redo) + + LDA Dlinel ; get current DATA line low byte + LDY Dlineh ; get current DATA line high byte + STA Clinel ; save current line low byte + STY Clineh ; save current line high byte +LAB_1910 + JMP LAB_SNER ; do syntax error then warm start + + ; mode was INPUT +LAB_1913 + LDA #LAB_REDO ; point to redo message (high addr) + JSR LAB_18C3 ; print null terminated string from memory + LDA Cpntrl ; get continue pointer low byte + LDY Cpntrh ; get continue pointer high byte + STA Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; perform INPUT + +LAB_INPUT + CMP #$22 ; compare next byte with open quote + BNE LAB_1934 ; branch if no prompt string + + JSR LAB_1BC1 ; print "..." string + LDA #$3B ; load A with ";" + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + JSR LAB_18C6 ; print string from Sutill/Sutilh + + ; done with prompt, now get data +LAB_1934 + JSR LAB_CKRN ; check not Direct, back here if ok + JSR LAB_INLN ; print "? " and get BASIC input + LDA #$00 ; set mode = INPUT + CMP Ibuffs ; test first byte in buffer + BNE LAB_1953 ; branch if not null input + + CLC ; was null input so clear carry to exit program + JMP LAB_1647 ; go do BREAK exit + +; perform READ + +LAB_READ + LDX Dptrl ; get DATA pointer low byte + LDY Dptrh ; get DATA pointer high byte + LDA #$80 ; set mode = READ + +LAB_1953 + STA Imode ; set input mode flag, $00=INPUT, $80=READ + STX Rdptrl ; save READ pointer low byte + STY Rdptrh ; save READ pointer high byte + + ; READ or INPUT next variable from list +LAB_195B + JSR LAB_GVAR ; get (var) address + STA Lvarpl ; save address low byte + STY Lvarph ; save address high byte + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STA Itempl ; save as temporary integer low byte + STY Itemph ; save as temporary integer high byte + LDX Rdptrl ; get READ pointer low byte + LDY Rdptrh ; get READ pointer high byte + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BNE LAB_1988 ; branch if not null + + ; pointer was to null entry + BIT Imode ; test input mode flag, $00=INPUT, $80=READ + BMI LAB_19DD ; branch if READ + + ; mode was INPUT + JSR LAB_18E3 ; print "?" character (double ? for extended input) + JSR LAB_INLN ; print "? " and get BASIC input + STX Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte +LAB_1985 + JSR LAB_GBYT ; scan memory +LAB_1988 + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_19B0 ; branch if numeric + + ; else get string + STA Srchc ; save search character + CMP #$22 ; was it " ? + BEQ LAB_1999 ; branch if so + + LDA #':' ; else search character is ":" + STA Srchc ; set new search character + LDA #',' ; other search character is "," + CLC ; clear carry for add +LAB_1999 + STA Asrch ; set second search character + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + + ADC #$00 ; c is =1 if we came via the BEQ LAB_1999, else =0 + BCC LAB_19A4 ; branch if no execute pointer low byte rollover + + INY ; else increment high byte +LAB_19A4 + JSR LAB_20B4 ; print Srchc or Asrch terminated string to Sutill/Sutilh + JSR LAB_23F3 ; restore BASIC execute pointer from temp (Btmpl/Btmph) + JSR LAB_17D5 ; go do string LET + JMP LAB_19B6 ; go check string terminator + + ; get numeric INPUT +LAB_19B0 + JSR LAB_2887 ; get FAC1 from string + JSR LAB_PFAC ; pack FAC1 into (Lvarpl) +LAB_19B6 + JSR LAB_GBYT ; scan memory + BEQ LAB_19C5 ; branch if null (last entry) + + CMP #',' ; else compare with "," + BEQ LAB_19C2 ; branch if "," + + JMP LAB_1904 ; else go handle bad input data + + ; got good input data +LAB_19C2 + JSR LAB_IGBY ; increment and scan memory +LAB_19C5 + LDA Bpntrl ; get BASIC execute pointer low byte (temp READ/INPUT ptr) + LDY Bpntrh ; get BASIC execute pointer high byte (temp READ/INPUT ptr) + STA Rdptrl ; save for now + STY Rdptrh ; save for now + LDA Itempl ; get temporary integer low byte (temp BASIC execute ptr) + LDY Itemph ; get temporary integer high byte (temp BASIC execute ptr) + STA Bpntrl ; set BASIC execute pointer low byte + STY Bpntrh ; set BASIC execute pointer high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_1A03 ; if null go do extra ignored message + + JSR LAB_1C01 ; else scan for "," , else do syntax error then warm start + JMP LAB_195B ; go INPUT next variable from list + + ; find next DATA statement or do "Out of DATA" error +LAB_19DD + JSR LAB_SNBS ; scan for next BASIC statement ([:] or [EOL]) + INY ; increment index + TAX ; copy character ([:] or [EOL]) + BNE LAB_19F6 ; branch if [:] + + LDX #$06 ; set for "Out of DATA" error + INY ; increment index, now points to next line pointer high byte + LDA (Bpntrl),Y ; get next line pointer high byte + BEQ LAB_1A54 ; branch if end (eventually does error X) + + INY ; increment index + LDA (Bpntrl),Y ; get next line # low byte + STA Dlinel ; save current DATA line low byte + INY ; increment index + LDA (Bpntrl),Y ; get next line # high byte + INY ; increment index + STA Dlineh ; save current DATA line high byte +LAB_19F6 + LDA (Bpntrl),Y ; get byte + INY ; increment index + TAX ; copy to X + JSR LAB_170F ; set BASIC execute pointer + CPX #TK_DATA ; compare with "DATA" token + BEQ LAB_1985 ; was "DATA" so go do next READ + + BNE LAB_19DD ; go find next statement if not "DATA" + +; end of INPUT/READ routine + +LAB_1A03 + LDA Rdptrl ; get temp READ pointer low byte + LDY Rdptrh ; get temp READ pointer high byte + LDX Imode ; get input mode flag, $00=INPUT, $80=READ + BPL LAB_1A0E ; branch if INPUT + + JMP LAB_1624 ; save AY as DATA pointer and return + + ; we were getting INPUT +LAB_1A0E + LDY #$00 ; clear index + LDA (Rdptrl),Y ; get next byte + BNE LAB_1A1B ; error if not end of INPUT + + RTS + + ; user typed too much +LAB_1A1B + LDA #LAB_IMSG ; point to extra ignored message (high addr) + JMP LAB_18C3 ; print null terminated string from memory and return + +; search the stack for FOR activity +; exit with z=1 if FOR else exit with z=0 + +LAB_11A1 + TSX ; copy stack pointer + INX ; +1 pass return address + INX ; +2 pass return address + INX ; +3 pass calling routine return address + INX ; +4 pass calling routine return address +LAB_11A6 + LDA LAB_STAK+1,X ; get token byte from stack + CMP #TK_FOR ; is it FOR token + BNE LAB_11CE ; exit if not FOR token + + ; was FOR token + LDA Frnxth ; get var pointer for FOR/NEXT high byte + BNE LAB_11BB ; branch if not null + + LDA LAB_STAK+2,X ; get FOR variable pointer low byte + STA Frnxtl ; save var pointer for FOR/NEXT low byte + LDA LAB_STAK+3,X ; get FOR variable pointer high byte + STA Frnxth ; save var pointer for FOR/NEXT high byte +LAB_11BB + CMP LAB_STAK+3,X ; compare var pointer with stacked var pointer (high byte) + BNE LAB_11C7 ; branch if no match + + LDA Frnxtl ; get var pointer for FOR/NEXT low byte + CMP LAB_STAK+2,X ; compare var pointer with stacked var pointer (low byte) + BEQ LAB_11CE ; exit if match found + +LAB_11C7 + TXA ; copy index + CLC ; clear carry for add + ADC #$10 ; add FOR stack use size + TAX ; copy back to index + BNE LAB_11A6 ; loop if not at start of stack + +LAB_11CE + RTS + +; perform NEXT + +LAB_NEXT + BNE LAB_1A46 ; branch if NEXT var + + LDY #$00 ; else clear Y + BEQ LAB_1A49 ; branch always (no variable to search for) + +; NEXT var + +LAB_1A46 + JSR LAB_GVAR ; get variable address +LAB_1A49 + STA Frnxtl ; store variable pointer low byte + STY Frnxth ; store variable pointer high byte + ; (both cleared if no variable defined) + JSR LAB_11A1 ; search the stack for FOR activity + BEQ LAB_1A56 ; branch if found + + LDX #$00 ; else set error $00 ("NEXT without FOR" error) +LAB_1A54 + BEQ LAB_1ABE ; do error #X, then warm start + +LAB_1A56 + TXS ; set stack pointer, X set by search, dumps return addresses + + TXA ; copy stack pointer + SEC ; set carry for subtract + SBC #$F7 ; point to TO var + STA ut2_pl ; save pointer to TO var for compare + ADC #$FB ; point to STEP var + + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_UFAC ; unpack memory (STEP value) into FAC1 + TSX ; get stack pointer back + LDA LAB_STAK+8,X ; get step sign + STA FAC1_s ; save FAC1 sign (b7) + LDA Frnxtl ; get FOR variable pointer low byte + LDY Frnxth ; get FOR variable pointer high byte + JSR LAB_246C ; add (FOR variable) to FAC1 + JSR LAB_PFAC ; pack FAC1 into (FOR variable) + LDY #>LAB_STAK ; point to stack page high byte + JSR LAB_27FA ; compare FAC1 with (Y,ut2_pl) (TO value) + TSX ; get stack pointer back + CMP LAB_STAK+8,X ; compare step sign + BEQ LAB_1A9B ; branch if = (loop complete) + + ; loop back and do it all again + LDA LAB_STAK+$0D,X ; get FOR line low byte + STA Clinel ; save current line low byte + LDA LAB_STAK+$0E,X ; get FOR line high byte + STA Clineh ; save current line high byte + LDA LAB_STAK+$10,X ; get BASIC execute pointer low byte + STA Bpntrl ; save BASIC execute pointer low byte + LDA LAB_STAK+$0F,X ; get BASIC execute pointer high byte + STA Bpntrh ; save BASIC execute pointer high byte +LAB_1A98 + JMP LAB_15C2 ; go do interpreter inner loop + + ; loop complete so carry on +LAB_1A9B + TXA ; stack copy to A + ADC #$0F ; add $10 ($0F+carry) to dump FOR structure + TAX ; copy back to index + TXS ; copy to stack pointer + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BNE LAB_1A98 ; branch if not "," (go do interpreter inner loop) + + ; was "," so another NEXT variable to do + JSR LAB_IGBY ; else increment and scan memory + JSR LAB_1A46 ; do NEXT (var) + +; evaluate expression and check is numeric, else do type mismatch + +LAB_EVNM + JSR LAB_EVEX ; evaluate expression + +; check if source is numeric, else do type mismatch + +LAB_CTNM + CLC ; destination is numeric + .byte $24 ; makes next line BIT $38 + +; check if source is string, else do type mismatch + +LAB_CTST + SEC ; required type is string + +; type match check, set C for string, clear C for numeric + +LAB_CKTM + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BMI LAB_1ABA ; branch if data type is string + + ; else data type was numeric + BCS LAB_1ABC ; if required type is string do type mismatch error +LAB_1AB9 + RTS + + ; data type was string, now check required type +LAB_1ABA + BCS LAB_1AB9 ; exit if required type is string + + ; else do type mismatch error +LAB_1ABC + LDX #$18 ; error code $18 ("Type mismatch" error) +LAB_1ABE + JMP LAB_XERR ; do error #X, then warm start + +; evaluate expression + +LAB_EVEX + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1AC7 ; skip next if not zero + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1AC7 + DEC Bpntrl ; decrement BASIC execute pointer low byte + +LAB_EVEZ + LDA #$00 ; set null precedence (flag done) +LAB_1ACC + PHA ; push precedence byte + LDA #$02 ; 2 bytes + JSR LAB_1212 ; check room on stack for A bytes + JSR LAB_GVAL ; get value from line + LDA #$00 ; clear A + STA comp_f ; clear compare function flag +LAB_1ADB + JSR LAB_GBYT ; scan memory +LAB_1ADE + SEC ; set carry for subtract + SBC #TK_GT ; subtract token for > (lowest comparison function) + BCC LAB_1AFA ; branch if < TK_GT + + CMP #$03 ; compare with ">" to "<" tokens + BCS LAB_1AFA ; branch if >= TK_SGN (highest evaluation function +1) + + ; was token for > = or < (A = 0, 1 or 2) + CMP #$01 ; compare with token for = + ROL ; *2, b0 = carry (=1 if token was = or <) + ; (A = 0, 3 or 5) + EOR #$01 ; toggle b0 + ; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <) + EOR comp_f ; EOR with compare function flag bits + CMP comp_f ; compare with compare function flag + BCC LAB_1B53 ; if <(comp_f) do syntax error then warm start + ; was more than one <, = or >) + + STA comp_f ; save new compare function flag + JSR LAB_IGBY ; increment and scan memory + JMP LAB_1ADE ; go do next character + + ; token is < ">" or > "<" tokens +LAB_1AFA + LDX comp_f ; get compare function flag + BNE LAB_1B2A ; branch if compare function + + BCS LAB_1B78 ; go do functions + + ; else was < TK_GT so is operator or lower + ADC #TK_GT-TK_PLUS ; add # of operators (+, -, *, /, ^, AND, OR or EOR) + BCC LAB_1B78 ; branch if < + operator + + ; carry was set so token was +, -, *, /, ^, AND, OR or EOR + BNE LAB_1B0B ; branch if not + token + + BIT Dtypef ; test data type flag, $FF=string, $00=numeric + BPL LAB_1B0B ; branch if not string + + ; will only be $00 if type is string and token was + + JMP LAB_224D ; add strings, string 1 is in descriptor des_pl, string 2 + ; is in line, and return + +LAB_1B0B + STA ut1_pl ; save it + ASL ; *2 + ADC ut1_pl ; *3 + TAY ; copy to index +LAB_1B13 + PLA ; pull previous precedence + CMP LAB_OPPT,Y ; compare with precedence byte + BCS LAB_1B7D ; branch if A >= + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B1C + PHA ; save precedence +LAB_1B1D + JSR LAB_1B43 ; get vector, execute function then continue evaluation + PLA ; restore precedence + LDY prstk ; get precedence stacked flag + BPL LAB_1B3C ; branch if stacked values + + TAX ; copy precedence (set flags) + BEQ LAB_1B9D ; exit if done + + BNE LAB_1B86 ; else pop FAC2 and return, branch always + +LAB_1B2A + ROL Dtypef ; shift data type flag into Cb + TXA ; copy compare function flag + STA Dtypef ; clear data type flag, X is 0xxx xxxx + ROL ; shift data type into compare function byte b0 + LDX Bpntrl ; get BASIC execute pointer low byte + BNE LAB_1B34 ; branch if no underflow + + DEC Bpntrh ; else decrement BASIC execute pointer high byte +LAB_1B34 + DEC Bpntrl ; decrement BASIC execute pointer low byte +TK_LT_PLUS = TK_LT-TK_PLUS + LDY #TK_LT_PLUS*3 ; set offset to last operator entry + STA comp_f ; save new compare function flag + BNE LAB_1B13 ; branch always + +LAB_1B3C + CMP LAB_OPPT,Y ;.compare with stacked function precedence + BCS LAB_1B86 ; branch if A >=, pop FAC2 and return + + BCC LAB_1B1C ; branch always + +;.get vector, execute function then continue evaluation + +LAB_1B43 + LDA LAB_OPPT+2,Y ; get function vector high byte + PHA ; onto stack + LDA LAB_OPPT+1,Y ; get function vector low byte + PHA ; onto stack + ; now push sign, round FAC1 and put on stack + JSR LAB_1B5B ; function will return here, then the next RTS will call + ; the function + LDA comp_f ; get compare function flag + PHA ; push compare evaluation byte + LDA LAB_OPPT,Y ; get precedence byte + JMP LAB_1ACC ; continue evaluating expression + +LAB_1B53 + JMP LAB_SNER ; do syntax error then warm start + +; push sign, round FAC1 and put on stack + +LAB_1B5B + PLA ; get return addr low byte + STA ut1_pl ; save it + INC ut1_pl ; increment it (was ret-1 pushed? yes!) + ; note! no check is made on the high byte! if the calling + ; routine assembles to a page edge then this all goes + ; horribly wrong !!! + PLA ; get return addr high byte + STA ut1_ph ; save it + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; push sign + +; round FAC1 and put on stack + +LAB_1B66 + JSR LAB_27BA ; round FAC1 + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_1 ; get FAC1 mantissa1 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + JMP (ut1_pl) ; return, sort of + +; do functions + +LAB_1B78 + LDY #$FF ; flag function + PLA ; pull precedence byte +LAB_1B7B + BEQ LAB_1B9D ; exit if done + +LAB_1B7D + CMP #$64 ; compare previous precedence with $64 + BEQ LAB_1B84 ; branch if was $64 (< function) + + JSR LAB_CTNM ; check if source is numeric, else do type mismatch +LAB_1B84 + STY prstk ; save precedence stacked flag + + ; pop FAC2 and return +LAB_1B86 + PLA ; pop byte + LSR ; shift out comparison evaluation lowest bit + STA Cflag ; save comparison evaluation flag + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + PLA ; pop mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) +LAB_1B9D + LDA FAC1_e ; get FAC1 exponent + RTS + +; print "..." string to string util area + +LAB_1BC1 + LDA Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + ADC #$00 ; add carry to low byte + BCC LAB_1BCA ; branch if no overflow + + INY ; increment high byte +LAB_1BCA + JSR LAB_20AE ; print " terminated string to Sutill/Sutilh + JMP LAB_23F3 ; restore BASIC execute pointer from temp and return + +; get value from line + +LAB_GVAL + JSR LAB_IGBY ; increment and scan memory + BCS LAB_1BAC ; branch if not numeric character + + ; else numeric string found (e.g. 123) +LAB_1BA9 + JMP LAB_2887 ; get FAC1 from string and return + +; get value from line .. continued + + ; wasn't a number so .. +LAB_1BAC + TAX ; set the flags + BMI LAB_1BD0 ; if -ve go test token values + + ; else it is either a string, number, variable or () + CMP #'$' ; compare with "$" + BEQ LAB_1BA9 ; branch if "$", hex number + + CMP #'%' ; else compare with "%" + BEQ LAB_1BA9 ; branch if "%", binary number + + CMP #'.' ; compare with "." + BEQ LAB_1BA9 ; if so get FAC1 from string and return (e.g. was .123) + + ; it wasn't any sort of number so .. + CMP #$22 ; compare with " + BEQ LAB_1BC1 ; branch if open quote + + ; wasn't any sort of number so .. + +; evaluate expression within parentheses + + CMP #'(' ; compare with "(" + BNE LAB_1C18 ; if not "(" get (var), return value in FAC1 and $ flag + +LAB_1BF7 + JSR LAB_EVEZ ; evaluate expression, no decrement + +; all the 'scan for' routines return the character after the sought character + +; scan for ")" , else do syntax error then warm start + +LAB_1BFB + LDA #$29 ; load A with ")" + +; scan for CHR$(A) , else do syntax error then warm start + +LAB_SCCA + LDY #$00 ; clear index + CMP (Bpntrl),Y ; check next byte is = A + BNE LAB_SNER ; if not do syntax error then warm start + + JMP LAB_IGBY ; increment and scan memory then return + +; scan for "(" , else do syntax error then warm start + +LAB_1BFE + LDA #$28 ; load A with "(" + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; scan for "," , else do syntax error then warm start + +LAB_1C01 + LDA #$2C ; load A with "," + BNE LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + ; (branch always) + +; syntax error then warm start + +LAB_SNER + LDX #$02 ; error code $02 ("Syntax" error) + JMP LAB_XERR ; do error #X, then warm start + +; get value from line .. continued +; do tokens + +LAB_1BD0 + CMP #TK_MINUS ; compare with token for - + BEQ LAB_1C11 ; branch if - token (do set-up for functions) + + ; wasn't -n so .. + CMP #TK_PLUS ; compare with token for + + BEQ LAB_GVAL ; branch if + token (+n = n so ignore leading +) + + CMP #TK_NOT ; compare with token for NOT + BNE LAB_1BE7 ; branch if not token for NOT + + ; was NOT token +TK_EQUAL_PLUS = TK_EQUAL-TK_PLUS + LDY #TK_EQUAL_PLUS*3 ; offset to NOT function + BNE LAB_1C13 ; do set-up for function then execute (branch always) + +; do = compare + +LAB_EQUAL + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; invert it + TAY ; copy it + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; invert it + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get value from line .. continued + + ; wasn't +, -, or NOT so .. +LAB_1BE7 + CMP #TK_FN ; compare with token for FN + BNE LAB_1BEE ; branch if not token for FN + + JMP LAB_201E ; go evaluate FNx + +; get value from line .. continued + + ; wasn't +, -, NOT or FN so .. +LAB_1BEE + SBC #TK_SGN ; subtract with token for SGN + BCS LAB_1C27 ; if a function token go do it + + JMP LAB_SNER ; else do syntax error + +; set-up for functions + +LAB_1C11 +TK_GT_PLUS = TK_GT-TK_PLUS + LDY #TK_GT_PLUS*3 ; set offset from base to > operator +LAB_1C13 + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_1B1D ; execute function then continue evaluation + +; variable name set-up +; get (var), return value in FAC_1 and $ flag + +LAB_1C18 + JSR LAB_GVAR ; get (var) address + STA FAC1_2 ; save address low byte in FAC1 mantissa2 + STY FAC1_3 ; save address high byte in FAC1 mantissa3 + LDX Dtypef ; get data type flag, $FF=string, $00=numeric + BMI LAB_1C25 ; if string then return (does RTS) + +LAB_1C24 + JMP LAB_UFAC ; unpack memory (AY) into FAC1 + +LAB_1C25 + RTS + +; get value from line .. continued +; only functions left so .. + +; set up function references + +; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed +; to process function calls. now the function vector is computed and pushed on the stack +; and the preprocess offset is read. if the preprocess offset is non zero then the vector +; is calculated and the routine called, if not this routine just does RTS. whichever +; happens the RTS at the end of this routine, or the end of the preprocess routine, calls +; the function code + +; this also removes some less than elegant code that was used to bypass type checking +; for functions that returned strings + +LAB_1C27 + ASL ; *2 (2 bytes per function address) + TAY ; copy to index + + LDA LAB_FTBM,Y ; get function jump vector high byte + PHA ; push functions jump vector high byte + LDA LAB_FTBL,Y ; get function jump vector low byte + PHA ; push functions jump vector low byte + + LDA LAB_FTPM,Y ; get function pre process vector high byte + BEQ LAB_1C56 ; skip pre process if null vector + + PHA ; push functions pre process vector high byte + LDA LAB_FTPL,Y ; get function pre process vector low byte + PHA ; push functions pre process vector low byte + +LAB_1C56 + RTS ; do function, or pre process, call + +; process string expression in parenthesis + +LAB_PPFS + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTST ; check if source is string then do function, + ; else do type mismatch + +; process numeric expression in parenthesis + +LAB_PPFN + JSR LAB_1BF7 ; process expression in parenthesis + JMP LAB_CTNM ; check if source is numeric then do function, + ; else do type mismatch + +; set numeric data type and increment BASIC execute pointer + +LAB_PPBI + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + JMP LAB_IGBY ; increment and scan memory then do function + +; process string for LEFT$, RIGHT$ or MID$ + +LAB_LRMS + JSR LAB_EVEZ ; evaluate (should be string) expression + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + PLA ; get function jump vector low byte + TAX ; save functions jump vector low byte + PLA ; get function jump vector high byte + TAY ; save functions jump vector high byte + LDA des_ph ; get descriptor pointer high byte + PHA ; push string pointer high byte + LDA des_pl ; get descriptor pointer low byte + PHA ; push string pointer low byte + TYA ; get function jump vector high byte back + PHA ; save functions jump vector high byte + TXA ; get function jump vector low byte back + PHA ; save functions jump vector low byte + JSR LAB_GTBY ; get byte parameter + TXA ; copy byte parameter to A + RTS ; go do function + +; process numeric expression(s) for BIN$ or HEX$ + +LAB_BHSS + JSR LAB_EVEZ ; process expression + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_BHER ; branch if n>=2^24 (is too big) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$02 ; 3 bytes to do +LAB_CFAC + LDA FAC1_1,X ; get byte from FAC1 + STA nums_1,X ; save byte to temp + DEX ; decrement index + BPL LAB_CFAC ; copy FAC1 mantissa to temp + + JSR LAB_GBYT ; get next BASIC byte + LDX #$00 ; set default to no leading "0"s + CMP #')' ; compare with close bracket + BEQ LAB_1C54 ; if ")" go do rest of function + + JSR LAB_SCGB ; scan for "," and get byte + JSR LAB_GBYT ; get last byte back + CMP #')' ; is next character ) + BNE LAB_BHER ; if not ")" go do error + +LAB_1C54 + RTS ; else do function + +LAB_BHER + JMP LAB_FCER ; do function call error then warm start + +; perform EOR + +; added operator format is the same as AND or OR, precedence is the same as OR + +; this bit worked first time but it took a while to sort out the operator table +; pointers and offsets afterwards! + +LAB_EOR + JSR GetFirst ; get first integer expression (no sign check) + EOR XOAw_l ; EOR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + EOR XOAw_h ; EOR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform OR + +LAB_OR + JSR GetFirst ; get first integer expression (no sign check) + ORA XOAw_l ; OR with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + ORA XOAw_h ; OR with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform AND + +LAB_AND + JSR GetFirst ; get first integer expression (no sign check) + AND XOAw_l ; AND with expression 1 low byte + TAY ; save in Y + LDA FAC1_2 ; get FAC1 mantissa2 + AND XOAw_h ; AND with expression 1 high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; get first value for OR, AND or EOR + +GetFirst + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_2 ; get FAC1 mantissa2 + STA XOAw_h ; save it + LDA FAC1_3 ; get FAC1 mantissa3 + STA XOAw_l ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JSR LAB_EVIR ; evaluate integer expression (no sign check) + LDA FAC1_3 ; get FAC1 mantissa3 +LAB_1C95 + RTS + +; perform comparisons + +; do < compare + +LAB_LTHAN + JSR LAB_CKTM ; type match check, set C for string + BCS LAB_1CAE ; branch if string + + ; do numeric < compare + LDA FAC2_s ; get FAC2 sign (b7) + ORA #$7F ; set all non sign bits + AND FAC2_1 ; and FAC2 mantissa1 (AND in sign bit) + STA FAC2_1 ; save FAC2 mantissa1 + LDA #FAC2_e ; set pointer high byte to FAC2 + JSR LAB_27F8 ; compare FAC1 with FAC2 (AY) + TAX ; copy result + JMP LAB_1CE1 ; go evaluate result + + ; do string < compare +LAB_1CAE + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + DEC comp_f ; clear < bit in compare function flag + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STA str_ln ; save length + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDA FAC2_2 ; get descriptor pointer low byte + LDY FAC2_3 ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=pointer low byte, + ; Y=pointer high byte + STX FAC2_2 ; save string pointer low byte + STY FAC2_3 ; save string pointer high byte + TAX ; copy length + SEC ; set carry for subtract + SBC str_ln ; subtract string 1 length + BEQ LAB_1CD6 ; branch if str 1 length = string 2 length + + LDA #$01 ; set str 1 length > string 2 length + BCC LAB_1CD6 ; branch if so + + LDX str_ln ; get string 1 length + LDA #$FF ; set str 1 length < string 2 length +LAB_1CD6 + STA FAC1_s ; save length compare + LDY #$FF ; set index + INX ; adjust for loop +LAB_1CDB + INY ; increment index + DEX ; decrement count + BNE LAB_1CE6 ; branch if still bytes to do + + LDX FAC1_s ; get length compare back +LAB_1CE1 + BMI LAB_1CF2 ; branch if str 1 < str 2 + + CLC ; flag str 1 <= str 2 + BCC LAB_1CF2 ; go evaluate result + +LAB_1CE6 + LDA (FAC2_2),Y ; get string 2 byte + CMP (FAC1_1),Y ; compare with string 1 byte + BEQ LAB_1CDB ; loop if bytes = + + LDX #$FF ; set str 1 < string 2 + BCS LAB_1CF2 ; branch if so + + LDX #$01 ; set str 1 > string 2 +LAB_1CF2 + INX ; x = 0, 1 or 2 + TXA ; copy to A + ROL ; *2 (1, 2 or 4) + AND Cflag ; AND with comparison evaluation flag + BEQ LAB_1CFB ; branch if 0 (compare is false) + + LDA #$FF ; else set result true +LAB_1CFB + JMP LAB_27DB ; save A as integer byte and return + +LAB_1CFE + JSR LAB_1C01 ; scan for ",", else do syntax error then warm start + +; perform DIM + +LAB_DIM + TAX ; copy "DIM" flag to X + JSR LAB_1D10 ; search for variable + JSR LAB_GBYT ; scan memory + BNE LAB_1CFE ; scan for "," and loop if not null + + RTS + +; perform << (left shift) + +LAB_LSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Ls_loop + ASL FAC1_3 ; shift low byte + ROL ; shift high byte + DEX ; decrement bit count + BNE Ls_loop ; loop if shift not complete + + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform >> (right shift) + +LAB_RSHIFT + JSR GetPair ; get integer expression and byte (no sign check) + LDA FAC1_2 ; get expression high byte + LDX TempB ; get shift count + BEQ NoShift ; branch if zero + + CPX #$10 ; compare bit count with 16d + BCS TooBig ; branch if >= + +Rs_loop + LSR ; shift high byte + ROR FAC1_3 ; shift low byte + DEX ; decrement bit count + BNE Rs_loop ; loop if shift not complete + +NoShift + LDY FAC1_3 ; get expression low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +TooBig + LDA #$00 ; clear high byte + TAY ; copy to low byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +GetPair + JSR LAB_EVBY ; evaluate byte expression, result in X + STX TempB ; save it + JSR LAB_279B ; copy FAC2 to FAC1 (get 2nd value in expression) + JMP LAB_EVIR ; evaluate integer expression (no sign check) + +; search for variable + +; return pointer to variable in Cvaral/Cvarah + +LAB_GVAR + LDX #$00 ; set DIM flag = $00 + JSR LAB_GBYT ; scan memory (1st character) +LAB_1D10 + STX Defdim ; save DIM flag +LAB_1D12 + STA Varnm1 ; save 1st character + AND #$7F ; clear FN flag bit + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D1F ; branch if ok + + JMP LAB_SNER ; else syntax error then warm start + + ; was variable name so .. +LAB_1D1F + LDX #$00 ; clear 2nd character temp + STX Dtypef ; clear data type flag, $FF=string, $00=numeric + JSR LAB_IGBY ; increment and scan memory (2nd character) + BCC LAB_1D2D ; branch if character = "0"-"9" (ok) + + ; 2nd character wasn't "0" to "9" so .. + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCC LAB_1D38 ; branch if <"A" or >"Z" (go check if string) + +LAB_1D2D + TAX ; copy 2nd character + + ; ignore further (valid) characters in the variable name +LAB_1D2E + JSR LAB_IGBY ; increment and scan memory (3rd character) + BCC LAB_1D2E ; loop if character = "0"-"9" (ignore) + + JSR LAB_CASC ; check byte, return C=0 if<"A" or >"Z" + BCS LAB_1D2E ; loop if character = "A"-"Z" (ignore) + + ; check if string variable +LAB_1D38 + CMP #'$' ; compare with "$" + BNE LAB_1D47 ; branch if not string + +; to introduce a new variable type (% suffix for integers say) then this branch +; will need to go to that check and then that branch, if it fails, go to LAB_1D47 + + ; type is string + LDA #$FF ; set data type = string + STA Dtypef ; set data type flag, $FF=string, $00=numeric + TXA ; get 2nd character back + ORA #$80 ; set top bit (indicate string var) + TAX ; copy back to 2nd character temp + JSR LAB_IGBY ; increment and scan memory + +; after we have determined the variable type we need to come back here to determine +; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely + + +LAB_1D47 ; gets here with character after var name in A + STX Varnm2 ; save 2nd character + ORA Sufnxf ; or with subscript/FNX flag (or FN name) + CMP #'(' ; compare with "(" + BNE LAB_1D53 ; branch if not "(" + + JMP LAB_1E17 ; go find, or make, array + +; either find or create var +; var name (1st two characters only!) is in Varnm1,Varnm2 + + ; variable name wasn't var(... so look for plain var +LAB_1D53 + LDA #$00 ; clear A + STA Sufnxf ; clear subscript/FNX flag + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + LDY #$00 ; clear index +LAB_1D5D + STX Vrschh ; save search address high byte +LAB_1D5F + STA Vrschl ; save search address low byte + CPX Sarryh ; compare high address with var space end + BNE LAB_1D69 ; skip next compare if <> + + ; high addresses were = so compare low addresses + CMP Sarryl ; compare low address with var space end + BEQ LAB_1D8B ; if not found go make new var + +LAB_1D69 + LDA Varnm1 ; get 1st character of var to find + CMP (Vrschl),Y ; compare with variable name 1st character + BNE LAB_1D77 ; branch if no match + + ; 1st characters match so compare 2nd characters + LDA Varnm2 ; get 2nd character of var to find + INY ; index to point to variable name 2nd character + CMP (Vrschl),Y ; compare with variable name 2nd character + BEQ LAB_1DD7 ; branch if match (found var) + + DEY ; else decrement index (now = $00) +LAB_1D77 + CLC ; clear carry for add + LDA Vrschl ; get search address low byte + ADC #$06 ; +6 (offset to next var name) + BCC LAB_1D5F ; loop if no overflow to high byte + + INX ; else increment high byte + BNE LAB_1D5D ; loop always (RAM doesn't extend to $FFFF !) + +; check byte, return C=0 if<"A" or >"Z" or "a" to "z" + +LAB_CASC + CMP #'a' ; compare with "a" + BCS LAB_1D83 ; go check <"z"+1 + +; check byte, return C=0 if<"A" or >"Z" + +LAB_1D82 + CMP #'A' ; compare with "A" + BCC LAB_1D8A ; exit if less + + ; carry is set + SBC #$5B ; subtract "Z"+1 + SEC ; set carry + SBC #$A5 ; subtract $A5 (restore byte) + ; carry clear if byte>$5A +LAB_1D8A + RTS + +LAB_1D83 + SBC #$7B ; subtract "z"+1 + SEC ; set carry + SBC #$85 ; subtract $85 (restore byte) + ; carry clear if byte>$7A + RTS + + ; reached end of variable mem without match + ; .. so create new variable +LAB_1D8B + PLA ; pop return address low byte + PHA ; push return address low byte +LAB_1C18p2 = LAB_1C18+2 + CMP #LAB_1D96 ; high byte point to $00,$00 + RTS + + ; create new numeric variable +LAB_1D98 + LDA Sarryl ; get var mem end low byte + LDY Sarryh ; get var mem end high byte + STA Ostrtl ; save old block start low byte + STY Ostrth ; save old block start high byte + LDA Earryl ; get array mem end low byte + LDY Earryh ; get array mem end high byte + STA Obendl ; save old block end low byte + STY Obendh ; save old block end high byte + CLC ; clear carry for add + ADC #$06 ; +6 (space for one var) + BCC LAB_1DAE ; branch if no overflow to high byte + + INY ; else increment high byte +LAB_1DAE + STA Nbendl ; set new block end low byte + STY Nbendh ; set new block end high byte + JSR LAB_11CF ; open up space in memory + LDA Nbendl ; get new start low byte + LDY Nbendh ; get new start high byte (-$100) + INY ; correct high byte + STA Sarryl ; save new var mem end low byte + STY Sarryh ; save new var mem end high byte + LDY #$00 ; clear index + LDA Varnm1 ; get var name 1st character + STA (Vrschl),Y ; save var name 1st character + INY ; increment index + LDA Varnm2 ; get var name 2nd character + STA (Vrschl),Y ; save var name 2nd character + LDA #$00 ; clear A + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + INY ; increment index + STA (Vrschl),Y ; initialise var byte + + ; found a match for var ((Vrschl) = ptr) +LAB_1DD7 + LDA Vrschl ; get var address low byte + CLC ; clear carry for add + ADC #$02 ; +2 (offset past var name bytes) + LDY Vrschh ; get var address high byte + BCC LAB_1DE1 ; branch if no overflow from add + + INY ; else increment high byte +LAB_1DE1 + STA Cvaral ; save current var address low byte + STY Cvarah ; save current var address high byte + RTS + +; set-up array pointer (Adatal/h) to first element in array +; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05 + +LAB_1DE6 + LDA Dimcnt ; get # of dimensions (1, 2 or 3) + ASL ; *2 (also clears the carry !) + ADC #$05 ; +5 (result is 7, 9 or 11 here) + ADC Astrtl ; add array start pointer low byte + LDY Astrth ; get array pointer high byte + BCC LAB_1DF2 ; branch if no overflow + + INY ; else increment high byte +LAB_1DF2 + STA Adatal ; save array data pointer low byte + STY Adatah ; save array data pointer high byte + RTS + +; evaluate integer expression + +LAB_EVIN + JSR LAB_IGBY ; increment and scan memory + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate integer expression (no check) + +LAB_EVPI + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_1E12 ; do function call error if -ve + +; evaluate integer expression (no sign check) + +LAB_EVIR + LDA FAC1_e ; get FAC1 exponent + CMP #$90 ; compare with exponent = 2^16 (n>2^15) + BCC LAB_1E14 ; branch if n<2^16 (is ok) + + LDA #LAB_1DF7 ; set pointer high byte to -32768 + JSR LAB_27F8 ; compare FAC1 with (AY) +LAB_1E12 + BNE LAB_FCER ; if <> do function call error then warm start + +LAB_1E14 + JMP LAB_2831 ; convert FAC1 floating-to-fixed and return + +; find or make array + +LAB_1E17 + LDA Defdim ; get DIM flag + PHA ; push it + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; push it + LDY #$00 ; clear dimensions count + +; now get the array dimension(s) and stack it (them) before the data type and DIM flag + +LAB_1E1F + TYA ; copy dimensions count + PHA ; save it + LDA Varnm2 ; get array name 2nd byte + PHA ; save it + LDA Varnm1 ; get array name 1st byte + PHA ; save it + JSR LAB_EVIN ; evaluate integer expression + PLA ; pull array name 1st byte + STA Varnm1 ; restore array name 1st byte + PLA ; pull array name 2nd byte + STA Varnm2 ; restore array name 2nd byte + PLA ; pull dimensions count + TAY ; restore it + TSX ; copy stack pointer + LDA LAB_STAK+2,X ; get DIM flag + PHA ; push it + LDA LAB_STAK+1,X ; get data type flag + PHA ; push it + LDA FAC1_2 ; get this dimension size high byte + STA LAB_STAK+2,X ; stack before flag bytes + LDA FAC1_3 ; get this dimension size low byte + STA LAB_STAK+1,X ; stack before flag bytes + INY ; increment dimensions count + JSR LAB_GBYT ; scan memory + CMP #',' ; compare with "," + BEQ LAB_1E1F ; if found go do next dimension + + STY Dimcnt ; store dimensions count + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull data type flag + STA Dtypef ; restore data type flag, $FF=string, $00=numeric + PLA ; pull DIM flag + STA Defdim ; restore DIM flag + LDX Sarryl ; get array mem start low byte + LDA Sarryh ; get array mem start high byte + +; now check to see if we are at the end of array memory (we would be if there were +; no arrays). + +LAB_1E5C + STX Astrtl ; save as array start pointer low byte + STA Astrth ; save as array start pointer high byte + CMP Earryh ; compare with array mem end high byte + BNE LAB_1E68 ; branch if not reached array mem end + + CPX Earryl ; else compare with array mem end low byte + BEQ LAB_1EA1 ; go build array if not found + + ; search for array +LAB_1E68 + LDY #$00 ; clear index + LDA (Astrtl),Y ; get array name first byte + INY ; increment index to second name byte + CMP Varnm1 ; compare with this array name first byte + BNE LAB_1E77 ; branch if no match + + LDA Varnm2 ; else get this array name second byte + CMP (Astrtl),Y ; compare with array name second byte + BEQ LAB_1E8D ; array found so branch + + ; no match +LAB_1E77 + INY ; increment index + LDA (Astrtl),Y ; get array size low byte + CLC ; clear carry for add + ADC Astrtl ; add array start pointer low byte + TAX ; copy low byte to X + INY ; increment index + LDA (Astrtl),Y ; get array size high byte + ADC Astrth ; add array mem pointer high byte + BCC LAB_1E5C ; if no overflow go check next array + +; do array bounds error + +LAB_1E85 + LDX #$10 ; error code $10 ("Array bounds" error) + .byte $2C ; makes next bit BIT LAB_08A2 + +; do function call error + +LAB_FCER + LDX #$08 ; error code $08 ("Function call" error) +LAB_1E8A + JMP LAB_XERR ; do error #X, then warm start + + ; found array, are we trying to dimension it? +LAB_1E8D + LDX #$12 ; set error $12 ("Double dimension" error) + LDA Defdim ; get DIM flag + BNE LAB_1E8A ; if we are trying to dimension it do error #X, then warm + ; start + +; found the array and we're not dimensioning it so we must find an element in it + + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + LDA Dimcnt ; get dimensions count + LDY #$04 ; set index to array's # of dimensions + CMP (Astrtl),Y ; compare with no of dimensions + BNE LAB_1E85 ; if wrong do array bounds error, could do "Wrong + ; dimensions" error here .. if we want a different + ; error message + + JMP LAB_1F28 ; found array so go get element + ; (could jump to LAB_1F28 as all LAB_1F24 does is take + ; Dimcnt and save it at (Astrtl),Y which is already the + ; same or we would have taken the BNE) + + ; array not found, so build it +LAB_1EA1 + JSR LAB_1DE6 ; set-up array pointer (Adatal/h) to first element in array + ; (Astrtl,Astrth points to start of array) + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + LDY #$00 ; clear Y (don't need to clear A) + STY Aspth ; clear array data size high byte + LDA Varnm1 ; get variable name 1st byte + STA (Astrtl),Y ; save array name 1st byte + INY ; increment index + LDA Varnm2 ; get variable name 2nd byte + STA (Astrtl),Y ; save array name 2nd byte + LDA Dimcnt ; get dimensions count + LDY #$04 ; index to dimension count + STY Asptl ; set array data size low byte (four bytes per element) + STA (Astrtl),Y ; set array's dimensions count + + ; now calculate the size of the data space for the array + CLC ; clear carry for add (clear on subsequent loops) +LAB_1EC0 + LDX #$0B ; set default dimension value low byte + LDA #$00 ; set default dimension value high byte + BIT Defdim ; test default DIM flag + BVC LAB_1ED0 ; branch if b6 of Defdim is clear + + PLA ; else pull dimension value low byte + ADC #$01 ; +1 (allow for zeroeth element) + TAX ; copy low byte to X + PLA ; pull dimension value high byte + ADC #$00 ; add carry from low byte + +LAB_1ED0 + INY ; index to dimension value high byte + STA (Astrtl),Y ; save dimension value high byte + INY ; index to dimension value high byte + TXA ; get dimension value low byte + STA (Astrtl),Y ; save dimension value low byte + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + STX Asptl ; save array data size low byte + STA Aspth ; save array data size high byte + LDY ut1_pl ; restore index (saved by subroutine) + DEC Dimcnt ; decrement dimensions count + BNE LAB_1EC0 ; loop while not = 0 + + ADC Adatah ; add size high byte to first element high byte + ; (carry is always clear here) + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + STA Adatah ; save end of array high byte + TAY ; copy end high byte to Y + TXA ; get array size low byte + ADC Adatal ; add array start low byte + BCC LAB_1EF3 ; branch if no carry + + INY ; else increment end of array high byte + BEQ LAB_1F45 ; if overflow go do "Out of memory" error + + ; set-up mostly complete, now zero the array +LAB_1EF3 + JSR LAB_121F ; check available memory, "Out of memory" error if no room + ; addr to check is in AY (low/high) + STA Earryl ; save array mem end low byte + STY Earryh ; save array mem end high byte + LDA #$00 ; clear byte for array clear + INC Aspth ; increment array size high byte (now block count) + LDY Asptl ; get array size low byte (now index to block) + BEQ LAB_1F07 ; branch if low byte = $00 + +LAB_1F02 + DEY ; decrement index (do 0 to n-1) + STA (Adatal),Y ; zero byte + BNE LAB_1F02 ; loop until this block done + +LAB_1F07 + DEC Adatah ; decrement array pointer high byte + DEC Aspth ; decrement block count high byte + BNE LAB_1F02 ; loop until all blocks done + + INC Adatah ; correct for last loop + SEC ; set carry for subtract + LDY #$02 ; index to array size low byte + LDA Earryl ; get array mem end low byte + SBC Astrtl ; subtract array start low byte + STA (Astrtl),Y ; save array size low byte + INY ; index to array size high byte + LDA Earryh ; get array mem end high byte + SBC Astrth ; subtract array start high byte + STA (Astrtl),Y ; save array size high byte + LDA Defdim ; get default DIM flag + BNE LAB_1F7B ; exit (RET) if this was a DIM command + + ; else, find element + INY ; index to # of dimensions + +LAB_1F24 + LDA (Astrtl),Y ; get array's dimension count + STA Dimcnt ; save it + +; we have found, or built, the array. now we need to find the element + +LAB_1F28 + LDA #$00 ; clear byte + STA Asptl ; clear array data pointer low byte +LAB_1F2C + STA Aspth ; save array data pointer high byte + INY ; increment index (point to array bound high byte) + PLA ; pull array index low byte + TAX ; copy to X + STA FAC1_2 ; save index low byte to FAC1 mantissa2 + PLA ; pull array index high byte + STA FAC1_3 ; save index high byte to FAC1 mantissa3 + CMP (Astrtl),Y ; compare with array bound high byte + BCC LAB_1F48 ; branch if within bounds + + BNE LAB_1F42 ; if outside bounds do array bounds error + + ; else high byte was = so test low bytes + INY ; index to array bound low byte + TXA ; get array index low byte + CMP (Astrtl),Y ; compare with array bound low byte + BCC LAB_1F49 ; branch if within bounds + +LAB_1F42 + JMP LAB_1E85 ; else do array bounds error + +LAB_1F45 + JMP LAB_OMER ; do "Out of memory" error then warm start + +LAB_1F48 + INY ; index to array bound low byte +LAB_1F49 + LDA Aspth ; get array data pointer high byte + ORA Asptl ; OR with array data pointer low byte + BEQ LAB_1F5A ; branch if array data pointer = null (skip multiply) + + JSR LAB_1F7C ; does XY = (Astrtl),Y * (Asptl) + TXA ; get result low byte + ADC FAC1_2 ; add index low byte from FAC1 mantissa2 + TAX ; save result low byte + TYA ; get result high byte + LDY ut1_pl ; restore index +LAB_1F5A + ADC FAC1_3 ; add index high byte from FAC1 mantissa3 + STX Asptl ; save array data pointer low byte + DEC Dimcnt ; decrement dimensions count + BNE LAB_1F2C ; loop if dimensions still to do + + ASL Asptl ; array data pointer low byte * 2 + ROL ; array data pointer high byte * 2 + ASL Asptl ; array data pointer low byte * 4 + ROL ; array data pointer high byte * 4 + TAY ; copy high byte + LDA Asptl ; get low byte + ADC Adatal ; add array data start pointer low byte + STA Cvaral ; save as current var address low byte + TYA ; get high byte back + ADC Adatah ; add array data start pointer high byte + STA Cvarah ; save as current var address high byte + TAY ; copy high byte to Y + LDA Cvaral ; get current var address low byte +LAB_1F7B + RTS + +; does XY = (Astrtl),Y * (Asptl) + +LAB_1F7C + STY ut1_pl ; save index + LDA (Astrtl),Y ; get dimension size low byte + STA dims_l ; save dimension size low byte + DEY ; decrement index + LDA (Astrtl),Y ; get dimension size high byte + STA dims_h ; save dimension size high byte + + LDA #$10 ; count = $10 (16 bit multiply) + STA numbit ; save bit count + LDX #$00 ; clear result low byte + LDY #$00 ; clear result high byte +LAB_1F8F + TXA ; get result low byte + ASL ; *2 + TAX ; save result low byte + TYA ; get result high byte + ROL ; *2 + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + + ASL Asptl ; shift multiplier low byte + ROL Aspth ; shift multiplier high byte + BCC LAB_1FA8 ; skip add if no carry + + CLC ; else clear carry for add + TXA ; get result low byte + ADC dims_l ; add dimension size low byte + TAX ; save result low byte + TYA ; get result high byte + ADC dims_h ; add dimension size high byte + TAY ; save result high byte + BCS LAB_1F45 ; if overflow go do "Out of memory" error + +LAB_1FA8 + DEC numbit ; decrement bit count + BNE LAB_1F8F ; loop until all done + + RTS + +; perform FRE() + +LAB_FRE + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + BPL LAB_1FB4 ; branch if numeric + + JSR LAB_22B6 ; pop string off descriptor stack, or from top of string + ; space returns with A = length, X=$71=pointer low byte, + ; Y=$72=pointer high byte + + ; FRE(n) was numeric so do this +LAB_1FB4 + JSR LAB_GARB ; go do garbage collection + SEC ; set carry for subtract + LDA Sstorl ; get bottom of string space low byte + SBC Earryl ; subtract array mem end low byte + TAY ; copy result to Y + LDA Sstorh ; get bottom of string space high byte + SBC Earryh ; subtract array mem end high byte + +; save and convert integer AY to FAC1 + +LAB_AYFC + LSR Dtypef ; clear data type flag, $FF=string, $00=numeric + STA FAC1_1 ; save FAC1 mantissa1 + STY FAC1_2 ; save FAC1 mantissa2 + LDX #$90 ; set exponent=2^16 (integer) + JMP LAB_27E3 ; set exp=X, clear FAC1_3, normalise and return + +; perform POS() + +LAB_POS + LDY TPos ; get terminal position + +; convert Y to byte in FAC1 + +LAB_1FD0 + LDA #$00 ; clear high byte + BEQ LAB_AYFC ; always save and convert integer AY to FAC1 and return + +; check not Direct (used by DEF and INPUT) + +LAB_CKRN + LDX Clineh ; get current line high byte + INX ; increment it + BNE LAB_1F7B ; return if can continue not direct mode + + ; else do illegal direct error +LAB_1FD9 + LDX #$16 ; error code $16 ("Illegal direct" error) +LAB_1FDB + JMP LAB_XERR ; go do error #X, then warm start + +; perform DEF + +LAB_DEF + JSR LAB_200B ; check FNx syntax + STA func_l ; save function pointer low byte + STY func_h ; save function pointer high byte + JSR LAB_CKRN ; check not Direct (back here if ok) + JSR LAB_1BFE ; scan for "(" , else do syntax error then warm start + LDA #$80 ; set flag for FNx + STA Sufnxf ; save subscript/FNx flag + JSR LAB_GVAR ; get (var) address + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDA #TK_EQUAL ; get = token + JSR LAB_SCCA ; scan for CHR$(A), else do syntax error then warm start + LDA Cvarah ; get current var address high byte + PHA ; push it + LDA Cvaral ; get current var address low byte + PHA ; push it + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + JSR LAB_DATA ; go perform DATA + JMP LAB_207A ; put execute pointer and variable pointer into function + ; and return + +; check FNx syntax + +LAB_200B + LDA #TK_FN ; get FN" token + JSR LAB_SCCA ; scan for CHR$(A) , else do syntax error then warm start + ; return character after A + ORA #$80 ; set FN flag bit + STA Sufnxf ; save FN flag so array variable test fails + JSR LAB_1D12 ; search for FN variable + JMP LAB_CTNM ; check if source is numeric and return, else do type + ; mismatch + + ; Evaluate FNx +LAB_201E + JSR LAB_200B ; check FNx syntax + PHA ; push function pointer low byte + TYA ; copy function pointer high byte + PHA ; push function pointer high byte + JSR LAB_1BFE ; scan for "(", else do syntax error then warm start + JSR LAB_EVEX ; evaluate expression + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + PLA ; pop function pointer high byte + STA func_h ; restore it + PLA ; pop function pointer low byte + STA func_l ; restore it + LDX #$20 ; error code $20 ("Undefined function" error) + LDY #$03 ; index to variable pointer high byte + LDA (func_l),Y ; get variable pointer high byte + BEQ LAB_1FDB ; if zero go do undefined function error + + STA Cvarah ; save variable address high byte + DEY ; index to variable address low byte + LDA (func_l),Y ; get variable address low byte + STA Cvaral ; save variable address low byte + TAX ; copy address low byte + + ; now stack the function variable value before use + INY ; index to mantissa_3 +LAB_2043 + LDA (Cvaral),Y ; get byte from variable + PHA ; stack it + DEY ; decrement index + BPL LAB_2043 ; loop until variable stacked + + LDY Cvarah ; get variable address high byte + JSR LAB_2778 ; pack FAC1 (function expression value) into (XY) + ; (function variable), return Y=0, always + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push it + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push it + LDA (func_l),Y ; get function execute pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + INY ; index to high byte + LDA (func_l),Y ; get function execute pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + LDA Cvarah ; get variable address high byte + PHA ; push it + LDA Cvaral ; get variable address low byte + PHA ; push it + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + PLA ; pull variable address low byte + STA func_l ; save variable address low byte + PLA ; pull variable address high byte + STA func_h ; save variable address high byte + JSR LAB_GBYT ; scan memory + BEQ LAB_2074 ; branch if null (should be [EOL] marker) + + JMP LAB_SNER ; else syntax error then warm start + +; restore Bpntrl,Bpntrh and function variable from stack + +LAB_2074 + PLA ; pull BASIC execute pointer low byte + STA Bpntrl ; restore BASIC execute pointer low byte + PLA ; pull BASIC execute pointer high byte + STA Bpntrh ; restore BASIC execute pointer high byte + +; put execute pointer and variable pointer into function + +LAB_207A + LDY #$00 ; clear index + PLA ; pull BASIC execute pointer low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull BASIC execute pointer high byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address low byte + STA (func_l),Y ; save to function + INY ; increment index + PLA ; pull current var address high byte + STA (func_l),Y ; save to function + RTS + +; perform STR$() + +LAB_STRS + JSR LAB_CTNM ; check if source is numeric, else do type mismatch + JSR LAB_296E ; convert FAC1 to string + LDA #Decssp1 ; set result string high pointer + BEQ LAB_20AE ; print null terminated string to Sutill/Sutilh + +; Do string vector +; copy des_pl/h to des_2l/h and make string space A bytes long + +LAB_209C + LDX des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + STX des_2l ; save descriptor pointer low byte + STY des_2h ; save descriptor pointer high byte + +; make string space A bytes long +; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + +LAB_MSSP + JSR LAB_2115 ; make space in string memory for string A long + ; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + STA str_ln ; save length + RTS + +; Scan, set up string +; print " terminated string to Sutill/Sutilh + +LAB_20AE + LDX #$22 ; set terminator to " + STX Srchc ; set search character (terminator 1) + STX Asrch ; set terminator 2 + +; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh +; source is AY + +LAB_20B4 + STA ssptr_l ; store string start low byte + STY ssptr_h ; store string start high byte + STA str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + LDY #$FF ; set length to -1 +LAB_20BE + INY ; increment length + LDA (ssptr_l),Y ; get byte from string + BEQ LAB_20CF ; exit loop if null byte [EOS] + + CMP Srchc ; compare with search character (terminator 1) + BEQ LAB_20CB ; branch if terminator + + CMP Asrch ; compare with terminator 2 + BNE LAB_20BE ; loop if not terminator 2 + +LAB_20CB + CMP #$22 ; compare with " + BEQ LAB_20D0 ; branch if " (carry set if = !) + +LAB_20CF + CLC ; clear carry for add (only if [EOL] terminated string) +LAB_20D0 + STY str_ln ; save length in FAC1 exponent + TYA ; copy length to A + ADC ssptr_l ; add string start low byte + STA Sendl ; save string end low byte + LDX ssptr_h ; get string start high byte + BCC LAB_20DC ; branch if no low byte overflow + + INX ; else increment high byte +LAB_20DC + STX Sendh ; save string end high byte + LDA ssptr_h ; get string start high byte + CMP #>Ram_base ; compare with start of program memory + BCS LAB_RTST ; branch if not in utility area + + ; string in utility area, move to string memory + TYA ; copy length to A + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + LDX ssptr_l ; get string start low byte + LDY ssptr_h ; get string start high byte + JSR LAB_2298 ; store string A bytes long from XY to (Sutill) + +; check for space on descriptor stack then .. +; put string address and length on descriptor stack and update stack pointers + +LAB_RTST + LDX next_s ; get string stack pointer + CPX #des_sk+$09 ; compare with max+1 + BNE LAB_20F8 ; branch if space on string stack + + ; else do string too complex error + LDX #$1C ; error code $1C ("String too complex" error) +LAB_20F5 + JMP LAB_XERR ; do error #X, then warm start + +; put string address and length on descriptor stack and update stack pointers + +LAB_20F8 + LDA str_ln ; get string length + STA PLUS_0,X ; put on string stack + LDA str_pl ; get string pointer low byte + STA PLUS_1,X ; put on string stack + LDA str_ph ; get string pointer high byte + STA PLUS_2,X ; put on string stack + LDY #$00 ; clear Y + STX des_pl ; save string descriptor pointer low byte + STY des_ph ; save string descriptor pointer high byte (always $00) + DEY ; Y = $FF + STY Dtypef ; save data type flag, $FF=string + STX last_sl ; save old stack pointer (current top item) + INX ; update stack pointer + INX ; update stack pointer + INX ; update stack pointer + STX next_s ; save new top item value + RTS + +; Build descriptor +; make space in string memory for string A long +; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte + +LAB_2115 + LSR Gclctd ; clear garbage collected flag (b7) + + ; make space for string A long +LAB_2117 + PHA ; save string length + EOR #$FF ; complement it + SEC ; set carry for subtract (twos comp add) + ADC Sstorl ; add bottom of string space low byte (subtract length) + LDY Sstorh ; get bottom of string space high byte + BCS LAB_2122 ; skip decrement if no underflow + + DEY ; decrement bottom of string space high byte +LAB_2122 + CPY Earryh ; compare with array mem end high byte + BCC LAB_2137 ; do out of memory error if less + + BNE LAB_212C ; if not = skip next test + + CMP Earryl ; compare with array mem end low byte + BCC LAB_2137 ; do out of memory error if less + +LAB_212C + STA Sstorl ; save bottom of string space low byte + STY Sstorh ; save bottom of string space high byte + STA Sutill ; save string utility ptr low byte + STY Sutilh ; save string utility ptr high byte + TAX ; copy low byte to X + PLA ; get string length back + RTS + +LAB_2137 + LDX #$0C ; error code $0C ("Out of memory" error) + LDA Gclctd ; get garbage collected flag + BMI LAB_20F5 ; if set then do error code X + + JSR LAB_GARB ; else go do garbage collection + LDA #$80 ; flag for garbage collected + STA Gclctd ; set garbage collected flag + PLA ; pull length + BNE LAB_2117 ; go try again (loop always, length should never be = $00) + +; garbage collection routine + +LAB_GARB + LDX Ememl ; get end of mem low byte + LDA Ememh ; get end of mem high byte + +; re-run routine from last ending + +LAB_214B + STX Sstorl ; set string storage low byte + STA Sstorh ; set string storage high byte + LDY #$00 ; clear index + STY garb_h ; clear working pointer high byte (flag no strings to move) + LDA Earryl ; get array mem end low byte + LDX Earryh ; get array mem end high byte + STA Histrl ; save as highest string low byte + STX Histrh ; save as highest string high byte + LDA #des_sk ; set descriptor stack pointer + STA ut1_pl ; save descriptor stack pointer low byte + STY ut1_ph ; save descriptor stack pointer high byte ($00) +LAB_2161 + CMP next_s ; compare with descriptor stack pointer + BEQ LAB_216A ; branch if = + + JSR LAB_21D7 ; go garbage collect descriptor stack + BEQ LAB_2161 ; loop always + + ; done stacked strings, now do string vars +LAB_216A + ASL g_step ; set step size = $06 + LDA Svarl ; get start of vars low byte + LDX Svarh ; get start of vars high byte + STA ut1_pl ; save as pointer low byte + STX ut1_ph ; save as pointer high byte +LAB_2176 + CPX Sarryh ; compare start of arrays high byte + BNE LAB_217E ; branch if no high byte match + + CMP Sarryl ; else compare start of arrays low byte + BEQ LAB_2183 ; branch if = var mem end + +LAB_217E + JSR LAB_21D1 ; go garbage collect strings + BEQ LAB_2176 ; loop always + + ; done string vars, now do string arrays +LAB_2183 + STA Nbendl ; save start of arrays low byte as working pointer + STX Nbendh ; save start of arrays high byte as working pointer + LDA #$04 ; set step size + STA g_step ; save step size +LAB_218B + LDA Nbendl ; get pointer low byte + LDX Nbendh ; get pointer high byte +LAB_218F + CPX Earryh ; compare with array mem end high byte + BNE LAB_219A ; branch if not at end + + CMP Earryl ; else compare with array mem end low byte + BEQ LAB_2216 ; tidy up and exit if at end + +LAB_219A + STA ut1_pl ; save pointer low byte + STX ut1_ph ; save pointer high byte + LDY #$02 ; set index + LDA (ut1_pl),Y ; get array size low byte + ADC Nbendl ; add start of this array low byte + STA Nbendl ; save start of next array low byte + INY ; increment index + LDA (ut1_pl),Y ; get array size high byte + ADC Nbendh ; add start of this array high byte + STA Nbendh ; save start of next array high byte + LDY #$01 ; set index + LDA (ut1_pl),Y ; get name second byte + BPL LAB_218B ; skip if not string array + +; was string array so .. + + LDY #$04 ; set index + LDA (ut1_pl),Y ; get # of dimensions + ASL ; *2 + ADC #$05 ; +5 (array header size) + JSR LAB_2208 ; go set up for first element +LAB_21C4 + CPX Nbendh ; compare with start of next array high byte + BNE LAB_21CC ; branch if <> (go do this array) + + CMP Nbendl ; else compare element pointer low byte with next array + ; low byte + BEQ LAB_218F ; if equal then go do next array + +LAB_21CC + JSR LAB_21D7 ; go defrag array strings + BEQ LAB_21C4 ; go do next array string (loop always) + +; defrag string variables +; enter with XA = variable pointer +; return with XA = next variable pointer + +LAB_21D1 + INY ; increment index (Y was $00) + LDA (ut1_pl),Y ; get var name byte 2 + BPL LAB_2206 ; if not string, step pointer to next var and return + + INY ; else increment index +LAB_21D7 + LDA (ut1_pl),Y ; get string length + BEQ LAB_2206 ; if null, step pointer to next string and return + + INY ; else increment index + LDA (ut1_pl),Y ; get string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte + CMP Sstorh ; compare bottom of string space high byte + BCC LAB_21EC ; branch if less + + BNE LAB_2206 ; if greater, step pointer to next string and return + + ; high bytes were = so compare low bytes + CPX Sstorl ; compare bottom of string space low byte + BCS LAB_2206 ; if >=, step pointer to next string and return + + ; string pointer is < string storage pointer (pos in mem) +LAB_21EC + CMP Histrh ; compare to highest string high byte + BCC LAB_2207 ; if <, step pointer to next string and return + + BNE LAB_21F6 ; if > update pointers, step to next and return + + ; high bytes were = so compare low bytes + CPX Histrl ; compare to highest string low byte + BCC LAB_2207 ; if <, step pointer to next string and return + + ; string is in string memory space +LAB_21F6 + STX Histrl ; save as new highest string low byte + STA Histrh ; save as new highest string high byte + LDA ut1_pl ; get start of vars(descriptors) low byte + LDX ut1_ph ; get start of vars(descriptors) high byte + STA garb_l ; save as working pointer low byte + STX garb_h ; save as working pointer high byte + DEY ; decrement index DIFFERS + DEY ; decrement index (should point to descriptor start) + STY g_indx ; save index pointer + + ; step pointer to next string +LAB_2206 + CLC ; clear carry for add +LAB_2207 + LDA g_step ; get step size +LAB_2208 + ADC ut1_pl ; add pointer low byte + STA ut1_pl ; save pointer low byte + BCC LAB_2211 ; branch if no overflow + + INC ut1_ph ; else increment high byte +LAB_2211 + LDX ut1_ph ; get pointer high byte + LDY #$00 ; clear Y + RTS + +; search complete, now either exit or set-up and move string + +LAB_2216 + DEC g_step ; decrement step size (now $03 for descriptor stack) + LDX garb_h ; get string to move high byte + BEQ LAB_2211 ; exit if nothing to move + + LDY g_indx ; get index byte back (points to descriptor) + CLC ; clear carry for add + LDA (garb_l),Y ; get string length + ADC Histrl ; add highest string low byte + STA Obendl ; save old block end low pointer + LDA Histrh ; get highest string high byte + ADC #$00 ; add any carry + STA Obendh ; save old block end high byte + LDA Sstorl ; get bottom of string space low byte + LDX Sstorh ; get bottom of string space high byte + STA Nbendl ; save new block end low byte + STX Nbendh ; save new block end high byte + JSR LAB_11D6 ; open up space in memory, don't set array end + LDY g_indx ; get index byte + INY ; point to descriptor low byte + LDA Nbendl ; get string pointer low byte + STA (garb_l),Y ; save new string pointer low byte + TAX ; copy string pointer low byte + INC Nbendh ; correct high byte (move sets high byte -1) + LDA Nbendh ; get new string pointer high byte + INY ; point to descriptor high byte + STA (garb_l),Y ; save new string pointer high byte + JMP LAB_214B ; re-run routine from last ending + ; (but don't collect this string) + +; concatenate +; add strings, string 1 is in descriptor des_pl, string 2 is in line + +LAB_224D + LDA des_ph ; get descriptor pointer high byte + PHA ; put on stack + LDA des_pl ; get descriptor pointer low byte + PHA ; put on stack + JSR LAB_GVAL ; get value from line + JSR LAB_CTST ; check if source is string, else do type mismatch + PLA ; get descriptor pointer low byte back + STA ssptr_l ; set pointer low byte + PLA ; get descriptor pointer high byte back + STA ssptr_h ; set pointer high byte + LDY #$00 ; clear index + LDA (ssptr_l),Y ; get length_1 from descriptor + CLC ; clear carry for add + ADC (des_pl),Y ; add length_2 + BCC LAB_226D ; branch if no overflow + + LDX #$1A ; else set error code $1A ("String too long" error) + JMP LAB_XERR ; do error #X, then warm start + +LAB_226D + JSR LAB_209C ; copy des_pl/h to des_2l/h and make string space A bytes + ; long + JSR LAB_228A ; copy string from descriptor (sdescr) to (Sutill) + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, ut1_pl = pointer low byte, + ; ut1_ph = pointer high byte + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + LDA ssptr_l ;.set descriptor pointer low byte + LDY ssptr_h ;.set descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + JSR LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + JMP LAB_1ADB ;.continue evaluation + +; copy string from descriptor (sdescr) to (Sutill) + +LAB_228A + LDY #$00 ; clear index + LDA (sdescr),Y ; get string length + PHA ; save on stack + INY ; increment index + LDA (sdescr),Y ; get source string pointer low byte + TAX ; copy to X + INY ; increment index + LDA (sdescr),Y ; get source string pointer high byte + TAY ; copy to Y + PLA ; get length back + +; store string A bytes long from YX to (Sutill) + +LAB_2298 + STX ut1_pl ; save source string pointer low byte + STY ut1_ph ; save source string pointer high byte + +; store string A bytes long from (ut1_pl) to (Sutill) + +LAB_229C + TAX ; copy length to index (don't count with Y) + BEQ LAB_22B2 ; branch if = $0 (null string) no need to add zero length + + LDY #$00 ; zero pointer (copy forward) +LAB_22A0 + LDA (ut1_pl),Y ; get source byte + STA (Sutill),Y ; save destination byte + + INY ; increment index + DEX ; decrement counter + BNE LAB_22A0 ; loop while <> 0 + + TYA ; restore length from Y +LAB_22A9 + CLC ; clear carry for add + ADC Sutill ; add string utility ptr low byte + STA Sutill ; save string utility ptr low byte + BCC LAB_22B2 ; branch if no carry + + INC Sutilh ; else increment string utility ptr high byte +LAB_22B2 + RTS + +; evaluate string + +LAB_EVST + JSR LAB_CTST ; check if source is string, else do type mismatch + +; pop string off descriptor stack, or from top of string space +; returns with A = length, X=pointer low byte, Y=pointer high byte + +LAB_22B6 + LDA des_pl ; get descriptor pointer low byte + LDY des_ph ; get descriptor pointer high byte + +; pop (YA) descriptor off stack or from top of string space +; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte + +LAB_22BA + STA ut1_pl ; save descriptor pointer low byte + STY ut1_ph ; save descriptor pointer high byte + JSR LAB_22EB ; clean descriptor stack, YA = pointer + PHP ; save status flags + LDY #$00 ; clear index + LDA (ut1_pl),Y ; get length from string descriptor + PHA ; put on stack + INY ; increment index + LDA (ut1_pl),Y ; get string pointer low byte from descriptor + TAX ; copy to X + INY ; increment index + LDA (ut1_pl),Y ; get string pointer high byte from descriptor + TAY ; copy to Y + PLA ; get string length back + PLP ; restore status + BNE LAB_22E6 ; branch if pointer <> last_sl,last_sh + + CPY Sstorh ; compare bottom of string space high byte + BNE LAB_22E6 ; branch if <> + + CPX Sstorl ; else compare bottom of string space low byte + BNE LAB_22E6 ; branch if <> + + PHA ; save string length + CLC ; clear carry for add + ADC Sstorl ; add bottom of string space low byte + STA Sstorl ; save bottom of string space low byte + BCC LAB_22E5 ; skip increment if no overflow + + INC Sstorh ; increment bottom of string space high byte +LAB_22E5 + PLA ; restore string length +LAB_22E6 + STX ut1_pl ; save string pointer low byte + STY ut1_ph ; save string pointer high byte + RTS + +; clean descriptor stack, YA = pointer +; checks if AY is on the descriptor stack, if so does a stack discard + +LAB_22EB + CPY last_sh ; compare pointer high byte + BNE LAB_22FB ; exit if <> + + CMP last_sl ; compare pointer low byte + BNE LAB_22FB ; exit if <> + + STA next_s ; save descriptor stack pointer + SBC #$03 ; -3 + STA last_sl ; save low byte -3 + LDY #$00 ; clear high byte +LAB_22FB + RTS + +; perform CHR$() + +LAB_CHRS + JSR LAB_EVBY ; evaluate byte expression, result in X + TXA ; copy to A + PHA ; save character + LDA #$01 ; string is single byte + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + PLA ; get character back + LDY #$00 ; clear index + STA (str_pl),Y ; save byte in string (byte IS string!) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform LEFT$() + +LAB_LEFT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CMP (des_2l),Y ; compare byte parameter with string length + TYA ; clear A + BEQ LAB_2316 ; go do string copy (branch always) + +; perform RIGHT$() + +LAB_RIGHT + PHA ; push byte parameter + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + CLC ; clear carry for add-1 + SBC (des_2l),Y ; subtract string length + EOR #$FF ; invert it (A=LEN(expression$)-l) + +LAB_2316 + BCC LAB_231C ; branch if string length > byte parameter + + LDA (des_2l),Y ; else make parameter = length + TAX ; copy to byte parameter copy + TYA ; clear string start offset +LAB_231C + PHA ; save string start offset +LAB_231D + TXA ; copy byte parameter (or string length if <) +LAB_231E + PHA ; save string length + JSR LAB_MSSP ; make string space A bytes long A=$AC=length, + ; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte + LDA des_2l ; get descriptor pointer low byte + LDY des_2h ; get descriptor pointer high byte + JSR LAB_22BA ; pop (YA) descriptor off stack or from top of string space + ; returns with A = length, X=ut1_pl=pointer low byte, + ; Y=ut1_ph=pointer high byte + PLA ; get string length back + TAY ; copy length to Y + PLA ; get string start offset back + CLC ; clear carry for add + ADC ut1_pl ; add start offset to string start pointer low byte + STA ut1_pl ; save string start pointer low byte + BCC LAB_2335 ; branch if no overflow + + INC ut1_ph ; else increment string start pointer high byte +LAB_2335 + TYA ; copy length to A + JSR LAB_229C ; store string A bytes long from (ut1_pl) to (Sutill) + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform MID$() + +LAB_MIDS + PHA ; push byte parameter + LDA #$FF ; set default length = 255 + STA mids_l ; save default length + JSR LAB_GBYT ; scan memory + CMP #')' ; compare with ")" + BEQ LAB_2358 ; branch if = ")" (skip second byte get) + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GTBY ; get byte parameter (use copy in mids_l) +LAB_2358 + JSR LAB_236F ; pull string data and byte parameter from stack + ; return pointer in des_2l/h, byte in A (and X), Y=0 + DEX ; decrement start index + TXA ; copy to A + PHA ; save string start offset + CLC ; clear carry for sub-1 + LDX #$00 ; clear output string length + SBC (des_2l),Y ; subtract string length + BCS LAB_231D ; if start>string length go do null string + + EOR #$FF ; complement -length + CMP mids_l ; compare byte parameter + BCC LAB_231E ; if length>remaining string go do RIGHT$ + + LDA mids_l ; get length byte + BCS LAB_231E ; go do string copy (branch always) + +; pull string data and byte parameter from stack +; return pointer in des_2l/h, byte in A (and X), Y=0 + +LAB_236F + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + PLA ; pull return address low byte (return address) + STA Fnxjpl ; save functions jump vector low byte + PLA ; pull return address high byte (return address) + STA Fnxjph ; save functions jump vector high byte + PLA ; pull byte parameter + TAX ; copy byte parameter to X + PLA ; pull string pointer low byte + STA des_2l ; save it + PLA ; pull string pointer high byte + STA des_2h ; save it + LDY #$00 ; clear index + TXA ; copy byte parameter + BEQ LAB_23A8 ; if null do function call error then warm start + + INC Fnxjpl ; increment function jump vector low byte + ; (JSR pushes return addr-1. this is all very nice + ; but will go tits up if either call is on a page + ; boundary!) + JMP (Fnxjpl) ; in effect, RTS + +; perform LCASE$() + +LAB_LCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +LC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_1D82 ; is character "A" to "Z" + BCC NoUcase ; branch if not upper case alpha + + ORA #$20 ; convert upper to lower case +NoUcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE LC_loop ; loop if not all done + + BEQ NoString ; tidy up and exit, branch always + +; perform UCASE$() + +LAB_UCASE + JSR LAB_EVST ; evaluate string + STA str_ln ; set string length + TAY ; copy length to Y + BEQ NoString ; branch if null string + + JSR LAB_MSSP ; make string space A bytes long A=length, + ; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte + STX str_pl ; save string pointer low byte + STY str_ph ; save string pointer high byte + TAY ; get string length back + +UC_loop + DEY ; decrement index + LDA (ut1_pl),Y ; get byte from string + JSR LAB_CASC ; is character "a" to "z" (or "A" to "Z") + BCC NoLcase ; branch if not alpha + + AND #$DF ; convert lower to upper case +NoLcase + STA (Sutill),Y ; save byte back to string + TYA ; test index + BNE UC_loop ; loop if not all done + +NoString + JMP LAB_RTST ; check for space on descriptor stack then put string + ; address and length on descriptor stack and update stack + ; pointers + +; perform SADD() + +LAB_SADD + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + + JSR LAB_1BFB ; scan for ")", else do syntax error then warm start + JSR LAB_CTST ; check if source is string, else do type mismatch + + LDY #$02 ; index to string pointer high byte + LDA (Cvaral),Y ; get string pointer high byte + TAX ; copy string pointer high byte to X + DEY ; index to string pointer low byte + LDA (Cvaral),Y ; get string pointer low byte + TAY ; copy string pointer low byte to Y + TXA ; copy string pointer high byte to A + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform LEN() + +LAB_LENS + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; evaluate string, get length in Y + +LAB_ESGL + JSR LAB_EVST ; evaluate string + TAY ; copy length to Y + RTS + +; perform ASC() + +LAB_ASC + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BEQ LAB_23A8 ; if null do function call error then warm start + + LDY #$00 ; set index to first character + LDA (ut1_pl),Y ; get byte + TAY ; copy to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; do function call error then warm start + +LAB_23A8 + JMP LAB_FCER ; do function call error then warm start + +; scan and get byte parameter + +LAB_SGBY + JSR LAB_IGBY ; increment and scan memory + +; get byte parameter + +LAB_GTBY + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + +; evaluate byte expression, result in X + +LAB_EVBY + JSR LAB_EVPI ; evaluate integer expression (no check) + + LDY FAC1_2 ; get FAC1 mantissa2 + BNE LAB_23A8 ; if top byte <> 0 do function call error then warm start + + LDX FAC1_3 ; get FAC1 mantissa3 + JMP LAB_GBYT ; scan memory and return + +; perform VAL() + +LAB_VAL + JSR LAB_ESGL ; evaluate string, get length in A (and Y) + BNE LAB_23C5 ; branch if not null string + + ; string was null so set result = $00 + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +LAB_23C5 + LDX Bpntrl ; get BASIC execute pointer low byte + LDY Bpntrh ; get BASIC execute pointer high byte + STX Btmpl ; save BASIC execute pointer low byte + STY Btmph ; save BASIC execute pointer high byte + LDX ut1_pl ; get string pointer low byte + STX Bpntrl ; save as BASIC execute pointer low byte + CLC ; clear carry + ADC ut1_pl ; add string length + STA ut2_pl ; save string end low byte + LDA ut1_ph ; get string pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + ADC #$00 ; add carry to high byte + STA ut2_ph ; save string end high byte + LDY #$00 ; set index to $00 + LDA (ut2_pl),Y ; get string end +1 byte + PHA ; push it + TYA ; clear A + STA (ut2_pl),Y ; terminate string with $00 + JSR LAB_GBYT ; scan memory + JSR LAB_2887 ; get FAC1 from string + PLA ; restore string end +1 byte + LDY #$00 ; set index to zero + STA (ut2_pl),Y ; put string end byte back + +; restore BASIC execute pointer from temp (Btmpl/Btmph) + +LAB_23F3 + LDX Btmpl ; get BASIC execute pointer low byte back + LDY Btmph ; get BASIC execute pointer high byte back + STX Bpntrl ; save BASIC execute pointer low byte + STY Bpntrh ; save BASIC execute pointer high byte + RTS + +; get two parameters for POKE or WAIT + +LAB_GADB + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + +; scan for "," and get byte, else do Syntax error then warm start + +LAB_SCGB + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + LDA Itemph ; save temporary integer high byte + PHA ; on stack + LDA Itempl ; save temporary integer low byte + PHA ; on stack + JSR LAB_GTBY ; get byte parameter + PLA ; pull low byte + STA Itempl ; restore temporary integer low byte + PLA ; pull high byte + STA Itemph ; restore temporary integer high byte + RTS + +; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or +; -ve and converts it into a right truncated integer in Itempl and Itemph + +; save unsigned 16 bit integer part of FAC1 in temporary integer + +LAB_F2FX + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with exponent = 2^24 + BCS LAB_23A8 ; if >= do function call error then warm start + +LAB_F2FU + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDA FAC1_2 ; get FAC1 mantissa2 + LDY FAC1_3 ; get FAC1 mantissa3 + STY Itempl ; save temporary integer low byte + STA Itemph ; save temporary integer high byte + RTS + +; perform PEEK() + +LAB_PEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; get byte via temporary integer (addr) + TAY ; copy byte to Y + JMP LAB_1FD0 ; convert Y to byte in FAC1 and return + +; perform POKE + +LAB_POKE + JSR LAB_GADB ; get two parameters for POKE or WAIT + TXA ; copy byte argument to A + LDX #$00 ; clear index + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +; perform DEEK() + +LAB_DEEK + JSR LAB_F2FX ; save integer part of FAC1 in temporary integer + LDX #$00 ; clear index + LDA (Itempl,X) ; PEEK low byte + TAY ; copy to Y + INC Itempl ; increment pointer low byte + BNE Deekh ; skip high increment if no rollover + + INC Itemph ; increment pointer high byte +Deekh + LDA (Itempl,X) ; PEEK high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform DOKE + +LAB_DOKE + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + STY Frnxtl ; save pointer low byte (float to fixed returns word in AY) + STA Frnxth ; save pointer high byte + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + + TYA ; copy value low byte (float to fixed returns word in AY) + LDX #$00 ; clear index + STA (Frnxtl,X) ; POKE low byte + INC Frnxtl ; increment pointer low byte + BNE Dokeh ; skip high increment if no rollover + + INC Frnxth ; increment pointer high byte +Dokeh + LDA Itemph ; get value high byte + STA (Frnxtl,X) ; POKE high byte + JMP LAB_GBYT ; scan memory and return + +; perform SWAP + +LAB_SWAP + JSR LAB_GVAR ; get var1 address + STA Lvarpl ; save var1 address low byte + STY Lvarph ; save var1 address high byte + LDA Dtypef ; get data type flag, $FF=string, $00=numeric + PHA ; save data type flag + + JSR LAB_1C01 ; scan for "," , else do syntax error then warm start + JSR LAB_GVAR ; get var2 address (pointer in Cvaral/h) + PLA ; pull var1 data type flag + EOR Dtypef ; compare with var2 data type + BPL SwapErr ; exit if not both the same type + + LDY #$03 ; four bytes to swap (either value or descriptor+1) +SwapLp + LDA (Lvarpl),Y ; get byte from var1 + TAX ; save var1 byte + LDA (Cvaral),Y ; get byte from var2 + STA (Lvarpl),Y ; save byte to var1 + TXA ; restore var1 byte + STA (Cvaral),Y ; save byte to var2 + DEY ; decrement index + BPL SwapLp ; loop until done + + RTS + +SwapErr + JMP LAB_1ABC ; do "Type mismatch" error then warm start + +; perform CALL + +LAB_CALL + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + JSR LAB_F2FX ; convert floating-to-fixed + LDA #>CallExit ; set return address high byte + PHA ; put on stack + LDA #8 shifts) + BCC LAB_24A8 ;.go subtract mantissas + +; add 0.5 to FAC1 + +LAB_244E + LDA #LAB_2A96 ; set 0.5 pointer high byte + +; add (AY) to FAC1 + +LAB_246C + JSR LAB_264D ; unpack memory (AY) into FAC2 + +; add FAC2 to FAC1 + +LAB_ADD + BNE LAB_2474 ; branch if FAC1 was not zero + +; copy FAC2 to FAC1 + +LAB_279B + LDA FAC2_s ; get FAC2 sign (b7) + +; save FAC1 sign and copy ABS(FAC2) to FAC1 + +LAB_279D + STA FAC1_s ; save FAC1 sign (b7) + LDX #$04 ; 4 bytes to copy +LAB_27A1 + LDA FAC1_o,X ; get byte from FAC2,X + STA FAC1_e-1,X ; save byte at FAC1,X + DEX ; decrement count + BNE LAB_27A1 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte + RTS + + ; FAC1 is non zero +LAB_2474 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC2_r ; save as FAC2 rounding byte + LDX #FAC2_e ; set index to FAC2 exponent addr + LDA FAC2_e ; get FAC2 exponent +LAB_247C + TAY ; copy exponent + BEQ LAB_244D ; exit if zero + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BEQ LAB_24A8 ; branch if = (go add mantissa) + + BCC LAB_2498 ; branch if < + + ; FAC2>FAC1 + STY FAC1_e ; save FAC1 exponent + LDY FAC2_s ; get FAC2 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$FF ; complement A + ADC #$00 ; +1 (twos complement, carry is set) + LDY #$00 ; clear Y + STY FAC2_r ; clear FAC2 rounding byte + LDX #FAC1_e ; set index to FAC1 exponent addr + BNE LAB_249C ; branch always + +LAB_2498 + LDY #$00 ; clear Y + STY FAC1_r ; clear FAC1 rounding byte +LAB_249C + CMP #$F9 ; compare exponent diff with $F9 + BMI LAB_2467 ; branch if range $79-$F8 + + TAY ; copy exponent difference to Y + LDA FAC1_r ; get FAC1 rounding byte + LSR PLUS_1,X ; shift FAC? mantissa1 + JSR LAB_2592 ; shift FACX Y times right + + ; exponents are equal now do mantissa subtract +LAB_24A8 + BIT FAC_sc ; test sign compare (FAC1 EOR FAC2) + BPL LAB_24F8 ; if = add FAC2 mantissa to FAC1 mantissa and return + + LDY #FAC1_e ; set index to FAC1 exponent addr + CPX #FAC2_e ; compare X to FAC2 exponent addr + BEQ LAB_24B4 ; branch if = + + LDY #FAC2_e ; else set index to FAC2 exponent addr + + ; subtract smaller from bigger (take sign of bigger) +LAB_24B4 + SEC ; set carry for subtract + EOR #$FF ; ones complement A + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA PLUS_3,Y ; get FACY mantissa3 + SBC PLUS_3,X ; subtract FACX mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA PLUS_2,Y ; get FACY mantissa2 + SBC PLUS_2,X ; subtract FACX mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA PLUS_1,Y ; get FACY mantissa1 + SBC PLUS_1,X ; subtract FACX mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + +; do ABS and normalise FAC1 + +LAB_24D0 + BCS LAB_24D5 ; branch if number is +ve + + JSR LAB_2537 ; negate FAC1 + +; normalise FAC1 + +LAB_24D5 + LDY #$00 ; clear Y + TYA ; clear A + CLC ; clear carry for add +LAB_24D9 + LDX FAC1_1 ; get FAC1 mantissa1 + BNE LAB_251B ; if not zero normalise FAC1 + + LDX FAC1_2 ; get FAC1 mantissa2 + STX FAC1_1 ; save FAC1 mantissa1 + LDX FAC1_3 ; get FAC1 mantissa3 + STX FAC1_2 ; save FAC1 mantissa2 + LDX FAC1_r ; get FAC1 rounding byte + STX FAC1_3 ; save FAC1 mantissa3 + STY FAC1_r ; clear FAC1 rounding byte + ADC #$08 ; add x to exponent offset + CMP #$18 ; compare with $18 (max offset, all bits would be =0) + BNE LAB_24D9 ; loop if not max + +; clear FAC1 exponent and sign + +LAB_24F1 + LDA #$00 ; clear A +LAB_24F3 + STA FAC1_e ; set FAC1 exponent + +; save FAC1 sign + +LAB_24F5 + STA FAC1_s ; save FAC1 sign (b7) + RTS + +; add FAC2 mantissa to FAC1 mantissa + +LAB_24F8 + ADC FAC2_r ; add FAC2 rounding byte + STA FAC1_r ; save FAC1 rounding byte + LDA FAC1_3 ; get FAC1 mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + BCS LAB_252A ; if carry then normalise FAC1 for C=1 + + RTS ; else just exit + +LAB_2511 + ADC #$01 ; add 1 to exponent offset + ASL FAC1_r ; shift FAC1 rounding byte + ROL FAC1_3 ; shift FAC1 mantissa3 + ROL FAC1_2 ; shift FAC1 mantissa2 + ROL FAC1_1 ; shift FAC1 mantissa1 + +; normalise FAC1 + +LAB_251B + BPL LAB_2511 ; loop if not normalised + + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent + BCS LAB_24F1 ; branch if underflow (set result = $0) + + EOR #$FF ; complement exponent + ADC #$01 ; +1 (twos complement) + STA FAC1_e ; save FAC1 exponent + +; test and normalise FAC1 for C=0/1 + +LAB_2528 + BCC LAB_2536 ; exit if no overflow + +; normalise FAC1 for C=1 + +LAB_252A + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_2564 ; if zero do overflow error and warm start + + ROR FAC1_1 ; shift FAC1 mantissa1 + ROR FAC1_2 ; shift FAC1 mantissa2 + ROR FAC1_3 ; shift FAC1 mantissa3 + ROR FAC1_r ; shift FAC1 rounding byte +LAB_2536 + RTS + +; negate FAC1 + +LAB_2537 + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) + +; twos complement FAC1 mantissa + +LAB_253D + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + STA FAC1_1 ; save FAC1 mantissa1 + LDA FAC1_2 ; get FAC1 mantissa2 + EOR #$FF ; complement it + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_3 ; get FAC1 mantissa3 + EOR #$FF ; complement it + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + EOR #$FF ; complement it + STA FAC1_r ; save FAC1 rounding byte + INC FAC1_r ; increment FAC1 rounding byte + BNE LAB_2563 ; exit if no overflow + +; increment FAC1 mantissa + +LAB_2559 + INC FAC1_3 ; increment FAC1 mantissa3 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_2 ; increment FAC1 mantissa2 + BNE LAB_2563 ; finished if no rollover + + INC FAC1_1 ; increment FAC1 mantissa1 +LAB_2563 + RTS + +; do overflow error (overflow exit) + +LAB_2564 + LDX #$0A ; error code $0A ("Overflow" error) + JMP LAB_XERR ; do error #X, then warm start + +; shift FCAtemp << A+8 times + +LAB_2569 + LDX #FACt_1-1 ; set offset to FACtemp +LAB_256B + LDY PLUS_3,X ; get FACX mantissa3 + STY FAC1_r ; save as FAC1 rounding byte + LDY PLUS_2,X ; get FACX mantissa2 + STY PLUS_3,X ; save FACX mantissa3 + LDY PLUS_1,X ; get FACX mantissa1 + STY PLUS_2,X ; save FACX mantissa2 + LDY FAC1_o ; get FAC1 overflow byte + STY PLUS_1,X ; save FACX mantissa1 + +; shift FACX -A times right (> 8 shifts) + +LAB_257B + ADC #$08 ; add 8 to shift count + BMI LAB_256B ; go do 8 shift if still -ve + + BEQ LAB_256B ; go do 8 shift if zero + + SBC #$08 ; else subtract 8 again + TAY ; save count to Y + LDA FAC1_r ; get FAC1 rounding byte + BCS LAB_259A ;. + +LAB_2588 + ASL PLUS_1,X ; shift FACX mantissa1 + BCC LAB_258E ; branch if +ve + + INC PLUS_1,X ; this sets b7 eventually +LAB_258E + ROR PLUS_1,X ; shift FACX mantissa1 (correct for ASL) + ROR PLUS_1,X ; shift FACX mantissa1 (put carry in b7) + +; shift FACX Y times right + +LAB_2592 + ROR PLUS_2,X ; shift FACX mantissa2 + ROR PLUS_3,X ; shift FACX mantissa3 + ROR ; shift FACX rounding byte + INY ; increment exponent diff + BNE LAB_2588 ; branch if range adjust not complete + +LAB_259A + CLC ; just clear it + RTS + +; perform LOG() + +LAB_LOG + JSR LAB_27CA ; test sign and zero + BEQ LAB_25C4 ; if zero do function call error then warm start + + BPL LAB_25C7 ; skip error if +ve + +LAB_25C4 + JMP LAB_FCER ; do function call error then warm start (-ve) + +LAB_25C7 + LDA FAC1_e ; get FAC1 exponent + SBC #$7F ; normalise it + PHA ; save it + LDA #$80 ; set exponent to zero + STA FAC1_e ; save FAC1 exponent + LDA #LAB_25AD ; set 1/root2 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 (1/root2) + LDA #LAB_25B1 ; set root2 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 (root2/(x+(1/root2))) + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_2455 ; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1) + LDA #LAB_25A0 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + LDA #LAB_25B5 ; set -0.5 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 exponent + JSR LAB_2912 ; evaluate new ASCII digit + LDA #LAB_25B9 ; set LOG(2) pointer high byte + +; do convert AY, FCA1*(AY) + +LAB_25FB + JSR LAB_264D ; unpack memory (AY) into FAC2 +LAB_MULTIPLY + BEQ LAB_264C ; exit if zero + + JSR LAB_2673 ; test and adjust accumulators + LDA #$00 ; clear A + STA FACt_1 ; clear temp mantissa1 + STA FACt_2 ; clear temp mantissa2 + STA FACt_3 ; clear temp mantissa3 + LDA FAC1_r ; get FAC1 rounding byte + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_3 ; get FAC1 mantissa3 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_2 ; get FAC1 mantissa2 + JSR LAB_2622 ; go do shift/add FAC2 + LDA FAC1_1 ; get FAC1 mantissa1 + JSR LAB_2627 ; go do shift/add FAC2 + JMP LAB_273C ; copy temp to FAC1, normalise and return + +LAB_2622 + BNE LAB_2627 ; branch if byte <> zero + + JMP LAB_2569 ; shift FCAtemp << A+8 times + + ; else do shift and add +LAB_2627 + LSR ; shift byte + ORA #$80 ; set top bit (mark for 8 times) +LAB_262A + TAY ; copy result + BCC LAB_2640 ; skip next if bit was zero + + CLC ; clear carry for add + LDA FACt_3 ; get temp mantissa3 + ADC FAC2_3 ; add FAC2 mantissa3 + STA FACt_3 ; save temp mantissa3 + LDA FACt_2 ; get temp mantissa2 + ADC FAC2_2 ; add FAC2 mantissa2 + STA FACt_2 ; save temp mantissa2 + LDA FACt_1 ; get temp mantissa1 + ADC FAC2_1 ; add FAC2 mantissa1 + STA FACt_1 ; save temp mantissa1 +LAB_2640 + ROR FACt_1 ; shift temp mantissa1 + ROR FACt_2 ; shift temp mantissa2 + ROR FACt_3 ; shift temp mantissa3 + ROR FAC1_r ; shift temp rounding byte + TYA ; get byte back + LSR ; shift byte + BNE LAB_262A ; loop if all bits not done + +LAB_264C + RTS + +; unpack memory (AY) into FAC2 + +LAB_264D + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to get (0-3) + LDA (ut1_pl),Y ; get mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get mantissa1+sign + STA FAC2_s ; save FAC2 sign (b7) + EOR FAC1_s ; EOR with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDA FAC2_s ; recover FAC2 sign (b7) + ORA #$80 ; set 1xxx xxx (set normal bit) + STA FAC2_1 ; save FAC2 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get exponent byte + STA FAC2_e ; save FAC2 exponent + LDA FAC1_e ; get FAC1 exponent + RTS + +; test and adjust accumulators + +LAB_2673 + LDA FAC2_e ; get FAC2 exponent +LAB_2675 + BEQ LAB_2696 ; branch if FAC2 = $00 (handle underflow) + + CLC ; clear carry for add + ADC FAC1_e ; add FAC1 exponent + BCC LAB_2680 ; branch if sum of exponents <$0100 + + BMI LAB_269B ; do overflow error + + CLC ; clear carry for the add + .byte $2C ; makes next line BIT $1410 +LAB_2680 + BPL LAB_2696 ; if +ve go handle underflow + + ADC #$80 ; adjust exponent + STA FAC1_e ; save FAC1 exponent + BNE LAB_268B ; branch if not zero + + JMP LAB_24F5 ; save FAC1 sign and return + +LAB_268B + LDA FAC_sc ; get sign compare (FAC1 EOR FAC2) + STA FAC1_s ; save FAC1 sign (b7) +LAB_268F + RTS + +; handle overflow and underflow + +LAB_2690 + LDA FAC1_s ; get FAC1 sign (b7) + BPL LAB_269B ; do overflow error + + ; handle underflow +LAB_2696 + PLA ; pop return address low byte + PLA ; pop return address high byte + JMP LAB_24F1 ; clear FAC1 exponent and sign and return + +; multiply by 10 + +LAB_269E + JSR LAB_27AB ; round and copy FAC1 to FAC2 + TAX ; copy exponent (set the flags) + BEQ LAB_268F ; exit if zero + + CLC ; clear carry for add + ADC #$02 ; add two to exponent (*4) + BCS LAB_269B ; do overflow error if > $FF + + LDX #$00 ; clear byte + STX FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_247C ; add FAC2 to FAC1 (*5) + INC FAC1_e ; increment FAC1 exponent (*10) + BNE LAB_268F ; if non zero just do RTS + +LAB_269B + JMP LAB_2564 ; do overflow error and warm start + +; divide by 10 + +LAB_26B9 + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_26B5 ; set pointer to 10d high addr + LDX #$00 ; clear sign + +; divide by (AY) (X=sign) + +LAB_26C2 + STX FAC_sc ; save sign compare (FAC1 EOR FAC2) + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + JMP LAB_DIVIDE ; do FAC2/FAC1 + + ; Perform divide-by +; convert AY and do (AY)/FAC1 + +LAB_26CA + JSR LAB_264D ; unpack memory (AY) into FAC2 + + ; Perform divide-into +LAB_DIVIDE + BEQ LAB_2737 ; if zero go do /0 error + + JSR LAB_27BA ; round FAC1 + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC FAC1_e ; subtract FAC1 exponent (2s complement) + STA FAC1_e ; save FAC1 exponent + JSR LAB_2673 ; test and adjust accumulators + INC FAC1_e ; increment FAC1 exponent + BEQ LAB_269B ; if zero do overflow error + + LDX #$FF ; set index for pre increment + LDA #$01 ; set bit to flag byte save +LAB_26E4 + LDY FAC2_1 ; get FAC2 mantissa1 + CPY FAC1_1 ; compare FAC1 mantissa1 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_2 ; get FAC2 mantissa2 + CPY FAC1_2 ; compare FAC1 mantissa2 + BNE LAB_26F4 ; branch if <> + + LDY FAC2_3 ; get FAC2 mantissa3 + CPY FAC1_3 ; compare FAC1 mantissa3 +LAB_26F4 + PHP ; save FAC2-FAC1 compare status + ROL ; shift the result byte + BCC LAB_2702 ; if no carry skip the byte save + + LDY #$01 ; set bit to flag byte save + INX ; else increment the index to FACt + CPX #$02 ; compare with the index to FACt_3 + BMI LAB_2701 ; if not last byte just go save it + + BNE LAB_272B ; if all done go save FAC1 rounding byte, normalise and + ; return + + LDY #$40 ; set bit to flag byte save for the rounding byte +LAB_2701 + STA FACt_1,X ; write result byte to FACt_1 + index + TYA ; copy the next save byte flag +LAB_2702 + PLP ; restore FAC2-FAC1 compare status + BCC LAB_2704 ; if FAC2 < FAC1 then skip the subtract + + TAY ; save FAC2-FAC1 compare status + LDA FAC2_3 ; get FAC2 mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + LDA FAC2_2 ; get FAC2 mantissa2 + SBC FAC1_2 ; subtract FAC1 mantissa2 + STA FAC2_2 ; save FAC2 mantissa2 + LDA FAC2_1 ; get FAC2 mantissa1 + SBC FAC1_1 ; subtract FAC1 mantissa1 + STA FAC2_1 ; save FAC2 mantissa1 + TYA ; restore FAC2-FAC1 compare status + + ; FAC2 = FAC2*2 +LAB_2704 + ASL FAC2_3 ; shift FAC2 mantissa3 + ROL FAC2_2 ; shift FAC2 mantissa2 + ROL FAC2_1 ; shift FAC2 mantissa1 + BCS LAB_26F4 ; loop with no compare + + BMI LAB_26E4 ; loop with compare + + BPL LAB_26F4 ; loop always with no compare + +; do A<<6, save as FAC1 rounding byte, normalise and return + +LAB_272B + LSR ; shift b1 - b0 .. + ROR ; .. + ROR ; .. to b7 - b6 + STA FAC1_r ; save FAC1 rounding byte + PLP ; dump FAC2-FAC1 compare status + JMP LAB_273C ; copy temp to FAC1, normalise and return + +; do "Divide by zero" error + +LAB_2737 + LDX #$14 ; error code $14 ("Divide by zero" error) + JMP LAB_XERR ; do error #X, then warm start + +; copy temp to FAC1 and normalise + +LAB_273C + LDA FACt_1 ; get temp mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + LDA FACt_2 ; get temp mantissa2 + STA FAC1_2 ; save FAC1 mantissa2 + LDA FACt_3 ; get temp mantissa3 + STA FAC1_3 ; save FAC1 mantissa3 + JMP LAB_24D5 ; normalise FAC1 and return + +; unpack memory (AY) into FAC1 + +LAB_UFAC + STA ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; 4 bytes to do + LDA (ut1_pl),Y ; get last byte + STA FAC1_3 ; save FAC1 mantissa3 + DEY ; decrement index + LDA (ut1_pl),Y ; get last-1 byte + STA FAC1_2 ; save FAC1 mantissa2 + DEY ; decrement index + LDA (ut1_pl),Y ; get second byte + STA FAC1_s ; save FAC1 sign (b7) + ORA #$80 ; set 1xxx xxxx (add normal bit) + STA FAC1_1 ; save FAC1 mantissa1 + DEY ; decrement index + LDA (ut1_pl),Y ; get first byte (exponent) + STA FAC1_e ; save FAC1 exponent + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; pack FAC1 into Adatal + +LAB_276E + LDX #Adatal ; set pointer high byte + BEQ LAB_2778 ; pack FAC1 into (XY) and return + +; pack FAC1 into (Lvarpl) + +LAB_PFAC + LDX Lvarpl ; get destination pointer low byte + LDY Lvarph ; get destination pointer high byte + +; pack FAC1 into (XY) + +LAB_2778 + JSR LAB_27BA ; round FAC1 + STX ut1_pl ; save pointer low byte + STY ut1_ph ; save pointer high byte + LDY #$03 ; set index + LDA FAC1_3 ; get FAC1 mantissa3 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_2 ; get FAC1 mantissa2 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_s ; get FAC1 sign (b7) + ORA #$7F ; set bits x111 1111 + AND FAC1_1 ; AND in FAC1 mantissa1 + STA (ut1_pl),Y ; store in destination + DEY ; decrement index + LDA FAC1_e ; get FAC1 exponent + STA (ut1_pl),Y ; store in destination + STY FAC1_r ; clear FAC1 rounding byte + RTS + +; round and copy FAC1 to FAC2 + +LAB_27AB + JSR LAB_27BA ; round FAC1 + +; copy FAC1 to FAC2 + +LAB_27AE + LDX #$05 ; 5 bytes to copy +LAB_27B0 + LDA FAC1_e-1,X ; get byte from FAC1,X + STA FAC1_o,X ; save byte at FAC2,X + DEX ; decrement count + BNE LAB_27B0 ; loop if not all done + + STX FAC1_r ; clear FAC1 rounding byte +LAB_27B9 + RTS + +; round FAC1 + +LAB_27BA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27B9 ; exit if zero + + ASL FAC1_r ; shift FAC1 rounding byte + BCC LAB_27B9 ; exit if no overflow + +; round FAC1 (no check) + +LAB_27C2 + JSR LAB_2559 ; increment FAC1 mantissa + BNE LAB_27B9 ; branch if no overflow + + JMP LAB_252A ; normalise FAC1 for C=1 and return + +; get FAC1 sign +; return A=FF,C=1/-ve A=01,C=0/+ve + +LAB_27CA + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_27D7 ; exit if zero (already correct SGN(0)=0) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check + +LAB_27CE + LDA FAC1_s ; else get FAC1 sign (b7) + +; return A=FF,C=1/-ve A=01,C=0/+ve +; no = 0 check, sign in A + +LAB_27D0 + ROL ; move sign bit to carry + LDA #$FF ; set byte for -ve result + BCS LAB_27D7 ; return if sign was set (-ve) + + LDA #$01 ; else set byte for +ve result +LAB_27D7 + RTS + +; perform SGN() + +LAB_SGN + JSR LAB_27CA ; get FAC1 sign + ; return A=$FF/-ve A=$01/+ve +; save A as integer byte + +LAB_27DB + STA FAC1_1 ; save FAC1 mantissa1 + LDA #$00 ; clear A + STA FAC1_2 ; clear FAC1 mantissa2 + LDX #$88 ; set exponent + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_27E3 + LDA FAC1_1 ; get FAC1 mantissa1 + EOR #$FF ; complement it + ROL ; sign bit into carry + +; set exp=X, clearFAC1 mantissa3 and normalise + +LAB_STFA + LDA #$00 ; clear A + STA FAC1_3 ; clear FAC1 mantissa3 + STX FAC1_e ; set FAC1 exponent + STA FAC1_r ; clear FAC1 rounding byte + STA FAC1_s ; clear FAC1 sign (b7) + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; perform ABS() + +LAB_ABS + LSR FAC1_s ; clear FAC1 sign (put zero in b7) + RTS + +; compare FAC1 with (AY) +; returns A=$00 if FAC1 = (AY) +; returns A=$01 if FAC1 > (AY) +; returns A=$FF if FAC1 < (AY) + +LAB_27F8 + STA ut2_pl ; save pointer low byte +LAB_27FA + STY ut2_ph ; save pointer high byte + LDY #$00 ; clear index + LDA (ut2_pl),Y ; get exponent + INY ; increment index + TAX ; copy (AY) exponent to X + BEQ LAB_27CA ; branch if (AY) exponent=0 and get FAC1 sign + ; A=FF,C=1/-ve A=01,C=0/+ve + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + EOR FAC1_s ; EOR FAC1 sign (b7) + BMI LAB_27CE ; if signs <> do return A=FF,C=1/-ve + ; A=01,C=0/+ve and return + + CPX FAC1_e ; compare (AY) exponent with FAC1 exponent + BNE LAB_2828 ; branch if different + + LDA (ut2_pl),Y ; get (AY) mantissa1 (with sign) + ORA #$80 ; normalise top bit + CMP FAC1_1 ; compare with FAC1 mantissa1 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA (ut2_pl),Y ; get mantissa2 + CMP FAC1_2 ; compare with FAC1 mantissa2 + BNE LAB_2828 ; branch if different + + INY ; increment index + LDA #$7F ; set for 1/2 value rounding byte + CMP FAC1_r ; compare with FAC1 rounding byte (set carry) + LDA (ut2_pl),Y ; get mantissa3 + SBC FAC1_3 ; subtract FAC1 mantissa3 + BEQ LAB_2850 ; exit if mantissa3 equal + +; gets here if number <> FAC1 + +LAB_2828 + LDA FAC1_s ; get FAC1 sign (b7) + BCC LAB_282E ; branch if FAC1 > (AY) + + EOR #$FF ; else toggle FAC1 sign +LAB_282E + JMP LAB_27D0 ; return A=FF,C=1/-ve A=01,C=0/+ve + +; convert FAC1 floating-to-fixed + +LAB_2831 + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_287F ; if zero go clear FAC1 and return + + SEC ; set carry for subtract + SBC #$98 ; subtract maximum integer range exponent + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2845 ; branch if FAC1 +ve + + ; FAC1 was -ve + TAX ; copy subtracted exponent + LDA #$FF ; overflow for -ve number + STA FAC1_o ; set FAC1 overflow byte + JSR LAB_253D ; twos complement FAC1 mantissa + TXA ; restore subtracted exponent +LAB_2845 + LDX #FAC1_e ; set index to FAC1 + CMP #$F9 ; compare exponent result + BPL LAB_2851 ; if < 8 shifts shift FAC1 A times right and return + + JSR LAB_257B ; shift FAC1 A times right (> 8 shifts) + STY FAC1_o ; clear FAC1 overflow byte +LAB_2850 + RTS + +; shift FAC1 A times right + +LAB_2851 + TAY ; copy shift count + LDA FAC1_s ; get FAC1 sign (b7) + AND #$80 ; mask sign bit only (x000 0000) + LSR FAC1_1 ; shift FAC1 mantissa1 + ORA FAC1_1 ; OR sign in b7 FAC1 mantissa1 + STA FAC1_1 ; save FAC1 mantissa1 + JSR LAB_2592 ; shift FAC1 Y times right + STY FAC1_o ; clear FAC1 overflow byte + RTS + +; perform INT() + +LAB_INT + LDA FAC1_e ; get FAC1 exponent + CMP #$98 ; compare with max int + BCS LAB_2886 ; exit if >= (already int, too big for fractional part!) + + JSR LAB_2831 ; convert FAC1 floating-to-fixed + STY FAC1_r ; save FAC1 rounding byte + LDA FAC1_s ; get FAC1 sign (b7) + STY FAC1_s ; save FAC1 sign (b7) + EOR #$80 ; toggle FAC1 sign + ROL ; shift into carry + LDA #$98 ; set new exponent + STA FAC1_e ; save FAC1 exponent + LDA FAC1_3 ; get FAC1 mantissa3 + STA Temp3 ; save for EXP() function + JMP LAB_24D0 ; do ABS and normalise FAC1 + +; clear FAC1 and return + +LAB_287F + STA FAC1_1 ; clear FAC1 mantissa1 + STA FAC1_2 ; clear FAC1 mantissa2 + STA FAC1_3 ; clear FAC1 mantissa3 + TAY ; clear Y +LAB_2886 + RTS + +; get FAC1 from string +; this routine now handles hex and binary values from strings +; starting with "$" and "%" respectively + +LAB_2887 + LDY #$00 ; clear Y + STY Dtypef ; clear data type flag, $FF=string, $00=numeric + LDX #$09 ; set index +LAB_288B + STY numexp,X ; clear byte + DEX ; decrement index + BPL LAB_288B ; loop until numexp to negnum (and FAC1) = $00 + + BCC LAB_28FE ; branch if 1st character numeric + +; get FAC1 from string .. first character wasn't numeric + + CMP #'-' ; else compare with "-" + BNE LAB_289A ; branch if not "-" + + STX negnum ; set flag for -ve number (X = $FF) + BEQ LAB_289C ; branch always (go scan and check for hex/bin) + +; get FAC1 from string .. first character wasn't numeric or - + +LAB_289A + CMP #'+' ; else compare with "+" + BNE LAB_289D ; branch if not "+" (go check for hex/bin) + +; was "+" or "-" to start, so get next character + +LAB_289C + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28FE ; branch if numeric character + +; code here for hex and binary numbers + +LAB_289D + CMP #'$' ; else compare with "$" + BNE LAB_NHEX ; branch if not "$" + + JMP LAB_CHEX ; branch if "$" + +LAB_NHEX + CMP #'%' ; else compare with "%" + BNE LAB_28A3 ; branch if not "%" (continue original code) + + JMP LAB_CBIN ; branch if "%" + +LAB_289E + JSR LAB_IGBY ; increment and scan memory (ignore + or get next number) +LAB_28A1 + BCC LAB_28FE ; branch if numeric character + +; get FAC1 from string .. character wasn't numeric, -, +, hex or binary + +LAB_28A3 + CMP #'.' ; else compare with "." + BEQ LAB_28D5 ; branch if "." + +; get FAC1 from string .. character wasn't numeric, -, + or . + + CMP #'E' ; else compare with "E" + BNE LAB_28DB ; branch if not "E" + + ; was "E" so evaluate exponential part + JSR LAB_IGBY ; increment and scan memory + BCC LAB_28C7 ; branch if numeric character + + CMP #TK_MINUS ; else compare with token for - + BEQ LAB_28C2 ; branch if token for - + + CMP #'-' ; else compare with "-" + BEQ LAB_28C2 ; branch if "-" + + CMP #TK_PLUS ; else compare with token for + + BEQ LAB_28C4 ; branch if token for + + + CMP #'+' ; else compare with "+" + BEQ LAB_28C4 ; branch if "+" + + BNE LAB_28C9 ; branch always + +LAB_28C2 + ROR expneg ; set exponent -ve flag (C, which=1, into b7) +LAB_28C4 + JSR LAB_IGBY ; increment and scan memory +LAB_28C7 + BCC LAB_2925 ; branch if numeric character + +LAB_28C9 + BIT expneg ; test exponent -ve flag + BPL LAB_28DB ; if +ve go evaluate exponent + + ; else do exponent = -exponent + LDA #$00 ; clear result + SEC ; set carry for subtract + SBC expcnt ; subtract exponent byte + JMP LAB_28DD ; go evaluate exponent + +LAB_28D5 + ROR numdpf ; set decimal point flag + BIT numdpf ; test decimal point flag + BVC LAB_289E ; branch if only one decimal point so far + + ; evaluate exponent +LAB_28DB + LDA expcnt ; get exponent count byte +LAB_28DD + SEC ; set carry for subtract + SBC numexp ; subtract numerator exponent + STA expcnt ; save exponent count byte + BEQ LAB_28F6 ; branch if no adjustment + + BPL LAB_28EF ; else if +ve go do FAC1*10^expcnt + + ; else go do FAC1/10^(0-expcnt) +LAB_28E6 + JSR LAB_26B9 ; divide by 10 + INC expcnt ; increment exponent count byte + BNE LAB_28E6 ; loop until all done + + BEQ LAB_28F6 ; branch always + +LAB_28EF + JSR LAB_269E ; multiply by 10 + DEC expcnt ; decrement exponent count byte + BNE LAB_28EF ; loop until all done + +LAB_28F6 + LDA negnum ; get -ve flag + BMI LAB_28FB ; if -ve do - FAC1 and return + + RTS + +; do - FAC1 and return + +LAB_28FB + JMP LAB_GTHAN ; do - FAC1 and return + +; do unsigned FAC1*10+number + +LAB_28FE + PHA ; save character + BIT numdpf ; test decimal point flag + BPL LAB_2905 ; skip exponent increment if not set + + INC numexp ; else increment number exponent +LAB_2905 + JSR LAB_269E ; multiply FAC1 by 10 + PLA ; restore character + AND #$0F ; convert to binary + JSR LAB_2912 ; evaluate new ASCII digit + JMP LAB_289E ; go do next character + +; evaluate new ASCII digit + +LAB_2912 + PHA ; save digit + JSR LAB_27AB ; round and copy FAC1 to FAC2 + PLA ; restore digit + JSR LAB_27DB ; save A as integer byte + LDA FAC2_s ; get FAC2 sign (b7) + EOR FAC1_s ; toggle with FAC1 sign (b7) + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + LDX FAC1_e ; get FAC1 exponent + JMP LAB_ADD ; add FAC2 to FAC1 and return + +; evaluate next character of exponential part of number + +LAB_2925 + LDA expcnt ; get exponent count byte + CMP #$0A ; compare with 10 decimal + BCC LAB_2934 ; branch if less + + LDA #$64 ; make all -ve exponents = -100 decimal (causes underflow) + BIT expneg ; test exponent -ve flag + BMI LAB_2942 ; branch if -ve + + JMP LAB_2564 ; else do overflow error + +LAB_2934 + ASL ; * 2 + ASL ; * 4 + ADC expcnt ; * 5 + ASL ; * 10 + LDY #$00 ; set index + ADC (Bpntrl),Y ; add character (will be $30 too much!) + SBC #'0'-1 ; convert character to binary +LAB_2942 + STA expcnt ; save exponent count byte + JMP LAB_28C4 ; go get next character + +; print " in line [LINE #]" + +LAB_2953 + LDA #LAB_LMSG ; point to " in line " message high byte + JSR LAB_18C3 ; print null terminated string from memory + + ; print Basic line # + LDA Clineh ; get current line high byte + LDX Clinel ; get current line low byte + +; print XA as unsigned integer + +LAB_295E + STA FAC1_1 ; save low byte as FAC1 mantissa1 + STX FAC1_2 ; save high byte as FAC1 mantissa2 + LDX #$90 ; set exponent to 16d bits + SEC ; set integer is +ve flag + JSR LAB_STFA ; set exp=X, clearFAC1 mantissa3 and normalise + LDY #$00 ; clear index + TYA ; clear A + JSR LAB_297B ; convert FAC1 to string, skip sign character save + JMP LAB_18C3 ; print null terminated string from memory and return + +; convert FAC1 to ASCII string result in (AY) +; not any more, moved scratchpad to page 0 + +LAB_296E + LDY #$01 ; set index = 1 + LDA #$20 ; character = " " (assume +ve) + BIT FAC1_s ; test FAC1 sign (b7) + BPL LAB_2978 ; branch if +ve + + LDA #$2D ; else character = "-" +LAB_2978 + STA Decss,Y ; save leading character (" " or "-") +LAB_297B + STA FAC1_s ; clear FAC1 sign (b7) + STY Sendl ; save index + INY ; increment index + LDX FAC1_e ; get FAC1 exponent + BNE LAB_2989 ; branch if FAC1<>0 + + ; exponent was $00 so FAC1 is 0 + LDA #'0' ; set character = "0" + JMP LAB_2A89 ; save last character, [EOT] and exit + + ; FAC1 is some non zero value +LAB_2989 + LDA #$00 ; clear (number exponent count) + CPX #$81 ; compare FAC1 exponent with $81 (>1.00000) + + BCS LAB_299A ; branch if FAC1=>1 + + ; FAC1<1 + LDA #LAB_294F ; set pointer high byte to 1,000,000 + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA #$FA ; set number exponent count (-6) +LAB_299A + STA numexp ; save number exponent count +LAB_299C + LDA #LAB_294B ; set pointer high byte to 999999.4375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29C3 ; exit if FAC1 = (AY) + + BPL LAB_29B9 ; go do /10 if FAC1 > (AY) + + ; FAC1 < (AY) +LAB_29A7 + LDA #LAB_2947 ; set pointer high byte to 99999.9375 + JSR LAB_27F8 ; compare FAC1 with (AY) + BEQ LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places) + + BPL LAB_29C0 ; branch if FAC1 > (AY) (no decimal places) + + ; FAC1 <= (AY) +LAB_29B2 + JSR LAB_269E ; multiply by 10 + DEC numexp ; decrement number exponent count + BNE LAB_29A7 ; go test again (branch always) + +LAB_29B9 + JSR LAB_26B9 ; divide by 10 + INC numexp ; increment number exponent count + BNE LAB_299C ; go test again (branch always) + +; now we have just the digits to do + +LAB_29C0 + JSR LAB_244E ; add 0.5 to FAC1 (round FAC1) +LAB_29C3 + JSR LAB_2831 ; convert FAC1 floating-to-fixed + LDX #$01 ; set default digits before dp = 1 + LDA numexp ; get number exponent count + CLC ; clear carry for add + ADC #$07 ; up to 6 digits before point + BMI LAB_29D8 ; if -ve then 1 digit before dp + + CMP #$08 ; A>=8 if n>=1E6 + BCS LAB_29D9 ; branch if >= $08 + + ; carry is clear + ADC #$FF ; take 1 from digit count + TAX ; copy to A + LDA #$02 ;.set exponent adjust +LAB_29D8 + SEC ; set carry for subtract +LAB_29D9 + SBC #$02 ; -2 + STA expcnt ;.save exponent adjust + STX numexp ; save digits before dp count + TXA ; copy to A + BEQ LAB_29E4 ; branch if no digits before dp + + BPL LAB_29F7 ; branch if digits before dp + +LAB_29E4 + LDY Sendl ; get output string index + LDA #$2E ; character "." + INY ; increment index + STA Decss,Y ; save to output string + TXA ;. + BEQ LAB_29F5 ;. + + LDA #'0' ; character "0" + INY ; increment index + STA Decss,Y ; save to output string +LAB_29F5 + STY Sendl ; save output string index +LAB_29F7 + LDY #$00 ; clear index (point to 100,000) + LDX #$80 ; +LAB_29FB + LDA FAC1_3 ; get FAC1 mantissa3 + CLC ; clear carry for add + ADC LAB_2A9C,Y ; add -ve LSB + STA FAC1_3 ; save FAC1 mantissa3 + LDA FAC1_2 ; get FAC1 mantissa2 + ADC LAB_2A9B,Y ; add -ve NMSB + STA FAC1_2 ; save FAC1 mantissa2 + LDA FAC1_1 ; get FAC1 mantissa1 + ADC LAB_2A9A,Y ; add -ve MSB + STA FAC1_1 ; save FAC1 mantissa1 + INX ; + BCS LAB_2A18 ; + + BPL LAB_29FB ; not -ve so try again + + BMI LAB_2A1A ; + +LAB_2A18 + BMI LAB_29FB ; + +LAB_2A1A + TXA ; + BCC LAB_2A21 ; + + EOR #$FF ; + ADC #$0A ; +LAB_2A21 + ADC #'0'-1 ; add "0"-1 to result + INY ; increment index .. + INY ; .. to next less .. + INY ; .. power of ten + STY Cvaral ; save as current var address low byte + LDY Sendl ; get output string index + INY ; increment output string index + TAX ; copy character to X + AND #$7F ; mask out top bit + STA Decss,Y ; save to output string + DEC numexp ; decrement # of characters before the dp + BNE LAB_2A3B ; branch if still characters to do + + ; else output the point + LDA #$2E ; character "." + INY ; increment output string index + STA Decss,Y ; save to output string +LAB_2A3B + STY Sendl ; save output string index + LDY Cvaral ; get current var address low byte + TXA ; get character back + EOR #$FF ; + AND #$80 ; + TAX ; + CPY #$12 ; compare index with max + BNE LAB_29FB ; loop if not max + + ; now remove trailing zeroes + LDY Sendl ; get output string index +LAB_2A4B + LDA Decss,Y ; get character from output string + DEY ; decrement output string index + CMP #'0' ; compare with "0" + BEQ LAB_2A4B ; loop until non "0" character found + + CMP #'.' ; compare with "." + BEQ LAB_2A58 ; branch if was dp + + ; restore last character + INY ; increment output string index +LAB_2A58 + LDA #$2B ; character "+" + LDX expcnt ; get exponent count + BEQ LAB_2A8C ; if zero go set null terminator and exit + + ; exponent isn't zero so write exponent + BPL LAB_2A68 ; branch if exponent count +ve + + LDA #$00 ; clear A + SEC ; set carry for subtract + SBC expcnt ; subtract exponent count adjust (convert -ve to +ve) + TAX ; copy exponent count to X + LDA #'-' ; character "-" +LAB_2A68 + STA Decss+2,Y ; save to output string + LDA #$45 ; character "E" + STA Decss+1,Y ; save exponent sign to output string + TXA ; get exponent count back + LDX #'0'-1 ; one less than "0" character + SEC ; set carry for subtract +LAB_2A74 + INX ; increment 10's character + SBC #$0A ;.subtract 10 from exponent count + BCS LAB_2A74 ; loop while still >= 0 + + ADC #':' ; add character ":" ($30+$0A, result is 10 less that value) + STA Decss+4,Y ; save to output string + TXA ; copy 10's character + STA Decss+3,Y ; save to output string + LDA #$00 ; set null terminator + STA Decss+5,Y ; save to output string + BEQ LAB_2A91 ; go set string pointer (AY) and exit (branch always) + + ; save last character, [EOT] and exit +LAB_2A89 + STA Decss,Y ; save last character to output string + + ; set null terminator and exit +LAB_2A8C + LDA #$00 ; set null terminator + STA Decss+1,Y ; save after last character + + ; set string pointer (AY) and exit +LAB_2A91 + LDA #Decssp1 ; set result string high pointer + RTS + +; perform power function + +LAB_POWER + BEQ LAB_EXP ; go do EXP() + + LDA FAC2_e ; get FAC2 exponent + BNE LAB_2ABF ; branch if FAC2<>0 + + JMP LAB_24F3 ; clear FAC1 exponent and sign and return + +LAB_2ABF + LDX #func_l ; set destination pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA FAC2_s ; get FAC2 sign (b7) + BPL LAB_2AD9 ; branch if FAC2>0 + + ; else FAC2 is -ve and can only be raised to an + ; integer power which gives an x +j0 result + JSR LAB_INT ; perform INT + LDA #func_l ; set source pointer high byte + JSR LAB_27F8 ; compare FAC1 with (AY) + BNE LAB_2AD9 ; branch if FAC1 <> (AY) to allow Function Call error + ; this will leave FAC1 -ve and cause a Function Call + ; error when LOG() is called + + TYA ; clear sign b7 + LDY Temp3 ; save mantissa 3 from INT() function as sign in Y + ; for possible later negation, b0 +LAB_2AD9 + JSR LAB_279D ; save FAC1 sign and copy ABS(FAC2) to FAC1 + TYA ; copy sign back .. + PHA ; .. and save it + JSR LAB_LOG ; do LOG(n) + LDA #garb_l ; set pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) (square the value) + JSR LAB_EXP ; go do EXP(n) + PLA ; pull sign from stack + LSR ; b0 is to be tested, shift to Cb + BCC LAB_2AF9 ; if no bit then exit + + ; Perform negation +; do - FAC1 + +LAB_GTHAN + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_2AF9 ; exit if FAC1_e = $00 + + LDA FAC1_s ; get FAC1 sign (b7) + EOR #$FF ; complement it + STA FAC1_s ; save FAC1 sign (b7) +LAB_2AF9 + RTS + +; perform EXP() (x^e) + +LAB_EXP + LDA #LAB_2AFA ; set 1.443 pointer high byte + JSR LAB_25FB ; do convert AY, FCA1*(AY) + LDA FAC1_r ; get FAC1 rounding byte + ADC #$50 ; +$50/$100 + BCC LAB_2B2B ; skip rounding if no carry + + JSR LAB_27C2 ; round FAC1 (no check) +LAB_2B2B + STA FAC2_r ; save FAC2 rounding byte + JSR LAB_27AE ; copy FAC1 to FAC2 + LDA FAC1_e ; get FAC1 exponent + CMP #$88 ; compare with EXP limit (256d) + BCC LAB_2B39 ; branch if less + +LAB_2B36 + JSR LAB_2690 ; handle overflow and underflow +LAB_2B39 + JSR LAB_INT ; perform INT + LDA Temp3 ; get mantissa 3 from INT() function + CLC ; clear carry for add + ADC #$81 ; normalise +1 + BEQ LAB_2B36 ; if $00 go handle overflow + + SEC ; set carry for subtract + SBC #$01 ; now correct for exponent + PHA ; save FAC2 exponent + + ; swap FAC1 and FAC2 + LDX #$04 ; 4 bytes to do +LAB_2B49 + LDA FAC2_e,X ; get FAC2,X + LDY FAC1_e,X ; get FAC1,X + STA FAC1_e,X ; save FAC1,X + STY FAC2_e,X ; save FAC2,X + DEX ; decrement count/index + BPL LAB_2B49 ; loop if not all done + + LDA FAC2_r ; get FAC2 rounding byte + STA FAC1_r ; save as FAC1 rounding byte + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + JSR LAB_GTHAN ; do - FAC1 + LDA #LAB_2AFE ; set counter pointer high byte + JSR LAB_2B84 ; go do series evaluation + LDA #$00 ; clear A + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + PLA ;.get saved FAC2 exponent + JMP LAB_2675 ; test and adjust accumulators and return + +; ^2 then series evaluation + +LAB_2B6E + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte + JSR LAB_276E ; pack FAC1 into Adatal + LDA #Adatal ; pointer to original # high byte + JMP LAB_25FB ; do convert AY, FCA1*(AY) and return + +; series evaluation + +LAB_2B84 + STA Cptrl ; save count pointer low byte + STY Cptrh ; save count pointer high byte +LAB_2B88 + LDX #numexp ; set pointer high byte to partial @ numexp + DEC numcon ; decrement constants count + BNE LAB_2B9B ; loop until all done + + RTS + +; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0 +; to get 19th next number in sequence after seed n. This version of the PRNG uses +; the Galois method and a sample of 65536 bytes produced gives the following values. + +; Entropy = 7.997442 bits per byte +; Optimum compression would reduce these 65536 bytes by 0 percent + +; Chi square distribution for 65536 samples is 232.01, and +; randomly would exceed this value 75.00 percent of the time + +; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random +; Monte Carlo value for Pi is 3.122871269, error 0.60 percent +; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0 + +LAB_RND + LDA FAC1_e ; get FAC1 exponent + BEQ NextPRN ; do next random # if zero + + ; else get seed into random number store + LDX #Rbyte4 ; set PRNG pointer low byte + LDY #$00 ; set PRNG pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) +NextPRN + LDX #$AF ; set EOR byte + LDY #$13 ; do this nineteen times +LoopPRN + ASL Rbyte1 ; shift PRNG most significant byte + ROL Rbyte2 ; shift PRNG middle byte + ROL Rbyte3 ; shift PRNG least significant byte + ROL Rbyte4 ; shift PRNG extra byte + BCC Ninc1 ; branch if bit 32 clear + + TXA ; set EOR byte + EOR Rbyte1 ; EOR PRNG extra byte + STA Rbyte1 ; save new PRNG extra byte +Ninc1 + DEY ; decrement loop count + BNE LoopPRN ; loop if not all done + + LDX #$02 ; three bytes to copy +CopyPRNG + LDA Rbyte1,X ; get PRNG byte + STA FAC1_1,X ; save FAC1 byte + DEX + BPL CopyPRNG ; loop if not complete + + LDA #$80 ; set the exponent + STA FAC1_e ; save FAC1 exponent + + ASL ; clear A + STA FAC1_s ; save FAC1 sign + + JMP LAB_24D5 ; normalise FAC1 and return + +; perform COS() + +LAB_COS + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + +; perform SIN() + +LAB_SIN + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #LAB_2C7C ; set (2*pi) pointer high byte + LDX FAC2_s ; get FAC2 sign (b7) + JSR LAB_26C2 ; divide by (AY) (X=sign) + JSR LAB_27AB ; round and copy FAC1 to FAC2 + JSR LAB_INT ; perform INT + LDA #$00 ; clear byte + STA FAC_sc ; clear sign compare (FAC1 EOR FAC2) + JSR LAB_SUBTRACT ; perform subtraction, FAC2 from FAC1 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save FAC1 sign + BPL LAB_2C35 ; branch if +ve + + ; FAC1 sign was -ve + JSR LAB_244E ; add 0.5 to FAC1 + LDA FAC1_s ; get FAC1 sign (b7) + BMI LAB_2C38 ; branch if -ve + + LDA Cflag ; get comparison evaluation flag + EOR #$FF ; toggle flag + STA Cflag ; save comparison evaluation flag +LAB_2C35 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C38 + LDA #LAB_2C80 ; set 0.25 pointer high byte + JSR LAB_246C ; add (AY) to FAC1 + PLA ; restore FAC1 sign + BPL LAB_2C45 ; branch if was +ve + + ; else correct FAC1 + JSR LAB_GTHAN ; do - FAC1 +LAB_2C45 + LDA #LAB_2C84 ; set pointer high byte to counter + JMP LAB_2B6E ; ^2 then series evaluation and return + +; perform TAN() + +LAB_TAN + JSR LAB_276E ; pack FAC1 into Adatal + LDA #$00 ; clear byte + STA Cflag ; clear comparison evaluation flag + JSR LAB_SIN ; go do SIN(n) + LDX #func_l ; set sin(n) pointer high byte + JSR LAB_2778 ; pack FAC1 into (XY) + LDA #Adatal ; set n pointer high addr + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + LDA #$00 ; clear byte + STA FAC1_s ; clear FAC1 sign (b7) + LDA Cflag ; get comparison evaluation flag + JSR LAB_2C74 ; save flag and go do series evaluation + + LDA #func_l ; set sin(n) pointer high byte + JMP LAB_26CA ; convert AY and do (AY)/FAC1 + +LAB_2C74 + PHA ; save comparison evaluation flag + JMP LAB_2C35 ; go do series evaluation + +; perform USR() + +LAB_USR + JSR Usrjmp ; call user code + JMP LAB_1BFB ; scan for ")", else do syntax error then warm start + +; perform ATN() + +LAB_ATN + LDA FAC1_s ; get FAC1 sign (b7) + PHA ; save sign + BPL LAB_2CA1 ; branch if +ve + + JSR LAB_GTHAN ; else do - FAC1 +LAB_2CA1 + LDA FAC1_e ; get FAC1 exponent + PHA ; push exponent + CMP #$81 ; compare with 1 + BCC LAB_2CAF ; branch if FAC1<1 + + LDA #LAB_259C ; set 1 pointer high byte + JSR LAB_26CA ; convert AY and do (AY)/FAC1 +LAB_2CAF + LDA #LAB_2CC9 ; set pointer high byte to counter + JSR LAB_2B6E ; ^2 then series evaluation + PLA ; restore old FAC1 exponent + CMP #$81 ; compare with 1 + BCC LAB_2CC2 ; branch if FAC1<1 + + LDA #LAB_2C78 ; set (pi/2) pointer high byte + JSR LAB_2455 ; perform subtraction, (AY) from FAC1 +LAB_2CC2 + PLA ; restore FAC1 sign + BPL LAB_2D04 ; exit if was +ve + + JMP LAB_GTHAN ; else do - FAC1 and return + +; perform BITSET + +LAB_BITSET + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$00 ; clear A + SEC ; set the carry +S_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bits ; loop if still +ve + + INX ; make X = $00 + ORA (Itempl,X) ; or with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) +LAB_2D04 + RTS + +; perform BITCLR + +LAB_BITCLR + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + LDA #$FF ; set A +S_Bitc + ROL ; shift bit + DEX ; decrement bit number + BPL S_Bitc ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; and with byte via temporary integer (addr) + STA (Itempl,X) ; save byte via temporary integer (addr) + RTS + +FCError + JMP LAB_FCER ; do function call error then warm start + +; perform BITTST() + +LAB_BTST + JSR LAB_IGBY ; increment BASIC pointer + JSR LAB_GADB ; get two parameters for POKE or WAIT + CPX #$08 ; only 0 to 7 are allowed + BCS FCError ; branch if > 7 + + JSR LAB_GBYT ; get next BASIC byte + CMP #')' ; is next character ")" + BEQ TST_OK ; if ")" go do rest of function + + JMP LAB_SNER ; do syntax error then warm start + +TST_OK + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + LDA #$00 ; clear A + SEC ; set the carry +T_Bits + ROL ; shift bit + DEX ; decrement bit number + BPL T_Bits ; loop if still +ve + + INX ; make X = $00 + AND (Itempl,X) ; AND with byte via temporary integer (addr) + BEQ LAB_NOTT ; branch if zero (already correct) + + LDA #$FF ; set for -1 result +LAB_NOTT + JMP LAB_27DB ; go do SGN tail + +; perform BIN$() + +LAB_BINS + CPX #$19 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters ($00 = leading zero remove) + LDA #$18 ; need A byte long space + JSR LAB_MSSP ; make string space A bytes long + LDY #$17 ; set index + LDX #$18 ; character count +NextB1 + LSR nums_1 ; shift highest byte + ROR nums_2 ; shift middle byte + ROR nums_3 ; shift lowest byte bit 0 to carry + TXA ; load with "0"/2 + ROL ; shift in carry + STA (str_pl),Y ; save to temp string + index + DEY ; decrement index + BPL NextB1 ; loop if not done + + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$18 ; add 24d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string + +; this is the exit code and is also used by HEX$() +; truncate string to remove leading "0"s + +EndBHS + TAY ; clear index (A=0, X=length here) +NextB2 + LDA (str_pl),Y ; get character from string + CMP #'0' ; compare with "0" + BNE GoPr ; if not "0" then go print string from here + + DEX ; decrement character count + BEQ GoPr3 ; if zero then end of string so go print it + + INY ; else increment index + BPL NextB2 ; loop always + +; make fixed length output string - ignore overflows! + +GoPr3 + INX ; need at least 1 character +GoPr + TYA ; copy result +GoPr1 + CLC ; clear carry for add + ADC str_pl ; add low address + STA str_pl ; save low address + LDA #$00 ; do high byte + ADC str_ph ; add high address + STA str_ph ; save high address +GoPr2 + STX str_ln ; X holds string length + JSR LAB_IGBY ; update BASIC execute pointer (to character past ")") + JMP LAB_RTST ; check for space on descriptor stack then put address + ; and length on descriptor stack and update stack pointers + +BinFErr + JMP LAB_FCER ; do function call error then warm start + +; perform HEX$() + +LAB_HEXS + CPX #$07 ; max + 1 + BCS BinFErr ; exit if too big ( > or = ) + + STX TempB ; save # of characters + + LDA #$06 ; need 6 bytes for string + JSR LAB_MSSP ; make string space A bytes long + LDY #$05 ; set string index + + SED ; need decimal mode for nibble convert + LDA nums_3 ; get lowest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_2 ; get middle byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + LDA nums_1 ; get highest byte + JSR LAB_A2HX ; convert A to ASCII hex byte and output + CLD ; back to binary + + LDX #$06 ; character count + LDA TempB ; get # of characters + BEQ EndBHS ; branch if truncate + + TAX ; copy length to X + SEC ; set carry for add ! + EOR #$FF ; 1's complement + ADC #$06 ; add 6d + BEQ GoPr2 ; if zero print whole string + + BNE GoPr1 ; else go make output string (branch always) + +; convert A to ASCII hex byte and output .. note set decimal mode before calling + +LAB_A2HX + TAX ; save byte + AND #$0F ; mask off top bits + JSR LAB_AL2X ; convert low nibble to ASCII and output + TXA ; get byte back + LSR ; /2 shift high nibble to low nibble + LSR ; /4 + LSR ; /8 + LSR ; /16 +LAB_AL2X + CMP #$0A ; set carry for +1 if >9 + ADC #'0' ; add ASCII "0" + STA (str_pl),Y ; save to temp string + DEY ; decrement counter + RTS + +LAB_NLTO + STA FAC1_e ; save FAC1 exponent + LDA #$00 ; clear sign compare +LAB_MLTE + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore character + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "$" for hex +; get hex number + +LAB_CHEX + JSR LAB_IGBY ; increment and scan memory + BCC LAB_ISHN ; branch if numeric character + + ORA #$20 ; case convert, allow "A" to "F" and "a" to "f" + SBC #'a' ; subtract "a" (carry set here) + CMP #$06 ; compare normalised with $06 (max+1) + BCS LAB_EXCH ; exit if >"f" or <"0" + + ADC #$0A ; convert to nibble +LAB_ISHN + AND #$0F ; convert to binary + TAX ; save nibble + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLTE ; skip multiply if zero + + ADC #$04 ; add four to exponent (*16 - carry clear here) + BCC LAB_NLTO ; if no overflow do evaluate digit + +LAB_MLTO + JMP LAB_2564 ; do overflow error and warm start + +LAB_NXCH + TAX ; save bit + LDA FAC1_e ; get FAC1 exponent + BEQ LAB_MLBT ; skip multiply if zero + + INC FAC1_e ; increment FAC1 exponent (*2) + BEQ LAB_MLTO ; do overflow error if = $00 + + LDA #$00 ; clear sign compare +LAB_MLBT + STA FAC_sc ; save sign compare (FAC1 EOR FAC2) + TXA ; restore bit + JSR LAB_2912 ; evaluate new ASCII digit + +; gets here if the first character was "%" for binary +; get binary number + +LAB_CBIN + JSR LAB_IGBY ; increment and scan memory + EOR #'0' ; convert "0" to 0 etc. + CMP #$02 ; compare with max+1 + BCC LAB_NXCH ; branch exit if < 2 + +LAB_EXCH + JMP LAB_28F6 ; evaluate -ve flag and return + +; ctrl-c check routine. includes limited "life" byte save for INGET routine +; now also the code that checks to see if an interrupt has occurred + +CTRLC + LDA ccflag ; get [CTRL-C] check flag + BNE LAB_FBA2 ; exit if inhibited + + JSR V_INPT ; scan input device + BCC LAB_FBA0 ; exit if buffer empty + + STA ccbyte ; save received byte + LDX #$20 ; "life" timer for bytes + STX ccnull ; set countdown + JMP LAB_1636 ; return to BASIC + +LAB_FBA0 + LDX ccnull ; get countdown byte + BEQ LAB_FBA2 ; exit if finished + + DEC ccnull ; else decrement countdown +LAB_FBA2 + LDX #NmiBase ; set pointer to NMI values + JSR LAB_CKIN ; go check interrupt + LDX #IrqBase ; set pointer to IRQ values + JSR LAB_CKIN ; go check interrupt +LAB_CRTS + RTS + +; check whichever interrupt is indexed by X + +LAB_CKIN + LDA PLUS_0,X ; get interrupt flag byte + BPL LAB_CRTS ; branch if interrupt not enabled + +; we disable the interrupt here and make two new commands RETIRQ and RETNMI to +; automatically enable the interrupt when we exit + + ASL ; move happened bit to setup bit + AND #$40 ; mask happened bits + BEQ LAB_CRTS ; if no interrupt then exit + + STA PLUS_0,X ; save interrupt flag byte + + TXA ; copy index .. + TAY ; .. to Y + + PLA ; dump return address low byte, call from CTRL-C + PLA ; dump return address high byte + + LDA #$05 ; need 5 bytes for GOSUB + JSR LAB_1212 ; check room on stack for A bytes + LDA Bpntrh ; get BASIC execute pointer high byte + PHA ; push on stack + LDA Bpntrl ; get BASIC execute pointer low byte + PHA ; push on stack + LDA Clineh ; get current line high byte + PHA ; push on stack + LDA Clinel ; get current line low byte + PHA ; push on stack + LDA #TK_GOSUB ; token for GOSUB + PHA ; push on stack + + LDA PLUS_1,Y ; get interrupt code pointer low byte + STA Bpntrl ; save as BASIC execute pointer low byte + LDA PLUS_2,Y ; get interrupt code pointer high byte + STA Bpntrh ; save as BASIC execute pointer high byte + + JMP LAB_15C2 ; go do interpreter inner loop + ; can't RTS, we used the stack! the RTS from the ctrl-c + ; check will be taken when the RETIRQ/RETNMI/RETURN is + ; executed at the end of the subroutine + +; get byte from input device, no waiting +; returns with carry set if byte in A + +INGET + JSR V_INPT ; call scan input device + BCS LAB_FB95 ; if byte go reset timer + + LDA ccnull ; get countdown + BEQ LAB_FB96 ; exit if empty + + LDA ccbyte ; get last received byte + SEC ; flag we got a byte +LAB_FB95 + LDX #$00 ; clear X + STX ccnull ; clear timer because we got a byte +LAB_FB96 + RTS + +; these routines only enable the interrupts if the set-up flag is set +; if not they have no effect + +; perform IRQ {ON|OFF|CLEAR} + +LAB_IRQ + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform NMI {ON|OFF|CLEAR} + +LAB_NMI + LDX #NmiBase ; set pointer to NMI values + CMP #TK_ON ; compare with token for ON + BEQ LAB_INON ; go turn on interrupt + + CMP #TK_OFF ; compare with token for OFF + BEQ LAB_IOFF ; go turn off interrupt + + EOR #TK_CLEAR ; compare with token for CLEAR, A = $00 if = TK_CLEAR + BEQ LAB_INEX ; go clear interrupt flags and return + + JMP LAB_SNER ; do syntax error then warm start + +LAB_IOFF + LDA #$7F ; clear A + AND PLUS_0,X ; AND with interrupt setup flag + BPL LAB_INEX ; go clear interrupt enabled flag and return + +LAB_INON + LDA PLUS_0,X ; get interrupt setup flag + ASL ; Shift bit to enabled flag + ORA PLUS_0,X ; OR with flag byte +LAB_INEX + STA PLUS_0,X ; save interrupt flag byte + JMP LAB_IGBY ; update BASIC execute pointer and return + +; these routines set up the pointers and flags for the interrupt routines +; note that the interrupts are also enabled by these commands + +; perform ON IRQ + +LAB_SIRQ + CLI ; enable interrupts + LDX #IrqBase ; set pointer to IRQ values + .byte $2C ; make next line BIT abs. + +; perform ON NMI + +LAB_SNMI + LDX #NmiBase ; set pointer to NMI values + + STX TempB ; save interrupt pointer + JSR LAB_IGBY ; increment and scan memory (past token) + JSR LAB_GFPN ; get fixed-point number into temp integer + LDA Smeml ; get start of mem low byte + LDX Smemh ; get start of mem high byte + JSR LAB_SHLN ; search Basic for temp integer line number from AX + BCS LAB_LFND ; if carry set go set-up interrupt + + JMP LAB_16F7 ; else go do "Undefined statement" error and warm start + +LAB_LFND + LDX TempB ; get interrupt pointer + LDA Baslnl ; get pointer low byte + SBC #$01 ; -1 (carry already set for subtract) + STA PLUS_1,X ; save as interrupt pointer low byte + LDA Baslnh ; get pointer high byte + SBC #$00 ; subtract carry + STA PLUS_2,X ; save as interrupt pointer high byte + + LDA #$C0 ; set interrupt enabled/setup bits + STA PLUS_0,X ; set interrupt flags +LAB_IRTS + RTS + +; return from IRQ service, restores the enabled flag. + +; perform RETIRQ + +LAB_RETIRQ + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA IrqBase ; get interrupt flags + ASL ; copy setup to enabled (b7) + ORA IrqBase ; OR in setup flag + STA IrqBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; return from NMI service, restores the enabled flag. + +; perform RETNMI + +LAB_RETNMI + BNE LAB_IRTS ; exit if following token (to allow syntax error) + + LDA NmiBase ; get set-up flag + ASL ; copy setup to enabled (b7) + ORA NmiBase ; OR in setup flag + STA NmiBase ; save enabled flag + JMP LAB_16E8 ; go do rest of RETURN + +; MAX() MIN() pre process + +LAB_MMPP + JSR LAB_EVEZ ; process expression + JMP LAB_CTNM ; check if source is numeric, else do type mismatch + +; perform MAX() + +LAB_MAX + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BPL LAB_MAX ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MAX ; go do next (branch always) + +; perform MIN() + +LAB_MIN + JSR LAB_PHFA ; push FAC1, evaluate expression, + ; pull FAC2 and compare with FAC1 + BMI LAB_MIN ; branch if no swap to do + + BEQ LAB_MIN ; branch if no swap to do + + LDA FAC2_1 ; get FAC2 mantissa1 + ORA #$80 ; set top bit (clear sign from compare) + STA FAC2_1 ; save FAC2 mantissa1 + JSR LAB_279B ; copy FAC2 to FAC1 + BEQ LAB_MIN ; go do next (branch always) + +; exit routine. don't bother returning to the loop code +; check for correct exit, else so syntax error + +LAB_MMEC + CMP #')' ; is it end of function? + BNE LAB_MMSE ; if not do MAX MIN syntax error + + PLA ; dump return address low byte + PLA ; dump return address high byte + JMP LAB_IGBY ; update BASIC execute pointer (to chr past ")") + +LAB_MMSE + JMP LAB_SNER ; do syntax error then warm start + +; check for next, evaluate and return or exit +; this is the routine that does most of the work + +LAB_PHFA + JSR LAB_GBYT ; get next BASIC byte + CMP #',' ; is there more ? + BNE LAB_MMEC ; if not go do end check + + ; push FAC1 + JSR LAB_27BA ; round FAC1 + LDA FAC1_s ; get FAC1 sign + ORA #$7F ; set all non sign bits + AND FAC1_1 ; AND FAC1 mantissa1 (AND in sign bit) + PHA ; push on stack + LDA FAC1_2 ; get FAC1 mantissa2 + PHA ; push on stack + LDA FAC1_3 ; get FAC1 mantissa3 + PHA ; push on stack + LDA FAC1_e ; get FAC1 exponent + PHA ; push on stack + + JSR LAB_IGBY ; scan and get next BASIC byte (after ",") + JSR LAB_EVNM ; evaluate expression and check is numeric, + ; else do type mismatch + + ; pop FAC2 (MAX/MIN expression so far) + PLA ; pop exponent + STA FAC2_e ; save FAC2 exponent + PLA ; pop mantissa3 + STA FAC2_3 ; save FAC2 mantissa3 + PLA ; pop mantissa1 + STA FAC2_2 ; save FAC2 mantissa2 + PLA ; pop sign/mantissa1 + STA FAC2_1 ; save FAC2 sign/mantissa1 + STA FAC2_s ; save FAC2 sign + + ; compare FAC1 with (packed) FAC2 + LDA #FAC2_e ; set pointer high byte to FAC2 + JMP LAB_27F8 ; compare FAC1 with FAC2 (AY) and return + ; returns A=$00 if FAC1 = (AY) + ; returns A=$01 if FAC1 > (AY) + ; returns A=$FF if FAC1 < (AY) + +; perform WIDTH + +LAB_WDTH + CMP #',' ; is next byte "," + BEQ LAB_TBSZ ; if so do tab size + + JSR LAB_GTBY ; get byte parameter + TXA ; copy width to A + BEQ LAB_NSTT ; branch if set for infinite line + + CPX #$10 ; else make min width = 16d + BCC TabErr ; if less do function call error and exit + +; this next compare ensures that we can't exit WIDTH via an error leaving the +; tab size greater than the line length. + + CPX TabSiz ; compare with tab size + BCS LAB_NSTT ; branch if >= tab size + + STX TabSiz ; else make tab size = terminal width +LAB_NSTT + STX TWidth ; set the terminal width + JSR LAB_GBYT ; get BASIC byte back + BEQ WExit ; exit if no following + + CMP #',' ; else is it "," + BNE LAB_MMSE ; if not do syntax error + +LAB_TBSZ + JSR LAB_SGBY ; scan and get byte parameter + TXA ; copy TAB size + BMI TabErr ; if >127 do function call error and exit + + CPX #$01 ; compare with min-1 + BCC TabErr ; if <=1 do function call error and exit + + LDA TWidth ; set flags for width + BEQ LAB_SVTB ; skip check if infinite line + + CPX TWidth ; compare TAB with width + BEQ LAB_SVTB ; ok if = + + BCS TabErr ; branch if too big + +LAB_SVTB + STX TabSiz ; save TAB size + +; calculate tab column limit from TAB size. The Iclim is set to the last tab +; position on a line that still has at least one whole tab width between it +; and the end of the line. + +WExit + LDA TWidth ; get width + BEQ LAB_SULP ; branch if infinite line + + CMP TabSiz ; compare with tab size + BCS LAB_WDLP ; branch if >= tab size + + STA TabSiz ; else make tab size = terminal width +LAB_SULP + SEC ; set carry for subtract +LAB_WDLP + SBC TabSiz ; subtract tab size + BCS LAB_WDLP ; loop while no borrow + + ADC TabSiz ; add tab size back + CLC ; clear carry for add + ADC TabSiz ; add tab size back again + STA Iclim ; save for now + LDA TWidth ; get width back + SEC ; set carry for subtract + SBC Iclim ; subtract remainder + STA Iclim ; save tab column limit +LAB_NOSQ + RTS + +TabErr + JMP LAB_FCER ; do function call error then warm start + +; perform SQR() + +LAB_SQR + LDA FAC1_s ; get FAC1 sign + BMI TabErr ; if -ve do function call error + + LDA FAC1_e ; get exponent + BEQ LAB_NOSQ ; if zero just return + + ; else do root + JSR LAB_27AB ; round and copy FAC1 to FAC2 + LDA #$00 ; clear A + + STA FACt_3 ; clear remainder + STA FACt_2 ; .. + STA FACt_1 ; .. + STA TempB ; .. + + STA FAC1_3 ; clear root + STA FAC1_2 ; .. + STA FAC1_1 ; .. + + LDX #$18 ; 24 pairs of bits to do + LDA FAC2_e ; get exponent + LSR ; check odd/even + BCS LAB_SQE2 ; if odd only 1 shift first time + +LAB_SQE1 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows +LAB_SQE2 + ASL FAC2_3 ; shift highest bit of number .. + ROL FAC2_2 ; .. + ROL FAC2_1 ; .. + ROL FACt_3 ; .. into remainder + ROL FACt_2 ; .. + ROL FACt_1 ; .. + ROL TempB ; .. never overflows + + ASL FAC1_3 ; root = root * 2 + ROL FAC1_2 ; .. + ROL FAC1_1 ; .. never overflows + + LDA FAC1_3 ; get root low byte + ROL ; *2 + STA Temp3 ; save partial low byte + LDA FAC1_2 ; get root low mid byte + ROL ; *2 + STA Temp3+1 ; save partial low mid byte + LDA FAC1_1 ; get root high mid byte + ROL ; *2 + STA Temp3+2 ; save partial high mid byte + LDA #$00 ; get root high byte (always $00) + ROL ; *2 + STA Temp3+3 ; save partial high byte + + ; carry clear for subtract +1 + LDA FACt_3 ; get remainder low byte + SBC Temp3 ; subtract partial low byte + STA Temp3 ; save partial low byte + + LDA FACt_2 ; get remainder low mid byte + SBC Temp3+1 ; subtract partial low mid byte + STA Temp3+1 ; save partial low mid byte + + LDA FACt_1 ; get remainder high mid byte + SBC Temp3+2 ; subtract partial high mid byte + TAY ; copy partial high mid byte + + LDA TempB ; get remainder high byte + SBC Temp3+3 ; subtract partial high byte + BCC LAB_SQNS ; skip sub if remainder smaller + + STA TempB ; save remainder high byte + + STY FACt_1 ; save remainder high mid byte + + LDA Temp3+1 ; get remainder low mid byte + STA FACt_2 ; save remainder low mid byte + + LDA Temp3 ; get partial low byte + STA FACt_3 ; save remainder low byte + + INC FAC1_3 ; increment root low byte (never any rollover) +LAB_SQNS + DEX ; decrement bit pair count + BNE LAB_SQE1 ; loop if not all done + + SEC ; set carry for subtract + LDA FAC2_e ; get exponent + SBC #$80 ; normalise + ROR ; /2 and re-bias to $80 + ADC #$00 ; add bit zero back in (allow for half shift) + STA FAC1_e ; save it + JMP LAB_24D5 ; normalise FAC1 and return + +; perform VARPTR() + +LAB_VARPTR + JSR LAB_IGBY ; increment and scan memory + JSR LAB_GVAR ; get var address + JSR LAB_1BFB ; scan for ")" , else do syntax error then warm start + LDY Cvaral ; get var address low byte + LDA Cvarah ; get var address high byte + JMP LAB_AYFC ; save and convert integer AY to FAC1 and return + +; perform PI + +LAB_PI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JSR LAB_UFAC ; unpack memory (AY) into FAC1 + DEC FAC1_e ; make result = PI + RTS + +; perform TWOPI + +LAB_TWOPI + LDA #LAB_2C7C ; set (2*pi) pointer high byte + JMP LAB_UFAC ; unpack memory (AY) into FAC1 and return + +; system dependant i/o vectors +; these are in RAM and are set by the monitor at start-up + +V_INPT + JMP (VEC_IN) ; non halting scan input device +V_OUTP + JMP (VEC_OUT) ; send byte to output device +V_LOAD + JMP (VEC_LD) ; load BASIC program +V_SAVE + JMP (VEC_SV) ; save BASIC program + +; The rest are tables messages and code for RAM + +; the rest of the code is tables and BASIC start-up code + +PG2_TABS + .byte $FF ; ctrl-c flag - $00 = enabled + .byte $00 ; ctrl-c byte - GET needs this + .byte $00 ; ctrl-c byte timeout - GET needs this + .word CTRLC ; ctrl c check vector + .word CHRIN ; non halting key input - monitor to set this + .word CHROUT ; output vector - monitor to set this +; .word xxxx ; load vector - monitor to set this +; .word xxxx ; save vector - monitor to set this +PG2_TABE + +; character get subroutine for zero page + +; For a 1.8432MHz 6502 including the JSR and RTS +; fastest (>=":") = 29 cycles = 15.7uS +; slowest (<":") = 40 cycles = 21.7uS +; space skip = +21 cycles = +11.4uS +; inc across page = +4 cycles = +2.2uS + +; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the +; block is copied to it's destination, any non zero page address will do at assembly +; time, to assemble a three byte instruction. + +; page 0 initialisation table from $BC +; increment and scan memory + +LAB_2CEE + INC Bpntrl ; increment BASIC execute pointer low byte + BNE LAB_2CF4 ; branch if no carry + ; else + INC Bpntrh ; increment BASIC execute pointer high byte + +; page 0 initialisation table from $C2 +; scan memory + +LAB_2CF4 + LDA $FFFF ; get byte to scan (addr set by call routine) + CMP #TK_ELSE ; compare with the token for ELSE + BEQ LAB_2D05 ; exit if ELSE, not numeric, carry set + + CMP #':' ; compare with ":" + BCS LAB_2D05 ; exit if >= ":", not numeric, carry set + + CMP #' ' ; compare with " " + BEQ LAB_2CEE ; if " " go do next + + SEC ; set carry for SBC + SBC #'0' ; subtract "0" + SEC ; set carry for SBC + SBC #$D0 ; subtract -"0" + ; clear carry if byte = "0"-"9" +LAB_2D05 + RTS + +; page zero initialisation table $00-$12 inclusive + +StrTab + .byte $4C ; JMP opcode + .word LAB_COLD ; initial warm start vector (cold start) + + .byte $00 ; these bytes are not used by BASIC + .word $0000 ; + .word $0000 ; + .word $0000 ; + + .byte $4C ; JMP opcode + .word LAB_FCER ; initial user function vector ("Function call" error) + .byte $00 ; default NULL count + .byte $00 ; clear terminal position + .byte $00 ; default terminal width byte + .byte $F2 ; default limit for TAB = 14 + .word Ram_base ; start of user RAM +EndTab + +LAB_MSZM + .byte $0D,$0A,"Memory size ",$00 + +LAB_SMSG + .byte " Bytes free",$0D,$0A,$0A + .byte "Enhanced BASIC 2.22",$0A,$00 + +; numeric constants and series + + ; constants and series for LOG(n) +LAB_25A0 + .byte $02 ; counter + .byte $80,$19,$56,$62 ; 0.59898 + .byte $80,$76,$22,$F3 ; 0.96147 +;## .byte $80,$76,$22,$F1 ; 0.96147 + .byte $82,$38,$AA,$40 ; 2.88539 +;## .byte $82,$38,$AA,$45 ; 2.88539 + +LAB_25AD + .byte $80,$35,$04,$F3 ; 0.70711 1/root 2 +LAB_25B1 + .byte $81,$35,$04,$F3 ; 1.41421 root 2 +LAB_25B5 + .byte $80,$80,$00,$00 ; -0.5 +LAB_25B9 + .byte $80,$31,$72,$18 ; 0.69315 LOG(2) + + ; numeric PRINT constants +LAB_2947 + .byte $91,$43,$4F,$F8 ; 99999.9375 (max value with at least one decimal) +LAB_294B + .byte $94,$74,$23,$F7 ; 999999.4375 (max value before scientific notation) +LAB_294F + .byte $94,$74,$24,$00 ; 1000000 + + ; EXP(n) constants and series +LAB_2AFA + .byte $81,$38,$AA,$3B ; 1.4427 (1/LOG base 2 e) +LAB_2AFE + .byte $06 ; counter + .byte $74,$63,$90,$8C ; 2.17023e-4 + .byte $77,$23,$0C,$AB ; 0.00124 + .byte $7A,$1E,$94,$00 ; 0.00968 + .byte $7C,$63,$42,$80 ; 0.05548 + .byte $7E,$75,$FE,$D0 ; 0.24023 + .byte $80,$31,$72,$15 ; 0.69315 + .byte $81,$00,$00,$00 ; 1.00000 + +;## .byte $07 ; counter +;## .byte $74,$94,$2E,$40 ; -1/7! (-1/5040) +;## .byte $77,$2E,$4F,$70 ; 1/6! ( 1/720) +;## .byte $7A,$88,$02,$6E ; -1/5! (-1/120) +;## .byte $7C,$2A,$A0,$E6 ; 1/4! ( 1/24) +;## .byte $7E,$AA,$AA,$50 ; -1/3! (-1/6) +;## .byte $7F,$7F,$FF,$FF ; 1/2! ( 1/2) +;## .byte $81,$80,$00,$00 ; -1/1! (-1/1) +;## .byte $81,$00,$00,$00 ; 1/0! ( 1/1) + + ; trigonometric constants and series +LAB_2C78 + .byte $81,$49,$0F,$DB ; 1.570796371 (pi/2) as floating # +LAB_2C84 + .byte $04 ; counter + .byte $86,$1E,$D7,$FB ; 39.7109 +;## .byte $86,$1E,$D7,$BA ; 39.7109 + .byte $87,$99,$26,$65 ;-76.575 +;## .byte $87,$99,$26,$64 ;-76.575 + .byte $87,$23,$34,$58 ; 81.6022 + .byte $86,$A5,$5D,$E1 ;-41.3417 +;## .byte $86,$A5,$5D,$E0 ;-41.3417 +LAB_2C7C + .byte $83,$49,$0F,$DB ; 6.28319 (2*pi) as floating # +;## .byte $83,$49,$0F,$DA ; 6.28319 (2*pi) as floating # + +LAB_2CC9 + .byte $08 ; counter + .byte $78,$3A,$C5,$37 ; 0.00285 + .byte $7B,$83,$A2,$5C ;-0.0160686 + .byte $7C,$2E,$DD,$4D ; 0.0426915 + .byte $7D,$99,$B0,$1E ;-0.0750429 + .byte $7D,$59,$ED,$24 ; 0.106409 + .byte $7E,$91,$72,$00 ;-0.142036 + .byte $7E,$4C,$B9,$73 ; 0.199926 + .byte $7F,$AA,$AA,$53 ;-0.333331 + +;## .byte $08 ; counter +;## .byte $78,$3B,$D7,$4A ; 1/17 +;## .byte $7B,$84,$6E,$02 ;-1/15 +;## .byte $7C,$2F,$C1,$FE ; 1/13 +;## .byte $7D,$9A,$31,$74 ;-1/11 +;## .byte $7D,$5A,$3D,$84 ; 1/9 +;## .byte $7E,$91,$7F,$C8 ;-1/7 +;## .byte $7E,$4C,$BB,$E4 ; 1/5 +;## .byte $7F,$AA,$AA,$6C ;-1/3 + +LAB_1D96 = *+1 ; $00,$00 used for undefined variables +LAB_259C + .byte $81,$00,$00,$00 ; 1.000000, used for INC +LAB_2AFD + .byte $81,$80,$00,$00 ; -1.00000, used for DEC. must be on the same page as +1.00 + + ; misc constants +LAB_1DF7 + .byte $90 ;-32768 (uses first three bytes from 0.5) +LAB_2A96 + .byte $80,$00,$00,$00 ; 0.5 +LAB_2C80 + .byte $7F,$00,$00,$00 ; 0.25 +LAB_26B5 + .byte $84,$20,$00,$00 ; 10.0000 divide by 10 constant + +; This table is used in converting numbers to ASCII. + +LAB_2A9A +LAB_2A9B = LAB_2A9A+1 +LAB_2A9C = LAB_2A9B+1 + .byte $FE,$79,$60 ; -100000 + .byte $00,$27,$10 ; 10000 + .byte $FF,$FC,$18 ; -1000 + .byte $00,$00,$64 ; 100 + .byte $FF,$FF,$F6 ; -10 + .byte $00,$00,$01 ; 1 + +LAB_CTBL + .word LAB_END-1 ; END + .word LAB_FOR-1 ; FOR + .word LAB_NEXT-1 ; NEXT + .word LAB_DATA-1 ; DATA + .word LAB_INPUT-1 ; INPUT + .word LAB_DIM-1 ; DIM + .word LAB_READ-1 ; READ + .word LAB_LET-1 ; LET + .word LAB_DEC-1 ; DEC new command + .word LAB_GOTO-1 ; GOTO + .word LAB_RUN-1 ; RUN + .word LAB_IF-1 ; IF + .word LAB_RESTORE-1 ; RESTORE modified command + .word LAB_GOSUB-1 ; GOSUB + .word LAB_RETIRQ-1 ; RETIRQ new command + .word LAB_RETNMI-1 ; RETNMI new command + .word LAB_RETURN-1 ; RETURN + .word LAB_REM-1 ; REM + .word LAB_STOP-1 ; STOP + .word LAB_ON-1 ; ON modified command + .word LAB_NULL-1 ; NULL modified command + .word LAB_INC-1 ; INC new command + .word LAB_WAIT-1 ; WAIT + .word V_LOAD-1 ; LOAD + .word V_SAVE-1 ; SAVE + .word LAB_DEF-1 ; DEF + .word LAB_POKE-1 ; POKE + .word LAB_DOKE-1 ; DOKE new command + .word LAB_CALL-1 ; CALL new command + .word LAB_DO-1 ; DO new command + .word LAB_LOOP-1 ; LOOP new command + .word LAB_PRINT-1 ; PRINT + .word LAB_CONT-1 ; CONT + .word LAB_LIST-1 ; LIST + .word LAB_CLEAR-1 ; CLEAR + .word LAB_NEW-1 ; NEW + .word LAB_WDTH-1 ; WIDTH new command + .word LAB_GET-1 ; GET new command + .word LAB_SWAP-1 ; SWAP new command + .word LAB_BITSET-1 ; BITSET new command + .word LAB_BITCLR-1 ; BITCLR new command + .word LAB_IRQ-1 ; IRQ new command + .word LAB_NMI-1 ; NMI new command + +; function pre process routine table + +LAB_FTPL +LAB_FTPM = LAB_FTPL+$01 + .word LAB_PPFN-1 ; SGN(n) process numeric expression in () + .word LAB_PPFN-1 ; INT(n) " + .word LAB_PPFN-1 ; ABS(n) " + .word LAB_EVEZ-1 ; USR(x) process any expression + .word LAB_1BF7-1 ; FRE(x) " + .word LAB_1BF7-1 ; POS(x) " + .word LAB_PPFN-1 ; SQR(n) process numeric expression in () + .word LAB_PPFN-1 ; RND(n) " + .word LAB_PPFN-1 ; LOG(n) " + .word LAB_PPFN-1 ; EXP(n) " + .word LAB_PPFN-1 ; COS(n) " + .word LAB_PPFN-1 ; SIN(n) " + .word LAB_PPFN-1 ; TAN(n) " + .word LAB_PPFN-1 ; ATN(n) " + .word LAB_PPFN-1 ; PEEK(n) " + .word LAB_PPFN-1 ; DEEK(n) " + .word $0000 ; SADD() none + .word LAB_PPFS-1 ; LEN($) process string expression in () + .word LAB_PPFN-1 ; STR$(n) process numeric expression in () + .word LAB_PPFS-1 ; VAL($) process string expression in () + .word LAB_PPFS-1 ; ASC($) " + .word LAB_PPFS-1 ; UCASE$($) " + .word LAB_PPFS-1 ; LCASE$($) " + .word LAB_PPFN-1 ; CHR$(n) process numeric expression in () + .word LAB_BHSS-1 ; HEX$(n) " + .word LAB_BHSS-1 ; BIN$(n) " + .word $0000 ; BITTST() none + .word LAB_MMPP-1 ; MAX() process numeric expression + .word LAB_MMPP-1 ; MIN() " + .word LAB_PPBI-1 ; PI advance pointer + .word LAB_PPBI-1 ; TWOPI " + .word $0000 ; VARPTR() none + .word LAB_LRMS-1 ; LEFT$() process string expression + .word LAB_LRMS-1 ; RIGHT$() " + .word LAB_LRMS-1 ; MID$() " + +; action addresses for functions + +LAB_FTBL +LAB_FTBM = LAB_FTBL+$01 + .word LAB_SGN-1 ; SGN() + .word LAB_INT-1 ; INT() + .word LAB_ABS-1 ; ABS() + .word LAB_USR-1 ; USR() + .word LAB_FRE-1 ; FRE() + .word LAB_POS-1 ; POS() + .word LAB_SQR-1 ; SQR() + .word LAB_RND-1 ; RND() modified function + .word LAB_LOG-1 ; LOG() + .word LAB_EXP-1 ; EXP() + .word LAB_COS-1 ; COS() + .word LAB_SIN-1 ; SIN() + .word LAB_TAN-1 ; TAN() + .word LAB_ATN-1 ; ATN() + .word LAB_PEEK-1 ; PEEK() + .word LAB_DEEK-1 ; DEEK() new function + .word LAB_SADD-1 ; SADD() new function + .word LAB_LENS-1 ; LEN() + .word LAB_STRS-1 ; STR$() + .word LAB_VAL-1 ; VAL() + .word LAB_ASC-1 ; ASC() + .word LAB_UCASE-1 ; UCASE$() new function + .word LAB_LCASE-1 ; LCASE$() new function + .word LAB_CHRS-1 ; CHR$() + .word LAB_HEXS-1 ; HEX$() new function + .word LAB_BINS-1 ; BIN$() new function + .word LAB_BTST-1 ; BITTST() new function + .word LAB_MAX-1 ; MAX() new function + .word LAB_MIN-1 ; MIN() new function + .word LAB_PI-1 ; PI new function + .word LAB_TWOPI-1 ; TWOPI new function + .word LAB_VARPTR-1 ; VARPTR() new function + .word LAB_LEFT-1 ; LEFT$() + .word LAB_RIGHT-1 ; RIGHT$() + .word LAB_MIDS-1 ; MID$() + +; hierarchy and action addresses for operator + +LAB_OPPT + .byte $79 ; + + .word LAB_ADD-1 + .byte $79 ; - + .word LAB_SUBTRACT-1 + .byte $7B ; * + .word LAB_MULTIPLY-1 + .byte $7B ; / + .word LAB_DIVIDE-1 + .byte $7F ; ^ + .word LAB_POWER-1 + .byte $50 ; AND + .word LAB_AND-1 + .byte $46 ; EOR new operator + .word LAB_EOR-1 + .byte $46 ; OR + .word LAB_OR-1 + .byte $56 ; >> new operator + .word LAB_RSHIFT-1 + .byte $56 ; << new operator + .word LAB_LSHIFT-1 + .byte $7D ; > + .word LAB_GTHAN-1 + .byte $5A ; = + .word LAB_EQUAL-1 + .byte $64 ; < + .word LAB_LTHAN-1 + +; keywords start with .. +; this is the first character table and must be in alphabetic order + +TAB_1STC + .byte "*" + .byte "+" + .byte "-" + .byte "/" + .byte "<" + .byte "=" + .byte ">" + .byte "?" + .byte "A" + .byte "B" + .byte "C" + .byte "D" + .byte "E" + .byte "F" + .byte "G" + .byte "H" + .byte "I" + .byte "L" + .byte "M" + .byte "N" + .byte "O" + .byte "P" + .byte "R" + .byte "S" + .byte "T" + .byte "U" + .byte "V" + .byte "W" + .byte "^" + .byte $00 ; table terminator + +; pointers to keyword tables + +TAB_CHRT + .word TAB_STAR ; table for "*" + .word TAB_PLUS ; table for "+" + .word TAB_MNUS ; table for "-" + .word TAB_SLAS ; table for "/" + .word TAB_LESS ; table for "<" + .word TAB_EQUL ; table for "=" + .word TAB_MORE ; table for ">" + .word TAB_QEST ; table for "?" + .word TAB_ASCA ; table for "A" + .word TAB_ASCB ; table for "B" + .word TAB_ASCC ; table for "C" + .word TAB_ASCD ; table for "D" + .word TAB_ASCE ; table for "E" + .word TAB_ASCF ; table for "F" + .word TAB_ASCG ; table for "G" + .word TAB_ASCH ; table for "H" + .word TAB_ASCI ; table for "I" + .word TAB_ASCL ; table for "L" + .word TAB_ASCM ; table for "M" + .word TAB_ASCN ; table for "N" + .word TAB_ASCO ; table for "O" + .word TAB_ASCP ; table for "P" + .word TAB_ASCR ; table for "R" + .word TAB_ASCS ; table for "S" + .word TAB_ASCT ; table for "T" + .word TAB_ASCU ; table for "U" + .word TAB_ASCV ; table for "V" + .word TAB_ASCW ; table for "W" + .word TAB_POWR ; table for "^" + +; tables for each start character, note if a longer keyword with the same start +; letters as a shorter one exists then it must come first, else the list is in +; alphabetical order as follows .. + +; [keyword,token +; [keyword,token]] +; end marker (#$00) + +TAB_STAR + .byte TK_MUL,$00 ; * +TAB_PLUS + .byte TK_PLUS,$00 ; + +TAB_MNUS + .byte TK_MINUS,$00 ; - +TAB_SLAS + .byte TK_DIV,$00 ; / +TAB_LESS +LBB_LSHIFT + .byte "<",TK_LSHIFT ; << note - "<<" must come before "<" + .byte TK_LT ; < + .byte $00 +TAB_EQUL + .byte TK_EQUAL,$00 ; = +TAB_MORE +LBB_RSHIFT + .byte ">",TK_RSHIFT ; >> note - ">>" must come before ">" + .byte TK_GT ; > + .byte $00 +TAB_QEST + .byte TK_PRINT,$00 ; ? +TAB_ASCA +LBB_ABS + .byte "BS(",TK_ABS ; ABS( +LBB_AND + .byte "ND",TK_AND ; AND +LBB_ASC + .byte "SC(",TK_ASC ; ASC( +LBB_ATN + .byte "TN(",TK_ATN ; ATN( + .byte $00 +TAB_ASCB +LBB_BINS + .byte "IN$(",TK_BINS ; BIN$( +LBB_BITCLR + .byte "ITCLR",TK_BITCLR ; BITCLR +LBB_BITSET + .byte "ITSET",TK_BITSET ; BITSET +LBB_BITTST + .byte "ITTST(",TK_BITTST + ; BITTST( + .byte $00 +TAB_ASCC +LBB_CALL + .byte "ALL",TK_CALL ; CALL +LBB_CHRS + .byte "HR$(",TK_CHRS ; CHR$( +LBB_CLEAR + .byte "LEAR",TK_CLEAR ; CLEAR +LBB_CONT + .byte "ONT",TK_CONT ; CONT +LBB_COS + .byte "OS(",TK_COS ; COS( + .byte $00 +TAB_ASCD +LBB_DATA + .byte "ATA",TK_DATA ; DATA +LBB_DEC + .byte "EC",TK_DEC ; DEC +LBB_DEEK + .byte "EEK(",TK_DEEK ; DEEK( +LBB_DEF + .byte "EF",TK_DEF ; DEF +LBB_DIM + .byte "IM",TK_DIM ; DIM +LBB_DOKE + .byte "OKE",TK_DOKE ; DOKE note - "DOKE" must come before "DO" +LBB_DO + .byte "O",TK_DO ; DO + .byte $00 +TAB_ASCE +LBB_ELSE + .byte "LSE",TK_ELSE ; ELSE +LBB_END + .byte "ND",TK_END ; END +LBB_EOR + .byte "OR",TK_EOR ; EOR +LBB_EXP + .byte "XP(",TK_EXP ; EXP( + .byte $00 +TAB_ASCF +LBB_FN + .byte "N",TK_FN ; FN +LBB_FOR + .byte "OR",TK_FOR ; FOR +LBB_FRE + .byte "RE(",TK_FRE ; FRE( + .byte $00 +TAB_ASCG +LBB_GET + .byte "ET",TK_GET ; GET +LBB_GOSUB + .byte "OSUB",TK_GOSUB ; GOSUB +LBB_GOTO + .byte "OTO",TK_GOTO ; GOTO + .byte $00 +TAB_ASCH +LBB_HEXS + .byte "EX$(",TK_HEXS ; HEX$( + .byte $00 +TAB_ASCI +LBB_IF + .byte "F",TK_IF ; IF +LBB_INC + .byte "NC",TK_INC ; INC +LBB_INPUT + .byte "NPUT",TK_INPUT ; INPUT +LBB_INT + .byte "NT(",TK_INT ; INT( +LBB_IRQ + .byte "RQ",TK_IRQ ; IRQ + .byte $00 +TAB_ASCL +LBB_LCASES + .byte "CASE$(",TK_LCASES + ; LCASE$( +LBB_LEFTS + .byte "EFT$(",TK_LEFTS ; LEFT$( +LBB_LEN + .byte "EN(",TK_LEN ; LEN( +LBB_LET + .byte "ET",TK_LET ; LET +LBB_LIST + .byte "IST",TK_LIST ; LIST +LBB_LOAD + .byte "OAD",TK_LOAD ; LOAD +LBB_LOG + .byte "OG(",TK_LOG ; LOG( +LBB_LOOP + .byte "OOP",TK_LOOP ; LOOP + .byte $00 +TAB_ASCM +LBB_MAX + .byte "AX(",TK_MAX ; MAX( +LBB_MIDS + .byte "ID$(",TK_MIDS ; MID$( +LBB_MIN + .byte "IN(",TK_MIN ; MIN( + .byte $00 +TAB_ASCN +LBB_NEW + .byte "EW",TK_NEW ; NEW +LBB_NEXT + .byte "EXT",TK_NEXT ; NEXT +LBB_NMI + .byte "MI",TK_NMI ; NMI +LBB_NOT + .byte "OT",TK_NOT ; NOT +LBB_NULL + .byte "ULL",TK_NULL ; NULL + .byte $00 +TAB_ASCO +LBB_OFF + .byte "FF",TK_OFF ; OFF +LBB_ON + .byte "N",TK_ON ; ON +LBB_OR + .byte "R",TK_OR ; OR + .byte $00 +TAB_ASCP +LBB_PEEK + .byte "EEK(",TK_PEEK ; PEEK( +LBB_PI + .byte "I",TK_PI ; PI +LBB_POKE + .byte "OKE",TK_POKE ; POKE +LBB_POS + .byte "OS(",TK_POS ; POS( +LBB_PRINT + .byte "RINT",TK_PRINT ; PRINT + .byte $00 +TAB_ASCR +LBB_READ + .byte "EAD",TK_READ ; READ +LBB_REM + .byte "EM",TK_REM ; REM +LBB_RESTORE + .byte "ESTORE",TK_RESTORE + ; RESTORE +LBB_RETIRQ + .byte "ETIRQ",TK_RETIRQ ; RETIRQ +LBB_RETNMI + .byte "ETNMI",TK_RETNMI ; RETNMI +LBB_RETURN + .byte "ETURN",TK_RETURN ; RETURN +LBB_RIGHTS + .byte "IGHT$(",TK_RIGHTS + ; RIGHT$( +LBB_RND + .byte "ND(",TK_RND ; RND( +LBB_RUN + .byte "UN",TK_RUN ; RUN + .byte $00 +TAB_ASCS +LBB_SADD + .byte "ADD(",TK_SADD ; SADD( +LBB_SAVE + .byte "AVE",TK_SAVE ; SAVE +LBB_SGN + .byte "GN(",TK_SGN ; SGN( +LBB_SIN + .byte "IN(",TK_SIN ; SIN( +LBB_SPC + .byte "PC(",TK_SPC ; SPC( +LBB_SQR + .byte "QR(",TK_SQR ; SQR( +LBB_STEP + .byte "TEP",TK_STEP ; STEP +LBB_STOP + .byte "TOP",TK_STOP ; STOP +LBB_STRS + .byte "TR$(",TK_STRS ; STR$( +LBB_SWAP + .byte "WAP",TK_SWAP ; SWAP + .byte $00 +TAB_ASCT +LBB_TAB + .byte "AB(",TK_TAB ; TAB( +LBB_TAN + .byte "AN(",TK_TAN ; TAN( +LBB_THEN + .byte "HEN",TK_THEN ; THEN +LBB_TO + .byte "O",TK_TO ; TO +LBB_TWOPI + .byte "WOPI",TK_TWOPI ; TWOPI + .byte $00 +TAB_ASCU +LBB_UCASES + .byte "CASE$(",TK_UCASES + ; UCASE$( +LBB_UNTIL + .byte "NTIL",TK_UNTIL ; UNTIL +LBB_USR + .byte "SR(",TK_USR ; USR( + .byte $00 +TAB_ASCV +LBB_VAL + .byte "AL(",TK_VAL ; VAL( +LBB_VPTR + .byte "ARPTR(",TK_VPTR ; VARPTR( + .byte $00 +TAB_ASCW +LBB_WAIT + .byte "AIT",TK_WAIT ; WAIT +LBB_WHILE + .byte "HILE",TK_WHILE ; WHILE +LBB_WIDTH + .byte "IDTH",TK_WIDTH ; WIDTH + .byte $00 +TAB_POWR + .byte TK_POWER,$00 ; ^ + +; new decode table for LIST +; Table is .. +; byte - keyword length, keyword first character +; word - pointer to rest of keyword from dictionary + +; note if length is 1 then the pointer is ignored + +LAB_KEYT + .byte 3,'E' + .word LBB_END ; END + .byte 3,'F' + .word LBB_FOR ; FOR + .byte 4,'N' + .word LBB_NEXT ; NEXT + .byte 4,'D' + .word LBB_DATA ; DATA + .byte 5,'I' + .word LBB_INPUT ; INPUT + .byte 3,'D' + .word LBB_DIM ; DIM + .byte 4,'R' + .word LBB_READ ; READ + .byte 3,'L' + .word LBB_LET ; LET + .byte 3,'D' + .word LBB_DEC ; DEC + .byte 4,'G' + .word LBB_GOTO ; GOTO + .byte 3,'R' + .word LBB_RUN ; RUN + .byte 2,'I' + .word LBB_IF ; IF + .byte 7,'R' + .word LBB_RESTORE ; RESTORE + .byte 5,'G' + .word LBB_GOSUB ; GOSUB + .byte 6,'R' + .word LBB_RETIRQ ; RETIRQ + .byte 6,'R' + .word LBB_RETNMI ; RETNMI + .byte 6,'R' + .word LBB_RETURN ; RETURN + .byte 3,'R' + .word LBB_REM ; REM + .byte 4,'S' + .word LBB_STOP ; STOP + .byte 2,'O' + .word LBB_ON ; ON + .byte 4,'N' + .word LBB_NULL ; NULL + .byte 3,'I' + .word LBB_INC ; INC + .byte 4,'W' + .word LBB_WAIT ; WAIT + .byte 4,'L' + .word LBB_LOAD ; LOAD + .byte 4,'S' + .word LBB_SAVE ; SAVE + .byte 3,'D' + .word LBB_DEF ; DEF + .byte 4,'P' + .word LBB_POKE ; POKE + .byte 4,'D' + .word LBB_DOKE ; DOKE + .byte 4,'C' + .word LBB_CALL ; CALL + .byte 2,'D' + .word LBB_DO ; DO + .byte 4,'L' + .word LBB_LOOP ; LOOP + .byte 5,'P' + .word LBB_PRINT ; PRINT + .byte 4,'C' + .word LBB_CONT ; CONT + .byte 4,'L' + .word LBB_LIST ; LIST + .byte 5,'C' + .word LBB_CLEAR ; CLEAR + .byte 3,'N' + .word LBB_NEW ; NEW + .byte 5,'W' + .word LBB_WIDTH ; WIDTH + .byte 3,'G' + .word LBB_GET ; GET + .byte 4,'S' + .word LBB_SWAP ; SWAP + .byte 6,'B' + .word LBB_BITSET ; BITSET + .byte 6,'B' + .word LBB_BITCLR ; BITCLR + .byte 3,'I' + .word LBB_IRQ ; IRQ + .byte 3,'N' + .word LBB_NMI ; NMI + +; secondary commands (can't start a statement) + + .byte 4,'T' + .word LBB_TAB ; TAB + .byte 4,'E' + .word LBB_ELSE ; ELSE + .byte 2,'T' + .word LBB_TO ; TO + .byte 2,'F' + .word LBB_FN ; FN + .byte 4,'S' + .word LBB_SPC ; SPC + .byte 4,'T' + .word LBB_THEN ; THEN + .byte 3,'N' + .word LBB_NOT ; NOT + .byte 4,'S' + .word LBB_STEP ; STEP + .byte 5,'U' + .word LBB_UNTIL ; UNTIL + .byte 5,'W' + .word LBB_WHILE ; WHILE + .byte 3,'O' + .word LBB_OFF ; OFF + +; opperators + + .byte 1,'+' + .word $0000 ; + + .byte 1,'-' + .word $0000 ; - + .byte 1,'*' + .word $0000 ; * + .byte 1,'/' + .word $0000 ; / + .byte 1,'^' + .word $0000 ; ^ + .byte 3,'A' + .word LBB_AND ; AND + .byte 3,'E' + .word LBB_EOR ; EOR + .byte 2,'O' + .word LBB_OR ; OR + .byte 2,'>' + .word LBB_RSHIFT ; >> + .byte 2,'<' + .word LBB_LSHIFT ; << + .byte 1,'>' + .word $0000 ; > + .byte 1,'=' + .word $0000 ; = + .byte 1,'<' + .word $0000 ; < + +; functions + + .byte 4,'S' ; + .word LBB_SGN ; SGN + .byte 4,'I' ; + .word LBB_INT ; INT + .byte 4,'A' ; + .word LBB_ABS ; ABS + .byte 4,'U' ; + .word LBB_USR ; USR + .byte 4,'F' ; + .word LBB_FRE ; FRE + .byte 4,'P' ; + .word LBB_POS ; POS + .byte 4,'S' ; + .word LBB_SQR ; SQR + .byte 4,'R' ; + .word LBB_RND ; RND + .byte 4,'L' ; + .word LBB_LOG ; LOG + .byte 4,'E' ; + .word LBB_EXP ; EXP + .byte 4,'C' ; + .word LBB_COS ; COS + .byte 4,'S' ; + .word LBB_SIN ; SIN + .byte 4,'T' ; + .word LBB_TAN ; TAN + .byte 4,'A' ; + .word LBB_ATN ; ATN + .byte 5,'P' ; + .word LBB_PEEK ; PEEK + .byte 5,'D' ; + .word LBB_DEEK ; DEEK + .byte 5,'S' ; + .word LBB_SADD ; SADD + .byte 4,'L' ; + .word LBB_LEN ; LEN + .byte 5,'S' ; + .word LBB_STRS ; STR$ + .byte 4,'V' ; + .word LBB_VAL ; VAL + .byte 4,'A' ; + .word LBB_ASC ; ASC + .byte 7,'U' ; + .word LBB_UCASES ; UCASE$ + .byte 7,'L' ; + .word LBB_LCASES ; LCASE$ + .byte 5,'C' ; + .word LBB_CHRS ; CHR$ + .byte 5,'H' ; + .word LBB_HEXS ; HEX$ + .byte 5,'B' ; + .word LBB_BINS ; BIN$ + .byte 7,'B' ; + .word LBB_BITTST ; BITTST + .byte 4,'M' ; + .word LBB_MAX ; MAX + .byte 4,'M' ; + .word LBB_MIN ; MIN + .byte 2,'P' ; + .word LBB_PI ; PI + .byte 5,'T' ; + .word LBB_TWOPI ; TWOPI + .byte 7,'V' ; + .word LBB_VPTR ; VARPTR + .byte 6,'L' ; + .word LBB_LEFTS ; LEFT$ + .byte 7,'R' ; + .word LBB_RIGHTS ; RIGHT$ + .byte 5,'M' ; + .word LBB_MIDS ; MID$ + +; BASIC messages, mostly error messages + +LAB_BAER + .word ERR_NF ;$00 NEXT without FOR + .word ERR_SN ;$02 syntax + .word ERR_RG ;$04 RETURN without GOSUB + .word ERR_OD ;$06 out of data + .word ERR_FC ;$08 function call + .word ERR_OV ;$0A overflow + .word ERR_OM ;$0C out of memory + .word ERR_US ;$0E undefined statement + .word ERR_BS ;$10 array bounds + .word ERR_DD ;$12 double dimension array + .word ERR_D0 ;$14 divide by 0 + .word ERR_ID ;$16 illegal direct + .word ERR_TM ;$18 type mismatch + .word ERR_LS ;$1A long string + .word ERR_ST ;$1C string too complex + .word ERR_CN ;$1E continue error + .word ERR_UF ;$20 undefined function + .word ERR_LD ;$22 LOOP without DO + +; I may implement these two errors to force definition of variables and +; dimensioning of arrays before use. + +; .word ERR_UV ;$24 undefined variable + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +; .word ERR_UA ;$26 undimensioned array + +ERR_NF .byte "NEXT without FOR",$00 +ERR_SN .byte "Syntax",$00 +ERR_RG .byte "RETURN without GOSUB",$00 +ERR_OD .byte "Out of DATA",$00 +ERR_FC .byte "Function call",$00 +ERR_OV .byte "Overflow",$00 +ERR_OM .byte "Out of memory",$00 +ERR_US .byte "Undefined statement",$00 +ERR_BS .byte "Array bounds",$00 +ERR_DD .byte "Double dimension",$00 +ERR_D0 .byte "Divide by zero",$00 +ERR_ID .byte "Illegal direct",$00 +ERR_TM .byte "Type mismatch",$00 +ERR_LS .byte "String too long",$00 +ERR_ST .byte "String too complex",$00 +ERR_CN .byte "Can't continue",$00 +ERR_UF .byte "Undefined function",$00 +ERR_LD .byte "LOOP without DO",$00 + +;ERR_UV .byte "Undefined variable",$00 + +; the above error has been tested and works (see code and comments below LAB_1D8B) + +;ERR_UA .byte "Undimensioned array",$00 + +LAB_BMSG .byte $0D,$0A,"Break",$00 +LAB_EMSG .byte " Error",$00 +LAB_LMSG .byte " in line ",$00 +LAB_RMSG .byte $0D,$0A,"Ready",$0D,$0A,$00 + +LAB_IMSG .byte " Extra ignored",$0D,$0A,$00 +LAB_REDO .byte " Redo from start",$0D,$0A,$00 + +AA_end_basic diff --git a/ehbas.dat b/ehbas.dat new file mode 100644 index 0000000..df282a4 --- /dev/null +++ b/ehbas.dat @@ -0,0 +1,2064 @@ +; Program disassembly from $C000 to $FFDF 3/4/2016 +; EhBasic image for MKBASIC 6502 simulator. +; +ORG +$C000 +; Char IO +IOADDR +$FFE0 +; ROM +ROMBEGIN +$FFC0 +ROMEND +$FFDF +; Enable char IO and ROM +ENIO +ENROM +; Auto-execute +EXEC +$C000 +; Data/Code +$D8, $A0, $08, $B9, $FB, $E0, $99, $00 +$02, $88, $10, $F7, $A2, $FF, $8E, $21 +$02, $86, $88, $9A, $A9, $4C, $85, $A1 +$A2, $1C, $BD, $03, $E1, $95, $BB, $CA +$D0, $F8, $A2, $12, $BD, $20, $E1, $95 +$00, $CA, $10, $F8, $A9, $00, $85, $DC +$85, $DF, $85, $B2, $85, $67, $A9, $0E +$85, $64, $A9, $03, $85, $A0, $A2, $68 +$86, $65, $20, $97, $C8, $A9, $33, $A0 +$E1, $20, $D8, $C8, $20, $45, $C2, $86 +$C3, $84, $C4, $20, $C2, $00, $D0, $1F +$A0, $00, $E6, $11, $D0, $08, $E6, $12 +$A5, $12, $C9, $C0, $F0, $1D, $A9, $55 +$91, $11, $D1, $11, $D0, $15, $0A, $91 +$11, $D1, $11, $F0, $E5, $D0, $0C, $20 +$AB, $D9, $A5, $AC, $C9, $98, $B0, $A2 +$20, $FC, $D4, $A5, $11, $A4, $12, $C0 +$01, $90, $97, $85, $85, $84, $86, $85 +$81, $84, $82, $A0, $00, $A2, $03, $84 +$79, $86, $7A, $98, $91, $79, $E6, $79 +$20, $97, $C8, $20, $55, $C3, $A5, $85 +$38, $E5, $79, $AA, $A5, $86, $E5, $7A +$20, $87, $DA, $A9, $42, $A0, $E1, $20 +$D8, $C8, $A9, $5E, $A0, $C1, $85, $01 +$84, $02, $6C, $01, $00, $20, $0F, $C1 +$85, $7F, $84, $80, $38, $A5, $A6, $E5 +$AA, $A8, $A5, $A7, $E5, $AB, $AA, $E8 +$98, $F0, $24, $38, $49, $FF, $65, $A6 +$85, $A6, $B0, $03, $C6, $A7, $38, $98 +$49, $FF, $65, $A4, $85, $A4, $B0, $08 +$C6, $A5, $90, $04, $B1, $A6, $91, $A4 +$88, $D0, $F9, $B1, $A6, $91, $A4, $C6 +$A7, $C6, $A5, $CA, $D0, $F2, $60, $85 +$78, $BA, $E4, $78, $90, $30, $60, $C4 +$82, $90, $2A, $D0, $04, $C5, $81, $90 +$24, $48, $A2, $08, $98, $48, $B5, $A3 +$CA, $10, $FA, $20, $E4, $D1, $A2, $00 +$68, $95, $A4, $E8, $E0, $08, $30, $F8 +$68, $A8, $68, $C4, $82, $90, $06, $D0 +$05, $C5, $81, $B0, $01, $60, $A2, $0C +$20, $97, $C8, $BD, $B2, $E6, $BC, $B3 +$E6, $20, $D8, $C8, $20, $8E, $C3, $A9 +$EF, $A0, $E7, $20, $D8, $C8, $A4, $88 +$C8, $F0, $03, $20, $7C, $DA, $A9, $00 +$85, $DF, $85, $DC, $A9, $00, $A0, $E8 +$20, $D8, $C8, $18, $20, $52, $C2, $86 +$C3, $84, $C4, $20, $C2, $00, $F0, $F4 +$A2, $FF, $86, $88, $90, $06, $20, $83 +$C2, $4C, $F8, $C4, $20, $5A, $C7, $20 +$83, $C2, $84, $5D, $20, $29, $C3, $90 +$44, $A0, $01, $B1, $AA, $85, $72, $A5 +$7B, $85, $71, $A5, $AB, $85, $74, $A5 +$AA, $88, $F1, $AA, $18, $65, $7B, $85 +$7B, $85, $73, $A5, $7C, $69, $FF, $85 +$7C, $E5, $AB, $AA, $38, $A5, $AA, $E5 +$7B, $A8, $B0, $03, $E8, $C6, $74, $18 +$65, $71, $90, $03, $C6, $72, $18, $B1 +$71, $91, $73, $C8, $D0, $F9, $E6, $72 +$E6, $74, $CA, $D0, $F2, $AD, $21, $02 +$F0, $3F, $A5, $85, $A4, $86, $85, $81 +$84, $82, $A5, $7B, $85, $A6, $A4, $7C +$84, $A7, $65, $5D, $90, $01, $C8, $85 +$A4, $84, $A5, $20, $C5, $C0, $A5, $7F +$A4, $80, $85, $7B, $84, $7C, $A4, $5D +$88, $B9, $1D, $02, $91, $AA, $88, $C0 +$03, $D0, $F6, $A5, $12, $91, $AA, $88 +$A5, $11, $91, $AA, $88, $A9, $FF, $91 +$AA, $20, $6A, $C3, $A6, $79, $A5, $7A +$A0, $01, $86, $71, $85, $72, $B1, $71 +$F0, $18, $A0, $04, $C8, $B1, $71, $D0 +$FB, $38, $98, $65, $71, $AA, $A0, $00 +$91, $71, $98, $65, $72, $C8, $91, $71 +$90, $E0, $4C, $6C, $C1, $20, $F0, $C8 +$20, $ED, $C8, $D0, $05, $20, $F2, $C8 +$CA, $2C, $A2, $00, $20, $EF, $E0, $90 +$FB, $F0, $F9, $C9, $07, $F0, $10, $C9 +$0D, $F0, $19, $E0, $00, $D0, $04, $C9 +$21, $90, $E9, $C9, $08, $F0, $DE, $E0 +$47, $B0, $0C, $9D, $21, $02, $E8, $20 +$F2, $C8, $D0, $D8, $4C, $8E, $C8, $A9 +$07, $D0, $F4, $A0, $FF, $38, $A5, $C3 +$E9, $21, $AA, $86, $60, $BD, $21, $02 +$F0, $51, $C9, $5F, $B0, $4D, $C9, $3C +$B0, $0E, $C9, $30, $B0, $45, $85, $5C +$C9, $22, $F0, $61, $C9, $2A, $90, $3B +$24, $60, $70, $37, $86, $78, $84, $BA +$A0, $19, $84, $73, $A0, $E3, $84, $74 +$A0, $00, $D1, $73, $F0, $05, $90, $21 +$C8, $D0, $F7, $98, $0A, $AA, $BD, $37 +$E3, $85, $73, $BD, $38, $E3, $85, $74 +$A0, $FF, $A6, $78, $C8, $B1, $73, $30 +$08, $E8, $DD, $21, $02, $F0, $F5, $D0 +$2B, $A4, $BA, $E8, $C8, $99, $21, $02 +$C9, $00, $F0, $32, $E9, $3A, $F0, $04 +$C9, $49, $D0, $02, $85, $60, $49, $57 +$D0, $93, $85, $5C, $BD, $21, $02, $F0 +$E2, $C5, $5C, $F0, $DE, $C8, $99, $21 +$02, $E8, $D0, $F0, $A6, $78, $B1, $73 +$08, $C8, $28, $10, $F9, $B1, $73, $D0 +$BE, $BD, $21, $02, $10, $C3, $C8, $C8 +$99, $21, $02, $C8, $C8, $C8, $C6, $C3 +$60, $A5, $79, $A6, $7A, $A0, $01, $85 +$AA, $86, $AB, $B1, $AA, $F0, $1A, $A0 +$03, $B1, $AA, $88, $C5, $12, $D0, $04 +$B1, $AA, $C5, $11, $B0, $09, $88, $B1 +$AA, $AA, $88, $B1, $AA, $90, $DE, $F0 +$01, $18, $60, $D0, $FD, $A9, $00, $A8 +$91, $79, $C8, $91, $79, $18, $A5, $79 +$69, $02, $85, $7B, $A5, $7A, $69, $00 +$85, $7C, $18, $A5, $79, $69, $FF, $85 +$C3, $A5, $7A, $69, $FF, $85, $C4, $A5 +$85, $A4, $86, $85, $81, $84, $82, $A5 +$7B, $A4, $7C, $85, $7D, $84, $7E, $85 +$7F, $84, $80, $20, $49, $C5, $A2, $68 +$86, $65, $68, $AA, $68, $8E, $FE, $01 +$8D, $FF, $01, $A2, $FD, $9A, $A9, $00 +$85, $8C, $85, $61, $60, $F0, $D0, $60 +$90, $06, $F0, $04, $C9, $B7, $D0, $F4 +$20, $5A, $C7, $20, $29, $C3, $20, $C2 +$00, $F0, $0C, $C9, $B7, $D0, $93, $20 +$BC, $00, $20, $5A, $C7, $D0, $8B, $A5 +$11, $05, $12, $D0, $06, $A9, $FF, $85 +$11, $85, $12, $A0, $01, $84, $60, $20 +$97, $C8, $B1, $AA, $F0, $3E, $20, $19 +$C5, $C8, $B1, $AA, $AA, $C8, $B1, $AA +$C5, $12, $D0, $04, $E4, $11, $F0, $02 +$B0, $2A, $84, $97, $20, $87, $DA, $A9 +$20, $A4, $97, $29, $7F, $20, $F2, $C8 +$C9, $22, $D0, $06, $A5, $60, $49, $FF +$85, $60, $C8, $B1, $AA, $D0, $0E, $A8 +$B1, $AA, $AA, $C8, $B1, $AA, $86, $AA +$85, $AB, $D0, $B7, $60, $10, $DE, $24 +$60, $30, $DA, $A2, $E5, $0A, $0A, $90 +$02, $E8, $18, $69, $1A, $90, $01, $E8 +$85, $73, $86, $74, $84, $97, $A0, $00 +$B1, $73, $AA, $C8, $B1, $73, $CA, $F0 +$B8, $20, $F2, $C8, $C8, $B1, $73, $48 +$C8, $B1, $73, $A0, $00, $85, $74, $68 +$85, $73, $B1, $73, $CA, $F0, $A2, $20 +$F2, $C8, $C8, $D0, $F5, $A9, $80, $85 +$61, $20, $B9, $C7, $68, $68, $A9, $10 +$20, $07, $C1, $20, $A2, $C6, $18, $98 +$65, $C3, $48, $A5, $C4, $69, $00, $48 +$A5, $88, $48, $A5, $87, $48, $A9, $AD +$20, $F6, $CB, $20, $D5, $CA, $20, $D2 +$CA, $A5, $B0, $09, $7F, $25, $AD, $85 +$AD, $A9, $9C, $A0, $C4, $85, $71, $84 +$72, $4C, $89, $CB, $A9, $E9, $A0, $E1 +$20, $82, $D8, $20, $C2, $00, $C9, $B2 +$D0, $06, $20, $BC, $00, $20, $D2, $CA +$20, $EE, $D8, $85, $B0, $20, $7E, $CB +$A5, $98, $48, $A5, $97, $48, $A9, $81 +$48, $20, $19, $C5, $A5, $C3, $A4, $C4 +$A6, $88, $E8, $F0, $04, $85, $8B, $84 +$8C, $A0, $00, $B1, $C3, $F0, $07, $C9 +$3A, $F0, $1D, $4C, $07, $CC, $A0, $02 +$B1, $C3, $18, $F0, $56, $C8, $B1, $C3 +$85, $87, $C8, $B1, $C3, $85, $88, $98 +$65, $C3, $85, $C3, $90, $02, $E6, $C4 +$20, $BC, $00, $20, $01, $C5, $4C, $C1 +$C4, $F0, $54, $0A, $B0, $03, $4C, $B9 +$C7, $C9, $56, $B0, $CE, $A8, $B9, $11 +$E2, $48, $B9, $10, $E2, $48, $4C, $BC +$00, $6C, $03, $02, $C9, $03, $B0, $01 +$18, $D0, $67, $A5, $C4, $49, $02, $F0 +$10, $49, $02, $A4, $C3, $84, $8B, $85 +$8C, $A5, $87, $A4, $88, $85, $89, $84 +$8A, $68, $68, $90, $07, $A9, $E7, $A0 +$E7, $4C, $53, $C1, $4C, $5E, $C1, $D0 +$0F, $38, $A5, $79, $E9, $01, $A4, $7A +$B0, $01, $88, $85, $8F, $84, $90, $60 +$20, $5A, $C7, $20, $A5, $C6, $A5, $88 +$C5, $12, $B0, $0B, $98, $38, $65, $C3 +$A6, $C4, $90, $07, $E8, $B0, $04, $A5 +$79, $A6, $7A, $20, $2D, $C3, $B0, $03 +$4C, $77, $C6, $A5, $AA, $E9, $01, $A4 +$AB, $B0, $D0, $90, $CD, $20, $91, $D4 +$86, $0D, $60, $D0, $FD, $A4, $8C, $D0 +$05, $A2, $1E, $4C, $40, $C1, $A9, $93 +$20, $19, $DF, $A9, $93, $20, $1C, $DF +$84, $C4, $A5, $8B, $85, $C3, $A5, $89 +$A4, $8A, $85, $87, $84, $88, $60, $D0 +$03, $4C, $6A, $C3, $20, $77, $C3, $F0 +$2E, $A9, $05, $20, $07, $C1, $A5, $C4 +$48, $A5, $C3, $48, $A5, $88, $48, $A5 +$87, $48, $A9, $9D, $48, $20, $C2, $00 +$4C, $C1, $C4, $A9, $05, $20, $07, $C1 +$A5, $C4, $48, $A5, $C3, $48, $A5, $88 +$48, $A5, $87, $48, $A9, $8D, $48, $20 +$C2, $00, $20, $F0, $C5, $4C, $C1, $C4 +$20, $5A, $C7, $20, $A5, $C6, $A5, $88 +$C5, $12, $B0, $0B, $98, $38, $65, $C3 +$A6, $C4, $90, $07, $E8, $B0, $04, $A5 +$79, $A6, $7A, $20, $2D, $C3, $90, $67 +$A5, $AA, $E9, $01, $85, $C3, $A5, $AB +$E9, $00, $85, $C4, $60, $A2, $22, $4C +$40, $C1, $A8, $BA, $BD, $03, $01, $C9 +$9D, $D0, $F2, $E8, $E8, $9A, $98, $F0 +$20, $C9, $3A, $F0, $1C, $E9, $B3, $AA +$F0, $04, $CA, $D0, $62, $CA, $86, $98 +$20, $BC, $00, $20, $E6, $CA, $A5, $AC +$F0, $02, $A9, $FF, $BA, $45, $98, $D0 +$1A, $BD, $02, $01, $85, $87, $BD, $03 +$01, $85, $88, $BD, $04, $01, $85, $C3 +$BD, $05, $01, $85, $C4, $20, $C2, $00 +$4C, $C1, $C4, $E8, $E8, $E8, $E8, $E8 +$9A, $4C, $91, $C6, $A2, $04, $2C, $A2 +$0E, $4C, $40, $C1, $D0, $9E, $68, $68 +$68, $C9, $8D, $D0, $EF, $68, $85, $87 +$68, $85, $88, $68, $85, $C3, $68, $85 +$C4, $20, $A2, $C6, $98, $18, $65, $C3 +$85, $C3, $90, $02, $E6, $C4, $60, $4C +$07, $CC, $A2, $3A, $2C, $A2, $00, $A0 +$00, $84, $5C, $8A, $45, $5C, $85, $5C +$B1, $C3, $F0, $EA, $C5, $5C, $F0, $E6 +$C8, $C9, $22, $D0, $F3, $F0, $EC, $20 +$E6, $CA, $20, $C2, $00, $C9, $B0, $F0 +$11, $C9, $89, $D0, $D2, $A6, $C3, $A4 +$C4, $20, $BC, $00, $B0, $C9, $86, $C3 +$84, $C4, $A5, $AC, $F0, $1B, $20, $BC +$00, $B0, $03, $4C, $F0, $C5, $C9, $90 +$D0, $03, $4C, $03, $C5, $20, $01, $C5 +$A0, $00, $B1, $C3, $C9, $AC, $F0, $99 +$60, $A0, $00, $A2, $01, $C8, $B1, $C3 +$F0, $0F, $C9, $8B, $D0, $03, $E8, $D0 +$F4, $C9, $AC, $D0, $F0, $CA, $D0, $ED +$C8, $98, $18, $65, $C3, $85, $C3, $90 +$02, $E6, $C4, $20, $C2, $00, $90, $C3 +$4C, $01, $C5, $20, $A5, $C6, $4C, $94 +$C6, $4C, $07, $CC, $C9, $A9, $D0, $03 +$4C, $3D, $DF, $C9, $AA, $D0, $03, $4C +$41, $DF, $20, $91, $D4, $48, $C9, $8D +$F0, $04, $C9, $89, $D0, $E3, $C6, $AF +$D0, $04, $68, $4C, $03, $C5, $20, $BC +$00, $20, $5A, $C7, $C9, $2C, $F0, $EE +$68, $60, $A2, $00, $86, $11, $86, $12 +$B0, $F7, $E0, $19, $A8, $B0, $DD, $E9 +$2F, $A8, $A5, $11, $0A, $26, $12, $0A +$26, $12, $65, $11, $85, $11, $8A, $65 +$12, $06, $11, $2A, $AA, $98, $65, $11 +$85, $11, $90, $01, $E8, $20, $BC, $00 +$4C, $5E, $C7, $A9, $ED, $2C, $A9, $E9 +$48, $20, $AF, $CD, $A6, $5F, $30, $1E +$85, $97, $84, $98, $20, $82, $D8, $68 +$48, $A0, $E1, $20, $C3, $D5, $20, $A8 +$D8, $20, $C2, $00, $C9, $2C, $D0, $A8 +$20, $BC, $00, $4C, $91, $C7, $4C, $E1 +$CA, $20, $AF, $CD, $85, $97, $84, $98 +$A9, $C1, $20, $F6, $CB, $A5, $5F, $48 +$20, $E6, $CA, $68, $2A, $20, $D8, $CA +$D0, $03, $4C, $A8, $D8, $A0, $02, $B1 +$AE, $C5, $82, $90, $17, $D0, $07, $88 +$B1, $AE, $C5, $81, $90, $0E, $A4, $AF +$C4, $7C, $90, $08, $D0, $0D, $A5, $AE +$C5, $7B, $B0, $07, $A5, $AE, $A4, $AF +$4C, $11, $C8, $A0, $00, $B1, $AE, $20 +$37, $D1, $A5, $9E, $A4, $9F, $85, $B8 +$84, $B9, $20, $16, $D3, $A9, $AC, $A0 +$00, $85, $9E, $84, $9F, $20, $78, $D3 +$A0, $00, $B1, $9E, $91, $97, $C8, $B1 +$9E, $91, $97, $C8, $B1, $9E, $91, $97 +$60, $20, $AF, $CD, $85, $97, $84, $98 +$20, $05, $DF, $A6, $5F, $30, $07, $A8 +$20, $6B, $D0, $4C, $A8, $D8, $48, $A9 +$01, $B0, $01, $68, $20, $3F, $D1, $F0 +$05, $68, $A0, $00, $91, $AD, $20, $8A +$D1, $4C, $D5, $C7, $20, $DB, $C8, $20 +$C2, $00, $F0, $3B, $C9, $AB, $F0, $56 +$C9, $AF, $F0, $52, $C9, $2C, $F0, $38 +$C9, $3B, $F0, $66, $20, $E6, $CA, $24 +$5F, $30, $E1, $20, $9A, $DA, $20, $49 +$D1, $A0, $00, $A5, $0F, $F0, $0A, $38 +$E5, $0E, $F1, $AE, $B0, $03, $20, $97 +$C8, $20, $DB, $C8, $F0, $C9, $A9, $00 +$9D, $21, $02, $A2, $21, $A0, $02, $A9 +$0D, $20, $F2, $C8, $A9, $0A, $D0, $52 +$A5, $0E, $C5, $10, $90, $05, $20, $97 +$C8, $D0, $27, $38, $E5, $64, $B0, $FC +$49, $FF, $69, $01, $D0, $12, $48, $20 +$8E, $D4, $C9, $29, $D0, $7B, $68, $C9 +$AB, $D0, $06, $8A, $E5, $0E, $90, $0A +$AA, $8A, $F0, $06, $20, $ED, $C8, $CA +$D0, $FA, $20, $BC, $00, $D0, $85, $60 +$20, $49, $D1, $20, $43, $D3, $A0, $00 +$AA, $F0, $49, $B1, $71, $20, $F2, $C8 +$C8, $CA, $D0, $F7, $60, $A9, $20, $2C +$A9, $3F, $C9, $20, $90, $19, $48, $A5 +$0F, $D0, $0A, $A5, $0E, $E5, $64, $D0 +$0B, $85, $0E, $F0, $07, $C5, $0E, $D0 +$03, $20, $97, $C8, $E6, $0E, $68, $20 +$F2, $E0, $C9, $0D, $D0, $14, $86, $78 +$A6, $0D, $F0, $0A, $A9, $00, $20, $F2 +$C8, $CA, $D0, $FA, $A9, $0D, $86, $0E +$A6, $78, $29, $FF, $60, $A5, $62, $10 +$0B, $A5, $8D, $A4, $8E, $85, $87, $84 +$88, $4C, $07, $CC, $A9, $1B, $A0, $E8 +$20, $D8, $C8, $A5, $8B, $A4, $8C, $85 +$C3, $84, $C4, $60, $C9, $22, $D0, $0B +$20, $C3, $CB, $A9, $3B, $20, $F6, $CB +$20, $DB, $C8, $20, $6F, $D0, $20, $45 +$C2, $A9, $00, $CD, $21, $02, $D0, $0A +$18, $4C, $31, $C5, $A6, $8F, $A4, $90 +$A9, $80, $85, $62, $86, $91, $84, $92 +$20, $AF, $CD, $85, $97, $84, $98, $A5 +$C3, $A4, $C4, $85, $11, $84, $12, $A6 +$91, $A4, $92, $86, $C3, $84, $C4, $20 +$C2, $00, $D0, $11, $24, $62, $30, $65 +$20, $F0, $C8, $20, $45, $C2, $86, $C3 +$84, $C4, $20, $C2, $00, $24, $5F, $10 +$24, $85, $5B, $C9, $22, $F0, $07, $A9 +$3A, $85, $5B, $A9, $2C, $18, $85, $5C +$A5, $C3, $A4, $C4, $69, $00, $90, $01 +$C8, $20, $4F, $D1, $20, $D4, $D4, $20 +$D5, $C7, $4C, $D3, $C9, $20, $AB, $D9 +$20, $A8, $D8, $20, $C2, $00, $F0, $0A +$C9, $2C, $F0, $03, $4C, $2D, $C9, $20 +$BC, $00, $A5, $C3, $A4, $C4, $85, $91 +$84, $92, $A5, $11, $A4, $12, $85, $C3 +$84, $C4, $20, $C2, $00, $F0, $2C, $20 +$03, $CC, $4C, $78, $C9, $20, $A2, $C6 +$C8, $AA, $D0, $12, $A2, $06, $C8, $B1 +$C3, $F0, $73, $C8, $B1, $C3, $85, $8D +$C8, $B1, $C3, $C8, $85, $8E, $B1, $C3 +$C8, $AA, $20, $94, $C6, $E0, $83, $F0 +$81, $D0, $DA, $A5, $91, $A4, $92, $A6 +$62, $10, $03, $4C, $53, $C5, $A0, $00 +$B1, $91, $D0, $01, $60, $A9, $0A, $A0 +$E8, $4C, $D8, $C8, $BA, $E8, $E8, $E8 +$E8, $BD, $01, $01, $C9, $81, $D0, $21 +$A5, $98, $D0, $0A, $BD, $02, $01, $85 +$97, $BD, $03, $01, $85, $98, $DD, $03 +$01, $D0, $07, $A5, $97, $DD, $02, $01 +$F0, $07, $8A, $18, $69, $10, $AA, $D0 +$D8, $60, $D0, $04, $A0, $00, $F0, $03 +$20, $AF, $CD, $85, $97, $84, $98, $20 +$3C, $CA, $F0, $04, $A2, $00, $F0, $63 +$9A, $8A, $38, $E9, $F7, $85, $73, $69 +$FB, $A0, $01, $20, $82, $D8, $BA, $BD +$08, $01, $85, $B0, $A5, $97, $A4, $98 +$20, $C3, $D5, $20, $A8, $D8, $A0, $01 +$20, $1E, $D9, $BA, $DD, $08, $01, $F0 +$17, $BD, $0D, $01, $85, $87, $BD, $0E +$01, $85, $88, $BD, $10, $01, $85, $C3 +$BD, $0F, $01, $85, $C4, $4C, $C1, $C4 +$8A, $69, $0F, $AA, $9A, $20, $C2, $00 +$C9, $2C, $D0, $F1, $20, $BC, $00, $20 +$70, $CA, $20, $E6, $CA, $18, $24, $38 +$24, $5F, $30, $03, $B0, $03, $60, $B0 +$FD, $A2, $18, $4C, $40, $C1, $A6, $C3 +$D0, $02, $C6, $C4, $C6, $C3, $A9, $00 +$48, $A9, $02, $20, $07, $C1, $20, $D2 +$CB, $A9, $00, $85, $9B, $20, $C2, $00 +$38, $E9, $C0, $90, $17, $C9, $03, $B0 +$13, $C9, $01, $2A, $49, $01, $45, $9B +$C5, $9B, $90, $67, $85, $9B, $20, $BC +$00, $4C, $00, $CB, $A6, $9B, $D0, $2C +$B0, $79, $69, $0A, $90, $75, $D0, $07 +$24, $5F, $10, $03, $4C, $D9, $D2, $85 +$71, $0A, $65, $71, $A8, $68, $D9, $F2 +$E2, $B0, $65, $20, $D5, $CA, $48, $20 +$67, $CB, $68, $A4, $99, $10, $19, $AA +$F0, $76, $D0, $5D, $26, $5F, $8A, $85 +$5F, $2A, $A6, $C3, $D0, $02, $C6, $C4 +$C6, $C3, $A0, $24, $85, $9B, $D0, $D5 +$D9, $F2, $E2, $B0, $44, $90, $D7, $B9 +$F4, $E2, $48, $B9, $F3, $E2, $48, $20 +$7E, $CB, $A5, $9B, $48, $B9, $F2, $E2 +$4C, $F0, $CA, $4C, $07, $CC, $68, $85 +$71, $E6, $71, $68, $85, $72, $A5, $B0 +$48, $20, $DE, $D8, $A5, $AF, $48, $A5 +$AE, $48, $A5, $AD, $48, $A5, $AC, $48 +$6C, $71, $00, $A0, $FF, $68, $F0, $20 +$C9, $64, $F0, $03, $20, $D5, $CA, $84 +$99, $68, $4A, $85, $63, $68, $85, $B3 +$68, $85, $B4, $68, $85, $B5, $68, $85 +$B6, $68, $85, $B7, $45, $B0, $85, $B8 +$A5, $AC, $60, $A5, $C3, $A4, $C4, $69 +$00, $90, $01, $C8, $20, $49, $D1, $4C +$D4, $D4, $20, $BC, $00, $B0, $03, $4C +$AB, $D9, $AA, $30, $2F, $C9, $24, $F0 +$F6, $C9, $25, $F0, $F2, $C9, $2E, $F0 +$EE, $C9, $22, $F0, $D6, $C9, $28, $D0 +$4F, $20, $EE, $CA, $A9, $29, $A0, $00 +$D1, $C3, $D0, $0B, $4C, $BC, $00, $A9 +$28, $D0, $F3, $A9, $2C, $D0, $EF, $A2 +$02, $4C, $40, $C1, $C9, $B7, $F0, $29 +$C9, $B6, $F0, $BE, $C9, $B1, $D0, $13 +$A0, $21, $D0, $1F, $20, $AB, $CE, $A5 +$AF, $49, $FF, $A8, $A5, $AE, $49, $FF +$4C, $5E, $D0, $C9, $AE, $D0, $03, $4C +$B9, $D0, $E9, $C3, $B0, $19, $4C, $07 +$CC, $A0, $1E, $68, $68, $4C, $3F, $CB +$20, $AF, $CD, $85, $AE, $84, $AF, $A6 +$5F, $30, $03, $4C, $82, $D8, $60, $0A +$A8, $B9, $AD, $E2, $48, $B9, $AC, $E2 +$48, $B9, $67, $E2, $F0, $05, $48, $B9 +$66, $E2, $48, $60, $20, $F1, $CB, $4C +$D7, $CA, $20, $F1, $CB, $4C, $D5, $CA +$46, $5F, $4C, $BC, $00, $20, $EE, $CA +$20, $03, $CC, $20, $D7, $CA, $68, $AA +$68, $A8, $A5, $AF, $48, $A5, $AE, $48 +$98, $48, $8A, $48, $20, $91, $D4, $8A +$60, $20, $EE, $CA, $20, $D5, $CA, $A5 +$AC, $C9, $98, $B0, $20, $20, $55, $D9 +$A2, $02, $B5, $AD, $95, $11, $CA, $10 +$F9, $20, $C2, $00, $A2, $00, $C9, $29 +$F0, $0A, $20, $E3, $D4, $20, $C2, $00 +$C9, $29, $D0, $01, $60, $4C, $2E, $CF +$20, $E7, $CC, $45, $5B, $A8, $A5, $AE +$45, $5C, $4C, $5E, $D0, $20, $E7, $CC +$05, $5B, $A8, $A5, $AE, $05, $5C, $4C +$5E, $D0, $20, $E7, $CC, $25, $5B, $A8 +$A5, $AE, $25, $5C, $4C, $5E, $D0, $20 +$AB, $CE, $A5, $AE, $85, $5C, $A5, $AF +$85, $5B, $20, $C8, $D5, $20, $AB, $CE +$A5, $AF, $60, $20, $D8, $CA, $B0, $13 +$A5, $B7, $09, $7F, $25, $B4, $85, $B4 +$A9, $B3, $A0, $00, $20, $1C, $D9, $AA +$4C, $44, $CD, $46, $5F, $C6, $9B, $20 +$43, $D3, $85, $AC, $86, $AD, $84, $AE +$A5, $B5, $A4, $B6, $20, $47, $D3, $86 +$B5, $84, $B6, $AA, $38, $E5, $AC, $F0 +$08, $A9, $01, $90, $04, $A6, $AC, $A9 +$FF, $85, $B0, $A0, $FF, $E8, $C8, $CA +$D0, $07, $A6, $B0, $30, $0F, $18, $90 +$0C, $B1, $B5, $D1, $AD, $F0, $EF, $A2 +$FF, $B0, $02, $A2, $01, $E8, $8A, $2A +$25, $63, $F0, $02, $A9, $FF, $4C, $FF +$D8, $20, $03, $CC, $AA, $20, $B4, $CD +$20, $C2, $00, $D0, $F4, $60, $20, $A4 +$CD, $A5, $AE, $A6, $78, $F0, $22, $E0 +$10, $B0, $23, $06, $AF, $2A, $CA, $D0 +$FA, $A4, $AF, $4C, $5E, $D0, $20, $A4 +$CD, $A5, $AE, $A6, $78, $F0, $0A, $E0 +$10, $B0, $0B, $4A, $66, $AF, $CA, $D0 +$FA, $A4, $AF, $4C, $5E, $D0, $A9, $00 +$A8, $4C, $5E, $D0, $20, $94, $D4, $86 +$78, $20, $C8, $D5, $4C, $AB, $CE, $A2 +$00, $20, $C2, $00, $86, $5E, $85, $93 +$29, $7F, $20, $23, $CE, $B0, $03, $4C +$07, $CC, $A2, $00, $86, $5F, $20, $BC +$00, $90, $05, $20, $23, $CE, $90, $0B +$AA, $20, $BC, $00, $90, $FB, $20, $23 +$CE, $B0, $F6, $C9, $24, $D0, $0B, $A9 +$FF, $85, $5F, $8A, $09, $80, $AA, $20 +$BC, $00, $86, $94, $05, $61, $C9, $28 +$D0, $03, $4C, $BD, $CE, $A9, $00, $85 +$61, $A5, $7B, $A6, $7C, $A0, $00, $86 +$AB, $85, $AA, $E4, $7E, $D0, $04, $C5 +$7D, $F0, $2C, $A5, $93, $D1, $AA, $D0 +$08, $A5, $94, $C8, $D1, $AA, $F0, $69 +$88, $18, $A5, $AA, $69, $06, $90, $E1 +$E8, $D0, $DC, $C9, $61, $B0, $0A, $C9 +$41, $90, $05, $E9, $5B, $38, $E9, $A5 +$60, $E9, $7B, $38, $E9, $85, $60, $68 +$48, $C9, $42, $D0, $05, $A9, $EA, $A0 +$E1, $60, $A5, $7D, $A4, $7E, $85, $AA +$84, $AB, $A5, $7F, $A4, $80, $85, $A6 +$84, $A7, $18, $69, $06, $90, $01, $C8 +$85, $A4, $84, $A5, $20, $C5, $C0, $A5 +$A4, $A4, $A5, $C8, $85, $7D, $84, $7E +$A0, $00, $A5, $93, $91, $AA, $C8, $A5 +$94, $91, $AA, $A9, $00, $C8, $91, $AA +$C8, $91, $AA, $C8, $91, $AA, $C8, $91 +$AA, $A5, $AA, $18, $69, $02, $A4, $AB +$90, $01, $C8, $85, $95, $84, $96, $60 +$A5, $5D, $0A, $69, $05, $65, $AA, $A4 +$AB, $90, $01, $C8, $85, $A4, $84, $A5 +$60, $20, $BC, $00, $20, $D2, $CA, $A5 +$B0, $30, $0D, $A5, $AC, $C9, $90, $90 +$09, $A9, $F1, $A0, $E1, $20, $1C, $D9 +$D0, $74, $4C, $55, $D9, $A5, $5E, $48 +$A5, $5F, $48, $A0, $00, $98, $48, $A5 +$94, $48, $A5, $93, $48, $20, $A1, $CE +$68, $85, $93, $68, $85, $94, $68, $A8 +$BA, $BD, $02, $01, $48, $BD, $01, $01 +$48, $A5, $AE, $9D, $02, $01, $A5, $AF +$9D, $01, $01, $C8, $20, $C2, $00, $C9 +$2C, $F0, $D2, $84, $5D, $20, $F4, $CB +$68, $85, $5F, $68, $85, $5E, $A6, $7D +$A5, $7E, $86, $AA, $85, $AB, $C5, $80 +$D0, $04, $E4, $7F, $F0, $39, $A0, $00 +$B1, $AA, $C8, $C5, $93, $D0, $06, $A5 +$94, $D1, $AA, $F0, $16, $C8, $B1, $AA +$18, $65, $AA, $AA, $C8, $B1, $AA, $65 +$AB, $90, $D7, $A2, $10, $2C, $A2, $08 +$4C, $40, $C1, $A2, $12, $A5, $5E, $D0 +$F7, $20, $90, $CE, $A5, $5D, $A0, $04 +$D1, $AA, $D0, $E7, $4C, $CA, $CF, $20 +$90, $CE, $20, $0F, $C1, $A0, $00, $84 +$BB, $A5, $93, $91, $AA, $C8, $A5, $94 +$91, $AA, $A5, $5D, $A0, $04, $84, $BA +$91, $AA, $18, $A2, $0B, $A9, $00, $24 +$5E, $50, $07, $68, $69, $01, $AA, $68 +$69, $00, $C8, $91, $AA, $C8, $8A, $91 +$AA, $20, $19, $D0, $86, $BA, $85, $BB +$A4, $71, $C6, $5D, $D0, $DD, $65, $A5 +$B0, $5D, $85, $A5, $A8, $8A, $65, $A4 +$90, $03, $C8, $F0, $52, $20, $0F, $C1 +$85, $7F, $84, $80, $A9, $00, $E6, $BB +$A4, $BA, $F0, $05, $88, $91, $A4, $D0 +$FB, $C6, $A5, $C6, $BB, $D0, $F5, $E6 +$A5, $38, $A0, $02, $A5, $7F, $E5, $AA +$91, $AA, $C8, $A5, $80, $E5, $AB, $91 +$AA, $A5, $5E, $D0, $53, $C8, $B1, $AA +$85, $5D, $A9, $00, $85, $BA, $85, $BB +$C8, $68, $AA, $85, $AE, $68, $85, $AF +$D1, $AA, $90, $0E, $D0, $06, $C8, $8A +$D1, $AA, $90, $07, $4C, $2B, $CF, $4C +$3E, $C1, $C8, $A5, $BB, $05, $BA, $F0 +$0A, $20, $19, $D0, $8A, $65, $AE, $AA +$98, $A4, $71, $65, $AF, $86, $BA, $C6 +$5D, $D0, $CB, $06, $BA, $2A, $06, $BA +$2A, $A8, $A5, $BA, $65, $A4, $85, $95 +$98, $65, $A5, $85, $96, $A8, $A5, $95 +$60, $84, $71, $B1, $AA, $85, $76, $88 +$B1, $AA, $85, $77, $A9, $10, $85, $A8 +$A2, $00, $A0, $00, $8A, $0A, $AA, $98 +$2A, $A8, $B0, $B3, $06, $BA, $26, $BB +$90, $0B, $18, $8A, $65, $76, $AA, $98 +$65, $77, $A8, $B0, $A2, $C6, $A8, $D0 +$E3, $60, $A5, $5F, $10, $03, $20, $43 +$D3, $20, $E4, $D1, $38, $A5, $81, $E5 +$7F, $A8, $A5, $82, $E5, $80, $46, $5F +$85, $AD, $84, $AE, $A2, $90, $4C, $07 +$D9, $A4, $0E, $A9, $00, $F0, $EF, $A6 +$88, $E8, $D0, $A4, $A2, $16, $4C, $40 +$C1, $20, $AA, $D0, $85, $9C, $84, $9D +$20, $6F, $D0, $20, $FF, $CB, $A9, $80 +$85, $61, $20, $AF, $CD, $20, $D5, $CA +$20, $F4, $CB, $A9, $C1, $20, $F6, $CB +$A5, $96, $48, $A5, $95, $48, $A5, $C4 +$48, $A5, $C3, $48, $20, $91, $C6, $4C +$19, $D1, $A9, $AE, $20, $F6, $CB, $09 +$80, $85, $61, $20, $B6, $CD, $4C, $D5 +$CA, $20, $AA, $D0, $48, $98, $48, $20 +$FF, $CB, $20, $E6, $CA, $20, $F4, $CB +$20, $D5, $CA, $68, $85, $9D, $68, $85 +$9C, $A2, $20, $A0, $03, $B1, $9C, $F0 +$9D, $85, $96, $88, $B1, $9C, $85, $95 +$AA, $C8, $B1, $95, $48, $88, $10, $FA +$A4, $96, $20, $AC, $D8, $A5, $C4, $48 +$A5, $C3, $48, $B1, $9C, $85, $C3, $C8 +$B1, $9C, $85, $C4, $A5, $96, $48, $A5 +$95, $48, $20, $D2, $CA, $68, $85, $9C +$68, $85, $9D, $20, $C2, $00, $F0, $03 +$4C, $07, $CC, $68, $85, $C3, $68, $85 +$C4, $A0, $00, $68, $91, $9C, $C8, $68 +$91, $9C, $C8, $68, $91, $9C, $C8, $68 +$91, $9C, $60, $20, $D5, $CA, $20, $9A +$DA, $A9, $F0, $A0, $00, $F0, $12, $A6 +$AE, $A4, $AF, $86, $9E, $84, $9F, $20 +$B2, $D1, $86, $AD, $84, $AE, $85, $AC +$60, $A2, $22, $86, $5B, $86, $5C, $85 +$B8, $84, $B9, $85, $AD, $84, $AE, $A0 +$FF, $C8, $B1, $B8, $F0, $0C, $C5, $5B +$F0, $04, $C5, $5C, $D0, $F3, $C9, $22 +$F0, $01, $18, $84, $AC, $98, $65, $B8 +$85, $BA, $A6, $B9, $90, $01, $E8, $86 +$BB, $A5, $B9, $C9, $03, $B0, $0B, $98 +$20, $37, $D1, $A6, $B8, $A4, $B9, $20 +$24, $D3, $A6, $65, $E0, $71, $D0, $05 +$A2, $1C, $4C, $40, $C1, $A5, $AC, $95 +$00, $A5, $AD, $95, $01, $A5, $AE, $95 +$02, $A0, $00, $86, $AE, $84, $AF, $88 +$84, $5F, $86, $66, $E8, $E8, $E8, $86 +$65, $60, $46, $60, $48, $49, $FF, $38 +$65, $81, $A4, $82, $B0, $01, $88, $C4 +$80, $90, $11, $D0, $04, $C5, $7F, $90 +$0B, $85, $81, $84, $82, $85, $83, $84 +$84, $AA, $68, $60, $A2, $0C, $A5, $60 +$30, $B8, $20, $E4, $D1, $A9, $80, $85 +$60, $68, $D0, $D0, $A6, $85, $A5, $86 +$86, $81, $85, $82, $A0, $00, $84, $9D +$A5, $7F, $A6, $80, $85, $AA, $86, $AB +$A9, $68, $85, $71, $84, $72, $C5, $65 +$F0, $05, $20, $68, $D2, $F0, $F7, $06 +$A0, $A5, $7B, $A6, $7C, $85, $71, $86 +$72, $E4, $7E, $D0, $04, $C5, $7D, $F0 +$05, $20, $62, $D2, $F0, $F3, $85, $A4 +$86, $A5, $A9, $04, $85, $A0, $A5, $A4 +$A6, $A5, $E4, $80, $D0, $04, $C5, $7F +$F0, $75, $85, $71, $86, $72, $A0, $02 +$B1, $71, $65, $A4, $85, $A4, $C8, $B1 +$71, $65, $A5, $85, $A5, $A0, $01, $B1 +$71, $10, $DB, $A0, $04, $B1, $71, $0A +$69, $05, $20, $9A, $D2, $E4, $A5, $D0 +$04, $C5, $A4, $F0, $CD, $20, $68, $D2 +$F0, $F3, $C8, $B1, $71, $10, $30, $C8 +$B1, $71, $F0, $2B, $C8, $B1, $71, $AA +$C8, $B1, $71, $C5, $82, $90, $06, $D0 +$1E, $E4, $81, $B0, $1A, $C5, $AB, $90 +$17, $D0, $04, $E4, $AA, $90, $11, $86 +$AA, $85, $AB, $A5, $71, $A6, $72, $85 +$9C, $86, $9D, $88, $88, $84, $A2, $18 +$A5, $A0, $65, $71, $85, $71, $90, $02 +$E6, $72, $A6, $72, $A0, $00, $60, $C6 +$A0, $A6, $9D, $F0, $F5, $A4, $A2, $18 +$B1, $9C, $65, $AA, $85, $A6, $A5, $AB +$69, $00, $85, $A7, $A5, $81, $A6, $82 +$85, $A4, $86, $A5, $20, $CC, $C0, $A4 +$A2, $C8, $A5, $A4, $91, $9C, $AA, $E6 +$A5, $A5, $A5, $C8, $91, $9C, $4C, $E8 +$D1, $A5, $AF, $48, $A5, $AE, $48, $20 +$D2, $CB, $20, $D7, $CA, $68, $85, $B8 +$68, $85, $B9, $A0, $00, $B1, $B8, $18 +$71, $AE, $90, $05, $A2, $1A, $4C, $40 +$C1, $20, $37, $D1, $20, $16, $D3, $A5 +$9E, $A4, $9F, $20, $47, $D3, $20, $28 +$D3, $A5, $B8, $A4, $B9, $20, $47, $D3 +$20, $8A, $D1, $4C, $FD, $CA, $A0, $00 +$B1, $B8, $48, $C8, $B1, $B8, $AA, $C8 +$B1, $B8, $A8, $68, $86, $71, $84, $72 +$AA, $F0, $14, $A0, $00, $B1, $71, $91 +$83, $C8, $CA, $D0, $F8, $98, $18, $65 +$83, $85, $83, $90, $02, $E6, $84, $60 +$20, $D7, $CA, $A5, $AE, $A4, $AF, $85 +$71, $84, $72, $20, $78, $D3, $08, $A0 +$00, $B1, $71, $48, $C8, $B1, $71, $AA +$C8, $B1, $71, $A8, $68, $28, $D0, $13 +$C4, $82, $D0, $0F, $E4, $81, $D0, $0B +$48, $18, $65, $81, $85, $81, $90, $02 +$E6, $82, $68, $86, $71, $84, $72, $60 +$C4, $67, $D0, $0C, $C5, $66, $D0, $08 +$85, $65, $E9, $03, $85, $66, $A0, $00 +$60, $20, $94, $D4, $8A, $48, $A9, $01 +$20, $3F, $D1, $68, $A0, $00, $91, $AD +$4C, $8A, $D1, $48, $20, $FC, $D3, $D1 +$9E, $98, $F0, $09, $48, $20, $FC, $D3 +$18, $F1, $9E, $49, $FF, $90, $04, $B1 +$9E, $AA, $98, $48, $8A, $48, $20, $3F +$D1, $A5, $9E, $A4, $9F, $20, $47, $D3 +$68, $A8, $68, $18, $65, $71, $85, $71 +$90, $02, $E6, $72, $98, $20, $28, $D3 +$4C, $8A, $D1, $48, $A9, $FF, $85, $AF +$20, $C2, $00, $C9, $29, $F0, $06, $20 +$03, $CC, $20, $91, $D4, $20, $FC, $D3 +$CA, $8A, $48, $18, $A2, $00, $F1, $9E +$B0, $C2, $49, $FF, $C5, $AF, $90, $BD +$A5, $AF, $B0, $B9, $20, $F4, $CB, $68 +$85, $A2, $68, $85, $A3, $68, $AA, $68 +$85, $9E, $68, $85, $9F, $A0, $00, $8A +$F0, $79, $E6, $A2, $6C, $A2, $00, $20 +$40, $D3, $85, $AC, $A8, $F0, $38, $20 +$3F, $D1, $86, $AD, $84, $AE, $A8, $88 +$B1, $71, $20, $27, $CE, $90, $02, $09 +$20, $91, $83, $98, $D0, $F1, $F0, $1F +$20, $40, $D3, $85, $AC, $A8, $F0, $17 +$20, $3F, $D1, $86, $AD, $84, $AE, $A8 +$88, $B1, $71, $20, $23, $CE, $90, $02 +$29, $DF, $91, $83, $98, $D0, $F1, $4C +$8A, $D1, $20, $BC, $00, $20, $AF, $CD +$20, $F4, $CB, $20, $D7, $CA, $A0, $02 +$B1, $95, $AA, $88, $B1, $95, $A8, $8A +$4C, $5E, $D0, $20, $79, $D4, $4C, $6B +$D0, $20, $40, $D3, $A8, $60, $20, $79 +$D4, $F0, $08, $A0, $00, $B1, $71, $A8 +$4C, $6B, $D0, $4C, $2E, $CF, $20, $BC +$00, $20, $D2, $CA, $20, $A7, $CE, $A4 +$AE, $D0, $F0, $A6, $AF, $4C, $C2, $00 +$20, $79, $D4, $D0, $03, $4C, $55, $D6 +$A6, $C3, $A4, $C4, $86, $BA, $84, $BB +$A6, $71, $86, $C3, $18, $65, $71, $85 +$73, $A5, $72, $85, $C4, $69, $00, $85 +$74, $A0, $00, $B1, $73, $48, $98, $91 +$73, $20, $C2, $00, $20, $AB, $D9, $68 +$A0, $00, $91, $73, $A6, $BA, $A4, $BB +$86, $C3, $84, $C4, $60, $20, $D2, $CA +$20, $F6, $D4, $20, $03, $CC, $A5, $12 +$48, $A5, $11, $48, $20, $91, $D4, $68 +$85, $11, $68, $85, $12, $60, $A5, $AC +$C9, $98, $B0, $8F, $20, $55, $D9, $A5 +$AE, $A4, $AF, $84, $11, $85, $12, $60 +$20, $F6, $D4, $A2, $00, $A1, $11, $A8 +$4C, $6B, $D0, $20, $DD, $D4, $8A, $A2 +$00, $81, $11, $60, $20, $F6, $D4, $A2 +$00, $A1, $11, $A8, $E6, $11, $D0, $02 +$E6, $12, $A1, $11, $4C, $5E, $D0, $20 +$D2, $CA, $20, $F6, $D4, $84, $97, $85 +$98, $20, $03, $CC, $20, $D2, $CA, $20 +$F6, $D4, $98, $A2, $00, $81, $97, $E6 +$97, $D0, $02, $E6, $98, $A5, $12, $81 +$97, $4C, $C2, $00, $20, $AF, $CD, $85 +$97, $84, $98, $A5, $5F, $48, $20, $03 +$CC, $20, $AF, $CD, $68, $45, $5F, $10 +$10, $A0, $03, $B1, $97, $AA, $B1, $95 +$91, $97, $8A, $91, $95, $88, $10, $F3 +$60, $4C, $E1, $CA, $20, $D2, $CA, $20 +$F6, $D4, $A9, $D5, $48, $A9, $8A, $48 +$6C, $11, $00, $4C, $C2, $00, $20, $DD +$D4, $86, $97, $A2, $00, $20, $C2, $00 +$F0, $03, $20, $E3, $D4, $86, $98, $B1 +$11, $45, $98, $25, $97, $F0, $F8, $60 +$20, $90, $D7, $A5, $B0, $49, $FF, $85 +$B0, $45, $B7, $85, $B8, $A5, $AC, $4C +$C6, $D5, $20, $DF, $D6, $90, $4D, $A9 +$F2, $A0, $E1, $20, $90, $D7, $D0, $10 +$A5, $B7, $85, $B0, $A2, $04, $B5, $B2 +$95, $AB, $CA, $D0, $F9, $86, $B9, $60 +$A6, $B9, $86, $A3, $A2, $B3, $A5, $B3 +$A8, $F0, $C4, $38, $E5, $AC, $F0, $24 +$90, $12, $84, $AC, $A4, $B7, $84, $B0 +$49, $FF, $69, $00, $A0, $00, $84, $A3 +$A2, $AC, $D0, $04, $A0, $00, $84, $B9 +$C9, $F9, $30, $B6, $A8, $A5, $B9, $56 +$01, $20, $F6, $D6, $24, $B8, $10, $4C +$A0, $AC, $E0, $B3, $F0, $02, $A0, $B3 +$38, $49, $FF, $65, $A3, $85, $B9, $B9 +$03, $00, $F5, $03, $85, $AF, $B9, $02 +$00, $F5, $02, $85, $AE, $B9, $01, $00 +$F5, $01, $85, $AD, $B0, $03, $20, $9B +$D6, $A0, $00, $98, $18, $A6, $AD, $D0 +$3E, $A6, $AE, $86, $AD, $A6, $AF, $86 +$AE, $A6, $B9, $86, $AF, $84, $B9, $69 +$08, $C9, $18, $D0, $E8, $A9, $00, $85 +$AC, $85, $B0, $60, $65, $A3, $85, $B9 +$A5, $AF, $65, $B6, $85, $AF, $A5, $AE +$65, $B5, $85, $AE, $A5, $AD, $65, $B4 +$85, $AD, $B0, $1A, $60, $69, $01, $06 +$B9, $26, $AF, $26, $AE, $26, $AD, $10 +$F4, $38, $E5, $AC, $B0, $CF, $49, $FF +$69, $01, $85, $AC, $90, $0C, $E6, $AC +$F0, $36, $66, $AD, $66, $AE, $66, $AF +$66, $B9, $60, $A5, $B0, $49, $FF, $85 +$B0, $A5, $AD, $49, $FF, $85, $AD, $A5 +$AE, $49, $FF, $85, $AE, $A5, $AF, $49 +$FF, $85, $AF, $A5, $B9, $49, $FF, $85 +$B9, $E6, $B9, $D0, $0A, $E6, $AF, $D0 +$06, $E6, $AE, $D0, $02, $E6, $AD, $60 +$A2, $0A, $4C, $40, $C1, $A2, $74, $B4 +$03, $84, $B9, $B4, $02, $94, $03, $B4 +$01, $94, $02, $A4, $B2, $94, $01, $69 +$08, $30, $EC, $F0, $EA, $E9, $08, $A8 +$A5, $B9, $B0, $12, $16, $01, $90, $02 +$F6, $01, $76, $01, $76, $01, $76, $02 +$76, $03, $6A, $C8, $D0, $EE, $18, $60 +$20, $EE, $D8, $F0, $02, $10, $03, $4C +$2E, $CF, $A5, $AC, $E9, $7F, $48, $A9 +$80, $85, $AC, $A9, $72, $A0, $E1, $20 +$C3, $D5, $A9, $76, $A0, $E1, $20, $06 +$D8, $A9, $E9, $A0, $E1, $20, $A8, $D5 +$A9, $65, $A0, $E1, $20, $56, $DC, $A9 +$7A, $A0, $E1, $20, $C3, $D5, $68, $20 +$4A, $DA, $A9, $7E, $A0, $E1, $20, $90 +$D7, $F0, $4C, $20, $B6, $D7, $A9, $00 +$85, $75, $85, $76, $85, $77, $A5, $B9 +$20, $65, $D7, $A5, $AF, $20, $65, $D7 +$A5, $AE, $20, $65, $D7, $A5, $AD, $20 +$6A, $D7, $4C, $73, $D8, $D0, $03, $4C +$CD, $D6, $4A, $09, $80, $A8, $90, $13 +$18, $A5, $77, $65, $B6, $85, $77, $A5 +$76, $65, $B5, $85, $76, $A5, $75, $65 +$B4, $85, $75, $66, $75, $66, $76, $66 +$77, $66, $B9, $98, $4A, $D0, $DE, $60 +$85, $71, $84, $72, $A0, $03, $B1, $71 +$85, $B6, $88, $B1, $71, $85, $B5, $88 +$B1, $71, $85, $B7, $45, $B0, $85, $B8 +$A5, $B7, $09, $80, $85, $B4, $88, $B1 +$71, $85, $B3, $A5, $AC, $60, $A5, $B3 +$F0, $1D, $18, $65, $AC, $90, $04, $30 +$31, $18, $2C, $10, $12, $69, $80, $85 +$AC, $D0, $03, $4C, $59, $D6, $A5, $B8 +$85, $B0, $60, $A5, $B0, $10, $1B, $68 +$68, $4C, $55, $D6, $20, $CF, $D8, $AA +$F0, $F0, $18, $69, $02, $B0, $0B, $A2 +$00, $86, $B8, $20, $E0, $D5, $E6, $AC +$D0, $E0, $4C, $C8, $D6, $20, $CF, $D8 +$A9, $FA, $A0, $E1, $A2, $00, $86, $B8 +$20, $82, $D8, $4C, $09, $D8, $20, $90 +$D7, $F0, $63, $20, $DE, $D8, $A9, $00 +$38, $E5, $AC, $85, $AC, $20, $B6, $D7 +$E6, $AC, $F0, $D6, $A2, $FF, $A9, $01 +$A4, $B4, $C4, $AD, $D0, $0A, $A4, $B5 +$C4, $AE, $D0, $04, $A4, $B6, $C4, $AF +$08, $2A, $90, $0E, $A0, $01, $E8, $E0 +$02, $30, $04, $D0, $28, $A0, $40, $95 +$75, $98, $28, $90, $14, $A8, $A5, $B6 +$E5, $AF, $85, $B6, $A5, $B5, $E5, $AE +$85, $B5, $A5, $B4, $E5, $AD, $85, $B4 +$98, $06, $B6, $26, $B5, $26, $B4, $B0 +$CF, $30, $BD, $10, $CB, $4A, $6A, $6A +$85, $B9, $28, $4C, $73, $D8, $A2, $14 +$4C, $40, $C1, $A5, $75, $85, $AD, $A5 +$76, $85, $AE, $A5, $77, $85, $AF, $4C +$39, $D6, $85, $71, $84, $72, $A0, $03 +$B1, $71, $85, $AF, $88, $B1, $71, $85 +$AE, $88, $B1, $71, $85, $B0, $09, $80 +$85, $AD, $88, $B1, $71, $85, $AC, $84 +$B9, $60, $A2, $A4, $A0, $00, $F0, $04 +$A6, $97, $A4, $98, $20, $DE, $D8, $86 +$71, $84, $72, $A0, $03, $A5, $AF, $91 +$71, $88, $A5, $AE, $91, $71, $88, $A5 +$B0, $09, $7F, $25, $AD, $91, $71, $88 +$A5, $AC, $91, $71, $84, $B9, $60, $20 +$DE, $D8, $A2, $05, $B5, $AB, $95, $B2 +$CA, $D0, $F9, $86, $B9, $60, $A5, $AC +$F0, $FB, $06, $B9, $90, $F7, $20, $BD +$D6, $D0, $F2, $4C, $8E, $D6, $A5, $AC +$F0, $09, $A5, $B0, $2A, $A9, $FF, $B0 +$02, $A9, $01, $60, $20, $EE, $D8, $85 +$AD, $A9, $00, $85, $AE, $A2, $88, $A5 +$AD, $49, $FF, $2A, $A9, $00, $85, $AF +$86, $AC, $85, $B9, $85, $B0, $4C, $34 +$D6, $46, $B0, $60, $85, $73, $84, $74 +$A0, $00, $B1, $73, $C8, $AA, $F0, $C6 +$B1, $73, $45, $B0, $30, $C4, $E4, $AC +$D0, $1A, $B1, $73, $09, $80, $C5, $AD +$D0, $12, $C8, $B1, $73, $C5, $AE, $D0 +$0B, $C8, $A9, $7F, $C5, $B9, $B1, $73 +$E5, $AF, $F0, $28, $A5, $B0, $90, $02 +$49, $FF, $4C, $F4, $D8, $A5, $AC, $F0 +$4A, $38, $E9, $98, $24, $B0, $10, $09 +$AA, $A9, $FF, $85, $B2, $20, $A1, $D6 +$8A, $A2, $AC, $C9, $F9, $10, $06, $20 +$DF, $D6, $84, $B2, $60, $A8, $A5, $B0 +$29, $80, $46, $AD, $05, $AD, $85, $AD +$20, $F6, $D6, $84, $B2, $60, $A5, $AC +$C9, $98, $B0, $1E, $20, $55, $D9, $84 +$B9, $A5, $B0, $84, $B0, $49, $80, $2A +$A9, $98, $85, $AC, $A5, $AF, $85, $5B +$4C, $34, $D6, $85, $AD, $85, $AE, $85 +$AF, $A8, $60, $A0, $00, $84, $5F, $A2 +$09, $94, $A8, $CA, $10, $FB, $90, $7F +$C9, $2D, $D0, $04, $86, $B1, $F0, $04 +$C9, $2B, $D0, $05, $20, $BC, $00, $90 +$6E, $C9, $24, $D0, $03, $4C, $73, $DE +$C9, $25, $D0, $08, $4C, $A1, $DE, $20 +$BC, $00, $90, $5B, $C9, $2E, $F0, $2E +$C9, $45, $D0, $30, $20, $BC, $00, $90 +$17, $C9, $B7, $F0, $0E, $C9, $2D, $F0 +$0A, $C9, $B6, $F0, $08, $C9, $2B, $F0 +$04, $D0, $07, $66, $AB, $20, $BC, $00 +$90, $5B, $24, $AB, $10, $0E, $A9, $00 +$38, $E5, $A9, $4C, $16, $DA, $66, $AA +$24, $AA, $50, $C3, $A5, $A9, $38, $E5 +$A8, $85, $A9, $F0, $12, $10, $09, $20 +$F5, $D7, $E6, $A9, $D0, $F9, $F0, $07 +$20, $DC, $D7, $C6, $A9, $D0, $F9, $A5 +$B1, $30, $01, $60, $4C, $F9, $DB, $48 +$24, $AA, $10, $02, $E6, $A8, $20, $DC +$D7, $68, $29, $0F, $20, $4A, $DA, $4C +$D7, $D9, $48, $20, $CF, $D8, $68, $20 +$FF, $D8, $A5, $B7, $45, $B0, $85, $B8 +$A6, $AC, $4C, $C6, $D5, $A5, $A9, $C9 +$0A, $90, $09, $A9, $64, $24, $AB, $30 +$0E, $4C, $C8, $D6, $0A, $0A, $65, $A9 +$0A, $A0, $00, $71, $C3, $E9, $2F, $85 +$A9, $4C, $FD, $D9, $A9, $F6, $A0, $E7 +$20, $D8, $C8, $A5, $88, $A6, $87, $85 +$AD, $86, $AE, $A2, $90, $38, $20, $0C +$D9, $A0, $00, $98, $20, $A7, $DA, $4C +$D8, $C8, $A0, $01, $A9, $20, $24, $B0 +$10, $02, $A9, $2D, $99, $EF, $00, $85 +$B0, $84, $BA, $C8, $A6, $AC, $D0, $05 +$A9, $30, $4C, $B3, $DB, $A9, $00, $E0 +$81, $B0, $09, $A9, $8A, $A0, $E1, $20 +$3E, $D7, $A9, $FA, $85, $A8, $A9, $86 +$A0, $E1, $20, $1C, $D9, $F0, $1E, $10 +$12, $A9, $82, $A0, $E1, $20, $1C, $D9 +$F0, $02, $10, $0E, $20, $DC, $D7, $C6 +$A8, $D0, $EE, $20, $F5, $D7, $E6, $A8 +$D0, $DC, $20, $BF, $D5, $20, $55, $D9 +$A2, $01, $A5, $A8, $18, $69, $07, $30 +$09, $C9, $08, $B0, $06, $69, $FF, $AA +$A9, $02, $38, $E9, $02, $85, $A9, $86 +$A8, $8A, $F0, $02, $10, $13, $A4, $BA +$A9, $2E, $C8, $99, $EF, $00, $8A, $F0 +$06, $A9, $30, $C8, $99, $EF, $00, $84 +$BA, $A0, $00, $A2, $80, $A5, $AF, $18 +$79, $00, $E2, $85, $AF, $A5, $AE, $79 +$FF, $E1, $85, $AE, $A5, $AD, $79, $FE +$E1, $85, $AD, $E8, $B0, $04, $10, $E5 +$30, $02, $30, $E1, $8A, $90, $04, $49 +$FF, $69, $0A, $69, $2F, $C8, $C8, $C8 +$84, $95, $A4, $BA, $C8, $AA, $29, $7F +$99, $EF, $00, $C6, $A8, $D0, $06, $A9 +$2E, $C8, $99, $EF, $00, $84, $BA, $A4 +$95, $8A, $49, $FF, $29, $80, $AA, $C0 +$12, $D0, $B2, $A4, $BA, $B9, $EF, $00 +$88, $C9, $30, $F0, $F8, $C9, $2E, $F0 +$01, $C8, $A9, $2B, $A6, $A9, $F0, $2E +$10, $08, $A9, $00, $38, $E5, $A9, $AA +$A9, $2D, $99, $F1, $00, $A9, $45, $99 +$F0, $00, $8A, $A2, $2F, $38, $E8, $E9 +$0A, $B0, $FB, $69, $3A, $99, $F3, $00 +$8A, $99, $F2, $00, $A9, $00, $99, $F4 +$00, $F0, $08, $99, $EF, $00, $A9, $00 +$99, $F0, $00, $A9, $F0, $A0, $00, $60 +$F0, $42, $A5, $B3, $D0, $03, $4C, $57 +$D6, $A2, $9C, $A0, $00, $20, $AC, $D8 +$A5, $B7, $10, $0F, $20, $86, $D9, $A9 +$9C, $A0, $00, $20, $1C, $D9, $D0, $03 +$98, $A4, $5B, $20, $CA, $D5, $98, $48 +$20, $00, $D7, $A9, $9C, $A0, $00, $20 +$3E, $D7, $20, $04, $DC, $68, $4A, $90 +$0A, $A5, $AC, $F0, $06, $A5, $B0, $49 +$FF, $85, $B0, $60, $A9, $8E, $A0, $E1 +$20, $3E, $D7, $A5, $B9, $69, $50, $90 +$03, $20, $E6, $D8, $85, $A3, $20, $D2 +$D8, $A5, $AC, $C9, $88, $90, $03, $20 +$D3, $D7, $20, $86, $D9, $A5, $5B, $18 +$69, $81, $F0, $F3, $38, $E9, $01, $48 +$A2, $04, $B5, $B3, $B4, $AC, $95, $AC +$94, $B3, $CA, $10, $F5, $A5, $A3, $85 +$B9, $20, $AB, $D5, $20, $F9, $DB, $A9 +$92, $A0, $E1, $20, $6C, $DC, $A9, $00 +$85, $B8, $68, $4C, $B8, $D7, $85, $BA +$84, $BB, $20, $A2, $D8, $A9, $A4, $20 +$3E, $D7, $20, $70, $DC, $A9, $A4, $A0 +$00, $4C, $3E, $D7, $85, $BA, $84, $BB +$A2, $A8, $20, $A4, $D8, $B1, $BA, $85 +$B1, $A4, $BA, $C8, $98, $D0, $02, $E6 +$BB, $85, $BA, $A4, $BB, $20, $3E, $D7 +$A5, $BA, $A4, $BB, $18, $69, $04, $90 +$01, $C8, $85, $BA, $84, $BB, $20, $C3 +$D5, $A9, $A8, $A0, $00, $C6, $B1, $D0 +$E4, $60, $A5, $AC, $F0, $07, $A2, $D8 +$A0, $00, $20, $AC, $D8, $A2, $AF, $A0 +$13, $06, $D9, $26, $DA, $26, $DB, $26 +$D8, $90, $05, $8A, $45, $D9, $85, $D9 +$88, $D0, $EE, $A2, $02, $B5, $D9, $95 +$AD, $CA, $10, $F9, $A9, $80, $85, $AC +$0A, $85, $B0, $4C, $39, $D6, $A9, $AF +$A0, $E1, $20, $C3, $D5, $20, $CF, $D8 +$A9, $C4, $A0, $E1, $A6, $B7, $20, $FE +$D7, $20, $CF, $D8, $20, $86, $D9, $A9 +$00, $85, $B8, $20, $AB, $D5, $A9, $F6 +$A0, $E1, $20, $A8, $D5, $A5, $B0, $48 +$10, $0D, $20, $BF, $D5, $A5, $B0, $30 +$09, $A5, $63, $49, $FF, $85, $63, $20 +$F9, $DB, $A9, $F6, $A0, $E1, $20, $C3 +$D5, $68, $10, $03, $20, $F9, $DB, $A9 +$B3, $A0, $E1, $4C, $56, $DC, $20, $A2 +$D8, $A9, $00, $85, $63, $20, $DD, $DC +$A2, $9C, $A0, $00, $20, $AC, $D8, $A9 +$A4, $A0, $00, $20, $82, $D8, $A9, $00 +$85, $B0, $A5, $63, $20, $4E, $DD, $A9 +$9C, $A0, $00, $4C, $06, $D8, $48, $4C +$0F, $DD, $20, $0A, $00, $4C, $F4, $CB +$A5, $B0, $48, $10, $03, $20, $F9, $DB +$A5, $AC, $48, $C9, $81, $90, $07, $A9 +$E9, $A0, $E1, $20, $06, $D8, $A9, $C8 +$A0, $E1, $20, $56, $DC, $68, $C9, $81 +$90, $07, $A9, $AF, $A0, $E1, $20, $A8 +$D5, $68, $10, $16, $4C, $F9, $DB, $20 +$DD, $D4, $E0, $08, $B0, $20, $A9, $00 +$38, $2A, $CA, $10, $FC, $E8, $01, $11 +$81, $11, $60, $20, $DD, $D4, $E0, $08 +$B0, $0C, $A9, $FF, $2A, $CA, $10, $FC +$E8, $21, $11, $81, $11, $60, $4C, $2E +$CF, $20, $BC, $00, $20, $DD, $D4, $E0 +$08, $B0, $F3, $20, $C2, $00, $C9, $29 +$F0, $03, $4C, $07, $CC, $20, $BC, $00 +$A9, $00, $38, $2A, $CA, $10, $FC, $E8 +$21, $11, $F0, $02, $A9, $FF, $4C, $FF +$D8, $E0, $19, $B0, $48, $86, $78, $A9 +$18, $20, $3F, $D1, $A0, $17, $A2, $18 +$46, $11, $66, $12, $66, $13, $8A, $2A +$91, $AD, $88, $10, $F3, $A5, $78, $F0 +$0A, $AA, $38, $49, $FF, $69, $18, $F0 +$1C, $D0, $0F, $A8, $B1, $AD, $C9, $30 +$D0, $07, $CA, $F0, $03, $C8, $10, $F4 +$E8, $98, $18, $65, $AD, $85, $AD, $A9 +$00, $65, $AE, $85, $AE, $86, $AC, $20 +$BC, $00, $4C, $8A, $D1, $4C, $2E, $CF +$E0, $07, $B0, $F9, $86, $78, $A9, $06 +$20, $3F, $D1, $A0, $05, $F8, $A5, $13 +$20, $56, $DE, $A5, $12, $20, $56, $DE +$A5, $11, $20, $56, $DE, $D8, $A2, $06 +$A5, $78, $F0, $B7, $AA, $38, $49, $FF +$69, $06, $F0, $C9, $D0, $BC, $AA, $29 +$0F, $20, $61, $DE, $8A, $4A, $4A, $4A +$4A, $C9, $0A, $69, $30, $91, $AD, $88 +$60, $85, $AC, $A9, $00, $85, $B8, $8A +$20, $4A, $DA, $20, $BC, $00, $90, $0A +$09, $20, $E9, $61, $C9, $06, $B0, $2A +$69, $0A, $29, $0F, $AA, $A5, $AC, $F0 +$E4, $69, $04, $90, $DC, $4C, $C8, $D6 +$AA, $A5, $AC, $F0, $06, $E6, $AC, $F0 +$F4, $A9, $00, $85, $B8, $8A, $20, $4A +$DA, $20, $BC, $00, $49, $30, $C9, $02 +$90, $E6, $4C, $2F, $DA, $AD, $00, $02 +$D0, $18, $20, $EF, $E0, $90, $0B, $8D +$01, $02, $A2, $20, $8E, $02, $02, $4C +$1C, $C5, $AE, $02, $02, $F0, $03, $CE +$02, $02, $A2, $DC, $20, $D5, $DE, $A2 +$DF, $20, $D5, $DE, $60, $B5, $00, $10 +$FB, $0A, $29, $40, $F0, $F6, $95, $00 +$8A, $A8, $68, $68, $A9, $05, $20, $07 +$C1, $A5, $C4, $48, $A5, $C3, $48, $A5 +$88, $48, $A5, $87, $48, $A9, $8D, $48 +$B9, $01, $00, $85, $C3, $B9, $02, $00 +$85, $C4, $4C, $C1, $C4, $20, $EF, $E0 +$B0, $09, $AD, $02, $02, $F0, $09, $AD +$01, $02, $38, $A2, $00, $8E, $02, $02 +$60, $A2, $DF, $2C, $A2, $DC, $C9, $93 +$F0, $11, $C9, $B5, $F0, $07, $49, $A2 +$F0, $0E, $4C, $07, $CC, $A9, $7F, $35 +$00, $10, $05, $B5, $00, $0A, $15, $00 +$95, $00, $4C, $BC, $00, $58, $A2, $DF +$2C, $A2, $DC, $86, $78, $20, $BC, $00 +$20, $5A, $C7, $A5, $79, $A6, $7A, $20 +$2D, $C3, $B0, $03, $4C, $77, $C6, $A6 +$78, $A5, $AA, $E9, $01, $95, $01, $A5 +$AB, $E9, $00, $95, $02, $A9, $C0, $95 +$00, $60, $D0, $FD, $A5, $DF, $0A, $05 +$DF, $85, $DF, $4C, $7E, $C6, $D0, $F1 +$A5, $DC, $0A, $05, $DC, $85, $DC, $4C +$7E, $C6, $20, $EE, $CA, $4C, $D5, $CA +$20, $B6, $DF, $10, $FB, $A5, $B4, $09 +$80, $85, $B4, $20, $C8, $D5, $F0, $F0 +$20, $B6, $DF, $30, $FB, $F0, $F9, $A5 +$B4, $09, $80, $85, $B4, $20, $C8, $D5 +$F0, $EE, $C9, $29, $D0, $05, $68, $68 +$4C, $BC, $00, $4C, $07, $CC, $20, $C2 +$00, $C9, $2C, $D0, $ED, $20, $DE, $D8 +$A5, $B0, $09, $7F, $25, $AD, $48, $A5 +$AE, $48, $A5, $AF, $48, $A5, $AC, $48 +$20, $BC, $00, $20, $D2, $CA, $68, $85 +$B3, $68, $85, $B6, $68, $85, $B5, $68 +$85, $B4, $85, $B7, $A9, $B3, $A0, $00 +$4C, $1C, $D9, $C9, $2C, $F0, $1B, $20 +$91, $D4, $8A, $F0, $0A, $E0, $10, $90 +$45, $E4, $64, $B0, $02, $86, $64, $86 +$0F, $20, $C2, $00, $F0, $1A, $C9, $2C +$D0, $A9, $20, $8E, $D4, $8A, $30, $2E +$E0, $01, $90, $2A, $A5, $0F, $F0, $06 +$E4, $0F, $F0, $02, $B0, $20, $86, $64 +$A5, $0F, $F0, $06, $C5, $64, $B0, $03 +$85, $64, $38, $E5, $64, $B0, $FC, $65 +$64, $18, $65, $64, $85, $10, $A5, $0F +$38, $E5, $10, $85, $10, $60, $4C, $2E +$CF, $A5, $B0, $30, $F9, $A5, $AC, $F0 +$F4, $20, $CF, $D8, $A9, $00, $85, $77 +$85, $76, $85, $75, $85, $78, $85, $AF +$85, $AE, $85, $AD, $A2, $18, $A5, $B3 +$4A, $B0, $0E, $06, $B6, $26, $B5, $26 +$B4, $26, $77, $26, $76, $26, $75, $26 +$78, $06, $B6, $26, $B5, $26, $B4, $26 +$77, $26, $76, $26, $75, $26, $78, $06 +$AF, $26, $AE, $26, $AD, $A5, $AF, $2A +$85, $5B, $A5, $AE, $2A, $85, $5C, $A5 +$AD, $2A, $85, $5D, $A9, $00, $2A, $85 +$5E, $A5, $77, $E5, $5B, $85, $5B, $A5 +$76, $E5, $5C, $85, $5C, $A5, $75, $E5 +$5D, $A8, $A5, $78, $E5, $5E, $90, $0E +$85, $78, $84, $75, $A5, $5C, $85, $76 +$A5, $5B, $85, $77, $E6, $AF, $CA, $D0 +$A2, $38, $A5, $B3, $E9, $80, $6A, $69 +$00, $85, $AC, $4C, $39, $D6, $20, $BC +$00, $20, $AF, $CD, $20, $F4, $CB, $A4 +$95, $A5, $96, $4C, $5E, $D0, $A9, $C4 +$A0, $E1, $20, $82, $D8, $C6, $AC, $60 +$A9, $C4, $A0, $E1, $4C, $82, $D8, $6C +$05, $02, $6C, $07, $02, $6C, $09, $02 +$6C, $0B, $02, $FF, $00, $00, $AD, $DE +$C0, $FF, $D3, $FF, $E6, $C3, $D0, $02 +$E6, $C4, $AD, $FF, $FF, $C9, $AC, $F0 +$0E, $C9, $3A, $B0, $0A, $C9, $20, $F0 +$EB, $38, $E9, $30, $38, $E9, $D0, $60 +$4C, $00, $C0, $00, $00, $00, $00, $00 +$00, $00, $4C, $2E, $CF, $00, $00, $00 +$F2, $00, $03, $0D, $0A, $4D, $65, $6D +$6F, $72, $79, $20, $73, $69, $7A, $65 +$20, $00, $20, $42, $79, $74, $65, $73 +$20, $66, $72, $65, $65, $0D, $0A, $0A +$45, $6E, $68, $61, $6E, $63, $65, $64 +$20, $42, $41, $53, $49, $43, $20, $32 +$2E, $32, $32, $0A, $00, $02, $80, $19 +$56, $62, $80, $76, $22, $F3, $82, $38 +$AA, $40, $80, $35, $04, $F3, $81, $35 +$04, $F3, $80, $80, $00, $00, $80, $31 +$72, $18, $91, $43, $4F, $F8, $94, $74 +$23, $F7, $94, $74, $24, $00, $81, $38 +$AA, $3B, $06, $74, $63, $90, $8C, $77 +$23, $0C, $AB, $7A, $1E, $94, $00, $7C +$63, $42, $80, $7E, $75, $FE, $D0, $80 +$31, $72, $15, $81, $00, $00, $00, $81 +$49, $0F, $DB, $04, $86, $1E, $D7, $FB +$87, $99, $26, $65, $87, $23, $34, $58 +$86, $A5, $5D, $E1, $83, $49, $0F, $DB +$08, $78, $3A, $C5, $37, $7B, $83, $A2 +$5C, $7C, $2E, $DD, $4D, $7D, $99, $B0 +$1E, $7D, $59, $ED, $24, $7E, $91, $72 +$00, $7E, $4C, $B9, $73, $7F, $AA, $AA +$53, $81, $00, $00, $00, $81, $80, $00 +$00, $90, $80, $00, $00, $00, $7F, $00 +$00, $00, $84, $20, $00, $00, $FE, $79 +$60, $00, $27, $10, $FF, $FC, $18, $00 +$00, $64, $FF, $FF, $F6, $00, $00, $01 +$1F, $C5, $5C, $C4, $69, $CA, $90, $C6 +$4B, $C9, $63, $CD, $6B, $C9, $B8, $C7 +$8A, $C7, $EF, $C5, $AE, $C5, $BE, $C6 +$46, $C5, $D2, $C5, $69, $DF, $75, $DF +$7B, $C6, $22, $C7, $1D, $C5, $2B, $C7 +$84, $C5, $8D, $C7, $8D, $D5, $F4, $E0 +$F7, $E0, $78, $D0, $12, $D5, $2E, $D5 +$7B, $D5, $B8, $C5, $21, $C6, $59, $C8 +$8A, $C5, $A7, $C3, $A4, $C3, $52, $C3 +$EA, $DF, $28, $C8, $53, $D5, $86, $DD +$9A, $DD, $18, $DF, $1B, $DF, $69, $CC +$69, $CC, $69, $CC, $ED, $CA, $F0, $CB +$F0, $CB, $69, $CC, $69, $CC, $69, $CC +$69, $CC, $69, $CC, $69, $CC, $69, $CC +$69, $CC, $69, $CC, $69, $CC, $00, $00 +$63, $CC, $69, $CC, $63, $CC, $63, $CC +$63, $CC, $63, $CC, $69, $CC, $90, $CC +$90, $CC, $00, $00, $81, $DF, $81, $DF +$6F, $CC, $6F, $CC, $00, $00, $74, $CC +$74, $CC, $74, $CC, $FB, $D8, $85, $D9 +$18, $D9, $51, $DD, $49, $D0, $68, $D0 +$40, $E0, $A1, $DC, $FF, $D6, $03, $DC +$D5, $DC, $DC, $DC, $25, $DD, $57, $DD +$07, $D5, $1B, $D5, $59, $D4, $72, $D4 +$2A, $D1, $9F, $D4, $7D, $D4, $37, $D4 +$16, $D4, $88, $D3, $27, $DE, $D8, $DD +$B0, $DD, $87, $DF, $97, $DF, $DD, $E0 +$E7, $E0, $CD, $E0, $9A, $D3, $A3, $D3 +$D2, $D3, $79, $C5, $D5, $79, $AA, $D5 +$7B, $40, $D7, $7B, $08, $D8, $7F, $BF +$DB, $50, $D9, $CC, $46, $BF, $CC, $46 +$CC, $CC, $56, $85, $CD, $56, $6D, $CD +$7D, $F8, $DB, $5A, $1B, $CC, $64, $FA +$CC, $2A, $2B, $2D, $2F, $3C, $3D, $3E +$3F, $41, $42, $43, $44, $45, $46, $47 +$48, $49, $4C, $4D, $4E, $4F, $50, $52 +$53, $54, $55, $56, $57, $5E, $00, $71 +$E3, $73, $E3, $75, $E3, $77, $E3, $79 +$E3, $7D, $E3, $7F, $E3, $83, $E3, $85 +$E3, $95, $E3, $AE, $E3, $C5, $E3, $DE +$E3, $ED, $E3, $F7, $E3, $04, $E4, $0A +$E4, $1C, $E4, $41, $E4, $4F, $E4, $61 +$E4, $69, $E4, $7E, $E4, $AD, $E4, $D8 +$E4, $EC, $E4, $FD, $E4, $09, $E5, $18 +$E5, $B8, $00, $B6, $00, $B7, $00, $B9 +$00, $3C, $BF, $C2, $00, $C1, $00, $3E +$BE, $C0, $00, $9F, $00, $42, $53, $28 +$C5, $4E, $44, $BB, $53, $43, $28, $D7 +$54, $4E, $28, $D0, $00, $49, $4E, $24 +$28, $DC, $49, $54, $43, $4C, $52, $A8 +$49, $54, $53, $45, $54, $A7, $49, $54 +$54, $53, $54, $28, $DD, $00, $41, $4C +$4C, $9C, $48, $52, $24, $28, $DA, $4C +$45, $41, $52, $A2, $4F, $4E, $54, $A0 +$4F, $53, $28, $CD, $00, $41, $54, $41 +$83, $45, $43, $88, $45, $45, $4B, $28 +$D2, $45, $46, $99, $49, $4D, $85, $4F +$4B, $45, $9B, $4F, $9D, $00, $4C, $53 +$45, $AC, $4E, $44, $80, $4F, $52, $BC +$58, $50, $28, $CC, $00, $4E, $AE, $4F +$52, $81, $52, $45, $28, $C7, $00, $45 +$54, $A5, $4F, $53, $55, $42, $8D, $4F +$54, $4F, $89, $00, $45, $58, $24, $28 +$DB, $00, $46, $8B, $4E, $43, $95, $4E +$50, $55, $54, $84, $4E, $54, $28, $C4 +$52, $51, $A9, $00, $43, $41, $53, $45 +$24, $28, $D9, $45, $46, $54, $24, $28 +$E3, $45, $4E, $28, $D4, $45, $54, $87 +$49, $53, $54, $A1, $4F, $41, $44, $97 +$4F, $47, $28, $CB, $4F, $4F, $50, $9E +$00, $41, $58, $28, $DE, $49, $44, $24 +$28, $E5, $49, $4E, $28, $DF, $00, $45 +$57, $A3, $45, $58, $54, $82, $4D, $49 +$AA, $4F, $54, $B1, $55, $4C, $4C, $94 +$00, $46, $46, $B5, $4E, $93, $52, $BD +$00, $45, $45, $4B, $28, $D1, $49, $E0 +$4F, $4B, $45, $9A, $4F, $53, $28, $C8 +$52, $49, $4E, $54, $9F, $00, $45, $41 +$44, $86, $45, $4D, $91, $45, $53, $54 +$4F, $52, $45, $8C, $45, $54, $49, $52 +$51, $8E, $45, $54, $4E, $4D, $49, $8F +$45, $54, $55, $52, $4E, $90, $49, $47 +$48, $54, $24, $28, $E4, $4E, $44, $28 +$CA, $55, $4E, $8A, $00, $41, $44, $44 +$28, $D3, $41, $56, $45, $98, $47, $4E +$28, $C3, $49, $4E, $28, $CE, $50, $43 +$28, $AF, $51, $52, $28, $C9, $54, $45 +$50, $B2, $54, $4F, $50, $92, $54, $52 +$24, $28, $D5, $57, $41, $50, $A6, $00 +$41, $42, $28, $AB, $41, $4E, $28, $CF +$48, $45, $4E, $B0, $4F, $AD, $57, $4F +$50, $49, $E1, $00, $43, $41, $53, $45 +$24, $28, $D8, $4E, $54, $49, $4C, $B3 +$53, $52, $28, $C6, $00, $41, $4C, $28 +$D6, $41, $52, $50, $54, $52, $28, $E2 +$00, $41, $49, $54, $96, $48, $49, $4C +$45, $B4, $49, $44, $54, $48, $A4, $00 +$BA, $00, $03, $45, $E2, $E3, $03, $46 +$EF, $E3, $04, $4E, $52, $E4, $04, $44 +$C5, $E3, $05, $49, $0F, $E4, $03, $44 +$D4, $E3, $04, $52, $7E, $E4, $03, $4C +$2D, $E4, $03, $44, $C9, $E3, $04, $47 +$FF, $E3, $03, $52, $A9, $E4, $02, $49 +$0A, $E4, $07, $52, $85, $E4, $05, $47 +$FA, $E3, $06, $52, $8C, $E4, $06, $52 +$92, $E4, $06, $52, $98, $E4, $03, $52 +$82, $E4, $04, $53, $CA, $E4, $02, $4F +$64, $E4, $04, $4E, $5C, $E4, $03, $49 +$0C, $E4, $04, $57, $09, $E5, $04, $4C +$34, $E4, $04, $53, $B2, $E4, $03, $44 +$D1, $E3, $04, $50, $70, $E4, $04, $44 +$D7, $E3, $04, $43, $AE, $E3, $02, $44 +$DB, $E3, $04, $4C, $3C, $E4, $05, $50 +$78, $E4, $04, $43, $BC, $E3, $04, $4C +$30, $E4, $05, $43, $B7, $E3, $03, $4E +$4F, $E4, $05, $57, $12, $E5, $03, $47 +$F7, $E3, $04, $53, $D3, $E4, $06, $42 +$A0, $E3, $06, $42, $9A, $E3, $03, $49 +$18, $E4, $03, $4E, $56, $E4, $04, $54 +$D8, $E4, $04, $45, $DE, $E3, $02, $54 +$E4, $E4, $02, $46, $ED, $E3, $04, $53 +$BE, $E4, $04, $54, $E0, $E4, $03, $4E +$59, $E4, $04, $53, $C6, $E4, $05, $55 +$F3, $E4, $05, $57, $0D, $E5, $03, $4F +$61, $E4, $01, $2B, $00, $00, $01, $2D +$00, $00, $01, $2A, $00, $00, $01, $2F +$00, $00, $01, $5E, $00, $00, $03, $41 +$89, $E3, $03, $45, $E5, $E3, $02, $4F +$66, $E4, $02, $3E, $7F, $E3, $02, $3C +$79, $E3, $01, $3E, $00, $00, $01, $3D +$00, $00, $01, $3C, $00, $00, $04, $53 +$B6, $E4, $04, $49, $14, $E4, $04, $41 +$85, $E3, $04, $55, $F8, $E4, $04, $46 +$F2, $E3, $04, $50, $74, $E4, $04, $53 +$C2, $E4, $04, $52, $A5, $E4, $04, $4C +$38, $E4, $04, $45, $E8, $E3, $04, $43 +$C0, $E3, $04, $53, $BA, $E4, $04, $54 +$DC, $E4, $04, $41, $90, $E3, $05, $50 +$69, $E4, $05, $44, $CC, $E3, $05, $53 +$AD, $E4, $04, $4C, $29, $E4, $05, $53 +$CE, $E4, $04, $56, $FD, $E4, $04, $41 +$8C, $E3, $07, $55, $EC, $E4, $07, $4C +$1C, $E4, $05, $43, $B2, $E3, $05, $48 +$04, $E4, $05, $42, $95, $E3, $07, $42 +$A6, $E3, $04, $4D, $41, $E4, $04, $4D +$4A, $E4, $02, $50, $6E, $E4, $05, $54 +$E6, $E4, $07, $56, $01, $E5, $06, $4C +$23, $E4, $07, $52, $9E, $E4, $05, $4D +$45, $E4, $D6, $E6, $E7, $E6, $EE, $E6 +$03, $E7, $0F, $E7, $1D, $E7, $26, $E7 +$34, $E7, $48, $E7, $55, $E7, $66, $E7 +$75, $E7, $84, $E7, $92, $E7, $A2, $E7 +$B5, $E7, $C4, $E7, $D7, $E7, $4E, $45 +$58, $54, $20, $77, $69, $74, $68, $6F +$75, $74, $20, $46, $4F, $52, $00, $53 +$79, $6E, $74, $61, $78, $00, $52, $45 +$54, $55, $52, $4E, $20, $77, $69, $74 +$68, $6F, $75, $74, $20, $47, $4F, $53 +$55, $42, $00, $4F, $75, $74, $20, $6F +$66, $20, $44, $41, $54, $41, $00, $46 +$75, $6E, $63, $74, $69, $6F, $6E, $20 +$63, $61, $6C, $6C, $00, $4F, $76, $65 +$72, $66, $6C, $6F, $77, $00, $4F, $75 +$74, $20, $6F, $66, $20, $6D, $65, $6D +$6F, $72, $79, $00, $55, $6E, $64, $65 +$66, $69, $6E, $65, $64, $20, $73, $74 +$61, $74, $65, $6D, $65, $6E, $74, $00 +$41, $72, $72, $61, $79, $20, $62, $6F +$75, $6E, $64, $73, $00, $44, $6F, $75 +$62, $6C, $65, $20, $64, $69, $6D, $65 +$6E, $73, $69, $6F, $6E, $00, $44, $69 +$76, $69, $64, $65, $20, $62, $79, $20 +$7A, $65, $72, $6F, $00, $49, $6C, $6C +$65, $67, $61, $6C, $20, $64, $69, $72 +$65, $63, $74, $00, $54, $79, $70, $65 +$20, $6D, $69, $73, $6D, $61, $74, $63 +$68, $00, $53, $74, $72, $69, $6E, $67 +$20, $74, $6F, $6F, $20, $6C, $6F, $6E +$67, $00, $53, $74, $72, $69, $6E, $67 +$20, $74, $6F, $6F, $20, $63, $6F, $6D +$70, $6C, $65, $78, $00, $43, $61, $6E +$27, $74, $20, $63, $6F, $6E, $74, $69 +$6E, $75, $65, $00, $55, $6E, $64, $65 +$66, $69, $6E, $65, $64, $20, $66, $75 +$6E, $63, $74, $69, $6F, $6E, $00, $4C +$4F, $4F, $50, $20, $77, $69, $74, $68 +$6F, $75, $74, $20, $44, $4F, $00, $0D +$0A, $42, $72, $65, $61, $6B, $00, $20 +$45, $72, $72, $6F, $72, $00, $20, $69 +$6E, $20, $6C, $69, $6E, $65, $20, $00 +$0D, $0A, $52, $65, $61, $64, $79, $0D +$0A, $00, $20, $45, $78, $74, $72, $61 +$20, $69, $67, $6E, $6F, $72, $65, $64 +$0D, $0A, $00, $20, $52, $65, $64, $6F +$20, $66, $72, $6F, $6D, $20, $73, $74 +$61, $72, $74, $0D, $0A, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$AD, $E1, $FF, $F0, $0C, $C9, $61, $90 +$06, $C9, $7B, $B0, $02, $29, $5F, $38 +$60, $18, $60, $8D, $E0, $FF, $29, $FF +$60, $00, $00, $00, $00, $00, $00, $00 diff --git a/hello_world.bas b/hello_world.bas index 00635af..eb77a7f 100644 --- a/hello_world.bas +++ b/hello_world.bas @@ -1,5 +1,5 @@ -10 LET A=1 -20 PR A;") HELLO WORLD FROM MKHBC!" -30 LET A=A+1 -40 IF A=0 THEN END -50 GOTO 20 +10 LET A=0 +20 PR A;") HELLO WORLD FROM MKHBC!" +30 LET A=A+1 +40 IF A>100 THEN END +50 GOTO 20 diff --git a/main.cpp b/main.cpp index 9c5c7ed..01bd0a3 100644 --- a/main.cpp +++ b/main.cpp @@ -1,333 +1,695 @@ -#include -#include -#include -#include "MKCpu.h" -#include "Memory.h" -#include "Display.h" -#include "VMachine.h" -#include "MKGenException.h" - -using namespace std; -using namespace MKBasic; - -/* - *-------------------------------------------------------------------- - * Method: ShowHelp() - * Purpose: Display commands help. - * Arguments: n/a - * Returns: n/a - *-------------------------------------------------------------------- - */ -void ShowHelp() -{ - cout << "Virtual Machine/CPU emulator/Debugger Command Reference." << endl << endl; - cout << "S - step" << endl; - cout << " Executes single opcode at current address." << endl; - cout << "C - continue" << endl; - cout << " Continues code execution from current address until BRK." << endl; - cout << "D - dump memory" << endl; - cout << " Usage: D [startaddr] [endaddr]" << endl; - cout << " Where: startaddr,endaddr - memory addr. in hexadecimal format [0000..FFFF]." << endl; - cout << " Dumps contents of memory, hexadecimal and ASCII formats." << endl; - cout << "G - go/continue from new address until BRK" << endl; - cout << " Usage: G [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]." << endl; - cout << " Executes code at provided address, interrupted by BRK opcode." << endl; - cout << "X - execute code from new address until RTS" << endl; - cout << " Usage: X [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]." << endl; - cout << " Executes code at provided address, until RTS (last one)." << endl; - cout << "Q - quit" << endl; - cout << " Exits from the emulator/debugger." << endl; - cout << "A - set address for next step" << endl; - cout << " Usage: A [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]." << endl; - cout << " Sets current address to a new value." << endl; - cout << "N - go number of steps" << endl; - cout << " Usage: N [steps]" << endl; - cout << " Where: steps - number of steps in decimal format" << endl; - cout << " Execute number of opcodes provided in steps argument starting" << endl; - cout << " from current address." << endl; - cout << "W - write to memory" << endl; - cout << " Usage: W [address] [hexval] [hexval] ... 100" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]," << endl; - cout << " hexval - byte value in hexadecimal format [00.FF]." << endl; - cout << " Writes provided values to memory starting at specified address." << endl; - cout << "I - toggle char I/O emulation" << endl; - cout << " Usage: I [address]" << endl; - cout << " Where: address - memory addr. in hexadecimal format [0000.FFFF]," << endl; - cout << " Toggles basic character I/O emulation. When enabled, all writes" << endl; - cout << " to the specified memory address also writes a character code to" << endl; - cout << " to a virtual console. All reads from specified memory address" << endl; - cout << " are interpreted as console character input." << endl; - cout << "R - regs" << endl; - cout << " Displays CPU registers and flags." << endl; - cout << "T - show I/O console" << endl; - cout << " Displays/prints the contents of the virtual console screen." << endl; - cout << " Note that in run mode (commands X, G or C), virtual screen is" << endl; - cout << " displayed automatically in real-time if I/O emulation is enabled." << endl; - cout << "E - toggle I/O local echo" << endl; - cout << " Toggles local echo on/off when I/O emulation is enabled." << endl; - cout << "B - blank (clear) screen" << endl; - cout << " Clears the screen, useful when after exiting I/O emulation" << endl; - cout << " your screen is messed up." << endl; - cout << "NOTE:" << endl; - cout << " If no arguments provided, each command will prompt user to enter" << endl; - cout << " missing data." << endl; - cout << endl; -} - -/* - *-------------------------------------------------------------------- - * Method: PromptNewAddress() - * Purpose: Prompt user to enter 16-bit address (hex) in console. - * Arguments: prompt - prompt text - * Returns: unsigned int - address entered by user - *-------------------------------------------------------------------- - */ -unsigned int PromptNewAddress(string prompt) -{ - unsigned int newaddr = 0x10000; - - while (newaddr > 0xFFFF) { - cout << prompt; - cin >> hex >> newaddr; - } - - return newaddr; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void ShowRegs(Regs *preg, VMachine *pvm, unsigned short ioaddr, bool ioecho) -{ - cout << "Registers:" << endl; - cout << " Acc: $" << hex << (unsigned short)preg->Acc << "\t(%" << bitset<8>((int)preg->Acc) << ")" << endl; - cout << " X: $" << hex << (unsigned short)preg->IndX << endl; - cout << " Y: $" << hex << (unsigned short)preg->IndY << endl; - cout << " Addr: $" << hex << preg->PtrAddr << endl; - cout << " Acc16: $" << hex << preg->Acc16 << endl; - cout << " Ptr16: $" << hex << preg->Ptr16 << endl; - cout << " Stack: $" << hex << (unsigned short)preg->PtrStack << endl; - cout << " Flags: NV-BDIZC" << endl; - cout << " " << bitset<8>((int)preg->Flags) << endl; - cout << endl << "I/O status: " << (pvm->GetCharIOActive() ? "enabled" : "disabled") << ", "; - cout << " at: $" << hex << ioaddr << ", "; - cout << " local echo: " << (ioecho ? "ON" : "OFF") << "." << endl; - // cout << "-------------------------------------------------------------------------------" << endl; -} - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -void ShowMenu() -{ - cout << "---------------------------------------------------------------------------" << endl; - cout << "S - step | C - continue, D - dump memory | G - go/continue from new address" << endl; - cout << "Q - quit | A - set address for next step | N - go number of steps" << endl; - cout << "H - help | I - toggle char I/O emulation | W - write to memory" << endl; - cout << "R - regs | T - show I/O console | E - toggle I/O local echo" << endl; - cout << " | X - execute from new address | B - blank (clear) screen" << endl; - cout << "---------------------------------------------------------------------------" << endl; -} - - -/* - *-------------------------------------------------------------------- - * Method: - * Purpose: - * Arguments: - * Returns: - *-------------------------------------------------------------------- - */ -#define RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts) \ - brk = preg->SoftIrq; \ - lrts = preg->LastRTS; \ - while(step && nsteps > 1 && !brk && !lrts) { \ - cout << "addr: $" << hex << preg->PtrAddr << ", step: " << dec << stct << "\r"; \ - preg = pvm->Step(); \ - brk = preg->SoftIrq; \ - nsteps--; \ - stct++; \ - } - -/* run this program using the console pauser or add your own getch, system("pause") or input loop */ - -int main(int argc, char** argv) { - string romfile("dummy.rom"), ramfile("dummy.ram"); - if (argc > 1) { - ramfile = argv[1]; - } - try { - cout << endl; - VMachine *pvm = new VMachine(romfile, ramfile); - pvm->ClearScreen(); - cout << "Welcome to Virtual Machine/CPU Emulator (6502)/Debugger." << endl; - cout << "Copyright (C) by Marek Karcz 2016. All rights reserved." << endl; - string cmd; - bool runvm = false, step = false, brk = false, execaddr = false, stop = true; - bool ioecho = false, lrts = false, execvm = false; - unsigned int newaddr = 0x10000, ioaddr = 0xE000, tmpaddr = 0x0000; - int nsteps = 0; - while (true) { - Regs *preg = pvm->GetRegs(); - if (runvm) { - int stct = 1; - if (execaddr) { - preg = ((step) ? pvm->Step(newaddr) : pvm->Run(newaddr)); - RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts); - execaddr = false; - newaddr = 0x10000; - } else { - preg = ((step) ? pvm->Step() : pvm->Run()); - RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts); - } - if (step) - cout << "\rExecuted " << dec << stct << ((stct == 1) ? " step." : " steps.") << " " << endl; - nsteps = 0; - runvm = step = false; - } else if (execvm) { - preg = (execaddr ? pvm->Exec(newaddr) : pvm->Exec()); - execvm = false; - brk = preg->SoftIrq; - lrts = preg->LastRTS; - } - if (brk || stop || lrts) { - cout << endl; - if (brk) { - cout << "BRK at " << hex << preg->PtrAddr << endl; - brk = stop = lrts = false; - } else if (lrts) { - cout << "FINISHED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; - brk = stop = lrts = false; - } else if (stop) { - cout << "STOPPED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; - brk = stop = lrts = false; - } - ShowRegs(preg,pvm,ioaddr,ioecho); - } - ShowMenu(); - cout << "> "; - cin >> cmd; - char c = tolower(cmd.c_str()[0]); - if (c == 'h') { - ShowHelp(); - } else if (c == 'b') { - pvm->ClearScreen(); - } else if (c == 'r') { - stop = true; - } else if (c == 'e') { - if (pvm->GetCharIOActive()) { - ioecho = !ioecho; - cout << "I/O echo is " << (ioecho ? "activated." : "deactivated.") << endl; - pvm->SetCharIO(ioaddr, ioecho); - } else { - cout << "ERROR: I/O is deactivated." << endl; - } - } else if (c == 't') { - if (pvm->GetCharIOActive()) { - pvm->ShowIO(); - } else { - cout << "ERROR: I/O is deactivated." << endl; - } - } else if (c == 'i') { - if (pvm->GetCharIOActive()) { - pvm->DisableCharIO(); - cout << "I/O deactivated." << endl; - } else { - ioaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << ioaddr << "]" << endl; - pvm->SetCharIO(ioaddr, ioecho); - cout << "I/O activated." << endl; - } - } else if (c == 'w') { - tmpaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << tmpaddr << "]" << endl; - cout << "Enter hex bytes [00..FF] values separated with NL or spaces, end with [100]:" << endl; - unsigned short v = 0; - while (true) { - cin >> hex >> v; - cout << " " << hex << v; - if (v > 0xFF) break; - pvm->MemPoke8bit(tmpaddr++, v & 0xFF); - }; - cout << endl; - } else if (c == 'a') { - execaddr = stop = true; - newaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << newaddr << "]" << endl; - } else if (c == 's') { - runvm = step = stop = true; - } else if (c == 'n') { - nsteps = 0; - while (nsteps < 1) { - cout << "# of steps [n>1]: "; - cin >> dec >> nsteps; - } - cout << " [" << dec << nsteps << "]" << endl; - runvm = step = stop = true; - } else if (c == 'c') { - runvm = true; - } else if (c == 'g') { - runvm = true; - execaddr = true; - newaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << newaddr << "]" << endl; - } else if (c == 'x') { - execvm = true; - execaddr = true; - newaddr = PromptNewAddress("Address (0..FFFF): "); - cout << " [" << hex << newaddr << "]" << endl; - } else if (c == 'q') { - break; - } else if (c == 'd') { - unsigned int addrbeg = 0x10000, addrend = 0x10000; - cout << "Enter address range (0..0xFFFF)..." << endl; - addrbeg = PromptNewAddress("Start address (0..FFFF): "); - cout << " [" << hex << addrbeg << "]" << endl; - addrend = PromptNewAddress("End address (0..FFFF): "); - cout << " [" << hex << addrend << "]" << endl; - cout << endl; - for (unsigned int addr = addrbeg; addr <= addrend; addr+=16) { - cout << "\t|"; - for (unsigned int j=0; j < 16; j++) { - unsigned int hv = (unsigned int)pvm->MemPeek8bit(addr+j); - if (hv < 16) { - cout << 0; - } - cout << hex << hv << " "; - } - cout << "|"; - for (int j=0; j < 16; j++) { - char cc = (char)pvm->MemPeek8bit(addr+j); - if (isprint(cc)) - cout << cc; - else - cout << "?"; - } - cout << '\r'; - cout << hex << addr; - cout << endl; - } - } - } - } - catch (MKGenException& ex) { - cout << "ERROR: " << ex.GetCause() << endl; - } - catch (...) { - cout << "ERROR: Fatal." << endl; - } - return 0; -} +#include +#include +#include +#include +#include +#include "system.h" +#include "MKCpu.h" +#include "Memory.h" +#include "Display.h" +#include "VMachine.h" +#include "MKGenException.h" + +using namespace std; +using namespace MKBasic; + +#define ANIM_DELAY 250 + +const bool ClsIfDirty = true; + +VMachine *pvm = NULL; +Regs *preg = NULL; +bool ioecho = false, opbrk = false; +int g_stackdisp_lines = 1; + +bool ShowRegs(Regs *preg, VMachine *pvm, bool ioecho, bool showiostat); +void ShowHelp(); + +#if defined(LINUX) + +#include + +void trap_signal(int signum); + +/* + *-------------------------------------------------------------------- + * Method: trap_signal() + * Purpose: handle signal + * Arguments: signum - signal # + * Returns: n/a + *-------------------------------------------------------------------- + */ +void trap_signal(int signum) +{ + cout << "Signal caught: " << dec << signum << endl; + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(); + opbrk = true; + } + //exit(signum); + return; +} + +#endif + +#if defined(WINDOWS) +#include + +BOOL CtrlHandler(DWORD fdwCtrlType); + +/* + *-------------------------------------------------------------------- + * Method: CtrlHandler() + * Purpose: handle signal + * Arguments: fdwCtrlType - event type + * Returns: BOOL - TRUE if event handled, FALSE if needs further + * processing. + *-------------------------------------------------------------------- + */ +BOOL CtrlHandler(DWORD fdwCtrlType) +{ + switch( fdwCtrlType ) + { + case CTRL_C_EVENT: + //Beep( 750, 300 ); + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(); + opbrk = true; + } + return TRUE; + + + case CTRL_CLOSE_EVENT: + //Beep( 600, 200 ); + cout << "Ctrl-Close event" << endl; + return TRUE ; + + case CTRL_BREAK_EVENT: + //Beep( 900, 200 ); + if (NULL != pvm && NULL != preg) { + pvm->SetOpInterrupt(); + opbrk = true; + } + return TRUE; + + case CTRL_LOGOFF_EVENT: + //Beep( 1000, 200 ); + cout << "Ctrl-Logoff event" << endl; + return FALSE; + + case CTRL_SHUTDOWN_EVENT: + Beep( 750, 500 ); + cout << "Ctrl-Shutdown event" << endl; + return FALSE; + + default: + return FALSE; + } +} + +#endif + +/* + *-------------------------------------------------------------------- + * Method: PromptNewAddress() + * Purpose: Prompt user to enter 16-bit address (hex) in console. + * Arguments: prompt - prompt text + * Returns: unsigned int - address entered by user + *-------------------------------------------------------------------- + */ +unsigned int PromptNewAddress(string prompt) +{ + unsigned int newaddr = 0x10000; + + while (newaddr > 0xFFFF) { + cout << prompt; + cin >> hex >> newaddr; + } + + return newaddr; +} + +/* + *-------------------------------------------------------------------- + * Thank you stackoverflow.com. + * http://stackoverflow.com/questions/111928/ + * is-there-a-printf-converter-to-print-in-binary-format + *-------------------------------------------------------------------- + */ +#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d" +#define BYTETOBINARY(byte) \ + (byte & 0x80 ? 1 : 0), \ + (byte & 0x40 ? 1 : 0), \ + (byte & 0x20 ? 1 : 0), \ + (byte & 0x10 ? 1 : 0), \ + (byte & 0x08 ? 1 : 0), \ + (byte & 0x04 ? 1 : 0), \ + (byte & 0x02 ? 1 : 0), \ + (byte & 0x01 ? 1 : 0) + +/* + *-------------------------------------------------------------------- + * Method: ShowRegs() + * Purpose: Display status of CPU registers on DOS console. + * Arguments: preg - pointer to registers structure + * pvm - pointer to VM + * ioaddr - address setup for char I/O emulation + * ioecho - local I/O echo flag + * showiostat - if true, I/O emulation status is shown + * Returns: boolean - true if the stack pointer was longer than + * 15 (the screen must be cleared). + *-------------------------------------------------------------------- + */ +bool ShowRegs(Regs *preg, VMachine *pvm, bool ioecho, bool showiostat) +{ + bool ret = false; + char sBuf[80] = {0}; + + sprintf(sBuf, "| PC: $%04x | Acc: $%02x (" BYTETOBINARYPATTERN ") | X: $%02x | Y: $%02x |", + preg->PtrAddr, preg->Acc, BYTETOBINARY(preg->Acc), preg->IndX, preg->IndY); + cout << "*-------------*-----------------------*----------*----------*" << endl; + cout << sBuf << endl; + cout << "*-------------*-----------------------*----------*----------*" << endl; + cout << "| NV-BDIZC |" << endl; + cout << "| " << bitset<8>((int)preg->Flags) << " |"; + cout << " Last instr.: " << preg->LastInstr << " " << endl; + cout << "*-------------*" << endl; + //cout << "Last instr.: " << preg->LastInstr << " " << endl; + cout << endl; + /* + cout << "Registers:" << endl; + cout << " Acc: $" << hex << (unsigned short)preg->Acc << "\t(%" << bitset<8>((int)preg->Acc) << ")" << endl; + cout << " X: $" << hex << (unsigned short)preg->IndX << " " << endl; + cout << " Y: $" << hex << (unsigned short)preg->IndY << " " << endl; + cout << " PC: $" << hex << preg->PtrAddr << " " << endl; + //cout << " Acc16: $" << hex << preg->Acc16 << " " << endl; + //cout << " Ptr16: $" << hex << preg->Ptr16 << " " << endl; + */ + cout << "Stack: $" << hex << (unsigned short)preg->PtrStack << " " << endl; + cout << " \r"; + // display stack contents + cout << " ["; + int j = 0, stacklines = 1; + for (unsigned int addr = 0x0101 + preg->PtrStack; addr < 0x0200; addr++) { + unsigned int hv = (unsigned int)pvm->MemPeek8bit(addr); + if (hv < 16) { + cout << 0; + } + cout << hex << hv << " "; + j++; + if (j > 15) { + cout << "]" << endl; + cout << " ["; + j=0; + stacklines++; + } + } + cout << "] " << endl; + ret = (stacklines < g_stackdisp_lines); + g_stackdisp_lines = stacklines; + // end display stack contents + + if (showiostat) { + cout << endl << "I/O status: " << (pvm->GetCharIOActive() ? "enabled" : "disabled") << ", "; + cout << " at: $" << hex << pvm->GetCharIOAddr() << ", "; + cout << " local echo: " << (ioecho ? "ON" : "OFF") << "." << endl; + cout << "ROM: " << ((pvm->IsROMEnabled()) ? "enabled." : "disabled.") << " "; + cout << "Range: $" << hex << pvm->GetROMBegin() << " - $" << hex << pvm->GetROMEnd() << "." << endl; + } + cout << " \r"; + // cout << "-------------------------------------------------------------------------------" << endl; + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: + * Purpose: + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void ShowMenu() +{ + cout << "------------------------------------+----------------------------------------" << endl; + cout << " C - continue, S - step | A - set address for next step" << endl; + cout << " G - go/cont. from new address | N - go number of steps" << endl; + cout << " I - toggle char I/O emulation | X - execute from new address" << endl; + cout << " T - show I/O console | B - blank (clear) screen" << endl; + cout << " E - toggle I/O local echo | F - toggle registers animation" << endl; + cout << " J - set animation delay | M - dump memory, W - write memory" << endl; + cout << " K - toggle ROM emulation | R - show registers" << endl; + cout << " L - load memory image | O - display op-codes history" << endl; + cout << " D - disassemble code in memory | Q - quit, H - help" << endl; + cout << "------------------------------------+----------------------------------------" << endl; +} + + +/* + *-------------------------------------------------------------------- + * Method: RUNSTEPS() - macro + * Purpose: Execute multiple steps of CPU emulation. + * Arguments: + * step - boolean flag, true if step by step mode + * nsteps - # if steps + * brk - current status of break flag + * preg - pointer to CPU registers + * stct - step counter + * pvm - pointer to VM + * lrts - status of last RTS flag + * anim - boolean flag, true - registers animation mode + * delay - delay for anim mode + * enrom - rom enabled/disabled flag + * rombegin - begin address of emulated ROM + * romend - end address of emulated ROM + * + * Returns: n/a + *-------------------------------------------------------------------- + */ +#define RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay) \ +{ \ + bool cls = false; \ + brk = preg->SoftIrq; \ + lrts = preg->LastRTS; \ + while(step && nsteps > 1 && !brk && !lrts) { \ + cout << "addr: $" << hex << preg->PtrAddr << ", step: " << dec << stct; \ + cout << " \r"; \ + preg = pvm->Step(); \ + if (anim) { \ + if (cls & ClsIfDirty) { pvm->ClearScreen(); cls = false; } \ + pvm->ScrHome(); \ + cls = ShowRegs(preg,pvm,false,false); \ + cout << endl; \ + this_thread::sleep_for(chrono::milliseconds(delay)); \ + } \ + brk = preg->SoftIrq; \ + nsteps--; \ + stct++; \ + } \ +} + +/* run this program using the console pauser or add your own getch, system("pause") or input loop */ + +int main(int argc, char** argv) { +#if defined(LINUX) + signal(SIGINT, trap_signal); + signal(SIGTERM, trap_signal); +#endif +#if defined(WINDOWS) + SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ); +#endif + string romfile("dummy.rom"), ramfile("dummy.ram"); + if (argc > 1) { + ramfile = argv[1]; + } + try { + cout << endl; + pvm = new VMachine(romfile, ramfile); + pvm->ClearScreen(); + cout << "Virtual Machine/CPU Emulator (MOS 6502) and Debugger." << endl; + cout << "Copyright (C) by Marek Karcz 2016. All rights reserved." << endl; + string cmd; + bool runvm = false, step = false, brk = false, execaddr = false, stop = true; + bool lrts = false, execvm = false, anim = false, enrom = pvm->IsROMEnabled(); + unsigned int newaddr = pvm->GetRunAddr(), ioaddr = pvm->GetCharIOAddr(), tmpaddr = 0x0000; + unsigned int rombegin = pvm->GetROMBegin(), romend = pvm->GetROMEnd(), delay = ANIM_DELAY; + int nsteps = 0; + if (pvm->IsAutoExec()) { + execvm = true; + } + if (newaddr == 0) newaddr = 0x10000; + while (true) { + preg = pvm->GetRegs(); + if (runvm) { + if (anim) pvm->ClearScreen(); + int stct = 1; + if (execaddr) { + preg = ((step) ? pvm->Step(newaddr) : pvm->Run(newaddr)); + RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay); + execaddr = false; + } else { + preg = ((step) ? pvm->Step() : pvm->Run()); + RUNSTEPS(step,nsteps,brk,preg,stct,pvm,lrts,anim,delay); + } + if (step) + cout << "\rExecuted " << dec << stct << ((stct == 1) ? " step." : " steps.") << " " << endl; + nsteps = 0; + runvm = step = false; + newaddr = 0x10000; + } else if (execvm) { + preg = (execaddr ? pvm->Exec(newaddr) : pvm->Exec()); + execvm = false; + execaddr = false; + brk = preg->SoftIrq; + lrts = preg->LastRTS; + newaddr = 0x10000; + } + if (brk || opbrk || stop || lrts) { + cout << endl; + if (opbrk) { + cout << "Interrupted at " << hex << preg->PtrAddr << endl; + opbrk = brk = stop = lrts = false; + } else if (brk) { + cout << "BRK at " << hex << preg->PtrAddr << endl; + opbrk = brk = stop = lrts = false; + } else if (lrts) { + cout << "FINISHED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; + opbrk = brk = stop = lrts = false; + } else if (stop) { + cout << "STOPPED at " << hex << ((newaddr > 0xFFFF) ? preg->PtrAddr : newaddr) << endl; + opbrk = brk = stop = lrts = false; + } + ShowRegs(preg,pvm,ioecho,true); + } + ShowMenu(); + cout << "> "; + cin >> cmd; + char c = tolower(cmd.c_str()[0]); + if (c == 'h') { // display help + ShowHelp(); + } else if (c == 'o') { + queue exechist(pvm->GetExecHistory()); + cout << "PC : INSTR ACC | X | Y | PS | SP" << endl; + cout << "------------------------------------+-----+-----+-----+-----" << endl; + while (exechist.size()) { + cout << exechist.front() << endl; + exechist.pop(); + } + } else if (c == 'l') { // load memory image + char typ = 0; + while (tolower(typ) != 'b' && tolower(typ) != 'd') { + cout << "Type (B - binary/D - definition): "; + cin >> typ; + } + cout << " [" << ((tolower(typ) == 'b') ? "binary" : "definition") << "]" << endl; + string name; + cout << "Memory Image File Name: "; + cin >> name; + cout << " [" << name << "]" << endl; + if (typ == 'b') pvm->LoadRAMBin(name); + else { + pvm->LoadRAM(name); + if (pvm->IsAutoExec()) execvm = true; + if (newaddr == 0) newaddr = 0x10000; + } + } else if (c == 'k') { // toggle ROM emulation + if (!enrom) { + enrom = true; + do { + rombegin = PromptNewAddress("ROM begin (0200..FFFF): "); + } while (rombegin < 0x0200); + cout << " [" << hex << rombegin << "]" << endl; + do { + romend = PromptNewAddress("ROM end (ROMBEGIN+1..FFFF): "); + } while (romend <= rombegin); + cout << " [" << hex << romend << "]" << endl; + pvm->EnableROM(rombegin, romend); + cout << "ROM activated." << endl; + } else { + enrom = false; + pvm->DisableROM(); + cout << "ROM deactivated." << endl; + } + } else if (c == 'j') { // set registers animation delay + cout << "Delay [ms]: "; + cin >> dec >> delay; + cout << " [" << dec << delay << "]" << endl; + } else if (c == 'f') { // toggle registers animation in step mode + anim = !anim; + cout << "Registers status animation " << ((anim) ? "enabled." : "disabled.") << endl; + } else if (c == 'b') { // clear screen + pvm->ClearScreen(); + } else if (c == 'r') { // show registers + stop = true; + } else if (c == 'e') { // toggle local echo for I/O console + if (pvm->GetCharIOActive()) { + ioecho = !ioecho; + cout << "I/O echo is " << (ioecho ? "activated." : "deactivated.") << endl; + pvm->SetCharIO(ioaddr, ioecho); + } else { + cout << "ERROR: I/O is deactivated." << endl; + } + } else if (c == 't') { // show I/O console + if (pvm->GetCharIOActive()) { + pvm->ShowIO(); + } else { + cout << "ERROR: I/O is deactivated." << endl; + } + } else if (c == 'i') { // toggle I/O + if (pvm->GetCharIOActive()) { + pvm->DisableCharIO(); + cout << "I/O deactivated." << endl; + } else { + ioaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << ioaddr << "]" << endl; + pvm->SetCharIO(ioaddr, ioecho); + cout << "I/O activated." << endl; + } + } else if (c == 'w') { // write to memory + tmpaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << tmpaddr << "]" << endl; + cout << "Enter hex bytes [00..FF] values separated with NL or spaces, end with [100]:" << endl; + unsigned short v = 0; + while (true) { + cin >> hex >> v; + cout << " " << hex << v; + if (v > 0xFF) break; + pvm->MemPoke8bit(tmpaddr++, v & 0xFF); + }; + cout << endl; + } else if (c == 'a') { // change run address + execaddr = stop = true; + newaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << newaddr << "]" << endl; + } else if (c == 's') { + runvm = step = stop = true; + } else if (c == 'n') { // execute # of steps + nsteps = 0; + while (nsteps < 1) { + cout << "# of steps [n>1]: "; + cin >> dec >> nsteps; + } + cout << " [" << dec << nsteps << "]" << endl; + runvm = step = stop = true; + } else if (c == 'c') { // continue running code + runvm = true; + } else if (c == 'g') { // run from new address until BRK + runvm = true; + execaddr = true; + newaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << newaddr << "]" << endl; + } else if (c == 'x') { // execute code at address + execvm = true; + execaddr = true; + newaddr = PromptNewAddress("Address (0..FFFF): "); + cout << " [" << hex << newaddr << "]" << endl; + } else if (c == 'q') { // quit + break; + } else if (c == 'd') { // disassemble code in memory + unsigned int addrbeg = 0x10000, addrend = 0x10000; + cout << "Enter address range (0..0xFFFF)..." << endl; + addrbeg = PromptNewAddress("Start address (0..FFFF): "); + cout << " [" << hex << addrbeg << "]" << endl; + addrend = PromptNewAddress("End address (0..FFFF): "); + cout << " [" << hex << addrend << "]" << endl; + cout << endl; + for (unsigned int addr = addrbeg; addr <= addrend;) { + char instrbuf[DISS_BUF_SIZE]; + addr = pvm->Disassemble((unsigned short)addr, instrbuf); + cout << instrbuf << endl; + } + } else if (c == 'm') { // dump memory + unsigned int addrbeg = 0x10000, addrend = 0x10000; + cout << "Enter address range (0..0xFFFF)..." << endl; + addrbeg = PromptNewAddress("Start address (0..FFFF): "); + cout << " [" << hex << addrbeg << "]" << endl; + addrend = PromptNewAddress("End address (0..FFFF): "); + cout << " [" << hex << addrend << "]" << endl; + cout << endl; + for (unsigned int addr = addrbeg; addr <= addrend; addr+=16) { + cout << "\t|"; + for (unsigned int j=0; j < 16; j++) { + unsigned int hv = (unsigned int)pvm->MemPeek8bit(addr+j); + if (hv < 16) { + cout << 0; + } + cout << hex << hv << " "; + } + cout << "|"; + for (int j=0; j < 16; j++) { + char cc = (char)pvm->MemPeek8bit(addr+j); + if (isprint(cc)) + cout << cc; + else + cout << "?"; + } + cout << '\r'; + cout << hex << addr; + cout << endl; + } + } + } + } + catch (MKGenException& ex) { + cout << ex.GetCause() << endl; + } + catch (...) { + cout << "ERROR: Fatal." << endl; + } + return 0; +} + +/* + *-------------------------------------------------------------------- + * Method: ShowHel2p() + * Purpose: Display commands help. + * Arguments: n/a + * Returns: n/a + *-------------------------------------------------------------------- + */ +void ShowHelp() +{ + cout << R"(Debugger Console Command Reference. + +S - step + Executes single opcode at current address. +C - continue + Continues code execution from current address until BRK. +M - dump memory + Usage: M [startaddr] [endaddr] + Where: startaddr,endaddr - memory addr. in hexadecimal format [0000..FFFF]. + Dumps contents of memory, hexadecimal and ASCII formats." +G - go/continue from new address until BRK + Usage: G [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF]. + Executes code at provided address, interrupted by BRK opcode. +X - execute code from new address until RTS + Usage: X [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF]. + Executes code at provided address, until RTS (last one). +Q - quit + Exits from the emulator/debugger. +A - set address for next step + Usage: A [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF]. + Sets current address to a new value. +N - go number of steps + Usage: N [steps] + Where: steps - number of steps in decimal format + Execute number of opcodes provided in steps argument starting + from current address. +W - write to memory + Usage: W [address] [hexval] [hexval] ... 100 + Where: address - memory addr. in hexadecimal format [0000.FFFF], + hexval - byte value in hexadecimal format [00.FF]. + Writes provided values to memory starting at specified address. +I - toggle char I/O emulation + Usage: I [address] + Where: address - memory addr. in hexadecimal format [0000.FFFF], + Toggles basic character I/O emulation. When enabled, all writes + to the specified memory address also writes a character code to + to a virtual console. All reads from specified memory address + are interpreted as console character input. +R - show registers + Displays CPU registers, flags and stack. +T - show I/O console + Displays/prints the contents of the virtual console screen. + Note that in run mode (commands X, G or C), virtual screen is + displayed automatically in real-time if I/O emulation is enabled. +E - toggle I/O local echo + Toggles local echo on/off when I/O emulation is enabled. +B - blank (clear) screen + Clears the screen, useful when after exiting I/O emulation or + registers animation (long stack) your screen is messed up. +F - toggle registers animation mode + When in multi-step debug mode (command: N), displaying registers + can be suppressed or, when animation mode is enabled - they will + be continuously displayed after each executed step. +J - set registers status animation delay + Usage: J [delay] + Where: delay - time of delay in milliseconds, + Sets the time added at the end of each execution step in multi + step mode (command: N). The default value is 250 ms. +K - toggle ROM emulation + Usage: K [rombegin] [romend] - to enable, + K - to disable, + (OR just use 'K' in both cases and be prompted for arguments.) + Where: + rombegin - hexadecimal address [0200..FFFF], + romend - hexadecimal address [rombegin+1..FFFF]. + Enable/disable ROM emulation and define address range to which the ROM + (read-only memory) will be mapped. Default range: $D000-$DFFF. +L - load memory image + Usage: L [image_type] [image_name] + Where: + image_type - B (binary) OR D (definition), + image_name - name of the image file. + This function allows to load new memory image from either binary + image file or the ASCII definition file. The binary image is always + loaded from address 0x0000 and can be up to 64kB long. The definition + file format is a plain text file that can contain following keywords + and data: + + ADDR This keyword defines the run address of the executable code. + It is optional, but if exists, it must be the 1-st keyword + in the definition file. + Address in decimal or hexadecimal ($xxxx) format must follow + in the next line. + + ORG Changes the current address counter. The line that follows + sets the new address in decimal or hexadecimal format. + Data that follows will be put in memory starting from that + address. This keyword is optional and can be used multiple + times in the definition file. + + IOADDR Defines the address of the character I/O emulation. The + next line sets the address of I/O emulation in decimal or + hexadecimal format. If the I/O emulation is enabled + (see ENIO keyword), then any character written to this + address will be sent to the virtual console. The reading + from that address will invoke character input from the + emulated console. That input procedure is of blocking + type. To invoke non-blocking character procedure, reading + should be performed from IOADDR+1. + + ROMBEGIN Defines the address in memory where the beginning of the + Read Only memory is mapped. The next line that follows this + keyword sets the address in decimal or hexadecimal format. + + ROMEND Defines the address in memory where the end of the Read + Only Memory is mapped. The next line that follows this + keyword sets the address in decimal or hexadecimal format. + + ENIO Putting this keyword in memory definition file enables + rudimentary character I/O emulation and virtual console + emulation. + + ENROM Putting this keyword in memory definition file enables + emulation of Read Only Memory, in range of addresses + defined by ROMBEGIN and ROMEND keywords. + + EXEC Define starting address of code which will be automatically + executed after the memory image is loaded. + The next line that follows this keyword sets the address + in decimal or hexadecimal format. + +O - display op-codes history + Show the history of last executed op-codes/instructions, full with + disassembled mnemonic and argument. +D - diassemble code in memory + Usage: D [startaddr] [endaddr] + Where: startaddr,endaddr - hexadecimal address [0000..FFFF]. + Attempt to disassemble code in specified address range and display + the results (print) on the screen in symbolic form. + +NOTE: + 1. If no arguments provided, each command will prompt user to enter + missing data. + 2. It is possible to exit from running program to debugger console + by pressing CTRL-C or CTRL-Pause/Break, which will generate + a "Operator Interrupt". However in the character input mode + use CTRL-Y combination or CTRL-Break (DOS), CTRL-C (Linux). + You may need to press ENTER after that in input mode (DOS) +)"; + cout << endl; +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..d8d1adb --- /dev/null +++ b/makefile @@ -0,0 +1,49 @@ +# Project: MKBasic + +CPP = g++ -D__DEBUG__ -DLINUX +CC = gcc -D__DEBUG__ +OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +BIN = mkbasic +LIBS = -static-libgcc -m32 -g3 -ltermcap +CLIBS = -static-libgcc -m32 -g3 +INCS = +CXXINCS = +CXXFLAGS = $(CXXINCS) -m32 -std=c++0x -Wall -pedantic -g3 +#CFLAGS = $(INCS) -m32 -std=c++0x -Wall -pedantic -g3 +CFLAGS = $(INCS) -m32 -Wall -pedantic -g3 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) bin2hex all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) bin2hex + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +VMachine.o: VMachine.cpp + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + +MKBasic.o: MKBasic.cpp + $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) + +MKCpu.o: MKCpu.cpp + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + +Memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + +Display.o: Display.cpp + $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) + +bin2hex: bin2hex.c + $(CC) bin2hex.c -o bin2hex $(CFLAGS) $(CLIBS) + +MKGenException.o: MKGenException.cpp + $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) diff --git a/makefile.mingw b/makefile.mingw new file mode 100644 index 0000000..a35382d --- /dev/null +++ b/makefile.mingw @@ -0,0 +1,58 @@ +# Project: MKBasic +# Makefile created by Dev-C++ 5.11 +# and modified for standalone MINGW compiler installation. + +CPP = g++.exe -D__DEBUG__ +CC = gcc.exe -D__DEBUG__ +WINDRES = windres.exe +OBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +OBJ2 = bin2hex.o +LINKOBJ = main.o VMachine.o MKBasic.o MKCpu.o Memory.o Display.o MKGenException.o +LINKOBJ2 = bin2hex.o +LIBS = -L"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/lib" -L"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/lib" -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic +INCS = -I"C:\mingw-w64\x86_64-5.3.0\mingw64/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\lib\gcc\x86_64-w64-mingw32\5.3.0/include" +CXXINCS = -I"C:\mingw-w64\x86_64-5.3.0\mingw64/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/include" -I"C:\mingw-w64\x86_64-5.3.0\mingw64\lib\gcc\x86_64-w64-mingw32\5.3.0/include" +BIN = mkbasic.exe +BIN2 = bin2hex.exe +CXXFLAGS = $(CXXINCS) -std=c++11 -Wall -Wextra -pedantic -g3 +CFLAGS = $(INCS) -std=c++11 -Wall -Wextra -pedantic -g3 +CXXFLAGS2 = $(CXXINCS) +CFLAGS2 = $(INCS) +RM = del /f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) $(BIN2) all-after + +clean: clean-custom + ${RM} $(OBJ) $(OBJ2) $(BIN) $(BIN2) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS) + +main.o: main.cpp + $(CPP) -c main.cpp -o main.o $(CXXFLAGS) + +VMachine.o: VMachine.cpp + $(CPP) -c VMachine.cpp -o VMachine.o $(CXXFLAGS) + +MKBasic.o: MKBasic.cpp + $(CPP) -c MKBasic.cpp -o MKBasic.o $(CXXFLAGS) + +MKCpu.o: MKCpu.cpp + $(CPP) -c MKCpu.cpp -o MKCpu.o $(CXXFLAGS) + +Memory.o: Memory.cpp + $(CPP) -c Memory.cpp -o Memory.o $(CXXFLAGS) + +Display.o: Display.cpp + $(CPP) -c Display.cpp -o Display.o $(CXXFLAGS) + +MKGenException.o: MKGenException.cpp + $(CPP) -c MKGenException.cpp -o MKGenException.o $(CXXFLAGS) + +$(BIN2): $(OBJ2) + $(CC) $(LINKOBJ2) -o $(BIN2) $(LIBS) + +bin2hex.o: bin2hex.c + $(CC) -c bin2hex.c -o bin2hex.o $(CFLAGS2) diff --git a/makeming.bat b/makeming.bat new file mode 100644 index 0000000..7f2ab63 --- /dev/null +++ b/makeming.bat @@ -0,0 +1,4 @@ +rem to make project on win64 with mingw +rem run in mingw console + +mingw32-make -f makefile.mingw clean all \ No newline at end of file diff --git a/microchess.asm b/microchess.asm new file mode 100644 index 0000000..0ee1a6e --- /dev/null +++ b/microchess.asm @@ -0,0 +1,1051 @@ +;*********************************************************************** +; +; MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com +; +;*********************************************************************** +; Daryl Rictor: +; I have been given permission to distribute this program by the +; author and copyright holder, Peter Jennings. Please get his +; permission if you wish to re-distribute a modified copy of +; this file to others. He specifically requested that his +; copyright notice be included in the source and binary images. +; Thanks! +; +; Marek Karcz: +; I have been given permission to distribute this program by the +; original author Peter Jennings under condition that I include +; link to his website in attribution. +; Here it is: http://www.benlo.com/microchess/index.html +; I did not bother to contact Daryl Rictor to ask permission to +; distribute his modifications to this software because according to +; the copyright notice on the web page of his project, permission is +; already given for personal non-commercial use: +; http://sbc.rictor.org/avr65c02.html +; http://sbc.rictor.org/download/AVR65C02.zip, readme.txt +; If this is incorrect or I misunderstood the author's intention, +; please note that I acted with no malicious intent and will remove +; this file from my project if I receive such request. +; +; To build this program with CL65: +; +; cl65 -C microchess.cfg -l --start-addr 1024 -t none -o microchess.bin +; microchess.asm +; +; Binary image microchess.bin can be loaded to emulator with 'L' +; command in debug console. Start emulator: mkbasic, then issue +; command in debug console: +; L B MICROCHESS.BIN +; +; Memory image definition file can be generated which can be loaded +; to emulator via command line argument and automatically executed. +; To create that file, build microchess.bin image, then execute: +; +; bin2hex -f microchess.bin -o microchess.dat -w 0 -x 1024 -z +; +; and add following lines at the end of microchess.dat file: +; +; IOADDR +; $E000 +; ENIO +; +; Instructions to play: +; +; Load the game to emulator and auto-execute with command: +; mkbasic microchess.dat +; then perform following steps: +; 1. Press 'C' to setup board. +; 2. Enter your move: 4 digits - BBEE, BB - piece coordinates, +; EE - destination coordinates and press ENTER +; 3. After board is updated, press 'P' to make program make the move. +; 4. Repeat steps 2 and 3 until the game is finished. +; +; +; 1/14/2012 +; Modified Daryl Rictor's port to run on MKHBC-8-R1 homebrew +; computer under MKHBCOS (derivative of M.O.S. by Scott + Chidester). +; +; 3/11/2016 +; Adapted to run in MKBASIC (V65) emulator. +; +; 3/12/2016 +; Modified UI behavior: +; - chess board is only printed after move, not after each +; keystroke +; - copyright banner is only printed once at the start +; of the program +; +; 6551 I/O Port Addresses +; +;ACIADat = $7F70 +;ACIAsta = $7F71 +;ACIACmd = $7F72 +;ACIACtl = $7F73 + +; M.O.S. API defines (kernal) - OK for emulator, no changes + +.define mos_StrPtr $E0 +.define tmp_zpgPt $F6 + +; jumps, originally for M.O.S., now modified for emulator + +.define mos_CallGetCh $FFED +.define mos_CallPutCh $FFF0 +.define mos_CallPuts $FFF3 + + +; +; page zero variables +; +BOARD = $50 +BK = $60 +PIECE = $B0 +SQUARE = $B1 +SP2 = $B2 +SP1 = $B3 +incHEK = $B4 +STATE = $B5 +MOVEN = $B6 +REV = $B7 +OMOVE = $2C +WCAP0 = $2D +COUNT = $2E +BCAP2 = $2E +WCAP2 = $2F +BCAP1 = $20 +WCAP1 = $21 +BCAP0 = $22 +MOB = $23 +MAXC = $24 +CC = $25 +PCAP = $26 +BMOB = $23 +BMAXC = $24 +BMCC = $25 ; was bcc (TASS doesn't like it as a label) +BMAXP = $26 +XMAXC = $28 +WMOB = $2B +WMAXC = $3C +WCC = $3D +WMAXP = $3E +PMOB = $3F +PMAXC = $40 +PCC = $41 +PCP = $42 +OLDKY = $43 +BESTP = $4B +BESTV = $4A +BESTM = $49 +DIS1 = $4B +DIS2 = $4A +DIS3 = $49 +temp = $4C + +; +; +; + +.segment "BEGN" + + .ORG $0000 + +.segment "CODE" + + .ORG $0400 ; load into RAM @ $1000-$15FF + + lda #$00 ; REVERSE TOGGLE + sta REV + jmp CHESS + +PAINT: .byte $FF ; set this flag if board needs painting + ; unset otherwise +PRNBANN: + .byte $FF ; set this flag to print copyright banner + + ;jsr Init_6551 +CHESS: cld ; INITIALIZE + ldx #$FF ; TWO STACKS + txs + ldx #$C8 + stx SP2 +; +; ROUTINES TO LIGHT LED +; DISPLAY and GET KEY +; FROM KEYBOARD +; +OUT: jsr POUT ; DISPLAY and + jsr KIN ; GET INPUT *** my routine waits for a keypress + cmp #$43 ; [C] + bne NOSET ; SET UP + lda #$FF ; set PAINT flag + sta PAINT ; board needs to be diplayed + ldx #$1F ; BOARD +WHSET: lda SETW,X ; FROM + sta BOARD,X ; SETW + dex + bpl WHSET + ldx #$1B ; *ADDED + stx OMOVE ; INITS TO $FF + lda #$CC ; DISPLAY CCC + bne CLDSP +; +NOSET: cmp #$45 ; [E] + bne NOREV ; REVERSE + lda #$FF + sta PAINT + jsr REVERSE ; BOARD IS + sec + lda #$01 + sbc REV + sta REV ; TOGGLE REV FLAG + lda #$EE ; IS + bne CLDSP +; +NOREV: cmp #$40 ; [P] + bne NOGO ; PLAY CHESS + lda #$FF + sta PAINT + jsr GO +CLDSP: sta DIS1 ; DISPLAY + sta DIS2 ; ACROSS + sta DIS3 ; DISPLAY + bne CHESS +; +NOGO: cmp #$0D ; [Enter] + bne NOMV ; MOVE MAN + pha + lda #$FF + sta PAINT + pla + jsr MOVE ; AS ENTERED + jmp DISP +NOMV: cmp #$41 ; [Q] ***Added to allow game exit*** + beq DONE ; quit the game, exit back to system. + pha + lda #$00 + sta PAINT + pla + jmp INPUT ; process move +DONE: rts +;jmp $FF00 ; *** MUST set this to YOUR OS starting address +; +; THE ROUTINE JANUS DIRECTS THE +; ANALYSIS BY DETERMINING WHAT +; SHOULD OCCUR AFTER EACH MOVE +; GENERATED BY GNM +; +; +; +JANUS: ldx STATE + bmi NOCOUNT +; +; THIS ROUTINE COUNTS OCCURRENCES +; IT DEPENDS UPON STATE TO INdex +; THE CORRECT COUNTERS +; +COUNTS: lda PIECE + beq OVER ; IF STATE=8 + cpx #$08 ; DO NOT COUNT + bne OVER ; BLK MAX CAP + cmp BMAXP ; MOVES FOR + beq XRT ; WHITE +; +OVER: inc MOB,X ; MOBILITY + cmp #$01 ; + QUEEN + bne NOQ ; FOR TWO + inc MOB,X +; +NOQ: bvc NOCAP + ldy #$0F ; CALCULATE + lda SQUARE ; POINTS +ELOOP: cmp BK,Y ; CAPTURED + beq FOUN ; BY THIS + dey ; MOVE + bpl ELOOP +FOUN: lda POINTS,Y + cmp MAXC,X + bcc LESS ; SAVE IF + sty PCAP,X ; BEST THIS + sta MAXC,X ; STATE +; +LESS: clc + php ; ADD TO + adc CC,X ; CAPTURE + sta CC,X ; COUNTS + plp +; +NOCAP: cpx #$04 + beq ON4 + bmi TREE ;(=00 ONLY) +XRT: rts +; +; GENERATE FURTHER MOVES FOR COUNT +; and ANALYSIS +; +ON4: lda XMAXC ; SAVE ACTUAL + sta WCAP0 ; CAPTURE + lda #$00 ; STATE=0 + sta STATE + jsr MOVE ; GENERATE + jsr REVERSE ; IMMEDIATE + jsr GNMZ ; REPLY MOVES + jsr REVERSE +; + lda #$08 ; STATE=8 + sta STATE ; GENERATE +; jsr OHM ; CONTINUATION + jsr UMOVE ; MOVES +; + jmp STRATGY ; FINAL EVALUATION +NOCOUNT:cpx #$F9 + bne TREE +; +; DETERMINE IF THE KING CAN BE +; TAKEN, USED BY CHKCHK +; + lda BK ; IS KING + cmp SQUARE ; IN CHECK? + bne RETJ ; SET incHEK=0 + lda #$00 ; IF IT IS + sta incHEK +RETJ: rts +; +; IF A PIECE HAS BEEN CAPTURED BY +; A TRIAL MOVE, GENERATE REPLIES & +; EVALUATE THE EXCHANGE GAIN/LOSS +; +TREE: bvc RETJ ; NO CAP + ldy #$07 ; (PIECES) + lda SQUARE +LOOPX: cmp BK,Y + beq FOUNX + dey + beq RETJ ; (KING) + bpl LOOPX ; SAVE +FOUNX: lda POINTS,Y ; BEST CAP + cmp BCAP0,X ; AT THIS + bcc NOMAX ; LEVEL + sta BCAP0,X +NOMAX: dec STATE + lda #$FB ; IF STATE=FB + cmp STATE ; TIME TO TURN + beq UPTREE ; AROUND + jsr GENRM ; GENERATE FURTHER +UPTREE: inc STATE ; CAPTURES + rts +; +; THE PLAYER'S MOVE IS INPUT +; +INPUT: cmp #$08 ; NOT A LEGAL + bcs ERROR ; SQUARE # + jsr DISMV +DISP: ldx #$1F +SEARCH: lda BOARD,X + cmp DIS2 + beq HERE ; DISPLAY + dex ; PIECE AT + bpl SEARCH ; FROM +HERE: stx DIS1 ; SQUARE + stx PIECE +ERROR: jmp CHESS +; +; GENERATE ALL MOVES FOR ONE +; SIDE, CALL JANUS AFTER EACH +; ONE FOR NEXT STE? +; +; +GNMZ: ldx #$10 ; CLEAR +GNMX: lda #$00 ; COUNTERS +CLEAR: sta COUNT,X + dex + bpl CLEAR +; +GNM: lda #$10 ; SET UP + sta PIECE ; PIECE +NEWP: dec PIECE ; NEW PIECE + bpl NEX ; ALL DONE? + rts ; #NAME? +; +NEX: jsr RESET ; READY + ldy PIECE ; GET PIECE + ldx #$08 + stx MOVEN ; COMMON staRT + cpy #$08 ; WHAT IS IT? + bpl PAWN ; PAWN + cpy #$06 + bpl KNIGHT ; KNIGHT + cpy #$04 + bpl BISHOP ; BISHOP + cpy #$01 + beq QUEEN ; QUEEN + bpl ROOK ; ROOK +; +KING: jsr SNGMV ; MUST BE KING! + bne KING ; MOVES + beq NEWP ; 8 TO 1 +QUEEN: jsr LINE + bne QUEEN ; MOVES + beq NEWP ; 8 TO 1 +; +ROOK: ldx #$04 + stx MOVEN ; MOVES +AGNR: jsr LINE ; 4 TO 1 + bne AGNR + beq NEWP +; +BISHOP: jsr LINE + lda MOVEN ; MOVES + cmp #$04 ; 8 TO 5 + bne BISHOP + beq NEWP +; +KNIGHT: ldx #$10 + stx MOVEN ; MOVES +AGNN: jsr SNGMV ; 16 TO 9 + lda MOVEN + cmp #$08 + bne AGNN + beq NEWP +; +PAWN: ldx #$06 + stx MOVEN +P1: jsr CMOVE ; RIGHT CAP? + bvc P2 + bmi P2 + jsr JANUS ; YES +P2: jsr RESET + dec MOVEN ; LEFT CAP? + lda MOVEN + cmp #$05 + beq P1 +P3: jsr CMOVE ; AHEAD + bvs NEWP ; ILLEGAL + bmi NEWP + jsr JANUS + lda SQUARE ; GETS TO + and #$F0 ; 3RD RANK? + cmp #$20 + beq P3 ; DO DOUBLE + jmp NEWP +; +; CALCULATE SINGLE STEP MOVES +; FOR K,N +; +SNGMV: jsr CMOVE ; CALC MOVE + bmi ILL1 ; -IF LEGAL + jsr JANUS ; -EVALUATE +ILL1: jsr RESET + dec MOVEN + rts +; +; CALCULATE ALL MOVES DOWN A +; STRAIGHT LINE FOR Q,B,R +; +LINE: jsr CMOVE ; CALC MOVE + bcc OVL ; NO CHK + bvc LINE ; NOCAP +OVL: bmi ILL ; RETURN + php + jsr JANUS ; EVALUATE POSN + plp + bvc LINE ; NOT A CAP +ILL: jsr RESET ; LINE STOPPED + dec MOVEN ; NEXT DIR + rts +; +; EXCHANGE SIDES FOR REPLY +; ANALYSIS +; +REVERSE:ldx #$0F +ETC: sec + ldy BK,X ; SUBTRACT + lda #$77 ; POSITION + sbc BOARD,X ; FROM 77 + sta BK,X + sty BOARD,X ; and + sec + lda #$77 ; EXCHANGE + sbc BOARD,X ; PIECES + sta BOARD,X + dex + bpl ETC + rts +; +; CMOVE CALCULATES THE TO SQUARE +; USING SQUARE and THE MOVE +; TABLE FLAGS SET AS FOLLOWS: +; N#NAME? MOVE +; V#NAME? (LEGAL UNLESS IN CR) +; C#NAME? BECAUSE OF CHECK +; [MY &THANKS TO JIM BUTTERFIELD +; WHO WROTE THIS MORE EFFICIENT +; VERSION OF CMOVE) +; +CMOVE: lda SQUARE ; GET SQUARE + ldx MOVEN ; MOVE POINTER + clc + adc MOVEX,X ; MOVE LIST + sta SQUARE ; NEW POS'N + and #$88 + bne ILLEGAL ; OFF BOARD + lda SQUARE +; + ldx #$20 +LOOP: dex ; IS TO + bmi NO ; SQUARE + cmp BOARD,X ; OCCUPIED? + bne LOOP +; + cpx #$10 ; BY SELF? + bmi ILLEGAL +; + lda #$7F ; MUST BE CAP! + adc #$01 ; SET V FLAG + bvs SPX ; (jmp) +; +NO: clv ; NO CAPTURE +; +SPX: lda STATE ; SHOULD WE + bmi RETL ; DO THE + cmp #$08 ; CHECK CHECK? + bpl RETL +; +; CHKCHK REVERSES SIDES +; and LOOKS FOR A KING +; CAPTURE TO INDICATE +; ILLEGAL MOVE BECAUSE OF +; CHECK SincE THIS IS +; TIME CONSUMING, IT IS NOT +; ALWAYS DONE +; +CHKCHK: pha ; STATE #392 + php + lda #$F9 + sta STATE ; GENERATE + sta incHEK ; ALL REPLY + jsr MOVE ; MOVES TO + jsr REVERSE ; SEE IF KING + jsr GNM ; IS IN + jsr RUM ; CHECK + plp + pla + sta STATE + lda incHEK + bmi RETL ; NO - SAFE + sec ; YES - IN CHK + lda #$FF + rts +; +RETL: clc ; LEGAL + lda #$00 ; RETURN + rts +; +ILLEGAL:lda #$FF + clc ; ILLEGAL + clv ; RETURN + rts +; +; REPLACE PIECE ON CORRECT SQUARE +; +RESET: ldx PIECE ; GET LOGAT + lda BOARD,X ; FOR PIECE + sta SQUARE ; FROM BOARD + rts +; +; +; +GENRM: jsr MOVE ; MAKE MOVE +GENR2: jsr REVERSE ; REVERSE BOARD + jsr GNM ; GENERATE MOVES +RUM: jsr REVERSE ; REVERSE BACK +; +; ROUTINE TO UNMAKE A MOVE MADE BY +; MOVE +; +UMOVE: tsx ; UNMAKE MOVE + stx SP1 + ldx SP2 ; EXCHANGE + txs ; STACKS + pla ; MOVEN + sta MOVEN + pla ; CAPTURED + sta PIECE ; PIECE + tax + pla ; FROM SQUARE + sta BOARD,X + pla ; PIECE + tax + pla ; TO SOUARE + sta SQUARE + sta BOARD,X + jmp STRV +; +; THIS ROUTINE MOVES PIECE +; TO SQUARE, PARAMETERS +; ARE SAVED IN A staCK TO UNMAKE +; THE MOVE LATER +; +MOVE: tsx + stx SP1 ; SWITCH + ldx SP2 ; STACKS + txs + lda SQUARE + pha ; TO SQUARE + tay + ldx #$1F +CHECK: cmp BOARD,X ; CHECK FOR + beq TAKE ; CAPTURE + dex + bpl CHECK +TAKE: lda #$CC + sta BOARD,X + txa ; CAPTURED + pha ; PIECE + ldx PIECE + lda BOARD,X + sty BOARD,X ; FROM + pha ; SQUARE + txa + pha ; PIECE + lda MOVEN + pha ; MOVEN +STRV: tsx + stx SP2 ; SWITCH + ldx SP1 ; STACKS + txs ; BACK + rts +; +; CONTINUATION OF SUB STRATGY +; -CHECKS FOR CHECK OR CHECKMATE +; and ASSIGNS VALUE TO MOVE +; +CKMATE: ldy BMAXC ; CAN BLK CAP + cpx POINTS ; MY KING? + bne NOCHEK + lda #$00 ; GULP! + beq RETV ; DUMB MOVE! +; +NOCHEK: ldx BMOB ; IS BLACK + bne RETV ; UNABLE TO + ldx WMAXP ; MOVE and + bne RETV ; KING IN CH? + lda #$FF ; YES! MATE +; +RETV: ldx #$04 ; RESTORE + stx STATE ; STATE=4 +; +; THE VALUE OF THE MOVE (IN ACCU) +; IS COMPARED TO THE BEST MOVE and +; REPLACES IT IF IT IS BETTER +; +PUSH: cmp BESTV ; IS THIS BEST + bcc RETP ; MOVE SO FAR? + beq RETP + sta BESTV ; YES! + lda PIECE ; SAVE IT + sta BESTP + lda SQUARE + sta BESTM ; FLASH DISPLAY +RETP: lda #'.' ; print ... instead of flashing disp + jmp syschout ; print . and return +; +; MAIN PROGRAM TO PLAY CHESS +; PLAY FROM OPENING OR THINK +; +GO: ldx OMOVE ; OPENING? + bmi NOOPEN ; -NO *ADD CHANGE FROM bpl + lda DIS3 ; -YES WAS + cmp OPNING,X ; OPPONENT'S + bne END ; MOVE OK? + dex + lda OPNING,X ; GET NEXT + sta DIS1 ; CANNED + dex ; OPENING MOVE + lda OPNING,X + sta DIS3 ; DISPLAY IT + dex + stx OMOVE ; MOVE IT + bne MV2 ; (jmp) +; +END: lda #$FF ; *ADD - STOP CANNED MOVES + sta OMOVE ; FLAG OPENING +NOOPEN: ldx #$0C ; FINISHED + stx STATE ; STATE=C + stx BESTV ; CLEAR BESTV + ldx #$14 ; GENERATE P + jsr GNMX ; MOVES +; + ldx #$04 ; STATE=4 + stx STATE ; GENERATE and + jsr GNMZ ; TEST AVAILABLE +; +; MOVES +; + ldx BESTV ; GET BEST MOVE + cpx #$0F ; IF NONE + bcc MATE ; OH OH! +; +MV2: ldx BESTP ; MOVE + lda BOARD,X ; THE + sta BESTV ; BEST + stx PIECE ; MOVE + lda BESTM + sta SQUARE ; and DISPLAY + jsr MOVE ; IT + jmp CHESS +; +MATE: lda #$FF ; RESIGN + rts ; OR staLEMATE +; +; SUBROUTINE TO ENTER THE +; PLAYER'S MOVE +; +DISMV: ldx #$04 ; ROTATE +Drol: asl DIS3 ; KEY + rol DIS2 ; INTO + dex ; DISPLAY + bne Drol ; + ora DIS3 + sta DIS3 + sta SQUARE + rts +; +; THE FOLLOWING SUBROUTINE ASSIGNS +; A VALUE TO THE MOVE UNDER +; CONSIDERATION and RETURNS IT IN +; THE ACCUMULATOR +; + +STRATGY:clc + lda #$80 + adc WMOB ; PARAMETERS + adc WMAXC ; WITH WHEIGHT + adc WCC ; OF O25 + adc WCAP1 + adc WCAP2 + sec + sbc PMAXC + sbc PCC + sbc BCAP0 + sbc BCAP1 + sbc BCAP2 + sbc PMOB + sbc BMOB + bcs POS ; UNDERFLOW + lda #$00 ; PREVENTION +POS: lsr + clc ; ************** + adc #$40 + adc WMAXC ; PARAMETERS + adc WCC ; WITH WEIGHT + sec ; OF 05 + sbc BMAXC + lsr ; ************** + clc + adc #$90 + adc WCAP0 ; PARAMETERS + adc WCAP0 ; WITH WEIGHT + adc WCAP0 ; OF 10 + adc WCAP0 + adc WCAP1 + sec ; [UNDER OR OVER- + sbc BMAXC ; FLOW MAY OCCUR + sbc BMAXC ; FROM THIS + sbc BMCC ; secTION] + sbc BMCC + sbc BCAP1 + ldx SQUARE ; *************** + cpx #$33 + beq POSN ; POSITION + cpx #$34 ; BONUS FOR + beq POSN ; MOVE TO + cpx #$22 ; CENTRE + beq POSN ; OR + cpx #$25 ; OUT OF + beq POSN ; BACK RANK + ldx PIECE + beq NOPOSN + ldy BOARD,X + cpy #$10 + bpl NOPOSN +POSN: clc + adc #$02 +NOPOSN: jmp CKMATE ; CONTINUE + + +;----------------------------------------------------------------- +; The following routines were added to allow text-based board +; DISPLAY over a standard RS-232 port. +; +POUT: lda PAINT + bne POUT0 + rts ; return if PAINT flag = 0 +POUT0: jsr POUT9 ; print CRLF + jsr POUT13 ; print copyright + jsr POUT10 ; print column labels + ldy #$00 ; init board location + jsr POUT5 ; print board horz edge +POUT1: lda #'|' ; print vert edge + jsr syschout ; PRINT ONE ASCII CHR - SPACE + ldx #$1F +POUT2: tya ; scan the pieces for a location match + cmp BOARD,X ; match found? + beq POUT4 ; yes; print the piece's color and type + dex ; no + bpl POUT2 ; if not the last piece, try again + tya ; empty square + and #$01 ; odd or even column? + sta temp ; save it + tya ; is the row odd or even + lsr ; shift column right 4 spaces + lsr ; + lsr ; + lsr ; + and #$01 ; strip LSB + clc ; + adc temp ; combine row & col to determine square color + and #$01 ; is board square white or blk? + bne POUT25 ; white, print space + lda #'*' ; black, print * + + .byte $2c ; used to skip over lda #$20 + ;jmp POUT25A + +POUT25: lda #$20 ; ASCII space +POUT25A:jsr syschout ; PRINT ONE ASCII CHR - SPACE + jsr syschout ; PRINT ONE ASCII CHR - SPACE +POUT3: iny ; + tya ; get row number + and #$08 ; have we completed the row? + beq POUT1 ; no, do next column + lda #'|' ; yes, put the right edge on + jsr syschout ; PRINT ONE ASCII CHR - | + jsr POUT12 ; print row number + jsr POUT9 ; print CRLF + jsr POUT5 ; print bottom edge of board + clc ; + tya ; + adc #$08 ; point y to beginning of next row + tay ; + cpy #$80 ; was that the last row? + beq POUT8 ; yes, print the LED values + bne POUT1 ; no, do new row + +POUT4: lda REV ; print piece's color & type + beq POUT41 ; + lda cpl+16,X ; + bne POUT42 ; +POUT41: lda cpl,x ; +POUT42: jsr syschout ; + lda cph,x ; + jsr syschout ; + bne POUT3 ; branch always + +POUT5: txa ; print "-----...-----" + pha + ldx #$19 + lda #'-' +POUT6: jsr syschout ; PRINT ONE ASCII CHR - "-" + dex + bne POUT6 + pla + tax + jsr POUT9 + rts + +POUT8: jsr POUT10 ; + lda BESTP + jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS + lda #$20 + jsr syschout ; PRINT ONE ASCII CHR - SPACE + lda BESTV + jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS + lda #$20 + jsr syschout ; PRINT ONE ASCII CHR - SPACE + lda DIS3 + jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS + +POUT9: lda #$0D + jsr syschout ; PRINT ONE ASCII CHR - CR + lda #$0A + jsr syschout ; PRINT ONE ASCII CHR - LF + rts + +POUT10: ldx #$00 ; print the column labels +POUT11: lda #$20 ; 00 01 02 03 ... 07 + jsr syschout + txa + jsr syshexout + inx + cpx #$08 + bne POUT11 + beq POUT9 +POUT12: tya + and #$70 + jsr syshexout + rts + +; print banner only once, preserve registers A, X, Y +POUT13: stx tmp_zpgPt + sta tmp_zpgPt+1 + sty tmp_zpgPt+2 + lda PRNBANN + beq NOPRNBANN + lda #banner + sta mos_StrPtr+1 + jsr mos_CallPuts +NOPRNBANN: + lda #$00 + sta PRNBANN + ldx tmp_zpgPt + lda tmp_zpgPt+1 + ldy tmp_zpgPt+2 + rts + +; ldx #$00 ; Print the copyright banner +;POUT14: lda banner,x +; beq POUT15 +; jsr syschout +; inx +; bne POUT14 +;POUT15: rts + +KIN: lda #'?' + jsr syschout ; PRINT ONE ASCII CHR - ? + jsr syskin ; GET A KEYSTROKE FROM SYSTEM + jsr syschout ; echo entered character + and #$4F ; MASK 0-7, and ALpha'S + rts +; +; 6551 I/O Support Routines +; +; +;Init_6551 lda #$1F ; 19.2K/8/1 +; sta ACIActl ; control reg +; lda #$0B ; N parity/echo off/rx int off/ dtr active low +; sta ACIAcmd ; command reg +; rts ; done +; +; input chr from ACIA1 (waiting) +; +syskin: + jsr mos_CallGetCh + rts + + ;lda ACIAsta ; Serial port status + ;and #$08 ; is recvr full + ;beq syskin ; no char to get + ;lda ACIAdat ; get chr + ;rts ; +; +; output to OutPut Port +; +syschout: ; MKHBCOS: must preserve X, Y and A + stx tmp_zpgPt + sta tmp_zpgPt+1 + ;sty tmp_zpgPt+2 + jsr mos_CallPutCh + ldx tmp_zpgPt + lda tmp_zpgPt+1 + ;ldy tmp_zpgPt+2 + rts +; pha ; save registers +;ACIA_Out1 lda ACIAsta ; serial port status +; and #$10 ; is tx buffer empty +; beq ACIA_Out1 ; no +; pla ; get chr +; sta ACIAdat ; put character to Port +; rts ; done + +syshexout: pha ; prints AA hex digits + lsr ; MOVE UPPER NIBBLE TO LOWER + lsr ; + lsr ; + lsr ; + jsr PrintDig ; + pla ; +PrintDig: + sty tmp_zpgPt+2 + and #$0F ; + tay ; + lda Hexdigdata,Y ; + ldy tmp_zpgPt+2 ; + jmp syschout ; + +Hexdigdata: .byte "0123456789ABCDEF" +banner: .byte "MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com" + .byte $0d, $0a, $00 +cpl: .byte "WWWWWWWWWWWWWWWWBBBBBBBBBBBBBBBBWWWWWWWWWWWWWWWW" +cph: .byte "KQCCBBRRPPPPPPPPKQCCBBRRPPPPPPPP" + .byte $00 +; +; end of added code +; +; BLOCK DATA + +.segment "DATA" + + .ORG $0A20 + +SETW: .byte $03, $04, $00, $07, $02, $05, $01, $06 + .byte $10, $17, $11, $16, $12, $15, $14, $13 + .byte $73, $74, $70, $77, $72, $75, $71, $76 + .byte $60, $67, $61, $66, $62, $65, $64, $63 + +MOVEX: .byte $00, $F0, $FF, $01, $10, $11, $0F, $EF, $F1 + .byte $DF, $E1, $EE, $F2, $12, $0E, $1F, $21 + +POINTS: .byte $0B, $0A, $06, $06, $04, $04, $04, $04 + .byte $02, $02, $02, $02, $02, $02, $02, $02 + +OPNING: .byte $99, $25, $0B, $25, $01, $00, $33, $25 + .byte $07, $36, $34, $0D, $34, $34, $0E, $52 + .byte $25, $0D, $45, $35, $04, $55, $22, $06 + .byte $43, $33, $0F, $CC + +.segment "KERN" + + .ORG $FE00 + +CHRIN: lda $E000 + rts + +CHROUT: sta $E000 + rts + +; this function was shamelessly ripped :-) from M.O.S. code (c) by Scott Chidester + +STROUT: + ldy #0 ; Non-indexed variant starts at zero, of course + lda mos_StrPtr+1 ; Save StrPtr so it isn't modified + pha +PutsLoop: + lda (mos_StrPtr),y ; Get the next char in the string + beq PutsDone ; Zero means end of string + jsr CHROUT ; Otherwise put the char + + ; Update string pointer + iny ; increment StrPtr-lo + bne PutsLoop ; No rollover? Loop back for next character + inc mos_StrPtr+1 ; StrPtr-lo rolled over--carry hi byte + jmp PutsLoop ; Now loop back + +PutsDone: + pla + sta mos_StrPtr+1 ; Restore StrPtr + rts + +.segment "VECT" + + .ORG $FFED + + jmp CHRIN + jmp CHROUT + jmp STROUT + +; +; +; end of file +; diff --git a/microchess.bin b/microchess.bin new file mode 100644 index 0000000..da73a58 Binary files /dev/null and b/microchess.bin differ diff --git a/microchess.cfg b/microchess.cfg new file mode 100644 index 0000000..9b86be7 --- /dev/null +++ b/microchess.cfg @@ -0,0 +1,16 @@ +MEMORY { + RAM0: start = $0000, size = $0400, fill = yes; + RAM1: start = $0400, size = $0620, fill = yes; + RAM2: start = $0A20, size = $F3E0, fill = yes; + ROM1: start = $FE00, size = $1ED, fill = yes; + ROM2: start = $FFED, size = $12; +} + +SEGMENTS { + BEGN: load = RAM0, type = rw; + CODE: load = RAM1, type = rw; + DATA: load = RAM2, type = rw; + KERN: load = ROM1, type = ro; + VECT: load = ROM2, type = ro; +} + diff --git a/microchess.dat b/microchess.dat new file mode 100644 index 0000000..1d593e4 --- /dev/null +++ b/microchess.dat @@ -0,0 +1,114 @@ +; Created with BIN2HEX (C) Marek Karcz 2016. All rights reserved. +; 03/13/16 00:08:59 +ADDR +$0400 +ORG +$0000 +ORG +$0400 +$a9 $00 $85 $b7 $4c $09 $04 $ff $ff $d8 $a2 $ff $9a $a2 $c8 $86 +$b2 $20 $92 $07 $20 $7d $08 $c9 $43 $d0 $17 $a9 $ff $8d $07 $04 +$a2 $1f $bd $20 $0a $95 $50 $ca $10 $f8 $a2 $1b $86 $2c $a9 $cc +$d0 $23 $c9 $45 $d0 $13 $a9 $ff $8d $07 $04 $20 $db $05 $38 $a9 +$01 $e5 $b7 $85 $b7 $a9 $ee $d0 $0c $c9 $40 $d0 $10 $a9 $ff $8d +$07 $04 $20 $cf $06 $85 $4b $85 $4a $85 $49 $d0 $ac $c9 $0d $d0 +$0d $48 $a9 $ff $8d $07 $04 $68 $20 $75 $06 $4c $17 $05 $c9 $41 +$f0 $0a $48 $a9 $00 $8d $07 $04 $68 $4c $10 $05 $60 $a6 $b5 $30 +$59 $a5 $b0 $f0 $08 $e0 $08 $d0 $04 $c5 $26 $f0 $2e $f6 $23 $c9 +$01 $d0 $02 $f6 $23 $50 $1e $a0 $0f $a5 $b1 $d9 $60 $00 $f0 $03 +$88 $10 $f8 $b9 $51 $0a $d5 $24 $90 $04 $94 $26 $95 $24 $18 $08 +$75 $25 $95 $25 $28 $e0 $04 $f0 $03 $30 $2e $60 $a5 $28 $85 $2d +$a9 $00 $85 $b5 $20 $75 $06 $20 $db $05 $20 $29 $05 $20 $db $05 +$a9 $08 $85 $b5 $20 $5b $06 $4c $2c $07 $e0 $f9 $d0 $0b $a5 $60 +$c5 $b1 $d0 $04 $a9 $00 $85 $b4 $60 $50 $fd $a0 $07 $a5 $b1 $d9 +$60 $00 $f0 $05 $88 $f0 $f1 $10 $f6 $b9 $51 $0a $d5 $22 $90 $02 +$95 $22 $c6 $b5 $a9 $fb $c5 $b5 $f0 $03 $20 $4f $06 $e6 $b5 $60 +$c9 $08 $b0 $12 $20 $1c $07 $a2 $1f $b5 $50 $c5 $4a $f0 $03 $ca +$10 $f7 $86 $4b $86 $b0 $4c $09 $04 $a2 $10 $a9 $00 $95 $2e $ca +$10 $fb $a9 $10 $85 $b0 $c6 $b0 $10 $01 $60 $20 $48 $06 $a4 $b0 +$a2 $08 $86 $b6 $c0 $08 $10 $41 $c0 $06 $10 $2e $c0 $04 $10 $1f +$c0 $01 $f0 $09 $10 $0e $20 $b7 $05 $d0 $fb $f0 $d9 $20 $c5 $05 +$d0 $fb $f0 $d2 $a2 $04 $86 $b6 $20 $c5 $05 $d0 $fb $f0 $c7 $20 +$c5 $05 $a5 $b6 $c9 $04 $d0 $f7 $f0 $bc $a2 $10 $86 $b6 $20 $b7 +$05 $a5 $b6 $c9 $08 $d0 $f7 $f0 $ad $a2 $06 $86 $b6 $20 $f3 $05 +$50 $05 $30 $03 $20 $7d $04 $20 $48 $06 $c6 $b6 $a5 $b6 $c9 $05 +$f0 $eb $20 $f3 $05 $70 $8f $30 $8d $20 $7d $04 $a5 $b1 $29 $f0 +$c9 $20 $f0 $ee $4c $36 $05 $20 $f3 $05 $30 $03 $20 $7d $04 $20 +$48 $06 $c6 $b6 $60 $20 $f3 $05 $90 $02 $50 $f9 $30 $07 $08 $20 +$7d $04 $28 $50 $f0 $20 $48 $06 $c6 $b6 $60 $a2 $0f $38 $b4 $60 +$a9 $77 $f5 $50 $95 $60 $94 $50 $38 $a9 $77 $f5 $50 $95 $50 $ca +$10 $eb $60 $a5 $b1 $a6 $b6 $18 $7d $40 $0a $85 $b1 $29 $88 $d0 +$42 $a5 $b1 $a2 $20 $ca $30 $0e $d5 $50 $d0 $f9 $e0 $10 $30 $33 +$a9 $7f $69 $01 $70 $01 $b8 $a5 $b5 $30 $24 $c9 $08 $10 $20 $48 +$08 $a9 $f9 $85 $b5 $85 $b4 $20 $75 $06 $20 $db $05 $20 $32 $05 +$20 $58 $06 $28 $68 $85 $b5 $a5 $b4 $30 $04 $38 $a9 $ff $60 $18 +$a9 $00 $60 $a9 $ff $18 $b8 $60 $a6 $b0 $b5 $50 $85 $b1 $60 $20 +$75 $06 $20 $db $05 $20 $32 $05 $20 $db $05 $ba $86 $b3 $a6 $b2 +$9a $68 $85 $b6 $68 $85 $b0 $aa $68 $95 $50 $68 $aa $68 $85 $b1 +$95 $50 $4c $9a $06 $ba $86 $b3 $a6 $b2 $9a $a5 $b1 $48 $a8 $a2 +$1f $d5 $50 $f0 $03 $ca $10 $f9 $a9 $cc $95 $50 $8a $48 $a6 $b0 +$b5 $50 $94 $50 $48 $8a $48 $a5 $b6 $48 $ba $86 $b2 $a6 $b3 $9a +$60 $a4 $24 $ec $51 $0a $d0 $04 $a9 $00 $f0 $0a $a6 $23 $d0 $06 +$a6 $3e $d0 $02 $a9 $ff $a2 $04 $86 $b5 $c5 $4a $90 $0c $f0 $0a +$85 $4a $a5 $b0 $85 $4b $a5 $b1 $85 $49 $a9 $2e $4c $8f $08 $a6 +$2c $30 $1c $a5 $49 $dd $61 $0a $d0 $11 $ca $bd $61 $0a $85 $4b +$ca $bd $61 $0a $85 $49 $ca $86 $2c $d0 $1c $a9 $ff $85 $2c $a2 +$0c $86 $b5 $86 $4a $a2 $14 $20 $2b $05 $a2 $04 $86 $b5 $20 $29 +$05 $a6 $4a $e0 $0f $90 $12 $a6 $4b $b5 $50 $85 $4a $86 $b0 $a5 +$49 $85 $b1 $20 $75 $06 $4c $09 $04 $a9 $ff $60 $a2 $04 $06 $49 +$26 $4a $ca $d0 $f9 $05 $49 $85 $49 $85 $b1 $60 $18 $a9 $80 $65 +$2b $65 $3c $65 $3d $65 $21 $65 $2f $38 $e5 $40 $e5 $41 $e5 $22 +$e5 $20 $e5 $2e $e5 $3f $e5 $23 $b0 $02 $a9 $00 $4a $18 $69 $40 +$65 $3c $65 $3d $38 $e5 $24 $4a $18 $69 $90 $65 $2d $65 $2d $65 +$2d $65 $2d $65 $21 $38 $e5 $24 $e5 $24 $e5 $25 $e5 $25 $e5 $20 +$a6 $b1 $e0 $33 $f0 $16 $e0 $34 $f0 $12 $e0 $22 $f0 $0e $e0 $25 +$f0 $0a $a6 $b0 $f0 $09 $b4 $50 $c0 $10 $10 $03 $18 $69 $02 $4c +$a1 $06 $ad $07 $04 $d0 $01 $60 $20 $37 $08 $20 $5b $08 $20 $42 +$08 $a0 $00 $20 $09 $08 $a9 $7c $20 $8f $08 $a2 $1f $98 $d5 $50 +$f0 $40 $ca $10 $f8 $98 $29 $01 $85 $4c $98 $4a $4a $4a $4a $29 +$01 $18 $65 $4c $29 $01 $d0 $03 $a9 $2a $2c $a9 $20 $20 $8f $08 +$20 $8f $08 $c8 $98 $29 $08 $f0 $cd $a9 $7c $20 $8f $08 $20 $54 +$08 $20 $37 $08 $20 $09 $08 $18 $98 $69 $08 $a8 $c0 $80 $f0 $2b +$d0 $b4 $a5 $b7 $f0 $05 $bd $0d $09 $d0 $03 $bd $fd $08 $20 $8f +$08 $bd $2d $09 $20 $8f $08 $d0 $ca $8a $48 $a2 $19 $a9 $2d $20 +$8f $08 $ca $d0 $fa $68 $aa $20 $37 $08 $60 $20 $42 $08 $a5 $4b +$20 $9b $08 $a9 $20 $20 $8f $08 $a5 $4a $20 $9b $08 $a9 $20 $20 +$8f $08 $a5 $49 $20 $9b $08 $a9 $0d $20 $8f $08 $a9 $0a $20 $8f +$08 $60 $a2 $00 $a9 $20 $20 $8f $08 $8a $20 $9b $08 $e8 $e0 $08 +$d0 $f2 $f0 $e3 $98 $29 $70 $20 $9b $08 $60 $86 $f6 $85 $f7 $84 +$f8 $ad $08 $04 $f0 $0b $a9 $c1 $85 $e0 $a9 $08 $85 $e1 $20 $f3 +$ff $a9 $00 $8d $08 $04 $a6 $f6 $a5 $f7 $a4 $f8 $60 $a9 $3f $20 +$8f $08 $20 $8b $08 $20 $8f $08 $29 $4f $60 $20 $ed $ff $60 $86 +$f6 $85 $f7 $20 $f0 $ff $a6 $f6 $a5 $f7 $60 $48 $4a $4a $4a $4a +$20 $a4 $08 $68 $84 $f8 $29 $0f $a8 $b9 $b1 $08 $a4 $f8 $4c $8f +$08 $30 $31 $32 $33 $34 $35 $36 $37 $38 $39 $41 $42 $43 $44 $45 +$46 $4d $69 $63 $72 $6f $43 $68 $65 $73 $73 $20 $28 $63 $29 $20 +$31 $39 $39 $36 $2d $32 $30 $30 $32 $20 $50 $65 $74 $65 $72 $20 +$4a $65 $6e $6e $69 $6e $67 $73 $2c $20 $70 $65 $74 $65 $72 $6a +$40 $62 $65 $6e $6c $6f $2e $63 $6f $6d $0d $0a $00 $57 $57 $57 +$57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $42 $42 $42 +$42 $42 $42 $42 $42 $42 $42 $42 $42 $42 $42 $42 $42 $57 $57 $57 +$57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $57 $4b $51 $43 +$43 $42 $42 $52 $52 $50 $50 $50 $50 $50 $50 $50 $50 $4b $51 $43 +$43 $42 $42 $52 $52 $50 $50 $50 $50 $50 $50 $50 $50 $00 $00 $00 +ORG +$0a20 +$03 $04 $00 $07 $02 $05 $01 $06 $10 $17 $11 $16 $12 $15 $14 $13 +$73 $74 $70 $77 $72 $75 $71 $76 $60 $67 $61 $66 $62 $65 $64 $63 +$00 $f0 $ff $01 $10 $11 $0f $ef $f1 $df $e1 $ee $f2 $12 $0e $1f +$21 $0b $0a $06 $06 $04 $04 $04 $04 $02 $02 $02 $02 $02 $02 $02 +$02 $99 $25 $0b $25 $01 $00 $33 $25 $07 $36 $34 $0d $34 $34 $0e +$52 $25 $0d $45 $35 $04 $55 $22 $06 $43 $33 $0f $cc $00 $00 $00 +ORG +$fe00 +$ad $00 $e0 $60 $8d $00 $e0 $60 $a0 $00 $a5 $e1 $48 $b1 $e0 $f0 +$0b $20 $04 $fe $c8 $d0 $f6 $e6 $e1 $4c $0d $fe $68 $85 $e1 $60 +ORG +$ffe0 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $4c $00 $fe +$4c $04 $fe $4c $08 $fe $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +IOADDR +$E000 +ENIO +EXEC +$0400 diff --git a/microchess.lst b/microchess.lst new file mode 100644 index 0000000..a733acc --- /dev/null +++ b/microchess.lst @@ -0,0 +1,1033 @@ +ca65 V2.13.2 - (C) Copyright 1998-2005 Ullrich von Bassewitz +Main file : microchess.asm +Current file: microchess.asm + +000000r 1 ;*********************************************************************** +000000r 1 ; +000000r 1 ; MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com +000000r 1 ; +000000r 1 ;*********************************************************************** +000000r 1 ; Daryl Rictor: +000000r 1 ; I have been given permission to distribute this program by the +000000r 1 ; author and copyright holder, Peter Jennings. Please get his +000000r 1 ; permission if you wish to re-distribute a modified copy of +000000r 1 ; this file to others. He specifically requested that his +000000r 1 ; copyright notice be included in the source and binary images. +000000r 1 ; Thanks! +000000r 1 ; +000000r 1 ; Marek Karcz: +000000r 1 ; I have been given permission to distribute this program by the +000000r 1 ; original author Peter Jennings under condition that I include +000000r 1 ; link to his website in attribution. +000000r 1 ; Here it is: http://www.benlo.com/microchess/index.html +000000r 1 ; I did not bother to contact Daryl Rictor to ask permission to +000000r 1 ; distribute his modifications to this software because according to +000000r 1 ; the copyright notice on the web page of his project, permission is +000000r 1 ; already given for personal non-commercial use: +000000r 1 ; http://sbc.rictor.org/avr65c02.html +000000r 1 ; http://sbc.rictor.org/download/AVR65C02.zip, readme.txt +000000r 1 ; If this is incorrect or I misunderstood the author's intention, +000000r 1 ; please note that I acted with no malicious intent and will remove +000000r 1 ; this file from my project if I receive such request. +000000r 1 ; +000000r 1 ; 1/14/2012 +000000r 1 ; Modified by Marek Karcz to run on MKHBC-8-R1 under MKHBCOS +000000r 1 ; (derivative of M.O.S. by Scott Chidester) +000000r 1 ; 3/11/2016 +000000r 1 ; Adapted to run in MKBASIC (V65) emulator. +000000r 1 ; +000000r 1 ; 6551 I/O Port Addresses +000000r 1 ; +000000r 1 ;ACIADat = $7F70 +000000r 1 ;ACIAsta = $7F71 +000000r 1 ;ACIACmd = $7F72 +000000r 1 ;ACIACtl = $7F73 +000000r 1 +000000r 1 ; M.O.S. API defines (kernal) - OK for emulator, no changes +000000r 1 +000000r 1 .define mos_StrPtr $E0 +000000r 1 .define tmp_zpgPt $F6 +000000r 1 +000000r 1 ; jumps, originally for M.O.S., now modified for emulator +000000r 1 +000000r 1 .define mos_CallGetCh $FFED +000000r 1 .define mos_CallPutCh $FFF0 +000000r 1 .define mos_CallPuts $FFF3 +000000r 1 +000000r 1 +000000r 1 ; +000000r 1 ; page zero variables +000000r 1 ; +000000r 1 BOARD = $50 +000000r 1 BK = $60 +000000r 1 PIECE = $B0 +000000r 1 SQUARE = $B1 +000000r 1 SP2 = $B2 +000000r 1 SP1 = $B3 +000000r 1 incHEK = $B4 +000000r 1 STATE = $B5 +000000r 1 MOVEN = $B6 +000000r 1 REV = $B7 +000000r 1 OMOVE = $2C +000000r 1 WCAP0 = $2D +000000r 1 COUNT = $2E +000000r 1 BCAP2 = $2E +000000r 1 WCAP2 = $2F +000000r 1 BCAP1 = $20 +000000r 1 WCAP1 = $21 +000000r 1 BCAP0 = $22 +000000r 1 MOB = $23 +000000r 1 MAXC = $24 +000000r 1 CC = $25 +000000r 1 PCAP = $26 +000000r 1 BMOB = $23 +000000r 1 BMAXC = $24 +000000r 1 BMCC = $25 ; was bcc (TASS doesn't like it as a label) +000000r 1 BMAXP = $26 +000000r 1 XMAXC = $28 +000000r 1 WMOB = $2B +000000r 1 WMAXC = $3C +000000r 1 WCC = $3D +000000r 1 WMAXP = $3E +000000r 1 PMOB = $3F +000000r 1 PMAXC = $40 +000000r 1 PCC = $41 +000000r 1 PCP = $42 +000000r 1 OLDKY = $43 +000000r 1 BESTP = $4B +000000r 1 BESTV = $4A +000000r 1 BESTM = $49 +000000r 1 DIS1 = $4B +000000r 1 DIS2 = $4A +000000r 1 DIS3 = $49 +000000r 1 temp = $4C +000000r 1 +000000r 1 ; +000000r 1 ; +000000r 1 ; +000000r 1 +000000r 1 .segment "BEGN" +000000r 1 +000000r 1 .ORG $0000 +000000 1 +000000 1 .segment "CODE" +000000 1 +000000 1 .ORG $0400 ; load into RAM @ $1000-$15FF +000400 1 +000400 1 A9 00 lda #$00 ; REVERSE TOGGLE +000402 1 85 B7 sta REV +000404 1 4C 09 04 jmp CHESS +000407 1 +000407 1 FF PAINT: .byte $FF ; set this flag if board needs painting +000408 1 ; unset otherwise +000408 1 PRNBANN: +000408 1 FF .byte $FF ; set this flag to print copyright banner +000409 1 +000409 1 ;jsr Init_6551 +000409 1 D8 CHESS: cld ; INITIALIZE +00040A 1 A2 FF ldx #$FF ; TWO STACKS +00040C 1 9A txs +00040D 1 A2 C8 ldx #$C8 +00040F 1 86 B2 stx SP2 +000411 1 ; +000411 1 ; ROUTINES TO LIGHT LED +000411 1 ; DISPLAY and GET KEY +000411 1 ; FROM KEYBOARD +000411 1 ; +000411 1 20 92 07 OUT: jsr POUT ; DISPLAY and +000414 1 20 7D 08 jsr KIN ; GET INPUT *** my routine waits for a keypress +000417 1 C9 43 cmp #$43 ; [C] +000419 1 D0 17 bne NOSET ; SET UP +00041B 1 A9 FF lda #$FF ; set PAINT flag +00041D 1 8D 07 04 sta PAINT ; board needs to be diplayed +000420 1 A2 1F ldx #$1F ; BOARD +000422 1 BD 20 0A WHSET: lda SETW,X ; FROM +000425 1 95 50 sta BOARD,X ; SETW +000427 1 CA dex +000428 1 10 F8 bpl WHSET +00042A 1 A2 1B ldx #$1B ; *ADDED +00042C 1 86 2C stx OMOVE ; INITS TO $FF +00042E 1 A9 CC lda #$CC ; DISPLAY CCC +000430 1 D0 23 bne CLDSP +000432 1 ; +000432 1 C9 45 NOSET: cmp #$45 ; [E] +000434 1 D0 13 bne NOREV ; REVERSE +000436 1 A9 FF lda #$FF +000438 1 8D 07 04 sta PAINT +00043B 1 20 DB 05 jsr REVERSE ; BOARD IS +00043E 1 38 sec +00043F 1 A9 01 lda #$01 +000441 1 E5 B7 sbc REV +000443 1 85 B7 sta REV ; TOGGLE REV FLAG +000445 1 A9 EE lda #$EE ; IS +000447 1 D0 0C bne CLDSP +000449 1 ; +000449 1 C9 40 NOREV: cmp #$40 ; [P] +00044B 1 D0 10 bne NOGO ; PLAY CHESS +00044D 1 A9 FF lda #$FF +00044F 1 8D 07 04 sta PAINT +000452 1 20 CF 06 jsr GO +000455 1 85 4B CLDSP: sta DIS1 ; DISPLAY +000457 1 85 4A sta DIS2 ; ACROSS +000459 1 85 49 sta DIS3 ; DISPLAY +00045B 1 D0 AC bne CHESS +00045D 1 ; +00045D 1 C9 0D NOGO: cmp #$0D ; [Enter] +00045F 1 D0 0D bne NOMV ; MOVE MAN +000461 1 48 pha +000462 1 A9 FF lda #$FF +000464 1 8D 07 04 sta PAINT +000467 1 68 pla +000468 1 20 75 06 jsr MOVE ; AS ENTERED +00046B 1 4C 17 05 jmp DISP +00046E 1 C9 41 NOMV: cmp #$41 ; [Q] ***Added to allow game exit*** +000470 1 F0 0A beq DONE ; quit the game, exit back to system. +000472 1 48 pha +000473 1 A9 00 lda #$00 +000475 1 8D 07 04 sta PAINT +000478 1 68 pla +000479 1 4C 10 05 jmp INPUT ; process move +00047C 1 60 DONE: rts +00047D 1 ;jmp $FF00 ; *** MUST set this to YOUR OS starting address +00047D 1 ; +00047D 1 ; THE ROUTINE JANUS DIRECTS THE +00047D 1 ; ANALYSIS BY DETERMINING WHAT +00047D 1 ; SHOULD OCCUR AFTER EACH MOVE +00047D 1 ; GENERATED BY GNM +00047D 1 ; +00047D 1 ; +00047D 1 ; +00047D 1 A6 B5 JANUS: ldx STATE +00047F 1 30 59 bmi NOCOUNT +000481 1 ; +000481 1 ; THIS ROUTINE COUNTS OCCURRENCES +000481 1 ; IT DEPENDS UPON STATE TO INdex +000481 1 ; THE CORRECT COUNTERS +000481 1 ; +000481 1 A5 B0 COUNTS: lda PIECE +000483 1 F0 08 beq OVER ; IF STATE=8 +000485 1 E0 08 cpx #$08 ; DO NOT COUNT +000487 1 D0 04 bne OVER ; BLK MAX CAP +000489 1 C5 26 cmp BMAXP ; MOVES FOR +00048B 1 F0 2E beq XRT ; WHITE +00048D 1 ; +00048D 1 F6 23 OVER: inc MOB,X ; MOBILITY +00048F 1 C9 01 cmp #$01 ; + QUEEN +000491 1 D0 02 bne NOQ ; FOR TWO +000493 1 F6 23 inc MOB,X +000495 1 ; +000495 1 50 1E NOQ: bvc NOCAP +000497 1 A0 0F ldy #$0F ; CALCULATE +000499 1 A5 B1 lda SQUARE ; POINTS +00049B 1 D9 60 00 ELOOP: cmp BK,Y ; CAPTURED +00049E 1 F0 03 beq FOUN ; BY THIS +0004A0 1 88 dey ; MOVE +0004A1 1 10 F8 bpl ELOOP +0004A3 1 B9 51 0A FOUN: lda POINTS,Y +0004A6 1 D5 24 cmp MAXC,X +0004A8 1 90 04 bcc LESS ; SAVE IF +0004AA 1 94 26 sty PCAP,X ; BEST THIS +0004AC 1 95 24 sta MAXC,X ; STATE +0004AE 1 ; +0004AE 1 18 LESS: clc +0004AF 1 08 php ; ADD TO +0004B0 1 75 25 adc CC,X ; CAPTURE +0004B2 1 95 25 sta CC,X ; COUNTS +0004B4 1 28 plp +0004B5 1 ; +0004B5 1 E0 04 NOCAP: cpx #$04 +0004B7 1 F0 03 beq ON4 +0004B9 1 30 2E bmi TREE ;(=00 ONLY) +0004BB 1 60 XRT: rts +0004BC 1 ; +0004BC 1 ; GENERATE FURTHER MOVES FOR COUNT +0004BC 1 ; and ANALYSIS +0004BC 1 ; +0004BC 1 A5 28 ON4: lda XMAXC ; SAVE ACTUAL +0004BE 1 85 2D sta WCAP0 ; CAPTURE +0004C0 1 A9 00 lda #$00 ; STATE=0 +0004C2 1 85 B5 sta STATE +0004C4 1 20 75 06 jsr MOVE ; GENERATE +0004C7 1 20 DB 05 jsr REVERSE ; IMMEDIATE +0004CA 1 20 29 05 jsr GNMZ ; REPLY MOVES +0004CD 1 20 DB 05 jsr REVERSE +0004D0 1 ; +0004D0 1 A9 08 lda #$08 ; STATE=8 +0004D2 1 85 B5 sta STATE ; GENERATE +0004D4 1 ; jsr OHM ; CONTINUATION +0004D4 1 20 5B 06 jsr UMOVE ; MOVES +0004D7 1 ; +0004D7 1 4C 2C 07 jmp STRATGY ; FINAL EVALUATION +0004DA 1 E0 F9 NOCOUNT:cpx #$F9 +0004DC 1 D0 0B bne TREE +0004DE 1 ; +0004DE 1 ; DETERMINE IF THE KING CAN BE +0004DE 1 ; TAKEN, USED BY CHKCHK +0004DE 1 ; +0004DE 1 A5 60 lda BK ; IS KING +0004E0 1 C5 B1 cmp SQUARE ; IN CHECK? +0004E2 1 D0 04 bne RETJ ; SET incHEK=0 +0004E4 1 A9 00 lda #$00 ; IF IT IS +0004E6 1 85 B4 sta incHEK +0004E8 1 60 RETJ: rts +0004E9 1 ; +0004E9 1 ; IF A PIECE HAS BEEN CAPTURED BY +0004E9 1 ; A TRIAL MOVE, GENERATE REPLIES & +0004E9 1 ; EVALUATE THE EXCHANGE GAIN/LOSS +0004E9 1 ; +0004E9 1 50 FD TREE: bvc RETJ ; NO CAP +0004EB 1 A0 07 ldy #$07 ; (PIECES) +0004ED 1 A5 B1 lda SQUARE +0004EF 1 D9 60 00 LOOPX: cmp BK,Y +0004F2 1 F0 05 beq FOUNX +0004F4 1 88 dey +0004F5 1 F0 F1 beq RETJ ; (KING) +0004F7 1 10 F6 bpl LOOPX ; SAVE +0004F9 1 B9 51 0A FOUNX: lda POINTS,Y ; BEST CAP +0004FC 1 D5 22 cmp BCAP0,X ; AT THIS +0004FE 1 90 02 bcc NOMAX ; LEVEL +000500 1 95 22 sta BCAP0,X +000502 1 C6 B5 NOMAX: dec STATE +000504 1 A9 FB lda #$FB ; IF STATE=FB +000506 1 C5 B5 cmp STATE ; TIME TO TURN +000508 1 F0 03 beq UPTREE ; AROUND +00050A 1 20 4F 06 jsr GENRM ; GENERATE FURTHER +00050D 1 E6 B5 UPTREE: inc STATE ; CAPTURES +00050F 1 60 rts +000510 1 ; +000510 1 ; THE PLAYER'S MOVE IS INPUT +000510 1 ; +000510 1 C9 08 INPUT: cmp #$08 ; NOT A LEGAL +000512 1 B0 12 bcs ERROR ; SQUARE # +000514 1 20 1C 07 jsr DISMV +000517 1 A2 1F DISP: ldx #$1F +000519 1 B5 50 SEARCH: lda BOARD,X +00051B 1 C5 4A cmp DIS2 +00051D 1 F0 03 beq HERE ; DISPLAY +00051F 1 CA dex ; PIECE AT +000520 1 10 F7 bpl SEARCH ; FROM +000522 1 86 4B HERE: stx DIS1 ; SQUARE +000524 1 86 B0 stx PIECE +000526 1 4C 09 04 ERROR: jmp CHESS +000529 1 ; +000529 1 ; GENERATE ALL MOVES FOR ONE +000529 1 ; SIDE, CALL JANUS AFTER EACH +000529 1 ; ONE FOR NEXT STE? +000529 1 ; +000529 1 ; +000529 1 A2 10 GNMZ: ldx #$10 ; CLEAR +00052B 1 A9 00 GNMX: lda #$00 ; COUNTERS +00052D 1 95 2E CLEAR: sta COUNT,X +00052F 1 CA dex +000530 1 10 FB bpl CLEAR +000532 1 ; +000532 1 A9 10 GNM: lda #$10 ; SET UP +000534 1 85 B0 sta PIECE ; PIECE +000536 1 C6 B0 NEWP: dec PIECE ; NEW PIECE +000538 1 10 01 bpl NEX ; ALL DONE? +00053A 1 60 rts ; #NAME? +00053B 1 ; +00053B 1 20 48 06 NEX: jsr RESET ; READY +00053E 1 A4 B0 ldy PIECE ; GET PIECE +000540 1 A2 08 ldx #$08 +000542 1 86 B6 stx MOVEN ; COMMON staRT +000544 1 C0 08 cpy #$08 ; WHAT IS IT? +000546 1 10 41 bpl PAWN ; PAWN +000548 1 C0 06 cpy #$06 +00054A 1 10 2E bpl KNIGHT ; KNIGHT +00054C 1 C0 04 cpy #$04 +00054E 1 10 1F bpl BISHOP ; BISHOP +000550 1 C0 01 cpy #$01 +000552 1 F0 09 beq QUEEN ; QUEEN +000554 1 10 0E bpl ROOK ; ROOK +000556 1 ; +000556 1 20 B7 05 KING: jsr SNGMV ; MUST BE KING! +000559 1 D0 FB bne KING ; MOVES +00055B 1 F0 D9 beq NEWP ; 8 TO 1 +00055D 1 20 C5 05 QUEEN: jsr LINE +000560 1 D0 FB bne QUEEN ; MOVES +000562 1 F0 D2 beq NEWP ; 8 TO 1 +000564 1 ; +000564 1 A2 04 ROOK: ldx #$04 +000566 1 86 B6 stx MOVEN ; MOVES +000568 1 20 C5 05 AGNR: jsr LINE ; 4 TO 1 +00056B 1 D0 FB bne AGNR +00056D 1 F0 C7 beq NEWP +00056F 1 ; +00056F 1 20 C5 05 BISHOP: jsr LINE +000572 1 A5 B6 lda MOVEN ; MOVES +000574 1 C9 04 cmp #$04 ; 8 TO 5 +000576 1 D0 F7 bne BISHOP +000578 1 F0 BC beq NEWP +00057A 1 ; +00057A 1 A2 10 KNIGHT: ldx #$10 +00057C 1 86 B6 stx MOVEN ; MOVES +00057E 1 20 B7 05 AGNN: jsr SNGMV ; 16 TO 9 +000581 1 A5 B6 lda MOVEN +000583 1 C9 08 cmp #$08 +000585 1 D0 F7 bne AGNN +000587 1 F0 AD beq NEWP +000589 1 ; +000589 1 A2 06 PAWN: ldx #$06 +00058B 1 86 B6 stx MOVEN +00058D 1 20 F3 05 P1: jsr CMOVE ; RIGHT CAP? +000590 1 50 05 bvc P2 +000592 1 30 03 bmi P2 +000594 1 20 7D 04 jsr JANUS ; YES +000597 1 20 48 06 P2: jsr RESET +00059A 1 C6 B6 dec MOVEN ; LEFT CAP? +00059C 1 A5 B6 lda MOVEN +00059E 1 C9 05 cmp #$05 +0005A0 1 F0 EB beq P1 +0005A2 1 20 F3 05 P3: jsr CMOVE ; AHEAD +0005A5 1 70 8F bvs NEWP ; ILLEGAL +0005A7 1 30 8D bmi NEWP +0005A9 1 20 7D 04 jsr JANUS +0005AC 1 A5 B1 lda SQUARE ; GETS TO +0005AE 1 29 F0 and #$F0 ; 3RD RANK? +0005B0 1 C9 20 cmp #$20 +0005B2 1 F0 EE beq P3 ; DO DOUBLE +0005B4 1 4C 36 05 jmp NEWP +0005B7 1 ; +0005B7 1 ; CALCULATE SINGLE STEP MOVES +0005B7 1 ; FOR K,N +0005B7 1 ; +0005B7 1 20 F3 05 SNGMV: jsr CMOVE ; CALC MOVE +0005BA 1 30 03 bmi ILL1 ; -IF LEGAL +0005BC 1 20 7D 04 jsr JANUS ; -EVALUATE +0005BF 1 20 48 06 ILL1: jsr RESET +0005C2 1 C6 B6 dec MOVEN +0005C4 1 60 rts +0005C5 1 ; +0005C5 1 ; CALCULATE ALL MOVES DOWN A +0005C5 1 ; STRAIGHT LINE FOR Q,B,R +0005C5 1 ; +0005C5 1 20 F3 05 LINE: jsr CMOVE ; CALC MOVE +0005C8 1 90 02 bcc OVL ; NO CHK +0005CA 1 50 F9 bvc LINE ; NOCAP +0005CC 1 30 07 OVL: bmi ILL ; RETURN +0005CE 1 08 php +0005CF 1 20 7D 04 jsr JANUS ; EVALUATE POSN +0005D2 1 28 plp +0005D3 1 50 F0 bvc LINE ; NOT A CAP +0005D5 1 20 48 06 ILL: jsr RESET ; LINE STOPPED +0005D8 1 C6 B6 dec MOVEN ; NEXT DIR +0005DA 1 60 rts +0005DB 1 ; +0005DB 1 ; EXCHANGE SIDES FOR REPLY +0005DB 1 ; ANALYSIS +0005DB 1 ; +0005DB 1 A2 0F REVERSE:ldx #$0F +0005DD 1 38 ETC: sec +0005DE 1 B4 60 ldy BK,X ; SUBTRACT +0005E0 1 A9 77 lda #$77 ; POSITION +0005E2 1 F5 50 sbc BOARD,X ; FROM 77 +0005E4 1 95 60 sta BK,X +0005E6 1 94 50 sty BOARD,X ; and +0005E8 1 38 sec +0005E9 1 A9 77 lda #$77 ; EXCHANGE +0005EB 1 F5 50 sbc BOARD,X ; PIECES +0005ED 1 95 50 sta BOARD,X +0005EF 1 CA dex +0005F0 1 10 EB bpl ETC +0005F2 1 60 rts +0005F3 1 ; +0005F3 1 ; CMOVE CALCULATES THE TO SQUARE +0005F3 1 ; USING SQUARE and THE MOVE +0005F3 1 ; TABLE FLAGS SET AS FOLLOWS: +0005F3 1 ; N#NAME? MOVE +0005F3 1 ; V#NAME? (LEGAL UNLESS IN CR) +0005F3 1 ; C#NAME? BECAUSE OF CHECK +0005F3 1 ; [MY &THANKS TO JIM BUTTERFIELD +0005F3 1 ; WHO WROTE THIS MORE EFFICIENT +0005F3 1 ; VERSION OF CMOVE) +0005F3 1 ; +0005F3 1 A5 B1 CMOVE: lda SQUARE ; GET SQUARE +0005F5 1 A6 B6 ldx MOVEN ; MOVE POINTER +0005F7 1 18 clc +0005F8 1 7D 40 0A adc MOVEX,X ; MOVE LIST +0005FB 1 85 B1 sta SQUARE ; NEW POS'N +0005FD 1 29 88 and #$88 +0005FF 1 D0 42 bne ILLEGAL ; OFF BOARD +000601 1 A5 B1 lda SQUARE +000603 1 ; +000603 1 A2 20 ldx #$20 +000605 1 CA LOOP: dex ; IS TO +000606 1 30 0E bmi NO ; SQUARE +000608 1 D5 50 cmp BOARD,X ; OCCUPIED? +00060A 1 D0 F9 bne LOOP +00060C 1 ; +00060C 1 E0 10 cpx #$10 ; BY SELF? +00060E 1 30 33 bmi ILLEGAL +000610 1 ; +000610 1 A9 7F lda #$7F ; MUST BE CAP! +000612 1 69 01 adc #$01 ; SET V FLAG +000614 1 70 01 bvs SPX ; (jmp) +000616 1 ; +000616 1 B8 NO: clv ; NO CAPTURE +000617 1 ; +000617 1 A5 B5 SPX: lda STATE ; SHOULD WE +000619 1 30 24 bmi RETL ; DO THE +00061B 1 C9 08 cmp #$08 ; CHECK CHECK? +00061D 1 10 20 bpl RETL +00061F 1 ; +00061F 1 ; CHKCHK REVERSES SIDES +00061F 1 ; and LOOKS FOR A KING +00061F 1 ; CAPTURE TO INDICATE +00061F 1 ; ILLEGAL MOVE BECAUSE OF +00061F 1 ; CHECK SincE THIS IS +00061F 1 ; TIME CONSUMING, IT IS NOT +00061F 1 ; ALWAYS DONE +00061F 1 ; +00061F 1 48 CHKCHK: pha ; STATE #392 +000620 1 08 php +000621 1 A9 F9 lda #$F9 +000623 1 85 B5 sta STATE ; GENERATE +000625 1 85 B4 sta incHEK ; ALL REPLY +000627 1 20 75 06 jsr MOVE ; MOVES TO +00062A 1 20 DB 05 jsr REVERSE ; SEE IF KING +00062D 1 20 32 05 jsr GNM ; IS IN +000630 1 20 58 06 jsr RUM ; CHECK +000633 1 28 plp +000634 1 68 pla +000635 1 85 B5 sta STATE +000637 1 A5 B4 lda incHEK +000639 1 30 04 bmi RETL ; NO - SAFE +00063B 1 38 sec ; YES - IN CHK +00063C 1 A9 FF lda #$FF +00063E 1 60 rts +00063F 1 ; +00063F 1 18 RETL: clc ; LEGAL +000640 1 A9 00 lda #$00 ; RETURN +000642 1 60 rts +000643 1 ; +000643 1 A9 FF ILLEGAL:lda #$FF +000645 1 18 clc ; ILLEGAL +000646 1 B8 clv ; RETURN +000647 1 60 rts +000648 1 ; +000648 1 ; REPLACE PIECE ON CORRECT SQUARE +000648 1 ; +000648 1 A6 B0 RESET: ldx PIECE ; GET LOGAT +00064A 1 B5 50 lda BOARD,X ; FOR PIECE +00064C 1 85 B1 sta SQUARE ; FROM BOARD +00064E 1 60 rts +00064F 1 ; +00064F 1 ; +00064F 1 ; +00064F 1 20 75 06 GENRM: jsr MOVE ; MAKE MOVE +000652 1 20 DB 05 GENR2: jsr REVERSE ; REVERSE BOARD +000655 1 20 32 05 jsr GNM ; GENERATE MOVES +000658 1 20 DB 05 RUM: jsr REVERSE ; REVERSE BACK +00065B 1 ; +00065B 1 ; ROUTINE TO UNMAKE A MOVE MADE BY +00065B 1 ; MOVE +00065B 1 ; +00065B 1 BA UMOVE: tsx ; UNMAKE MOVE +00065C 1 86 B3 stx SP1 +00065E 1 A6 B2 ldx SP2 ; EXCHANGE +000660 1 9A txs ; STACKS +000661 1 68 pla ; MOVEN +000662 1 85 B6 sta MOVEN +000664 1 68 pla ; CAPTURED +000665 1 85 B0 sta PIECE ; PIECE +000667 1 AA tax +000668 1 68 pla ; FROM SQUARE +000669 1 95 50 sta BOARD,X +00066B 1 68 pla ; PIECE +00066C 1 AA tax +00066D 1 68 pla ; TO SOUARE +00066E 1 85 B1 sta SQUARE +000670 1 95 50 sta BOARD,X +000672 1 4C 9A 06 jmp STRV +000675 1 ; +000675 1 ; THIS ROUTINE MOVES PIECE +000675 1 ; TO SQUARE, PARAMETERS +000675 1 ; ARE SAVED IN A staCK TO UNMAKE +000675 1 ; THE MOVE LATER +000675 1 ; +000675 1 BA MOVE: tsx +000676 1 86 B3 stx SP1 ; SWITCH +000678 1 A6 B2 ldx SP2 ; STACKS +00067A 1 9A txs +00067B 1 A5 B1 lda SQUARE +00067D 1 48 pha ; TO SQUARE +00067E 1 A8 tay +00067F 1 A2 1F ldx #$1F +000681 1 D5 50 CHECK: cmp BOARD,X ; CHECK FOR +000683 1 F0 03 beq TAKE ; CAPTURE +000685 1 CA dex +000686 1 10 F9 bpl CHECK +000688 1 A9 CC TAKE: lda #$CC +00068A 1 95 50 sta BOARD,X +00068C 1 8A txa ; CAPTURED +00068D 1 48 pha ; PIECE +00068E 1 A6 B0 ldx PIECE +000690 1 B5 50 lda BOARD,X +000692 1 94 50 sty BOARD,X ; FROM +000694 1 48 pha ; SQUARE +000695 1 8A txa +000696 1 48 pha ; PIECE +000697 1 A5 B6 lda MOVEN +000699 1 48 pha ; MOVEN +00069A 1 BA STRV: tsx +00069B 1 86 B2 stx SP2 ; SWITCH +00069D 1 A6 B3 ldx SP1 ; STACKS +00069F 1 9A txs ; BACK +0006A0 1 60 rts +0006A1 1 ; +0006A1 1 ; CONTINUATION OF SUB STRATGY +0006A1 1 ; -CHECKS FOR CHECK OR CHECKMATE +0006A1 1 ; and ASSIGNS VALUE TO MOVE +0006A1 1 ; +0006A1 1 A4 24 CKMATE: ldy BMAXC ; CAN BLK CAP +0006A3 1 EC 51 0A cpx POINTS ; MY KING? +0006A6 1 D0 04 bne NOCHEK +0006A8 1 A9 00 lda #$00 ; GULP! +0006AA 1 F0 0A beq RETV ; DUMB MOVE! +0006AC 1 ; +0006AC 1 A6 23 NOCHEK: ldx BMOB ; IS BLACK +0006AE 1 D0 06 bne RETV ; UNABLE TO +0006B0 1 A6 3E ldx WMAXP ; MOVE and +0006B2 1 D0 02 bne RETV ; KING IN CH? +0006B4 1 A9 FF lda #$FF ; YES! MATE +0006B6 1 ; +0006B6 1 A2 04 RETV: ldx #$04 ; RESTORE +0006B8 1 86 B5 stx STATE ; STATE=4 +0006BA 1 ; +0006BA 1 ; THE VALUE OF THE MOVE (IN ACCU) +0006BA 1 ; IS COMPARED TO THE BEST MOVE and +0006BA 1 ; REPLACES IT IF IT IS BETTER +0006BA 1 ; +0006BA 1 C5 4A PUSH: cmp BESTV ; IS THIS BEST +0006BC 1 90 0C bcc RETP ; MOVE SO FAR? +0006BE 1 F0 0A beq RETP +0006C0 1 85 4A sta BESTV ; YES! +0006C2 1 A5 B0 lda PIECE ; SAVE IT +0006C4 1 85 4B sta BESTP +0006C6 1 A5 B1 lda SQUARE +0006C8 1 85 49 sta BESTM ; FLASH DISPLAY +0006CA 1 A9 2E RETP: lda #'.' ; print ... instead of flashing disp +0006CC 1 4C 8F 08 jmp syschout ; print . and return +0006CF 1 ; +0006CF 1 ; MAIN PROGRAM TO PLAY CHESS +0006CF 1 ; PLAY FROM OPENING OR THINK +0006CF 1 ; +0006CF 1 A6 2C GO: ldx OMOVE ; OPENING? +0006D1 1 30 1C bmi NOOPEN ; -NO *ADD CHANGE FROM bpl +0006D3 1 A5 49 lda DIS3 ; -YES WAS +0006D5 1 DD 61 0A cmp OPNING,X ; OPPONENT'S +0006D8 1 D0 11 bne END ; MOVE OK? +0006DA 1 CA dex +0006DB 1 BD 61 0A lda OPNING,X ; GET NEXT +0006DE 1 85 4B sta DIS1 ; CANNED +0006E0 1 CA dex ; OPENING MOVE +0006E1 1 BD 61 0A lda OPNING,X +0006E4 1 85 49 sta DIS3 ; DISPLAY IT +0006E6 1 CA dex +0006E7 1 86 2C stx OMOVE ; MOVE IT +0006E9 1 D0 1C bne MV2 ; (jmp) +0006EB 1 ; +0006EB 1 A9 FF END: lda #$FF ; *ADD - STOP CANNED MOVES +0006ED 1 85 2C sta OMOVE ; FLAG OPENING +0006EF 1 A2 0C NOOPEN: ldx #$0C ; FINISHED +0006F1 1 86 B5 stx STATE ; STATE=C +0006F3 1 86 4A stx BESTV ; CLEAR BESTV +0006F5 1 A2 14 ldx #$14 ; GENERATE P +0006F7 1 20 2B 05 jsr GNMX ; MOVES +0006FA 1 ; +0006FA 1 A2 04 ldx #$04 ; STATE=4 +0006FC 1 86 B5 stx STATE ; GENERATE and +0006FE 1 20 29 05 jsr GNMZ ; TEST AVAILABLE +000701 1 ; +000701 1 ; MOVES +000701 1 ; +000701 1 A6 4A ldx BESTV ; GET BEST MOVE +000703 1 E0 0F cpx #$0F ; IF NONE +000705 1 90 12 bcc MATE ; OH OH! +000707 1 ; +000707 1 A6 4B MV2: ldx BESTP ; MOVE +000709 1 B5 50 lda BOARD,X ; THE +00070B 1 85 4A sta BESTV ; BEST +00070D 1 86 B0 stx PIECE ; MOVE +00070F 1 A5 49 lda BESTM +000711 1 85 B1 sta SQUARE ; and DISPLAY +000713 1 20 75 06 jsr MOVE ; IT +000716 1 4C 09 04 jmp CHESS +000719 1 ; +000719 1 A9 FF MATE: lda #$FF ; RESIGN +00071B 1 60 rts ; OR staLEMATE +00071C 1 ; +00071C 1 ; SUBROUTINE TO ENTER THE +00071C 1 ; PLAYER'S MOVE +00071C 1 ; +00071C 1 A2 04 DISMV: ldx #$04 ; ROTATE +00071E 1 06 49 Drol: asl DIS3 ; KEY +000720 1 26 4A rol DIS2 ; INTO +000722 1 CA dex ; DISPLAY +000723 1 D0 F9 bne Drol ; +000725 1 05 49 ora DIS3 +000727 1 85 49 sta DIS3 +000729 1 85 B1 sta SQUARE +00072B 1 60 rts +00072C 1 ; +00072C 1 ; THE FOLLOWING SUBROUTINE ASSIGNS +00072C 1 ; A VALUE TO THE MOVE UNDER +00072C 1 ; CONSIDERATION and RETURNS IT IN +00072C 1 ; THE ACCUMULATOR +00072C 1 ; +00072C 1 +00072C 1 18 STRATGY:clc +00072D 1 A9 80 lda #$80 +00072F 1 65 2B adc WMOB ; PARAMETERS +000731 1 65 3C adc WMAXC ; WITH WHEIGHT +000733 1 65 3D adc WCC ; OF O25 +000735 1 65 21 adc WCAP1 +000737 1 65 2F adc WCAP2 +000739 1 38 sec +00073A 1 E5 40 sbc PMAXC +00073C 1 E5 41 sbc PCC +00073E 1 E5 22 sbc BCAP0 +000740 1 E5 20 sbc BCAP1 +000742 1 E5 2E sbc BCAP2 +000744 1 E5 3F sbc PMOB +000746 1 E5 23 sbc BMOB +000748 1 B0 02 bcs POS ; UNDERFLOW +00074A 1 A9 00 lda #$00 ; PREVENTION +00074C 1 4A POS: lsr +00074D 1 18 clc ; ************** +00074E 1 69 40 adc #$40 +000750 1 65 3C adc WMAXC ; PARAMETERS +000752 1 65 3D adc WCC ; WITH WEIGHT +000754 1 38 sec ; OF 05 +000755 1 E5 24 sbc BMAXC +000757 1 4A lsr ; ************** +000758 1 18 clc +000759 1 69 90 adc #$90 +00075B 1 65 2D adc WCAP0 ; PARAMETERS +00075D 1 65 2D adc WCAP0 ; WITH WEIGHT +00075F 1 65 2D adc WCAP0 ; OF 10 +000761 1 65 2D adc WCAP0 +000763 1 65 21 adc WCAP1 +000765 1 38 sec ; [UNDER OR OVER- +000766 1 E5 24 sbc BMAXC ; FLOW MAY OCCUR +000768 1 E5 24 sbc BMAXC ; FROM THIS +00076A 1 E5 25 sbc BMCC ; secTION] +00076C 1 E5 25 sbc BMCC +00076E 1 E5 20 sbc BCAP1 +000770 1 A6 B1 ldx SQUARE ; *************** +000772 1 E0 33 cpx #$33 +000774 1 F0 16 beq POSN ; POSITION +000776 1 E0 34 cpx #$34 ; BONUS FOR +000778 1 F0 12 beq POSN ; MOVE TO +00077A 1 E0 22 cpx #$22 ; CENTRE +00077C 1 F0 0E beq POSN ; OR +00077E 1 E0 25 cpx #$25 ; OUT OF +000780 1 F0 0A beq POSN ; BACK RANK +000782 1 A6 B0 ldx PIECE +000784 1 F0 09 beq NOPOSN +000786 1 B4 50 ldy BOARD,X +000788 1 C0 10 cpy #$10 +00078A 1 10 03 bpl NOPOSN +00078C 1 18 POSN: clc +00078D 1 69 02 adc #$02 +00078F 1 4C A1 06 NOPOSN: jmp CKMATE ; CONTINUE +000792 1 +000792 1 +000792 1 ;----------------------------------------------------------------- +000792 1 ; The following routines were added to allow text-based board +000792 1 ; DISPLAY over a standard RS-232 port. +000792 1 ; +000792 1 AD 07 04 POUT: lda PAINT +000795 1 D0 01 bne POUT0 +000797 1 60 rts ; return if PAINT flag = 0 +000798 1 20 37 08 POUT0: jsr POUT9 ; print CRLF +00079B 1 20 5B 08 jsr POUT13 ; print copyright +00079E 1 20 42 08 jsr POUT10 ; print column labels +0007A1 1 A0 00 ldy #$00 ; init board location +0007A3 1 20 09 08 jsr POUT5 ; print board horz edge +0007A6 1 A9 7C POUT1: lda #'|' ; print vert edge +0007A8 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - SPACE +0007AB 1 A2 1F ldx #$1F +0007AD 1 98 POUT2: tya ; scan the pieces for a location match +0007AE 1 D5 50 cmp BOARD,X ; match found? +0007B0 1 F0 40 beq POUT4 ; yes; print the piece's color and type +0007B2 1 CA dex ; no +0007B3 1 10 F8 bpl POUT2 ; if not the last piece, try again +0007B5 1 98 tya ; empty square +0007B6 1 29 01 and #$01 ; odd or even column? +0007B8 1 85 4C sta temp ; save it +0007BA 1 98 tya ; is the row odd or even +0007BB 1 4A lsr ; shift column right 4 spaces +0007BC 1 4A lsr ; +0007BD 1 4A lsr ; +0007BE 1 4A lsr ; +0007BF 1 29 01 and #$01 ; strip LSB +0007C1 1 18 clc ; +0007C2 1 65 4C adc temp ; combine row & col to determine square color +0007C4 1 29 01 and #$01 ; is board square white or blk? +0007C6 1 D0 03 bne POUT25 ; white, print space +0007C8 1 A9 2A lda #'*' ; black, print * +0007CA 1 +0007CA 1 2C .byte $2c ; used to skip over lda #$20 +0007CB 1 ;jmp POUT25A +0007CB 1 +0007CB 1 A9 20 POUT25: lda #$20 ; ASCII space +0007CD 1 20 8F 08 POUT25A:jsr syschout ; PRINT ONE ASCII CHR - SPACE +0007D0 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - SPACE +0007D3 1 C8 POUT3: iny ; +0007D4 1 98 tya ; get row number +0007D5 1 29 08 and #$08 ; have we completed the row? +0007D7 1 F0 CD beq POUT1 ; no, do next column +0007D9 1 A9 7C lda #'|' ; yes, put the right edge on +0007DB 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - | +0007DE 1 20 54 08 jsr POUT12 ; print row number +0007E1 1 20 37 08 jsr POUT9 ; print CRLF +0007E4 1 20 09 08 jsr POUT5 ; print bottom edge of board +0007E7 1 18 clc ; +0007E8 1 98 tya ; +0007E9 1 69 08 adc #$08 ; point y to beginning of next row +0007EB 1 A8 tay ; +0007EC 1 C0 80 cpy #$80 ; was that the last row? +0007EE 1 F0 2B beq POUT8 ; yes, print the LED values +0007F0 1 D0 B4 bne POUT1 ; no, do new row +0007F2 1 +0007F2 1 A5 B7 POUT4: lda REV ; print piece's color & type +0007F4 1 F0 05 beq POUT41 ; +0007F6 1 BD 0D 09 lda cpl+16,X ; +0007F9 1 D0 03 bne POUT42 ; +0007FB 1 BD FD 08 POUT41: lda cpl,x ; +0007FE 1 20 8F 08 POUT42: jsr syschout ; +000801 1 BD 2D 09 lda cph,x ; +000804 1 20 8F 08 jsr syschout ; +000807 1 D0 CA bne POUT3 ; branch always +000809 1 +000809 1 8A POUT5: txa ; print "-----...-----" +00080A 1 48 pha +00080B 1 A2 19 ldx #$19 +00080D 1 A9 2D lda #'-' +00080F 1 20 8F 08 POUT6: jsr syschout ; PRINT ONE ASCII CHR - "-" +000812 1 CA dex +000813 1 D0 FA bne POUT6 +000815 1 68 pla +000816 1 AA tax +000817 1 20 37 08 jsr POUT9 +00081A 1 60 rts +00081B 1 +00081B 1 20 42 08 POUT8: jsr POUT10 ; +00081E 1 A5 4B lda BESTP +000820 1 20 9B 08 jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS +000823 1 A9 20 lda #$20 +000825 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - SPACE +000828 1 A5 4A lda BESTV +00082A 1 20 9B 08 jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS +00082D 1 A9 20 lda #$20 +00082F 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - SPACE +000832 1 A5 49 lda DIS3 +000834 1 20 9B 08 jsr syshexout ; PRINT 1 BYTE AS 2 HEX CHRS +000837 1 +000837 1 A9 0D POUT9: lda #$0D +000839 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - CR +00083C 1 A9 0A lda #$0A +00083E 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - LF +000841 1 60 rts +000842 1 +000842 1 A2 00 POUT10: ldx #$00 ; print the column labels +000844 1 A9 20 POUT11: lda #$20 ; 00 01 02 03 ... 07 +000846 1 20 8F 08 jsr syschout +000849 1 8A txa +00084A 1 20 9B 08 jsr syshexout +00084D 1 E8 inx +00084E 1 E0 08 cpx #$08 +000850 1 D0 F2 bne POUT11 +000852 1 F0 E3 beq POUT9 +000854 1 98 POUT12: tya +000855 1 29 70 and #$70 +000857 1 20 9B 08 jsr syshexout +00085A 1 60 rts +00085B 1 +00085B 1 ; print banner only once, preserve registers A, X, Y +00085B 1 86 F6 POUT13: stx tmp_zpgPt +00085D 1 85 F7 sta tmp_zpgPt+1 +00085F 1 84 F8 sty tmp_zpgPt+2 +000861 1 AD 08 04 lda PRNBANN +000864 1 F0 0B beq NOPRNBANN +000866 1 A9 C1 lda #banner +00086C 1 85 E1 sta mos_StrPtr+1 +00086E 1 20 F3 FF jsr mos_CallPuts +000871 1 NOPRNBANN: +000871 1 A9 00 lda #$00 +000873 1 8D 08 04 sta PRNBANN +000876 1 A6 F6 ldx tmp_zpgPt +000878 1 A5 F7 lda tmp_zpgPt+1 +00087A 1 A4 F8 ldy tmp_zpgPt+2 +00087C 1 60 rts +00087D 1 +00087D 1 ; ldx #$00 ; Print the copyright banner +00087D 1 ;POUT14: lda banner,x +00087D 1 ; beq POUT15 +00087D 1 ; jsr syschout +00087D 1 ; inx +00087D 1 ; bne POUT14 +00087D 1 ;POUT15: rts +00087D 1 +00087D 1 A9 3F KIN: lda #'?' +00087F 1 20 8F 08 jsr syschout ; PRINT ONE ASCII CHR - ? +000882 1 20 8B 08 jsr syskin ; GET A KEYSTROKE FROM SYSTEM +000885 1 20 8F 08 jsr syschout ; echo entered character +000888 1 29 4F and #$4F ; MASK 0-7, and ALpha'S +00088A 1 60 rts +00088B 1 ; +00088B 1 ; 6551 I/O Support Routines +00088B 1 ; +00088B 1 ; +00088B 1 ;Init_6551 lda #$1F ; 19.2K/8/1 +00088B 1 ; sta ACIActl ; control reg +00088B 1 ; lda #$0B ; N parity/echo off/rx int off/ dtr active low +00088B 1 ; sta ACIAcmd ; command reg +00088B 1 ; rts ; done +00088B 1 ; +00088B 1 ; input chr from ACIA1 (waiting) +00088B 1 ; +00088B 1 syskin: +00088B 1 20 ED FF jsr mos_CallGetCh +00088E 1 60 rts +00088F 1 +00088F 1 ;lda ACIAsta ; Serial port status +00088F 1 ;and #$08 ; is recvr full +00088F 1 ;beq syskin ; no char to get +00088F 1 ;lda ACIAdat ; get chr +00088F 1 ;rts ; +00088F 1 ; +00088F 1 ; output to OutPut Port +00088F 1 ; +00088F 1 syschout: ; MKHBCOS: must preserve X, Y and A +00088F 1 86 F6 stx tmp_zpgPt +000891 1 85 F7 sta tmp_zpgPt+1 +000893 1 ;sty tmp_zpgPt+2 +000893 1 20 F0 FF jsr mos_CallPutCh +000896 1 A6 F6 ldx tmp_zpgPt +000898 1 A5 F7 lda tmp_zpgPt+1 +00089A 1 ;ldy tmp_zpgPt+2 +00089A 1 60 rts +00089B 1 ; pha ; save registers +00089B 1 ;ACIA_Out1 lda ACIAsta ; serial port status +00089B 1 ; and #$10 ; is tx buffer empty +00089B 1 ; beq ACIA_Out1 ; no +00089B 1 ; pla ; get chr +00089B 1 ; sta ACIAdat ; put character to Port +00089B 1 ; rts ; done +00089B 1 +00089B 1 48 syshexout: pha ; prints AA hex digits +00089C 1 4A lsr ; MOVE UPPER NIBBLE TO LOWER +00089D 1 4A lsr ; +00089E 1 4A lsr ; +00089F 1 4A lsr ; +0008A0 1 20 A4 08 jsr PrintDig ; +0008A3 1 68 pla ; +0008A4 1 PrintDig: +0008A4 1 84 F8 sty tmp_zpgPt+2 +0008A6 1 29 0F and #$0F ; +0008A8 1 A8 tay ; +0008A9 1 B9 B1 08 lda Hexdigdata,Y ; +0008AC 1 A4 F8 ldy tmp_zpgPt+2 ; +0008AE 1 4C 8F 08 jmp syschout ; +0008B1 1 +0008B1 1 30 31 32 33 Hexdigdata: .byte "0123456789ABCDEF" +0008B5 1 34 35 36 37 +0008B9 1 38 39 41 42 +0008C1 1 4D 69 63 72 banner: .byte "MicroChess (c) 1996-2002 Peter Jennings, peterj@benlo.com" +0008C5 1 6F 43 68 65 +0008C9 1 73 73 20 28 +0008FA 1 0D 0A 00 .byte $0d, $0a, $00 +0008FD 1 57 57 57 57 cpl: .byte "WWWWWWWWWWWWWWWWBBBBBBBBBBBBBBBBWWWWWWWWWWWWWWWW" +000901 1 57 57 57 57 +000905 1 57 57 57 57 +00092D 1 4B 51 43 43 cph: .byte "KQCCBBRRPPPPPPPPKQCCBBRRPPPPPPPP" +000931 1 42 42 52 52 +000935 1 50 50 50 50 +00094D 1 00 .byte $00 +00094E 1 ; +00094E 1 ; end of added code +00094E 1 ; +00094E 1 ; BLOCK DATA +00094E 1 +00094E 1 .segment "DATA" +00094E 1 +00094E 1 .ORG $0A20 +000A20 1 +000A20 1 03 04 00 07 SETW: .byte $03, $04, $00, $07, $02, $05, $01, $06 +000A24 1 02 05 01 06 +000A28 1 10 17 11 16 .byte $10, $17, $11, $16, $12, $15, $14, $13 +000A2C 1 12 15 14 13 +000A30 1 73 74 70 77 .byte $73, $74, $70, $77, $72, $75, $71, $76 +000A34 1 72 75 71 76 +000A38 1 60 67 61 66 .byte $60, $67, $61, $66, $62, $65, $64, $63 +000A3C 1 62 65 64 63 +000A40 1 +000A40 1 00 F0 FF 01 MOVEX: .byte $00, $F0, $FF, $01, $10, $11, $0F, $EF, $F1 +000A44 1 10 11 0F EF +000A48 1 F1 +000A49 1 DF E1 EE F2 .byte $DF, $E1, $EE, $F2, $12, $0E, $1F, $21 +000A4D 1 12 0E 1F 21 +000A51 1 +000A51 1 0B 0A 06 06 POINTS: .byte $0B, $0A, $06, $06, $04, $04, $04, $04 +000A55 1 04 04 04 04 +000A59 1 02 02 02 02 .byte $02, $02, $02, $02, $02, $02, $02, $02 +000A5D 1 02 02 02 02 +000A61 1 +000A61 1 99 25 0B 25 OPNING: .byte $99, $25, $0B, $25, $01, $00, $33, $25 +000A65 1 01 00 33 25 +000A69 1 07 36 34 0D .byte $07, $36, $34, $0D, $34, $34, $0E, $52 +000A6D 1 34 34 0E 52 +000A71 1 25 0D 45 35 .byte $25, $0D, $45, $35, $04, $55, $22, $06 +000A75 1 04 55 22 06 +000A79 1 43 33 0F CC .byte $43, $33, $0F, $CC +000A7D 1 +000A7D 1 .segment "KERN" +000A7D 1 +000A7D 1 .ORG $FE00 +00FE00 1 +00FE00 1 AD 00 E0 CHRIN: lda $E000 +00FE03 1 60 rts +00FE04 1 +00FE04 1 8D 00 E0 CHROUT: sta $E000 +00FE07 1 60 rts +00FE08 1 +00FE08 1 ; this function was shamelessly ripped :-) from M.O.S. code (c) by Scott Chidester +00FE08 1 +00FE08 1 STROUT: +00FE08 1 A0 00 ldy #0 ; Non-indexed variant starts at zero, of course +00FE0A 1 A5 E1 lda mos_StrPtr+1 ; Save StrPtr so it isn't modified +00FE0C 1 48 pha +00FE0D 1 PutsLoop: +00FE0D 1 B1 E0 lda (mos_StrPtr),y ; Get the next char in the string +00FE0F 1 F0 0B beq PutsDone ; Zero means end of string +00FE11 1 20 04 FE jsr CHROUT ; Otherwise put the char +00FE14 1 +00FE14 1 ; Update string pointer +00FE14 1 C8 iny ; increment StrPtr-lo +00FE15 1 D0 F6 bne PutsLoop ; No rollover? Loop back for next character +00FE17 1 E6 E1 inc mos_StrPtr+1 ; StrPtr-lo rolled over--carry hi byte +00FE19 1 4C 0D FE jmp PutsLoop ; Now loop back +00FE1C 1 +00FE1C 1 PutsDone: +00FE1C 1 68 pla +00FE1D 1 85 E1 sta mos_StrPtr+1 ; Restore StrPtr +00FE1F 1 60 rts +00FE20 1 +00FE20 1 .segment "VECT" +00FE20 1 +00FE20 1 .ORG $FFED +00FFED 1 +00FFED 1 4C 00 FE jmp CHRIN +00FFF0 1 4C 04 FE jmp CHROUT +00FFF3 1 4C 08 FE jmp STROUT +00FFF6 1 +00FFF6 1 ; +00FFF6 1 ; +00FFF6 1 ; end of file +00FFF6 1 ; +00FFF6 1 diff --git a/microchess.o b/microchess.o new file mode 100644 index 0000000..f69541f Binary files /dev/null and b/microchess.o differ diff --git a/numbers.bas b/numbers.bas new file mode 100644 index 0000000..1aee208 --- /dev/null +++ b/numbers.bas @@ -0,0 +1,10 @@ +10 LET A=0 +15 LET B=0 +20 PRINT A;" "; +30 LET A=A+1 +32 LET B=B+1 +35 IF B>9 THEN GOTO 60 +40 IF A>1000 THEN END +50 GOTO 20 +60 PRINT +70 GOTO 15 diff --git a/system.h b/system.h new file mode 100644 index 0000000..b9aebea --- /dev/null +++ b/system.h @@ -0,0 +1,3 @@ +#if !defined(LINUX) +#define WINDOWS +#endif diff --git a/t_adc_bcd_01.65s b/t_adc_bcd_01.65s index 6266710..17a2233 100644 --- a/t_adc_bcd_01.65s +++ b/t_adc_bcd_01.65s @@ -1,99 +1,99 @@ -; ADC, test decimal mode. -; -; NV-BDIZC -; ??1110?? -; -; The results I got on Rockwell 6502 AP -; -; 00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (3A) -; 79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (F8) -; 24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (F8) -; 93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (79) -; 89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (39) -; 89 + 76 and C=1 gives 66 and N=0 V=0 Z=0 C=1 (39) -; 80 + f0 and C=0 gives d0 and N=1 V=1 Z=0 C=1 (F9) -; 80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (B9) -; 2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (38) -; 6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (38) - -RES=$0300 - - *=$0200 - - SED - CLC - LDA #$00 - ADC #$00 - STA RES - PHP - PLA - STA RES+1 - SEC - LDA #$79 - ADC #$00 - STA RES+2 - PHP - PLA - STA RES+3 - CLC - LDA #$24 - ADC #$56 - STA RES+4 - PHP - PLA - STA RES+5 - CLC - LDA #$93 - ADC #$82 - STA RES+6 - PHP - PLA - STA RES+7 - CLC - LDA #$89 - ADC #$76 - STA RES+8 - PHP - PLA - STA RES+9 - SEC - LDA #$89 - ADC #$76 - STA RES+10 - PHP - PLA - STA RES+11 - CLC - LDA #$80 - ADC #$F0 - STA RES+12 - PHP - PLA - STA RES+13 - CLC - LDA #$80 - ADC #$FA - STA RES+14 - PHP - PLA - STA RES+15 - CLC - LDA #$2F - ADC #$4F - STA RES+16 - PHP - PLA - STA RES+17 - SEC - LDA #$6F - ADC #$00 - STA RES+18 - PHP - PLA - STA RES+19 - BRK - - *=$0300 - - .DS 20 +; ADC, test decimal mode. +; +; NV-BDIZC +; ??1110?? +; +; The results I got on Rockwell 6502 AP +; +; 00 + 00 and C=0 gives 00 and N=0 V=0 Z=1 C=0 (3A) +; 79 + 00 and C=1 gives 80 and N=1 V=1 Z=0 C=0 (F8) +; 24 + 56 and C=0 gives 80 and N=1 V=1 Z=0 C=0 (F8) +; 93 + 82 and C=0 gives 75 and N=0 V=1 Z=0 C=1 (79) +; 89 + 76 and C=0 gives 65 and N=0 V=0 Z=0 C=1 (39) +; 89 + 76 and C=1 gives 66 and N=0 V=0 Z=0 C=1 (39) +; 80 + f0 and C=0 gives d0 and N=1 V=1 Z=0 C=1 (F9) +; 80 + fa and C=0 gives e0 and N=1 V=0 Z=0 C=1 (B9) +; 2f + 4f and C=0 gives 74 and N=0 V=0 Z=0 C=0 (38) +; 6f + 00 and C=1 gives 76 and N=0 V=0 Z=0 C=0 (38) + +RES=$0300 + + *=$0200 + + SED + CLC + LDA #$00 + ADC #$00 + STA RES + PHP + PLA + STA RES+1 + SEC + LDA #$79 + ADC #$00 + STA RES+2 + PHP + PLA + STA RES+3 + CLC + LDA #$24 + ADC #$56 + STA RES+4 + PHP + PLA + STA RES+5 + CLC + LDA #$93 + ADC #$82 + STA RES+6 + PHP + PLA + STA RES+7 + CLC + LDA #$89 + ADC #$76 + STA RES+8 + PHP + PLA + STA RES+9 + SEC + LDA #$89 + ADC #$76 + STA RES+10 + PHP + PLA + STA RES+11 + CLC + LDA #$80 + ADC #$F0 + STA RES+12 + PHP + PLA + STA RES+13 + CLC + LDA #$80 + ADC #$FA + STA RES+14 + PHP + PLA + STA RES+15 + CLC + LDA #$2F + ADC #$4F + STA RES+16 + PHP + PLA + STA RES+17 + SEC + LDA #$6F + ADC #$00 + STA RES+18 + PHP + PLA + STA RES+19 + BRK + + *=$0300 + + .DS 20 \ No newline at end of file diff --git a/t_adc_bcd_01.dat b/t_adc_bcd_01.dat index 52375ca..bb09293 100644 --- a/t_adc_bcd_01.dat +++ b/t_adc_bcd_01.dat @@ -1,36 +1,36 @@ -; Test ADC BCD mode. -ORG -$0200 -$F8 $18 $A9 $00 $69 $00 $8D $00 -$03 $08 $68 $8D $01 $03 $38 $A9 -$79 $69 $00 $8D $02 $03 $08 $68 -$8D $03 $03 $18 $A9 $24 $69 $56 -$8D $04 $03 $08 $68 $8D $05 $03 -$18 $A9 $93 $69 $82 $8D $06 $03 -$08 $68 $8D $07 $03 $18 $A9 $89 -$69 $76 $8D $08 $03 $08 $68 $8D -$09 $03 $38 $A9 $89 $69 $76 $8D -$0A $03 $08 $68 $8D $0B $03 $18 -$A9 $80 $69 $F0 $8D $0C $03 $08 -$68 $8D $0D $03 $18 $A9 $80 $69 -$FA $8D $0E $03 $08 $68 $8D $0F -$03 $18 $A9 $2F $69 $4F $8D $10 -$03 $08 $68 $8D $11 $03 $38 $A9 -$6F $69 $00 $8D $12 $03 $08 $68 -$8D $13 $03 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 - +; Test ADC BCD mode. +ORG +$0200 +$F8 $18 $A9 $00 $69 $00 $8D $00 +$03 $08 $68 $8D $01 $03 $38 $A9 +$79 $69 $00 $8D $02 $03 $08 $68 +$8D $03 $03 $18 $A9 $24 $69 $56 +$8D $04 $03 $08 $68 $8D $05 $03 +$18 $A9 $93 $69 $82 $8D $06 $03 +$08 $68 $8D $07 $03 $18 $A9 $89 +$69 $76 $8D $08 $03 $08 $68 $8D +$09 $03 $38 $A9 $89 $69 $76 $8D +$0A $03 $08 $68 $8D $0B $03 $18 +$A9 $80 $69 $F0 $8D $0C $03 $08 +$68 $8D $0D $03 $18 $A9 $80 $69 +$FA $8D $0E $03 $08 $68 $8D $0F +$03 $18 $A9 $2F $69 $4F $8D $10 +$03 $08 $68 $8D $11 $03 $38 $A9 +$6F $69 $00 $8D $12 $03 $08 $68 +$8D $13 $03 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 + diff --git a/t_sbc_bcd_01.65s b/t_sbc_bcd_01.65s index e78c36c..c164095 100644 --- a/t_sbc_bcd_01.65s +++ b/t_sbc_bcd_01.65s @@ -1,85 +1,85 @@ -; SBC, test decimal mode. -; -; NV-BDIZC -; ??1110?? -; -; Expected results (I got on Rockwell 6502 AP): -; 00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (B8) -; 00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (3B) -; 00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (B8) -; 0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (39) -; 0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (39) -; 9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (B9) -; 9b - 00 and C=0 gives 9a and N=1 V=0 Z=0 C=1 (B9) -; - - *=$0200 - - SED - CLC - LDA #$00 - SBC #$00 - STA SBT1A - PHP - PLA - STA SBT1F - SEC - LDA #$00 - SBC #$00 - STA SBT2A - PHP - PLA - STA SBT2F - SEC - LDA #$00 - SBC #$01 - STA SBT3A - PHP - PLA - STA SBT3F - SEC - LDA #$0A - SBC #$00 - STA SBT4A - PHP - PLA - STA SBT4F - CLC - LDA #$0B - SBC #$00 - STA SBT5A - PHP - PLA - STA SBT5F - SEC - LDA #$9A - SBC #$00 - STA SBT6A - PHP - PLA - STA SBT6F - CLC - LDA #$9B - SBC #$00 - STA SBT7A - PHP - PLA - STA SBT7F - BRK - - *=$0300 - -SBT1A: .DB 0 -SBT1F: .DB 0 -SBT2A: .DB 0 -SBT2F: .DB 0 -SBT3A: .DB 0 -SBT3F: .DB 0 -SBT4A: .DB 0 -SBT4F: .DB 0 -SBT5A: .DB 0 -SBT5F: .DB 0 -SBT6A: .DB 0 -SBT6F: .DB 0 -SBT7A: .DB 0 +; SBC, test decimal mode. +; +; NV-BDIZC +; ??1110?? +; +; Expected results (I got on Rockwell 6502 AP): +; 00 - 00 and C=0 gives 99 and N=1 V=0 Z=0 C=0 (B8) +; 00 - 00 and C=1 gives 00 and N=0 V=0 Z=1 C=1 (3B) +; 00 - 01 and C=1 gives 99 and N=1 V=0 Z=0 C=0 (B8) +; 0a - 00 and C=1 gives 0a and N=0 V=0 Z=0 C=1 (39) +; 0b - 00 and C=0 gives 0a and N=0 V=0 Z=0 C=1 (39) +; 9a - 00 and C=1 gives 9a and N=1 V=0 Z=0 C=1 (B9) +; 9b - 00 and C=0 gives 9a and N=1 V=0 Z=0 C=1 (B9) +; + + *=$0200 + + SED + CLC + LDA #$00 + SBC #$00 + STA SBT1A + PHP + PLA + STA SBT1F + SEC + LDA #$00 + SBC #$00 + STA SBT2A + PHP + PLA + STA SBT2F + SEC + LDA #$00 + SBC #$01 + STA SBT3A + PHP + PLA + STA SBT3F + SEC + LDA #$0A + SBC #$00 + STA SBT4A + PHP + PLA + STA SBT4F + CLC + LDA #$0B + SBC #$00 + STA SBT5A + PHP + PLA + STA SBT5F + SEC + LDA #$9A + SBC #$00 + STA SBT6A + PHP + PLA + STA SBT6F + CLC + LDA #$9B + SBC #$00 + STA SBT7A + PHP + PLA + STA SBT7F + BRK + + *=$0300 + +SBT1A: .DB 0 +SBT1F: .DB 0 +SBT2A: .DB 0 +SBT2F: .DB 0 +SBT3A: .DB 0 +SBT3F: .DB 0 +SBT4A: .DB 0 +SBT4F: .DB 0 +SBT5A: .DB 0 +SBT5F: .DB 0 +SBT6A: .DB 0 +SBT6F: .DB 0 +SBT7A: .DB 0 SBT7F: .DB 0 \ No newline at end of file diff --git a/t_sbc_bcd_01.dat b/t_sbc_bcd_01.dat index 941c928..5ab2019 100644 --- a/t_sbc_bcd_01.dat +++ b/t_sbc_bcd_01.dat @@ -1,36 +1,36 @@ -; Test BCD mode. -ORG -$0200 -$F8 $18 $A9 $00 $E9 $00 $8D $00 -$03 $08 $68 $8D $01 $03 $38 $A9 -$00 $E9 $00 $8D $02 $03 $08 $68 -$8D $03 $03 $38 $A9 $00 $E9 $01 -$8D $04 $03 $08 $68 $8D $05 $03 -$38 $A9 $0A $E9 $00 $8D $06 $03 -$08 $68 $8D $07 $03 $18 $A9 $0B -$E9 $00 $8D $08 $03 $08 $68 $8D -$09 $03 $38 $A9 $9A $E9 $00 $8D -$0A $03 $08 $68 $8D $0B $03 $18 -$A9 $9B $E9 $00 $8D $0C $03 $08 -$68 $8D $0D $03 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 - +; Test BCD mode. +ORG +$0200 +$F8 $18 $A9 $00 $E9 $00 $8D $00 +$03 $08 $68 $8D $01 $03 $38 $A9 +$00 $E9 $00 $8D $02 $03 $08 $68 +$8D $03 $03 $38 $A9 $00 $E9 $01 +$8D $04 $03 $08 $68 $8D $05 $03 +$38 $A9 $0A $E9 $00 $8D $06 $03 +$08 $68 $8D $07 $03 $18 $A9 $0B +$E9 $00 $8D $08 $03 $08 $68 $8D +$09 $03 $38 $A9 $9A $E9 $00 $8D +$0A $03 $08 $68 $8D $0B $03 $18 +$A9 $9B $E9 $00 $8D $0C $03 $08 +$68 $8D $0D $03 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 + diff --git a/tall.bin b/tall.bin new file mode 100644 index 0000000..1a307cf Binary files /dev/null and b/tall.bin differ diff --git a/tall.dat b/tall.dat new file mode 100644 index 0000000..dec9dd3 --- /dev/null +++ b/tall.dat @@ -0,0 +1,109 @@ +; Created with BIN2HEX (C) Marek Karcz 2016. All rights reserved. +; 03/09/16 20:30:42 +ADDR +$4000 +ORG +$0000 +ORG +$4000 +$a9 $00 $8d $10 $02 $a9 $55 $8d $00 $02 $a9 $aa $8d $01 $02 $a9 +$ff $8d $02 $02 $a9 $6e $8d $03 $02 $a9 $42 $8d $04 $02 $a9 $33 +$8d $05 $02 $a9 $9d $8d $06 $02 $a9 $7f $8d $07 $02 $a9 $a5 $8d +$08 $02 $a9 $1f $8d $09 $02 $a9 $ce $8d $0a $02 $a9 $29 $8d $0b +$02 $a9 $42 $8d $0c $02 $a9 $6c $8d $0d $02 $a9 $42 $8d $0e $02 +$a9 $55 $a2 $2a $a0 $73 $85 $81 $a9 $01 $85 $61 $a9 $7e $a5 $81 +$8d $10 $09 $a9 $7e $ad $10 $09 $95 $56 $a9 $7e $b5 $56 $84 $60 +$91 $60 $a9 $7e $b1 $60 $9d $ff $07 $a9 $7e $bd $ff $07 $99 $ff +$07 $a9 $7e $b9 $ff $07 $81 $36 $a9 $7e $a1 $36 $86 $50 $a6 $60 +$a4 $50 $8e $13 $09 $a2 $22 $ae $13 $09 $8c $14 $09 $a0 $99 $ac +$14 $09 $94 $2d $96 $77 $a0 $99 $b4 $2d $a2 $22 $b6 $77 $a0 $99 +$bc $a0 $08 $a2 $22 $be $a1 $08 $9d $00 $02 $ad $2a $02 $cd $00 +$02 $f0 $03 $4c $c0 $45 $a9 $fe $8d $10 $02 $a9 $55 $29 $53 $09 +$38 $49 $11 $85 $99 $a9 $b9 $85 $10 $a9 $e7 $85 $11 $a9 $39 $85 +$12 $a5 $99 $25 $10 $05 $11 $45 $12 $a2 $10 $85 $99 $a9 $bc $85 +$20 $a9 $31 $85 $21 $a9 $17 $85 $22 $a5 $99 $35 $10 $15 $11 $55 +$12 $85 $99 $a9 $6f $8d $10 $01 $a9 $3c $8d $11 $01 $a9 $27 $8d +$12 $01 $a5 $99 $2d $10 $01 $0d $11 $01 $4d $12 $01 $85 $99 $a9 +$8a $8d $20 $01 $a9 $47 $8d $21 $01 $a9 $8f $8d $22 $01 $a5 $99 +$3d $10 $01 $1d $11 $01 $5d $12 $01 $a0 $20 $85 $99 $a9 $73 $8d +$30 $01 $a9 $2a $8d $31 $01 $a9 $f1 $8d $32 $01 $a5 $99 $39 $10 +$01 $19 $11 $01 $59 $12 $01 $85 $99 $a9 $70 $85 $30 $a9 $01 $85 +$31 $a9 $71 $85 $32 $a9 $01 $85 $33 $a9 $72 $85 $34 $a9 $01 $85 +$35 $a9 $c5 $8d $70 $01 $a9 $7c $8d $71 $01 $a9 $a1 $8d $72 $01 +$a5 $99 $21 $20 $01 $22 $41 $24 $85 $99 $a9 $60 $85 $40 $a9 $01 +$85 $41 $a9 $61 $85 $42 $a9 $01 $85 $43 $a9 $62 $85 $44 $a9 $01 +$85 $45 $a9 $37 $8d $50 $02 $a9 $23 $8d $51 $02 $a9 $9d $8d $52 +$02 $a5 $99 $a0 $f0 $31 $40 $11 $42 $51 $44 $85 $a9 $a5 $a9 $cd +$01 $02 $f0 $08 $a9 $01 $8d $10 $02 $4c $c0 $45 $a9 $ff $a2 $00 +$85 $90 $e6 $90 $e6 $90 $a5 $90 $a6 $90 $95 $90 $f6 $90 $b5 $90 +$a6 $91 $9d $90 $01 $ee $92 $01 $bd $90 $01 $ae $92 $01 $9d $90 +$01 $fe $90 $01 $bd $90 $01 $ae $93 $01 $9d $70 $01 $de $70 $01 +$bd $70 $01 $ae $74 $01 $9d $70 $01 $ce $73 $01 $bd $70 $01 $ae +$73 $01 $95 $70 $d6 $70 $b5 $70 $a6 $72 $95 $70 $c6 $71 $c6 $71 +$a5 $71 $cd $02 $02 $f0 $08 $a9 $02 $8d $10 $02 $4c $c0 $45 $a9 +$4b $4a $0a $85 $50 $06 $50 $06 $50 $46 $50 $a5 $50 $a6 $50 $09 +$c9 $85 $60 $16 $4c $56 $4c $56 $4c $b5 $4c $a6 $60 $09 $41 $8d +$2e $01 $5e $00 $01 $5e $00 $01 $1e $00 $01 $bd $00 $01 $ae $2e +$01 $09 $81 $9d $00 $01 $4e $36 $01 $4e $36 $01 $0e $36 $01 $bd +$00 $01 $2a $2a $6a $85 $70 $a6 $70 $09 $03 $95 $0c $26 $c0 $66 +$c0 $66 $c0 $b5 $0c $a6 $c0 $85 $d0 $36 $75 $36 $75 $76 $75 $a5 +$d0 $a6 $d0 $9d $00 $01 $2e $b7 $01 $2e $b7 $01 $2e $b7 $01 $6e +$b7 $01 $bd $00 $01 $ae $b7 $01 $8d $dd $01 $3e $00 $01 $7e $00 +$01 $7e $00 $01 $ad $dd $01 $cd $03 $02 $f0 $08 $a9 $03 $8d $10 +$02 $4c $c0 $45 $a9 $e8 $85 $20 $a9 $42 $85 $21 $a9 $00 $09 $03 +$4c $d5 $42 $09 $ff $09 $30 $20 $e1 $42 $09 $42 $6c $20 $00 $09 +$ff $85 $30 $a6 $30 $a9 $00 $60 $95 $0d $a5 $40 $cd $04 $02 $f0 +$08 $a9 $04 $8d $10 $02 $4c $c0 $45 $a9 $35 $aa $ca $ca $e8 $8a +$a8 $88 $88 $c8 $98 $aa $a9 $20 $9a $a2 $10 $ba $8a $85 $40 $a5 +$40 $cd $05 $02 $f0 $08 $a9 $05 $8d $10 $02 $4c $c0 $45 $2a $a9 +$6a $85 $50 $a9 $6b $85 $51 $a9 $a1 $85 $60 $a9 $a2 $85 $61 $a9 +$ff $69 $ff $69 $ff $e9 $ae $85 $40 $a6 $40 $75 $00 $f5 $01 $65 +$60 $e5 $61 $8d $20 $01 $a9 $4d $8d $21 $01 $a9 $23 $6d $20 $01 +$ed $21 $01 $85 $f0 $a6 $f0 $a9 $64 $8d $24 $01 $a9 $62 $8d $25 +$01 $a9 $26 $7d $00 $01 $fd $01 $01 $85 $f1 $a4 $f1 $a9 $e5 $8d +$28 $01 $a9 $e9 $8d $29 $01 $a9 $34 $79 $00 $01 $f9 $01 $01 $85 +$f2 $a6 $f2 $a9 $20 $85 $70 $a9 $01 $85 $71 $a9 $24 $85 $72 $a9 +$01 $85 $73 $61 $41 $e1 $3f $85 $f3 $a4 $f3 $a9 $da $85 $80 $a9 +$00 $85 $81 $a9 $dc $85 $82 $a9 $00 $85 $83 $a9 $aa $71 $80 $f1 +$82 $85 $30 $a5 $30 $cd $06 $02 $f0 $08 $a9 $06 $8d $10 $02 $4c +$c0 $45 $a9 $00 $85 $34 $a9 $ff $8d $30 $01 $a9 $99 $8d $9d $01 +$a9 $db $8d $99 $01 $a9 $2f $85 $32 $a9 $32 $85 $4f $a9 $30 $85 +$33 $a9 $70 $85 $af $a9 $18 $85 $30 $c9 $18 $f0 $02 $29 $00 $09 +$01 $c5 $30 $d0 $02 $29 $00 $a2 $00 $cd $30 $01 $f0 $04 $85 $40 +$a6 $40 $d5 $27 $d0 $06 $09 $84 $85 $41 $a6 $41 $29 $db $dd $00 +$01 $f0 $02 $29 $00 $85 $42 $a4 $42 $29 $00 $d9 $00 $01 $d0 $02 +$09 $0f $85 $43 $a6 $43 $09 $24 $c1 $40 $f0 $02 $09 $7f $85 $44 +$a4 $44 $49 $0f $d1 $33 $d0 $04 $a5 $44 $85 $15 $a5 $15 $cd $07 +$02 $f0 $08 $a9 $07 $8d $10 $02 $4c $c0 $45 $a9 $a5 $85 $20 $8d +$20 $01 $a9 $5a $85 $21 $a2 $a5 $e0 $a5 $f0 $02 $a2 $01 $e4 $20 +$f0 $02 $a2 $02 $ec $20 $01 $f0 $02 $a2 $03 $86 $30 $a4 $30 $c0 +$a5 $f0 $02 $a0 $04 $c4 $20 $f0 $02 $a0 $05 $cc $20 $01 $f0 $02 +$a0 $06 $84 $31 $a5 $31 $24 $20 $d0 $02 $a9 $07 $2c $20 $01 $d0 +$02 $a9 $08 $24 $21 $d0 $02 $85 $42 $a5 $42 $cd $08 $02 $f0 $08 +$a9 $08 $8d $10 $02 $4c $c0 $45 $a9 $54 $85 $32 $a9 $b3 $85 $a1 +$a9 $87 $85 $43 $a2 $a1 $10 $02 $a2 $32 $b4 $00 $10 $04 $a9 $05 +$a6 $a1 $30 $02 $e9 $03 $30 $02 $a9 $41 $49 $30 $85 $32 $75 $00 +$50 $02 $a9 $03 $85 $54 $b6 $00 $75 $51 $50 $02 $a9 $e5 $75 $40 +$70 $05 $99 $01 $00 $65 $55 $70 $02 $a9 $00 $69 $f0 $90 $04 $85 +$60 $65 $43 $90 $02 $a9 $ff $65 $54 $b0 $04 $69 $87 $a6 $60 $b0 +$02 $a9 $00 $95 $73 $a5 $80 $cd $09 $02 $f0 $08 $a9 $09 $8d $10 +$02 $4c $c0 $45 $69 $00 $a9 $99 $69 $87 $18 $ea $90 $04 $69 $60 +$69 $93 $38 $ea $90 $01 $b8 $50 $02 $a9 $00 $69 $ad $ea $85 $30 +$a5 $30 $cd $0a $02 $f0 $08 $a9 $0a $8d $10 $02 $4c $c0 $45 $69 +$01 $a9 $27 $69 $01 $38 $08 $18 $28 $69 $00 $48 $a9 $00 $68 $85 +$30 $a5 $30 $cd $0b $02 $f0 $08 $a9 $0b $8d $10 $02 $4c $c0 $45 +$18 $a9 $42 $90 $04 $85 $33 $b0 $0a $a9 $45 $48 $a9 $61 $48 $38 +$08 $18 $40 $a5 $33 $cd $0c $02 $f0 $08 $a9 $0c $8d $10 $02 $4c +$c0 $45 $69 $01 $78 $f8 $08 $68 $85 $20 $58 $d8 $08 $68 $65 $20 +$85 $21 $a5 $21 $cd $0d $02 $f0 $08 $a9 $0d $8d $10 $02 $4c $c0 +$45 $a9 $41 $85 $60 $e6 $60 $a5 $60 $cd $0e $02 $f0 $08 $a9 $0e +$8d $10 $02 $4c $c0 $45 $a9 $fe $cd $10 $02 $d0 $03 $ee $10 $02 +$00 $00 $a2 $ff $9a $60 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +ORG +$ff00 +$40 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 +ORG +$fff0 +$00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $ff $00 $ff $00 $ff +EXEC +$4000 diff --git a/tb.asm b/tb.asm new file mode 100644 index 0000000..b98ba6a --- /dev/null +++ b/tb.asm @@ -0,0 +1,1484 @@ +;---------------------------------------------------------------------------------- +; Tiny Basic port to MKHBC-8-R2 6502 computer +; by Marek Karcz 2012. +; +; Based on the work by: +; +; ================= ORIGINAL HEADER ====================================== +; +; OMS-02 Firmware +; +; Bill O'Neill - Last update: 2008/12/06 +; +; Tiny Basic and minimal Monitor (BIOS) +; +; This version is for the assembler that comes with +; Michal Kowalski's 6502 emulator. To run it, load it +; into the emulator, assemle it, begin debug mode then, +; set the PC to $1CF0 then run. +; +; The emulator was used to help figure out Tiny Basic +; and this code is only documented to that extent. +; +; It should be easy enough to configure this to run any- +; where in memory or convert it to assemble with any 6502 +; assembler. The current location is being used as this is +; to be placed into a controller I designed (OMS-02) around +; a 6507 CPU (a 6502 variant) that has only 8k off memory. +; The memory map for the OMS-02 is; +; +; $0000-$0FFF RAM +; $1000-$13FF I/O space (ACIA is at $1200) +; $1400-$1FFF Tiny Basic and simple monitor +; +; +; Next steps: +; Write a BREAK routine that will enable a break if any charater is typed at the console +; More comments to document this code +; Investigate using assembler variables and directives to make it easy to re-locate this code +; +; ============ END OF ORIGINAL HEADER ========================================= +; +; Revision history (MKHBC-8-R1 port): +; +; 1/4/2012: +; TB port created. +; +; 1/5/2012: +; Version 1.0.1. +; Added 2-byte peek routine. +; +; 1/11/2012: +; Figured out jump addresses for routines and used symbolic labels +; instead of hardcoded addresses. Relocated TB to $0400 (from $1400). +; +; 2/15/2016 +; Ported to my own 6502 emulator. +; +; 2/20/2016 +; Increased stack size. Changed prompt. +; +; +;-------------------------------------------------------------------------------------- + +;.segment "BASIC" + +; +; Tiny Basic starts here +; + .org $0400 ; Start of Basic. First 1K of ROM is shaded by I/O on the OMS-02 + +SOBAS: + +;CLRSC = ClearScreen +C_00BC = $00BC ; These are needed because my assembler +C_20 = $20 ; does not hanle standard 6502 notation +C_22 = $22 ; properly +C_24 = $24 ; +C_2A = $2A ; I may just fix this someday - HA! +C_2C = $2C ; +C_2E = $2E ; +C_B8 = $B8 ; +C_BC = $BC ; +C_C1 = $C1 ; +C_C2 = $C2 ; +C_C6 = $C6 ; + +SR_V_L = SOBAS + $1E ; Base address for subroutine vector lo byte +SR_V_H = SOBAS + $1F ; Base address for subroutine vector hi byte + +CV: jmp COLD_S ; Cold start vector +WV: jmp WARM_S ; Warm start vector +IN_V: jmp RCCHR ; Input routine address. +OUT_V: jmp SNDCHR ; Output routine address. +BREAK: nop ; Begin dummy break routine + clc ; Clear the carry flag + rts ; End break routine +; +; Some codes +; +BSC: .byte $5f ; Backspace code +LSC: .byte $18 ; Line cancel code +PCC: .byte $80 ; Pad character control +TMC: .byte $00 ; Tape mode control +;SSS: .byte $04 ; Spare Stack size. (was $04 but documentation suggests $20 ?) +SSS: .byte $20 ; Spare Stack size. (was $04 but documentation suggests $20 ?) + +; +; Code fragment +; Seems to store or retreive a byte to/from memory and the accumulator +; --- +; M.K.: I think this code it is used from Tiny Basic programs by calling USR to store/retrieve +; data (since TB does not support arrays, this is one way to emulate them). +; This location is at exactly 20 bytes distance from the start of TB code. +; TB programs typically make USR calls to locations: +; SOBAS+20 +; SOBAS+24 +; E.g: +; LET S=_SOBAS_ REM (_SOBAS_ is TB start) +; LET B=_ARRAY_SIZE_+2 (_ARRAY_SIZE_ is the size of 2-dim array) +; Get byte from location V(I,J), store in Z. +; LET Z=USR(S+20,V+B*I+J,0) +; Store Z in location V(I,J) +; LET Z=USR(S+24,V+B*I+J,Z) +; From TB documentation: +; For your convenience two subroutines have been included in the TINY BASIC interpreter to access memory. +; If S contains the address of the beginning of the TINY BASIC interpreter (256 for standard 6800, 512 +; for standard 6502, etc.), then location S+20 (hex 0114) is the entry point of a subroutine to read one +; byte from the memory address in the index register, and location S+24 (hex 0118) is the entry point of +; a subroutine to store one byte into memory. +;------------------------------------------------- +; USR (address) +; USR (address,Xreg) +; USR (address,Xreg,Areg) +; +; This function is actually a machine-language subroutine call to the address in the first argument. +; If the second argument is included the index registers contain that value on entry to the subroutine, +; with the most significant part in X. If the third argument is included, the accumulators contain that +; value on entry to the subroutine, with the least significant part in A. On exit, the value in the +; Accumulators (for the 6800; A and Y for the 6502) becomes the value of the function, with the least +; significant part in A. All three arguments are evaluated as normal expressions. +; It should be noted that machine language subroutine addresses are 16-bit Binary numbers. TINY BASIC +; evaluates all expressions to 16-bit binary numbers, so any valid expression may be used to define a +; subroutine address. However, most addresses are expressed in hexadecimal whereas TINY BASIC only accepts +; numerical constants in decimal. Thus to jump to a subroutine at hex address 40AF, you must code USR(16559). +; Hex address FFB5 is similarly 65461 in decimal, though the equivalent (-75) may be easier to use. +; + +OneBytePeek: + + stx $C3 ; read one byte from memory address in the index register + bcc LBL008 + +OneBytePoke: + + stx $C3 ; store one byte into memory + sta (C_C2),Y + rts +LBL008: lda (C_C2),Y + ldy #$00 + rts + + + ; These seem to be addresses associated with the IL branch instructions + ;.byte $62,$15, $64,$15, $D8,$15, $05,$16, $33,$16, $FD,$15 + .byte JUMP01 + .byte LBL027 + .byte JUMP02 + .byte JUMP03 + .byte JUMP04 + .byte JUMP05 + + ; NOTE: The original comment below is obsolete now, since I found the jump + ; addresses locations and put them in this table. Now assembler will + ; take care of the reallocation. + ; START OF ORIGINAL COMMENT + ; This appears to be a table of + ; execution addresses to jump to ML routines + ; that handle the the IL instructions. + ; You cannot add code to or relocate this program + ; without updating these + ; END OF ORIGINAL COMMENT + + ;.byte $9F,$17, $42,$1B, $3F,$1B, $7A,$17, $FC,$18, $95,$17, $9F,$17, $9F,$17 + .byte LBL067 + .byte LBL132 + .byte JUMP06 + .byte JUMP07 + .byte LBL035 + .byte LBL097 + .byte LBL067 + .byte LBL067 + + ;.byte $BD,$1A, $C1,$1A, $8A,$1A, $9B,$1A, $E9,$1A, $61,$17, $51,$17, $41,$1A + .byte JUMP08 + .byte JUMP09 + .byte JUMP10 + .byte JUMP11 + .byte JUMP12 + .byte JUMP13 + .byte JUMP14 + .byte LBL071 + + ;.byte $52,$1A, $4F,$1A, $62,$1A, $E7,$19, $CD,$16, $06,$17, $9F,$17, $15,$18 + .byte JUMP15 + .byte JUMP16 + .byte JUMP17 + .byte JUMP18 + .byte JUMP19 + .byte JUMP20 + .byte LBL067 + .byte JUMP21 + + ;.byte $A7,$17, $B7,$16, $BF,$16, $83,$18, $A1,$16, $9F,$17, $9F,$17, $A8,$18 + .byte JUMP22 + .byte JUMP23 + .byte LBL047 + .byte LBL081 + .byte LBL013 + .byte LBL067 + .byte LBL067 + .byte JUMP24 + + ;.byte $4F,$1B, $4D,$1B, $07,$19, $AA,$14, $37,$17, $BD,$14, $1B,$1B, $B1,$1A + .byte JUMP25 + .byte JUMP26 + .byte JUMP27 + .byte MEM_T2 + .byte JUMP28 + .byte WARM_S + .byte JUMP29 + .byte JUMP30 + + .byte $20,$41, $54,$20 ; No idea ???? + + .byte $80 ; No idea + +LBL002: .byte ILTBL ;$1B ; $1B - hi byte of IL address + +; +;Begin Cold Start +; +; +; +; Load start of free ram ($1C00) into locations $0020 and $0022 +; The memory between $1000 and $1Bff (3 kB) is free for assembler programs +; that can be loaded and used simultaneously with TB. +; $1C00 to the end of writable memory is the BASIC memory space. +; +COLD_S: lda #$00 ; Load accumulator with lo byte of lower and upper prg memory limits + sta $20 ; Store in $20 + sta $22 ; Store in $22 + lda #$1C ; Load accumulator with hi byte of lower and upper prg memory limits + sta $21 ; Store in $21 + sta $23 ; Store in $23 + ; NOTE: $22,$23 vector will be updated by routine below to be the upper RAM limit for TB. +; +; +; Begin test for free ram +; As a result, memory locations $20,$21 will contain lo,hi byte order address of lower RAM boundary +; and $22,$23 upper RAM boundary respectively. +; + + ldy #$01 ; Load register Y with $01 +MEM_T: lda (C_22),Y ; Load accumulator With the contents of a byte of memory + tax ; Save it to X + eor #$FF ; Next 4 instuctions test to see if this memeory location + sta (C_22),Y ; is ram by trying to write something new to it - new value + cmp (C_22),Y ; gets created by XORing the old value with $FF - store the + php ; result of the test on the stack to look at later + txa ; Retrieve the old memory value + sta (C_22),Y ; Put it back where it came from + inc $22 ; Increment $22 (for next memory location) + bne SKP_PI ; Goto $14A6 if we don't need to increment page + inc $23 ; Increment $23 (for next memory page) +SKP_PI: plp ; Now look at the result of the memory test + beq MEM_T ; Go test the next mempry location if the last one was ram + dey ; If last memory location did not test as ram, decrement Y (should be $00 now) +MEM_T2: cld ; Make sure we're not in decimal mode + lda $20 ; Load up the low-order by of the start of free ram + adc SSS ; Add to the spare stack size + sta $24 ; Store the result in $0024 + tya ; Retrieve Y + adc $21 ; And add it to the high order byte of the start of free ram (this does not look right) + sta $25 ; Store the result in $0025 + tya ; Retrieve Y again + sta (C_20),Y ; Store A in the first byte of program memory + iny ; Increment Y + sta (C_20),Y ; Store A in the second byte of program memory +; +;Begin Warm Start; +; +WARM_S: lda $22 + sta $C6 + sta $26 + lda $23 + sta $C7 + sta $27 + jsr LBL001 ; Go print CR, LF and pad charachters +LBL014: lda LBL002 + sta $2A + lda LBL003 + sta $2B + lda #$80 + sta $C1 + lda #$30 + sta $C0 + ldx #$00 + stx $BE + stx $C2 + dex + txs +LBL006: cld + jsr LBL004 ; Go read a byte from the TBIL table + jsr LBL005 + jmp LBL006 +; +; +; + .byte $83 ; No idea about this + .byte $65 ; No idea about this +; +; +; Routine to service the TBIL Instructions +; +LBL005: cmp #$30 ; + bcs LBL011 ; If it's $30 or higher, it's a Branch or Jump - go handle it + cmp #$08 ; + bcc LBL007 ; If it's less than $08 it's a stack exchange - go handle it + asl ; Multiply the OP code by 2 + tax ; Transfer it to X +LBL022: lda SR_V_H,X ; Get the hi byte of the OP Code handling routine + pha ; and save it on the stack + lda SR_V_L,X ; Get the lo byte + pha ; and save it on the stack + php ; save the processor status too + rti ; now go execute the OP Code handling routine +; +; +; Routine to handle the stack exchange +; +LBL007: adc $C1 + tax + lda (C_C1),Y + pha + lda $00,X + sta (C_C1),Y + pla + sta $00,X + rts +; +; +; +LBL015: jsr LBL001 ; Go print CR, LF and pad charachters + lda #$21 ; Load an ASCII DC2 + jsr OUT_V ; Go print it + lda $2A ; Load the current TBIL pointer (lo) + sec ; Set the carry flag + sbc LBL002 ; Subtract the TBIL table origin (lo) + tax ; Move the difference to X + lda $2B ; Load the current TBIL pointer (hi) + sbc LBL003 ; Subtract the TBIL table origin (hi) + jsr LBL010 + lda $BE + beq LBL012 + lda #$7E + sta $2A + lda #$20 + sta $2B + jsr LBL013 + ldx $28 + lda $29 + jsr LBL010 +LBL012: lda #$07 ; ASCII Bell + jsr OUT_V ; Go ring Bell + jsr LBL001 ; Go print CR, LF and pad charachters +LBL060: lda $26 + sta $C6 + lda $27 + sta $C7 + jmp LBL014 +; +; +; +LBL115: ldx #$7C +LBL048: cpx $C1 +LBL019: bcc LBL015 + ldx $C1 + inc $C1 + inc $C1 + clc + rts +; +; +; +JUMP01: dec $BD +LBL027: lda $BD + beq LBL015 +LBL017: lda $BC + sta $2A + lda $BD + sta $2B + rts +; +; Branch handling routine +; +LBL011: cmp #$40 ; + bcs LBL016 ; If it's not a Jump, go to branch handler + pha + jsr LBL004 ; Go read a byte from the TBIL table + adc LBL002 + sta $BC + pla + pha + and #$07 + adc LBL003 + sta $BD + pla + and #$08 + bne LBL017 + lda $BC + ldx $2A + sta $2A + stx $BC + lda $BD + ldx $2B + sta $2B + stx $BD +LBL126: lda $C6 + sbc #$01 + sta $C6 + bcs LBL018 + dec $C7 +LBL018: cmp $24 + lda $C7 + sbc $25 + bcc LBL019 + lda $BC + sta (C_C6),Y + iny + lda $BD + sta (C_C6),Y + rts +; +;Branch handler +; +LBL016: pha + lsr + lsr + lsr + lsr + and #$0E + tax + pla + cmp #$60 + and #$1F + bcs LBL020 + ora #$E0 +LBL020: clc + beq LBL021 + adc $2A + sta $BC + tya + adc $2B +LBL021: sta $BD + JMP LBL022 +; +; +; +JUMP02: lda $2C + sta $B8 + lda $2D + sta $B9 +LBL025: jsr LBL023 + jsr LBL024 + eor (C_2A),Y + tax + jsr LBL004 ; Go read a byte from the TBIL table + txa + beq LBL025 + asl + beq LBL026 + lda $B8 + sta $2C + lda $B9 + sta $2D +LBL028: jmp LBL027 +JUMP05: jsr LBL023 + cmp #$0D + bne LBL028 +LBL026: rts +; +; +; +JUMP03: jsr LBL023 + cmp #$5B + bcs LBL028 + cmp #$41 + bcc LBL028 + asl + jsr LBL029 +LBL024: ldy #$00 + lda (C_2C),Y + inc $2C + bne LBL030 + inc $2D +LBL030: cmp #$0D + clc + rts +; +; + +LBL031: jsr LBL024 +LBL023: lda (C_2C),Y + cmp #$20 + beq LBL031 + cmp #$3A + clc + bpl LBL032 + cmp #$30 +LBL032: rts +; +; +; +JUMP04: jsr LBL023 + bcc LBL028 + sty $BC + sty $BD +LBL033: lda $BC + ldx $BD + asl $BC + rol $BD + asl $BC + rol $BD + clc + adc $BC + sta $BC + txa + adc $BD + asl $BC + rol + sta $BD + jsr LBL024 + and #$0F + adc $BC + sta $BC + tya + adc $BD + sta $BD + jsr LBL023 + bcs LBL033 + jmp LBL034 +LBL061: jsr LBL035 + lda $BC + ora $BD + beq LBL036 +LBL065: lda $20 + sta $2C + lda $21 + sta $2D +LBL040: jsr LBL037 + beq LBL038 + lda $28 + cmp $BC + lda $29 + sbc $BD + bcs LBL038 +LBL039: jsr LBL024 + bne LBL039 + jmp LBL040 +LBL038: lda $28 + eor $BC + bne LBL041 + lda $29 + eor $BD +LBL041: rts +; +; +; +LBL043: jsr LBL042 +LBL013: jsr LBL004 ; Entry point for TBIL PC (print literal) - Go read a byte from the TBIL table + bpl LBL043 ; +LBL042: inc $BF + bmi LBL044 + jmp OUT_V ; Go print it +LBL044: dec $BF +LBL045: rts +; +; +; +LBL046: cmp #$22 + beq LBL045 + jsr LBL042 +JUMP23: jsr LBL024 + bne LBL046 +LBL036: jmp LBL015 +LBL047: lda #$20 + jsr LBL042 + lda $BF + and #$87 + bmi LBL045 + bne LBL047 + rts +; +; +; +JUMP19: ldx #$7B + jsr LBL048 + inc $C1 + inc $C1 + inc $C1 + sec + lda $03,X + sbc $00,X + sta $00,X + lda $04,X + sbc $01,X + bvc LBL052 + eor #$80 + ora #$01 +LBL052: bmi LBL053 + bne LBL054 + ora $00,X + beq LBL049 +LBL054: lsr $02,X +LBL049: lsr $02,X +LBL053: lsr $02,X + bcc LBL050 +LBL004: ldy #$00 ; Read a byte from the TBIL Table + lda (C_2A),Y ; + inc $2A ; Increment TBIL Table pointer as required + bne LBL051 ; + inc $2B ; +LBL051: ora #$00 ; Check for $00 and set the 'Z' flag acordingly +LBL050: rts ; Return +; +; +; +JUMP20: lda $BE + beq LBL055 +LBL056: jsr LBL024 + bne LBL056 + jsr LBL037 + beq LBL057 +LBL062: jsr LBL058 + jsr BREAK + bcs LBL059 + lda $C4 + sta $2A + lda $C5 + sta $2B + rts +; +; +; +LBL059: lda LBL002 + sta $2A + lda LBL003 + sta $2B +LBL057: jmp LBL015 +LBL055: sta $BF + jmp LBL060 +JUMP28: lda $20 + sta $2C + lda $21 + sta $2D + jsr LBL037 + beq LBL057 + lda $2A + sta $C4 + lda $2B + sta $C5 +LBL058: lda #$01 + sta $BE + rts +; +; +; +JUMP14: jsr LBL061 + beq LBL062 +LBL066: lda $BC + sta $28 + lda $BD + sta $29 + jmp LBL015 +JUMP13: jsr LBL063 + jsr LBL064 + jsr LBL065 + bne LBL066 + rts +; +; +; +LBL037: jsr LBL024 + sta $28 + jsr LBL024 + sta $29 + ora $28 + rts +; +; +; +JUMP07: jsr LBL035 + jsr LBL034 +LBL034: lda $BD +LBL131: jsr LBL029 + lda $BC +LBL029: ldx $C1 + dex + sta $00,X + stx $C1 + cpx $C0 + bne LBL067 +LBL068: jmp LBL015 +LBL097: ldx $C1 + cpx #$80 + bpl LBL068 + lda $00,X + inc $C1 +LBL067: rts +; +; +; +LBL010: sta $BD + stx $BC + jmp LBL069 +JUMP22: ldx $C1 ; entry point to TBIL PN (print number) + lda $01,X + bpl LBL070 + jsr LBL071 + lda #$2D + jsr LBL042 +LBL070: jsr LBL035 +LBL069: lda #$1F + sta $B8 + sta $BA + lda #$2A + sta $B9 + sta $BB + ldx $BC + ldy $BD + sec +LBL072: inc $B8 + txa + sbc #$10 + tax + tya + sbc #$27 + tay + bcs LBL072 +LBL073: dec $B9 + txa + adc #$E8 + tax + tya + adc #$03 + tay + bcc LBL073 + txa +LBL074: sec + inc $BA + sbc #$64 + bcs LBL074 + dey + bpl LBL074 +LBL075: dec $BB + adc #$0A + bcc LBL075 + ora #$30 + sta $BC + lda #$20 + sta $BD + ldx #$FB +LBL199: stx $C3 + lda $BD,X + ora $BD + cmp #$20 + beq LBL076 + ldy #$30 + sty $BD + ora $BD + jsr LBL042 +LBL076: ldx $C3 + inx + bne LBL199 + rts +; +; +; +JUMP21: lda $2D + pha + lda $2C + pha + lda $20 + sta $2C + lda $21 + sta $2D + lda $24 + ldx $25 + jsr LBL077 + beq LBL078 + jsr LBL077 +LBL078: lda $2C + sec + sbc $B6 + lda $2D + sbc $B7 + bcs LBL079 + jsr LBL037 + beq LBL079 + ldx $28 + lda $29 + jsr LBL010 + lda #$20 +LBL080: jsr LBL042 + jsr BREAK + bcs LBL079 + jsr LBL024 + bne LBL080 + jsr LBL081 + jmp LBL078 +LBL077: sta $B6 + inc $B6 + bne LBL082 + inx +LBL082: stx $B7 + ldy $C1 + cpy #$80 + beq LBL083 + jsr LBL061 +LBL099: lda $2C + ldx $2D + sec + sbc #$02 + bcs LBL084 + dex +LBL084: sta $2C + jmp LBL085 +LBL079: pla + sta $2C + pla + sta $2D +LBL083: rts +LBL081: lda $BF + bmi LBL083 +; +; +; Routine to handle CR, LF and pad characters in the ouput +; +LBL001: lda #$0D ; Load up a CR + jsr OUT_V ; Go print it + lda PCC ; Load the pad character code + and #$7F ; Test to see - + sta $BF ; how many pad charachters to print + beq LBL086 ; Skip if 0 +LBL088: jsr LBL087 ; Go print pad charcter + dec $BF ; One less + bne LBL088 ; Loop until 0 +LBL086: lda #$0A ; Load up a LF + jmp LBL089 ; Go print it +; +; +; +LBL092: ldy TMC +LBL091: sty $BF + bcs LBL090 +JUMP24: lda #$30 ; Entry pont for TBIL GL (get input line) + sta $2C + sta $C0 + sty $2D + jsr LBL034 +LBL090: eor $80 + sta $80 + jsr IN_V + ldy #$00 + ldx $C0 + and #$7F + beq LBL090 + cmp #$7F + beq LBL090 + cmp #$13 + beq LBL091 + cmp #$0A + beq LBL092 + cmp LSC + beq LBL093 + cmp BSC + bne LBL094 + cpx #$30 + bne LBL095 +LBL093: ldx $2C + sty $BF + lda #$0D +LBL094: cpx $C1 + bmi LBL096 + lda #$07 + jsr LBL042 + jmp LBL090 +LBL096: sta $00,X + inx + inx +LBL095: dex + stx $C0 + cmp #$0D + bne LBL090 + jsr LBL081 +LBL035: jsr LBL097 + sta $BC + jsr LBL097 + sta $BD + rts +; +; +; +JUMP27: jsr LBL098 + jsr LBL061 + php + jsr LBL099 + sta $B8 + stx $B9 + lda $BC + sta $B6 + lda $BD + sta $B7 + ldx #$00 + plp + bne LBL100 + jsr LBL037 + dex + dex +LBL101: dex + jsr LBL024 + bne LBL101 +LBL100: sty $28 + sty $29 + jsr LBL098 + lda #$0D + cmp (C_2C),Y + beq LBL102 + inx + inx + inx +LBL103: inx + iny + cmp (C_2C),Y + bne LBL103 + lda $B6 + sta $28 + lda $B7 + sta $29 +LBL102: lda $B8 + sta $BC + lda $B9 + sta $BD + clc + ldy #$00 + txa + beq LBL104 + bpl LBL105 + adc $2E + sta $B8 + lda $2F + sbc #$00 + sta $B9 +LBL109: lda (C_2E),Y + sta (C_B8),Y + ldx $2E + cpx $24 + bne LBL106 + lda $2F + cmp $25 + beq LBL107 +LBL106: inx + stx $2E + bne LBL108 + inc $2F +LBL108: inc $B8 + bne LBL109 + inc $B9 + bne LBL109 +LBL105: adc $24 + sta $B8 + sta $2E + tya + adc $25 + sta $B9 + sta $2F + lda $2E + sbc $C6 + lda $2F + sbc $C7 + bcc LBL110 + dec $2A + jmp LBL015 +LBL110: lda (C_24),Y + sta (C_2E),Y + ldx $24 + bne LBL111 + dec $25 +LBL111: dec $24 + ldx $2E + bne LBL112 + dec $2F +LBL112: dex + stx $2E + cpx $BC + bne LBL110 + ldx $2F + cpx $BD + bne LBL110 +LBL107: lda $B8 + sta $24 + lda $B9 + sta $25 +LBL104: lda $28 + ora $29 + beq LBL113 + lda $28 + sta (C_BC),Y + iny + lda $29 + sta (C_BC),Y +LBL114: iny + sty $B6 + jsr LBL024 + php + ldy $B6 + sta (C_BC),Y + plp + bne LBL114 +LBL113: jmp LBL014 +JUMP18: jsr LBL115 + lda $03,X + and #$80 + beq LBL116 + lda #$FF +LBL116: sta $BC + sta $BD + pha + adc $02,X + sta $02,X + pla + pha + adc $03,X + sta $03,X + pla + eor $01,X + sta $BB + bpl LBL117 + jsr LBL118 +LBL117: ldy #$11 + lda $00,X + ora $01,X + bne LBL119 + jmp LBL015 +LBL119: sec + lda $BC + sbc $00,X + pha + lda $BD + sbc $01,X + pha + eor $BD + bmi LBL120 + pla + sta $BD + pla + sta $BC + sec + jmp LBL121 +LBL120: pla + pla + clc +LBL121: rol $02,X + rol $03,X + rol $BC + rol $BD + dey + bne LBL119 + lda $BB + bpl LBL122 +LBL071: ldx $C1 +LBL118: sec + tya + sbc $00,X + sta $00,X + tya + sbc $01,X + sta $01,X +LBL122: rts +; +; +; +JUMP16: jsr LBL071 +JUMP15: jsr LBL115 + lda $00,X + adc $02,X + sta $02,X + lda $01,X + adc $03,X + sta $03,X + rts +; +; +; +JUMP17: jsr LBL115 + ldy #$10 + lda $02,X + sta $BC + lda $03,X + sta $BD +LBL124: asl $02,X + rol $03,X + rol $BC + rol $BD + bcc LBL123 + clc + lda $02,X + adc $00,X + sta $02,X + lda $03,X + adc $01,X + sta $03,X +LBL123: dey + bne LBL124 + rts +; +; +; +JUMP10: jsr LBL097 + tax + lda $00,X + ldy $01,X + dec $C1 + ldx $C1 + sty $00,X + jmp LBL029 +JUMP11: ldx #$7D + jsr LBL048 + lda $01,X + pha + lda $00,X + pha + jsr LBL097 + tax + pla + sta $00,X + pla + sta $01,X + rts +JUMP30: jsr LBL063 + lda $BC + sta $2A + lda $BD + sta $2B + rts +; +; +; +JUMP08: ldx #$2C ; Entry point to Save Basic Pointer SB + bne LBL125 +JUMP09: ldx #$2E +LBL125: lda $00,X + cmp #$80 + bcs LBL098 + lda $01,X + bne LBL098 + lda $2C + sta $2E + lda $2D + sta $2F + rts +; +; +; +LBL098: lda $2C + ldy $2E + sty $2C + sta $2E + lda $2D + ldy $2F + sty $2D + sta $2F + ldy #$00 + rts +; +; +; +JUMP12: lda $28 + sta $BC + lda $29 + sta $BD + jsr LBL126 + lda $C6 + sta $26 + lda $C7 +LBL064: sta $27 +LBL129: rts +; +; +; +LBL063: lda (C_C6),Y + sta $BC + jsr LBL127 + lda (C_C6),Y + sta $BD +LBL127: inc $C6 + bne LBL128 + inc $C7 +LBL128: lda $22 + cmp $C6 + lda $23 + sbc $C7 + bcs LBL129 + jmp LBL015 +JUMP29: jsr LBL130 + sta $BC + tya + jmp LBL131 +LBL130: jsr LBL035 + lda $BC + sta $B6 + jsr LBL035 + lda $BD + sta $B7 + ldy $BC + jsr LBL035 + ldx $B7 + lda $B6 + clc + jmp (C_00BC) +JUMP06: jsr LBL132 +LBL132: jsr LBL004 ; Go read a byte from the TBIL Table + jmp LBL029 +LBL085: stx $2D + cpx #$00 + rts +; +; +; +JUMP26: ldy #$02 +JUMP25: sty $BC + ldy #$29 + sty $BD + ldy #$00 + lda (C_BC),Y + cmp #$08 + bne LBL133 + jmp LBL117 +LBL133: rts +; +; +; Subroutine to decide which pad character to print +; +LBL089: jsr OUT_V ; Entry point with a charater to print first +LBL087: lda #$FF ; Normal entry point - Set pad to $FF + bit PCC ; Check if the pad flag is on + bmi LBL134 ; Skip it if not + lda #$00 ; set pad to $00 +LBL134: jmp OUT_V ; Go print it + + +; +; TBIL Tables +; +ILTBL: .byte $24, $3A, $91, $27, $10, $E1, $59, $C5, $2A, $56, $10, $11, $2C, $8B, $4C + .byte $45, $D4, $A0, $80, $BD, $30, $BC, $E0, $13, $1D, $94, $47, $CF, $88, $54 + .byte $CF, $30, $BC, $E0, $10, $11, $16, $80, $53, $55, $C2, $30, $BC, $E0, $14 + .byte $16, $90, $50, $D2, $83, $49, $4E, $D4, $E5, $71, $88, $BB, $E1, $1D, $8F + .byte $A2, $21, $58, $6F, $83, $AC, $22, $55, $83, $BA, $24, $93, $E0, $23, $1D + .byte $30, $BC, $20, $48, $91, $49, $C6, $30, $BC, $31, $34, $30, $BC, $84, $54 + .byte $48, $45, $CE, $1C, $1D, $38, $0D, $9A, $49, $4E, $50, $55, $D4, $A0, $10 + .byte $E7, $24, $3F, $20, $91, $27, $E1, $59, $81, $AC, $30, $BC, $13, $11, $82 + .byte $AC, $4D, $E0, $1D, $89, $52, $45, $54, $55, $52, $CE, $E0, $15, $1D, $85 + .byte $45, $4E, $C4, $E0, $2D, $98, $4C, $49, $53, $D4, $EC, $24, $00, $00, $00 + .byte $00, $0A, $80, $1F, $24, $93, $23, $1D, $30, $BC, $E1, $50, $80, $AC, $59 + .byte $85, $52, $55, $CE, $38, $0A, $86, $43, $4C, $45, $41, $D2, $2B, $84, $52 + .byte $45, $CD, $1D, $A0, $80, $BD, $38, $14, $85, $AD, $30, $D3, $17, $64, $81 + .byte $AB, $30, $D3, $85, $AB, $30, $D3, $18, $5A, $85, $AD, $30, $D3, $19, $54 + .byte $2F, $30, $E2, $85, $AA, $30, $E2, $1A, $5A, $85, $AF, $30, $E2, $1B, $54 + .byte $2F, $98, $52, $4E, $C4, $0A, $80, $80, $12, $0A, $09, $29, $1A, $0A, $1A + .byte $85, $18, $13, $09, $80, $12, $01, $0B, $31, $30, $61, $72, $0B, $04, $02 + .byte $03, $05, $03, $1B, $1A, $19, $0B, $09, $06, $0A, $00, $00, $1C, $17, $2F + .byte $8F, $55, $53, $D2, $80, $A8, $30, $BC, $31, $2A, $31, $2A, $80, $A9, $2E + .byte $2F, $A2, $12, $2F, $C1, $2F, $80, $A8, $30, $BC, $80, $A9, $2F, $83, $AC + .byte $38, $BC, $0B, $2F, $80, $A8, $52, $2F, $84, $BD, $09, $02, $2F, $8E, $BC + .byte $84, $BD, $09, $93, $2F, $84, $BE, $09, $05, $2F, $09, $91, $2F, $80, $BE + .byte $84, $BD, $09, $06, $2F, $84, $BC, $09, $95, $2F, $09, $04, $2F, $00, $00 + .byte $00 +; +; End of Tiny Basic + + +;.segment "MAIN" + + .org $0CF0 ; Address of main program + +; Code needs work below here, BIOS must be changed for MKHBC-8-R2 + +;FBLK: +; +; Set some symbols +; +;ACIARW = $1200 ; Base address of ACIA +;ACIAST = ACIARW+$01 ; ACIA status register +;ACIACM = ACIARW+$02 ; ACIA commnad register +;ACIACN = ACIARW+$03 ; ACIA control register + + +; +; Begin base system initialization +; +; jmp main ; no 6522 on MKHBC-8-R1 +;-------------------- +; sta ACIAST ; Do a soft reset on the ACIA +; lda #$0B ; Set it up for : +; sta ACIACM ; no echo, no parity, RTS low, No IRQ, DTR low +; lda #$1A ; and : +; sta ACIACN ; 2400, 8 bits, 1 stop bit, external Rx clock +;-------------------- + +main: + jsr CLRSC ; Go clear the screen + ldy #$00 ; Offset for welcome message and prompt + jsr SNDMSG ; Go print it +ST_LP: JSR RCCHR ; Go get a character from the console + cmp #$43 ; Check for 'C' + BNE IS_WRM ; If not branch to next check + jmp COLD_S ; Otherwise cold-start Tiny Basic +IS_WRM: cmp #$57 ; Check for 'W' + BNE PRMPT ; If not, branch to re-prompt them + jmp WARM_S ; Otherwise warm-start Tiny Basic +PRMPT: ldx #$2F ; Offset of prompt + jsr SNDMSG ; Go print the prompt + jmp ST_LP ; Go get the response + +;.segment "MESG" + + .org $0E00 ; Address of message area +MBLK: + +; +; The message block begins at $1E00 and is at most 256 bytes long. +; Messages terminate with an FF. +; + .byte "MKHBC-8-R2 TINY BASIC 6502 PORT" + .byte $0D, $0A ;, $0A + .byte "Version: 1.0.3, 2/20/2016" + .byte $0D, $0A ;, $0A + .byte "(NOTE: Use UPPER CASE.)" + .byte $0D, $0A ;, $0A + .byte "Boot ([C]old/[W]arm)? " + .byte $07, $FF + +;.segment "SUBR" + + .org $0F00 ;address of subroutine area + +SBLK: +; +; Begin BIOS subroutines +; + +; M.O.S. API defines. + +StrPtr = $E0 + +; Kernel jump table + +GetCh = $FFED +PutCh = $FFF0 +Gets = $FFF3 +Puts = $FFF6 + + +;SNDCHR = PutCh +;RCCHR = GetCh + + +; +; Clear the screen +; +ESC = $1b + +; 2-BYTE PEEK USR FUNCTION +; For TINY BASIC IL ASSEMBLER VERSION 0 + +TwoBytePeek: + + STX $C3 ;($C2=00) + LDA ($C2),Y ;GET MSB + PHA ;SAVE IT + INY + LDA ($C2),Y ;GET LSB + TAX + PLA + TAY ;Y=MSB + TXA + RTS + + +;ClrScrCode: + +; .BYTE ESC,"[2J",0 ;clear screen sequence (ANSI). + +;ClearScreen: + +; lda #ClrScrCode +; sta StrPtr+1 +; jsr Puts +; rts + +CLRSC: ldx #$19 ; Load X - we're going tp print 25 lines + lda #$0D ; CR + jsr SNDCHR ; Send a carriage retuen + lda #$0A ; LF +CSLP: jsr SNDCHR ; Send the line feed + dex ; One less to do + bne CSLP ; Go send another untill we're done + rts ; Return + +; +; Print a message. +; This sub expects the messsage offset from MBLK in X. +; +SNDMSG: lda MBLK,y ; Get a character from teh message block + cmp #$FF ; Look for end of message marker + beq EXSM ; Finish up if it is + jsr SNDCHR ; Otherwise send the character + iny ; Increment the pointer + jmp SNDMSG ; Go get next character +EXSM: rts ; Return + +; +; Get a character from the ACIA +; Runs into SNDCHR to provide echo +; +RCCHR: ;lda ACIAST ; Read the ACAI status to (for OMS-02) + ;and #$08 ; Check if there is character in the receiver (for OMS-02) + ;beq RCCHR ; Loop util we get one (for OMS-02) + ;lda ACIARW ; Load it into the accumulator (for OMS-02) + LDA $E000 ; Check if a character typed (for emulator) + BEQ RCCHR ; Loop until we get one (for emulator) + +;RCCHR: jsr GetCh +; jsr SNDCHR ; echo character to the console +; rts + +; +;Send a character to the ACIA +; +SNDCHR: sta $FE ; Save the character to be printed + cmp #$FF ; Check for a bunch of characters + BEQ EXSC ; that we don't want to print to + cmp #$00 ; the terminal and discard them to + BEQ EXSC ; clean up the output + cmp #$91 ; + BEQ EXSC ; + cmp #$93 ; + BEQ EXSC ; + cmp #$80 ; + BEQ EXSC ; + jmp SCLP ; VM6502 emulator, comment for MKHBC-8-R2 + jsr PutCh ; MKHBC-8-R2 + lda $fe + rts +SCLP: ;lda ACIAST ; Check ACIA Status (don't need for emulator) + ;and #$10 ; See if transmiter it busy (don't need for emulator) + ;beq SCLP ; Wait for it (don't need for emulator) + lda $FE ; Restore the character + ;sta ACIARW ; Transmit it (for OMS-02) + STA $E000 ; Transmit it (for emulator) +EXSC: rts ; Return + +; .org $1FFC ; Address of reset vector (for 6507 not required for emulator) +;RSVEC +; .byte $F0, $1C ; Reset vector + +; .org $3000 ; Address of last byte of EPROM +;EOROM: + +;--------------------------- END ---------------------------------------------------------------------- diff --git a/tb.dat b/tb.dat new file mode 100644 index 0000000..45d7737 --- /dev/null +++ b/tb.dat @@ -0,0 +1,398 @@ +ADDR +$0CF0 +; Program disassembly from $0400 to $1000 2/20/2016 +; Tiny Basic port for VM6502 emulator. +; Exec address: $0CF0 +ORG +$0400 +; Enable ROM and IO emulation. +ENROM +ENIO +; Set char IO address +IOADDR +$E000 +; Code/Data +$4C, $85, $04, $4C, $BD, $04, $4C, $2C +$0F, $4C, $31, $0F, $EA, $18, $60, $5F +$18, $80, $00, $20, $86, $C3, $90, $05 +$86, $C3, $91, $C2, $60, $B1, $C2, $A0 +$00, $60, $62, $05, $64, $05, $D8, $05 +$05, $06, $33, $06, $FD, $05, $9F, $07 +$42, $0B, $3F, $0B, $7A, $07, $FC, $08 +$95, $07, $9F, $07, $9F, $07, $BD, $0A +$C1, $0A, $8A, $0A, $9B, $0A, $E9, $0A +$61, $07, $51, $07, $41, $0A, $52, $0A +$4F, $0A, $62, $0A, $E7, $09, $CD, $06 +$06, $07, $9F, $07, $15, $08, $A7, $07 +$B7, $06, $BF, $06, $83, $08, $A1, $06 +$9F, $07, $9F, $07, $A8, $08, $4F, $0B +$4D, $0B, $07, $09, $AA, $04, $37, $07 +$BD, $04, $1B, $0B, $B1, $0A, $20, $41 +$54, $20, $80, $70, $0B, $A9, $00, $85 +$20, $85, $22, $A9, $1C, $85, $21, $85 +$23, $A0, $01, $B1, $22, $AA, $49, $FF +$91, $22, $D1, $22, $08, $8A, $91, $22 +$E6, $22, $D0, $02, $E6, $23, $28, $F0 +$EA, $88, $D8, $A5, $20, $6D, $13, $04 +$85, $24, $98, $65, $21, $85, $25, $98 +$91, $20, $C8, $91, $20, $A5, $22, $85 +$C6, $85, $26, $A5, $23, $85, $C7, $85 +$27, $20, $87, $08, $AD, $83, $04, $85 +$2A, $AD, $84, $04, $85, $2B, $A9, $80 +$85, $C1, $A9, $30, $85, $C0, $A2, $00 +$86, $BE, $86, $C2, $CA, $9A, $D8, $20 +$F9, $06, $20, $F2, $04, $4C, $E6, $04 +$83, $65, $C9, $30, $B0, $7B, $C9, $08 +$90, $0C, $0A, $AA, $BD, $1F, $04, $48 +$BD, $1E, $04, $48, $08, $40, $65, $C1 +$AA, $B1, $C1, $48, $B5, $00, $91, $C1 +$68, $95, $00, $60, $20, $87, $08, $A9 +$21, $20, $09, $04, $A5, $2A, $38, $ED +$83, $04, $AA, $A5, $2B, $ED, $84, $04 +$20, $A0, $07, $A5, $BE, $F0, $12, $A9 +$7E, $85, $2A, $A9, $20, $85, $2B, $20 +$A1, $06, $A6, $28, $A5, $29, $20, $A0 +$07, $A9, $07, $20, $09, $04, $20, $87 +$08, $A5, $26, $85, $C6, $A5, $27, $85 +$C7, $4C, $CC, $04, $A2, $7C, $E4, $C1 +$90, $BA, $A6, $C1, $E6, $C1, $E6, $C1 +$18, $60, $C6, $BD, $A5, $BD, $F0, $AC +$A5, $BC, $85, $2A, $A5, $BD, $85, $2B +$60, $C9, $40, $B0, $43, $48, $20, $F9 +$06, $6D, $83, $04, $85, $BC, $68, $48 +$29, $07, $6D, $84, $04, $85, $BD, $68 +$29, $08, $D0, $DC, $A5, $BC, $A6, $2A +$85, $2A, $86, $BC, $A5, $BD, $A6, $2B +$85, $2B, $86, $BD, $A5, $C6, $E9, $01 +$85, $C6, $B0, $02, $C6, $C7, $C5, $24 +$A5, $C7, $E5, $25, $90, $AA, $A5, $BC +$91, $C6, $C8, $A5, $BD, $91, $C6, $60 +$48, $4A, $4A, $4A, $4A, $29, $0E, $AA +$68, $C9, $60, $29, $1F, $B0, $02, $09 +$E0, $18, $F0, $07, $65, $2A, $85, $BC +$98, $65, $2B, $85, $BD, $4C, $FC, $04 +$A5, $2C, $85, $B8, $A5, $2D, $85, $B9 +$20, $25, $06, $20, $14, $06, $51, $2A +$AA, $20, $F9, $06, $8A, $F0, $F1, $0A +$F0, $12, $A5, $B8, $85, $2C, $A5, $B9 +$85, $2D, $4C, $64, $05, $20, $25, $06 +$C9, $0D, $D0, $F6, $60, $20, $25, $06 +$C9, $5B, $B0, $EE, $C9, $41, $90, $EA +$0A, $20, $87, $07, $A0, $00, $B1, $2C +$E6, $2C, $D0, $02, $E6, $2D, $C9, $0D +$18, $60, $20, $14, $06, $B1, $2C, $C9 +$20, $F0, $F7, $C9, $3A, $18, $10, $02 +$C9, $30, $60, $20, $25, $06, $90, $C2 +$84, $BC, $84, $BD, $A5, $BC, $A6, $BD +$06, $BC, $26, $BD, $06, $BC, $26, $BD +$18, $65, $BC, $85, $BC, $8A, $65, $BD +$06, $BC, $2A, $85, $BD, $20, $14, $06 +$29, $0F, $65, $BC, $85, $BC, $98, $65 +$BD, $85, $BD, $20, $25, $06, $B0, $D4 +$4C, $80, $07, $20, $FC, $08, $A5, $BC +$05, $BD, $F0, $48, $A5, $20, $85, $2C +$A5, $21, $85, $2D, $20, $6D, $07, $F0 +$12, $A5, $28, $C5, $BC, $A5, $29, $E5 +$BD, $B0, $08, $20, $14, $06, $D0, $FB +$4C, $7C, $06, $A5, $28, $45, $BC, $D0 +$04, $A5, $29, $45, $BD, $60, $20, $A6 +$06, $20, $F9, $06, $10, $F8, $E6, $BF +$30, $03, $4C, $09, $04, $C6, $BF, $60 +$C9, $22, $F0, $FB, $20, $A6, $06, $20 +$14, $06, $D0, $F4, $4C, $14, $05, $A9 +$20, $20, $A6, $06, $A5, $BF, $29, $87 +$30, $E5, $D0, $F3, $60, $A2, $7B, $20 +$56, $05, $E6, $C1, $E6, $C1, $E6, $C1 +$38, $B5, $03, $F5, $00, $95, $00, $B5 +$04, $F5, $01, $50, $04, $49, $80, $09 +$01, $30, $0A, $D0, $04, $15, $00, $F0 +$02, $56, $02, $56, $02, $56, $02, $90 +$0C, $A0, $00, $B1, $2A, $E6, $2A, $D0 +$02, $E6, $2B, $09, $00, $60, $A5, $BE +$F0, $28, $20, $14, $06, $D0, $FB, $20 +$6D, $07, $F0, $1B, $20, $4C, $07, $20 +$0C, $04, $B0, $09, $A5, $C4, $85, $2A +$A5, $C5, $85, $2B, $60, $AD, $83, $04 +$85, $2A, $AD, $84, $04, $85, $2B, $4C +$14, $05, $85, $BF, $4C, $49, $05, $A5 +$20, $85, $2C, $A5, $21, $85, $2D, $20 +$6D, $07, $F0, $EB, $A5, $2A, $85, $C4 +$A5, $2B, $85, $C5, $A9, $01, $85, $BE +$60, $20, $6B, $06, $F0, $BE, $A5, $BC +$85, $28, $A5, $BD, $85, $29, $4C, $14 +$05, $20, $FD, $0A, $20, $FA, $0A, $20 +$74, $06, $D0, $EA, $60, $20, $14, $06 +$85, $28, $20, $14, $06, $85, $29, $05 +$28, $60, $20, $FC, $08, $20, $80, $07 +$A5, $BD, $20, $87, $07, $A5, $BC, $A6 +$C1, $CA, $95, $00, $86, $C1, $E4, $C0 +$D0, $0D, $4C, $14, $05, $A6, $C1, $E0 +$80, $10, $F7, $B5, $00, $E6, $C1, $60 +$85, $BD, $86, $BC, $4C, $B8, $07, $A6 +$C1, $B5, $01, $10, $08, $20, $41, $0A +$A9, $2D, $20, $A6, $06, $20, $FC, $08 +$A9, $1F, $85, $B8, $85, $BA, $A9, $2A +$85, $B9, $85, $BB, $A6, $BC, $A4, $BD +$38, $E6, $B8, $8A, $E9, $10, $AA, $98 +$E9, $27, $A8, $B0, $F4, $C6, $B9, $8A +$69, $E8, $AA, $98, $69, $03, $A8, $90 +$F4, $8A, $38, $E6, $BA, $E9, $64, $B0 +$F9, $88, $10, $F6, $C6, $BB, $69, $0A +$90, $FA, $09, $30, $85, $BC, $A9, $20 +$85, $BD, $A2, $FB, $86, $C3, $B5, $BD +$05, $BD, $C9, $20, $F0, $09, $A0, $30 +$84, $BD, $05, $BD, $20, $A6, $06, $A6 +$C3, $E8, $D0, $E8, $60, $A5, $2D, $48 +$A5, $2C, $48, $A5, $20, $85, $2C, $A5 +$21, $85, $2D, $A5, $24, $A6, $25, $20 +$5B, $08, $F0, $03, $20, $5B, $08, $A5 +$2C, $38, $E5, $B6, $A5, $2D, $E5, $B7 +$B0, $42, $20, $6D, $07, $F0, $3D, $A6 +$28, $A5, $29, $20, $A0, $07, $A9, $20 +$20, $A6, $06, $20, $0C, $04, $B0, $2C +$20, $14, $06, $D0, $F3, $20, $83, $08 +$4C, $2F, $08, $85, $B6, $E6, $B6, $D0 +$01, $E8, $86, $B7, $A4, $C1, $C0, $80 +$F0, $18, $20, $6B, $06, $A5, $2C, $A6 +$2D, $38, $E9, $02, $B0, $01, $CA, $85 +$2C, $4C, $48, $0B, $68, $85, $2C, $68 +$85, $2D, $60, $A5, $BF, $30, $FB, $A9 +$0D, $20, $09, $04, $AD, $11, $04, $29 +$7F, $85, $BF, $F0, $07, $20, $64, $0B +$C6, $BF, $D0, $F9, $A9, $0A, $4C, $61 +$0B, $AC, $12, $04, $84, $BF, $B0, $0B +$A9, $30, $85, $2C, $85, $C0, $84, $2D +$20, $80, $07, $45, $80, $85, $80, $20 +$06, $04, $A0, $00, $A6, $C0, $29, $7F +$F0, $F1, $C9, $7F, $F0, $ED, $C9, $13 +$F0, $DA, $C9, $0A, $F0, $D3, $CD, $10 +$04, $F0, $09, $CD, $0F, $04, $D0, $0A +$E0, $30, $D0, $16, $A6, $2C, $84, $BF +$A9, $0D, $E4, $C1, $30, $08, $A9, $07 +$20, $A6, $06, $4C, $B3, $08, $95, $00 +$E8, $E8, $CA, $86, $C0, $C9, $0D, $D0 +$BA, $20, $83, $08, $20, $95, $07, $85 +$BC, $20, $95, $07, $85, $BD, $60, $20 +$D6, $0A, $20, $6B, $06, $08, $20, $6D +$08, $85, $B8, $86, $B9, $A5, $BC, $85 +$B6, $A5, $BD, $85, $B7, $A2, $00, $28 +$D0, $0B, $20, $6D, $07, $CA, $CA, $CA +$20, $14, $06, $D0, $FA, $84, $28, $84 +$29, $20, $D6, $0A, $A9, $0D, $D1, $2C +$F0, $11, $E8, $E8, $E8, $E8, $C8, $D1 +$2C, $D0, $FA, $A5, $B6, $85, $28, $A5 +$B7, $85, $29, $A5, $B8, $85, $BC, $A5 +$B9, $85, $BD, $18, $A0, $00, $8A, $F0 +$6E, $10, $29, $65, $2E, $85, $B8, $A5 +$2F, $E9, $00, $85, $B9, $B1, $2E, $91 +$B8, $A6, $2E, $E4, $24, $D0, $06, $A5 +$2F, $C5, $25, $F0, $4A, $E8, $86, $2E +$D0, $02, $E6, $2F, $E6, $B8, $D0, $E5 +$E6, $B9, $D0, $E1, $65, $24, $85, $B8 +$85, $2E, $98, $65, $25, $85, $B9, $85 +$2F, $A5, $2E, $E5, $C6, $A5, $2F, $E5 +$C7, $90, $05, $C6, $2A, $4C, $14, $05 +$B1, $24, $91, $2E, $A6, $24, $D0, $02 +$C6, $25, $C6, $24, $A6, $2E, $D0, $02 +$C6, $2F, $CA, $86, $2E, $E4, $BC, $D0 +$E7, $A6, $2F, $E4, $BD, $D0, $E1, $A5 +$B8, $85, $24, $A5, $B9, $85, $25, $A5 +$28, $05, $29, $F0, $17, $A5, $28, $91 +$BC, $C8, $A5, $29, $91, $BC, $C8, $84 +$B6, $20, $14, $06, $08, $A4, $B6, $91 +$BC, $28, $D0, $F2, $4C, $CC, $04, $20 +$54, $05, $B5, $03, $29, $80, $F0, $02 +$A9, $FF, $85, $BC, $85, $BD, $48, $75 +$02, $95, $02, $68, $48, $75, $03, $95 +$03, $68, $55, $01, $85, $BB, $10, $03 +$20, $43, $0A, $A0, $11, $B5, $00, $15 +$01, $D0, $03, $4C, $14, $05, $38, $A5 +$BC, $F5, $00, $48, $A5, $BD, $F5, $01 +$48, $45, $BD, $30, $0A, $68, $85, $BD +$68, $85, $BC, $38, $4C, $32, $0A, $68 +$68, $18, $36, $02, $36, $03, $26, $BC +$26, $BD, $88, $D0, $D9, $A5, $BB, $10 +$0D, $A6, $C1, $38, $98, $F5, $00, $95 +$00, $98, $F5, $01, $95, $01, $60, $20 +$41, $0A, $20, $54, $05, $B5, $00, $75 +$02, $95, $02, $B5, $01, $75, $03, $95 +$03, $60, $20, $54, $05, $A0, $10, $B5 +$02, $85, $BC, $B5, $03, $85, $BD, $16 +$02, $36, $03, $26, $BC, $26, $BD, $90 +$0D, $18, $B5, $02, $75, $00, $95, $02 +$B5, $03, $75, $01, $95, $03, $88, $D0 +$E6, $60, $20, $95, $07, $AA, $B5, $00 +$B4, $01, $C6, $C1, $A6, $C1, $94, $00 +$4C, $87, $07, $A2, $7D, $20, $56, $05 +$B5, $01, $48, $B5, $00, $48, $20, $95 +$07, $AA, $68, $95, $00, $68, $95, $01 +$60, $20, $FD, $0A, $A5, $BC, $85, $2A +$A5, $BD, $85, $2B, $60, $A2, $2C, $D0 +$02, $A2, $2E, $B5, $00, $C9, $80, $B0 +$0D, $B5, $01, $D0, $09, $A5, $2C, $85 +$2E, $A5, $2D, $85, $2F, $60, $A5, $2C +$A4, $2E, $84, $2C, $85, $2E, $A5, $2D +$A4, $2F, $84, $2D, $85, $2F, $A0, $00 +$60, $A5, $28, $85, $BC, $A5, $29, $85 +$BD, $20, $9C, $05, $A5, $C6, $85, $26 +$A5, $C7, $85, $27, $60, $B1, $C6, $85 +$BC, $20, $08, $0B, $B1, $C6, $85, $BD +$E6, $C6, $D0, $02, $E6, $C7, $A5, $22 +$C5, $C6, $A5, $23, $E5, $C7, $B0, $E4 +$4C, $14, $05, $20, $24, $0B, $85, $BC +$98, $4C, $82, $07, $20, $FC, $08, $A5 +$BC, $85, $B6, $20, $FC, $08, $A5, $BD +$85, $B7, $A4, $BC, $20, $FC, $08, $A6 +$B7, $A5, $B6, $18, $6C, $BC, $00, $20 +$42, $0B, $20, $F9, $06, $4C, $87, $07 +$86, $2D, $E0, $00, $60, $A0, $02, $84 +$BC, $A0, $29, $84, $BD, $A0, $00, $B1 +$BC, $C9, $08, $D0, $03, $4C, $0B, $0A +$60, $20, $09, $04, $A9, $FF, $2C, $11 +$04, $30, $02, $A9, $00, $4C, $09, $04 +$24, $3A, $91, $27, $10, $E1, $59, $C5 +$2A, $56, $10, $11, $2C, $8B, $4C, $45 +$D4, $A0, $80, $BD, $30, $BC, $E0, $13 +$1D, $94, $47, $CF, $88, $54, $CF, $30 +$BC, $E0, $10, $11, $16, $80, $53, $55 +$C2, $30, $BC, $E0, $14, $16, $90, $50 +$D2, $83, $49, $4E, $D4, $E5, $71, $88 +$BB, $E1, $1D, $8F, $A2, $21, $58, $6F +$83, $AC, $22, $55, $83, $BA, $24, $93 +$E0, $23, $1D, $30, $BC, $20, $48, $91 +$49, $C6, $30, $BC, $31, $34, $30, $BC +$84, $54, $48, $45, $CE, $1C, $1D, $38 +$0D, $9A, $49, $4E, $50, $55, $D4, $A0 +$10, $E7, $24, $3F, $20, $91, $27, $E1 +$59, $81, $AC, $30, $BC, $13, $11, $82 +$AC, $4D, $E0, $1D, $89, $52, $45, $54 +$55, $52, $CE, $E0, $15, $1D, $85, $45 +$4E, $C4, $E0, $2D, $98, $4C, $49, $53 +$D4, $EC, $24, $00, $00, $00, $00, $0A +$80, $1F, $24, $93, $23, $1D, $30, $BC +$E1, $50, $80, $AC, $59, $85, $52, $55 +$CE, $38, $0A, $86, $43, $4C, $45, $41 +$D2, $2B, $84, $52, $45, $CD, $1D, $A0 +$80, $BD, $38, $14, $85, $AD, $30, $D3 +$17, $64, $81, $AB, $30, $D3, $85, $AB +$30, $D3, $18, $5A, $85, $AD, $30, $D3 +$19, $54, $2F, $30, $E2, $85, $AA, $30 +$E2, $1A, $5A, $85, $AF, $30, $E2, $1B +$54, $2F, $98, $52, $4E, $C4, $0A, $80 +$80, $12, $0A, $09, $29, $1A, $0A, $1A +$85, $18, $13, $09, $80, $12, $01, $0B +$31, $30, $61, $72, $0B, $04, $02, $03 +$05, $03, $1B, $1A, $19, $0B, $09, $06 +$0A, $00, $00, $1C, $17, $2F, $8F, $55 +$53, $D2, $80, $A8, $30, $BC, $31, $2A +$31, $2A, $80, $A9, $2E, $2F, $A2, $12 +$2F, $C1, $2F, $80, $A8, $30, $BC, $80 +$A9, $2F, $83, $AC, $38, $BC, $0B, $2F +$80, $A8, $52, $2F, $84, $BD, $09, $02 +$2F, $8E, $BC, $84, $BD, $09, $93, $2F +$84, $BE, $09, $05, $2F, $09, $91, $2F +$80, $BE, $84, $BD, $09, $06, $2F, $84 +$BC, $09, $95, $2F, $09, $04, $2F, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$20, $0D, $0F, $A0, $00, $20, $1D, $0F +$20, $2C, $0F, $C9, $43, $D0, $03, $4C +$85, $04, $C9, $57, $D0, $03, $4C, $BD +$04, $A2, $2F, $20, $1D, $0F, $4C, $F8 +$0C, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$4D, $4B, $48, $42, $43, $2D, $38, $2D +$52, $32, $20, $54, $49, $4E, $59, $20 +$42, $41, $53, $49, $43, $20, $36, $35 +$30, $32, $20, $50, $4F, $52, $54, $0D +$0A, $56, $65, $72, $73, $69, $6F, $6E +$3A, $20, $31, $2E, $30, $2E, $33, $2C +$20, $32, $2F, $32, $30, $2F, $32, $30 +$31, $36, $0D, $0A, $28, $4E, $4F, $54 +$45, $3A, $20, $55, $73, $65, $20, $55 +$50, $50, $45, $52, $20, $43, $41, $53 +$45, $2E, $29, $0D, $0A, $42, $6F, $6F +$74, $20, $28, $5B, $43, $5D, $6F, $6C +$64, $2F, $5B, $57, $5D, $61, $72, $6D +$29, $3F, $20, $07, $FF, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$86, $C3, $B1, $C2, $48, $C8, $B1, $C2 +$AA, $68, $A8, $8A, $60, $A2, $19, $A9 +$0D, $20, $31, $0F, $A9, $0A, $20, $31 +$0F, $CA, $D0, $FA, $60, $B9, $00, $0E +$C9, $FF, $F0, $07, $20, $31, $0F, $C8 +$4C, $1D, $0F, $60, $AD, $00, $E0, $F0 +$FB, $85, $FE, $C9, $FF, $F0, $1E, $C9 +$00, $F0, $1A, $C9, $91, $F0, $16, $C9 +$93, $F0, $12, $C9, $80, $F0, $0E, $4C +$50, $0F, $20, $F0, $FF, $A5, $FE, $60 +$A5, $FE, $8D, $00, $E0, $60, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 diff --git a/tbe.dat b/tbe.dat new file mode 100644 index 0000000..1669f0b --- /dev/null +++ b/tbe.dat @@ -0,0 +1,423 @@ +ADDR +$0CF0 +; Program disassembly from $0400 to $1000 2/20/2016 +; Tiny Basic port for VM6502 emulator. +; Exec address: $0CF0 +;------------------------------------------------------ +ORG +$0400 +;------------------------------------------------------ +; Character I/O emulation address. +;------------------------------------------------------ +IOADDR +$E000 +;------------------------------------------------------ +; Enable character I/O emulation. +;------------------------------------------------------ +ENIO +;------------------------------------------------------ +; Begin of ROM. +;------------------------------------------------------ +ROMBEGIN +$DF00 +;------------------------------------------------------ +; End of ROM. +;------------------------------------------------------ +ROMEND +$FFFF +;------------------------------------------------------ +; Enable ROM (protected read-only memory) emulation. +;------------------------------------------------------ +ENROM +;------------------------------------------------------ +; Auto-execute code from address. +;------------------------------------------------------ +EXEC +$0CF0 +;------------------------------------------------------ +; Code/Data +;------------------------------------------------------ +$4C, $85, $04, $4C, $BD, $04, $4C, $2C +$0F, $4C, $31, $0F, $EA, $18, $60, $5F +$18, $80, $00, $20, $86, $C3, $90, $05 +$86, $C3, $91, $C2, $60, $B1, $C2, $A0 +$00, $60, $62, $05, $64, $05, $D8, $05 +$05, $06, $33, $06, $FD, $05, $9F, $07 +$42, $0B, $3F, $0B, $7A, $07, $FC, $08 +$95, $07, $9F, $07, $9F, $07, $BD, $0A +$C1, $0A, $8A, $0A, $9B, $0A, $E9, $0A +$61, $07, $51, $07, $41, $0A, $52, $0A +$4F, $0A, $62, $0A, $E7, $09, $CD, $06 +$06, $07, $9F, $07, $15, $08, $A7, $07 +$B7, $06, $BF, $06, $83, $08, $A1, $06 +$9F, $07, $9F, $07, $A8, $08, $4F, $0B +$4D, $0B, $07, $09, $AA, $04, $37, $07 +$BD, $04, $1B, $0B, $B1, $0A, $20, $41 +$54, $20, $80, $70, $0B, $A9, $00, $85 +$20, $85, $22, $A9, $1C, $85, $21, $85 +$23, $A0, $01, $B1, $22, $AA, $49, $FF +$91, $22, $D1, $22, $08, $8A, $91, $22 +$E6, $22, $D0, $02, $E6, $23, $28, $F0 +$EA, $88, $D8, $A5, $20, $6D, $13, $04 +$85, $24, $98, $65, $21, $85, $25, $98 +$91, $20, $C8, $91, $20, $A5, $22, $85 +$C6, $85, $26, $A5, $23, $85, $C7, $85 +$27, $20, $87, $08, $AD, $83, $04, $85 +$2A, $AD, $84, $04, $85, $2B, $A9, $80 +$85, $C1, $A9, $30, $85, $C0, $A2, $00 +$86, $BE, $86, $C2, $CA, $9A, $D8, $20 +$F9, $06, $20, $F2, $04, $4C, $E6, $04 +$83, $65, $C9, $30, $B0, $7B, $C9, $08 +$90, $0C, $0A, $AA, $BD, $1F, $04, $48 +$BD, $1E, $04, $48, $08, $40, $65, $C1 +$AA, $B1, $C1, $48, $B5, $00, $91, $C1 +$68, $95, $00, $60, $20, $87, $08, $A9 +$21, $20, $09, $04, $A5, $2A, $38, $ED +$83, $04, $AA, $A5, $2B, $ED, $84, $04 +$20, $A0, $07, $A5, $BE, $F0, $12, $A9 +$7E, $85, $2A, $A9, $20, $85, $2B, $20 +$A1, $06, $A6, $28, $A5, $29, $20, $A0 +$07, $A9, $07, $20, $09, $04, $20, $87 +$08, $A5, $26, $85, $C6, $A5, $27, $85 +$C7, $4C, $CC, $04, $A2, $7C, $E4, $C1 +$90, $BA, $A6, $C1, $E6, $C1, $E6, $C1 +$18, $60, $C6, $BD, $A5, $BD, $F0, $AC +$A5, $BC, $85, $2A, $A5, $BD, $85, $2B +$60, $C9, $40, $B0, $43, $48, $20, $F9 +$06, $6D, $83, $04, $85, $BC, $68, $48 +$29, $07, $6D, $84, $04, $85, $BD, $68 +$29, $08, $D0, $DC, $A5, $BC, $A6, $2A +$85, $2A, $86, $BC, $A5, $BD, $A6, $2B +$85, $2B, $86, $BD, $A5, $C6, $E9, $01 +$85, $C6, $B0, $02, $C6, $C7, $C5, $24 +$A5, $C7, $E5, $25, $90, $AA, $A5, $BC +$91, $C6, $C8, $A5, $BD, $91, $C6, $60 +$48, $4A, $4A, $4A, $4A, $29, $0E, $AA +$68, $C9, $60, $29, $1F, $B0, $02, $09 +$E0, $18, $F0, $07, $65, $2A, $85, $BC +$98, $65, $2B, $85, $BD, $4C, $FC, $04 +$A5, $2C, $85, $B8, $A5, $2D, $85, $B9 +$20, $25, $06, $20, $14, $06, $51, $2A +$AA, $20, $F9, $06, $8A, $F0, $F1, $0A +$F0, $12, $A5, $B8, $85, $2C, $A5, $B9 +$85, $2D, $4C, $64, $05, $20, $25, $06 +$C9, $0D, $D0, $F6, $60, $20, $25, $06 +$C9, $5B, $B0, $EE, $C9, $41, $90, $EA +$0A, $20, $87, $07, $A0, $00, $B1, $2C +$E6, $2C, $D0, $02, $E6, $2D, $C9, $0D +$18, $60, $20, $14, $06, $B1, $2C, $C9 +$20, $F0, $F7, $C9, $3A, $18, $10, $02 +$C9, $30, $60, $20, $25, $06, $90, $C2 +$84, $BC, $84, $BD, $A5, $BC, $A6, $BD +$06, $BC, $26, $BD, $06, $BC, $26, $BD +$18, $65, $BC, $85, $BC, $8A, $65, $BD +$06, $BC, $2A, $85, $BD, $20, $14, $06 +$29, $0F, $65, $BC, $85, $BC, $98, $65 +$BD, $85, $BD, $20, $25, $06, $B0, $D4 +$4C, $80, $07, $20, $FC, $08, $A5, $BC +$05, $BD, $F0, $48, $A5, $20, $85, $2C +$A5, $21, $85, $2D, $20, $6D, $07, $F0 +$12, $A5, $28, $C5, $BC, $A5, $29, $E5 +$BD, $B0, $08, $20, $14, $06, $D0, $FB +$4C, $7C, $06, $A5, $28, $45, $BC, $D0 +$04, $A5, $29, $45, $BD, $60, $20, $A6 +$06, $20, $F9, $06, $10, $F8, $E6, $BF +$30, $03, $4C, $09, $04, $C6, $BF, $60 +$C9, $22, $F0, $FB, $20, $A6, $06, $20 +$14, $06, $D0, $F4, $4C, $14, $05, $A9 +$20, $20, $A6, $06, $A5, $BF, $29, $87 +$30, $E5, $D0, $F3, $60, $A2, $7B, $20 +$56, $05, $E6, $C1, $E6, $C1, $E6, $C1 +$38, $B5, $03, $F5, $00, $95, $00, $B5 +$04, $F5, $01, $50, $04, $49, $80, $09 +$01, $30, $0A, $D0, $04, $15, $00, $F0 +$02, $56, $02, $56, $02, $56, $02, $90 +$0C, $A0, $00, $B1, $2A, $E6, $2A, $D0 +$02, $E6, $2B, $09, $00, $60, $A5, $BE +$F0, $28, $20, $14, $06, $D0, $FB, $20 +$6D, $07, $F0, $1B, $20, $4C, $07, $20 +$0C, $04, $B0, $09, $A5, $C4, $85, $2A +$A5, $C5, $85, $2B, $60, $AD, $83, $04 +$85, $2A, $AD, $84, $04, $85, $2B, $4C +$14, $05, $85, $BF, $4C, $49, $05, $A5 +$20, $85, $2C, $A5, $21, $85, $2D, $20 +$6D, $07, $F0, $EB, $A5, $2A, $85, $C4 +$A5, $2B, $85, $C5, $A9, $01, $85, $BE +$60, $20, $6B, $06, $F0, $BE, $A5, $BC +$85, $28, $A5, $BD, $85, $29, $4C, $14 +$05, $20, $FD, $0A, $20, $FA, $0A, $20 +$74, $06, $D0, $EA, $60, $20, $14, $06 +$85, $28, $20, $14, $06, $85, $29, $05 +$28, $60, $20, $FC, $08, $20, $80, $07 +$A5, $BD, $20, $87, $07, $A5, $BC, $A6 +$C1, $CA, $95, $00, $86, $C1, $E4, $C0 +$D0, $0D, $4C, $14, $05, $A6, $C1, $E0 +$80, $10, $F7, $B5, $00, $E6, $C1, $60 +$85, $BD, $86, $BC, $4C, $B8, $07, $A6 +$C1, $B5, $01, $10, $08, $20, $41, $0A +$A9, $2D, $20, $A6, $06, $20, $FC, $08 +$A9, $1F, $85, $B8, $85, $BA, $A9, $2A +$85, $B9, $85, $BB, $A6, $BC, $A4, $BD +$38, $E6, $B8, $8A, $E9, $10, $AA, $98 +$E9, $27, $A8, $B0, $F4, $C6, $B9, $8A +$69, $E8, $AA, $98, $69, $03, $A8, $90 +$F4, $8A, $38, $E6, $BA, $E9, $64, $B0 +$F9, $88, $10, $F6, $C6, $BB, $69, $0A +$90, $FA, $09, $30, $85, $BC, $A9, $20 +$85, $BD, $A2, $FB, $86, $C3, $B5, $BD +$05, $BD, $C9, $20, $F0, $09, $A0, $30 +$84, $BD, $05, $BD, $20, $A6, $06, $A6 +$C3, $E8, $D0, $E8, $60, $A5, $2D, $48 +$A5, $2C, $48, $A5, $20, $85, $2C, $A5 +$21, $85, $2D, $A5, $24, $A6, $25, $20 +$5B, $08, $F0, $03, $20, $5B, $08, $A5 +$2C, $38, $E5, $B6, $A5, $2D, $E5, $B7 +$B0, $42, $20, $6D, $07, $F0, $3D, $A6 +$28, $A5, $29, $20, $A0, $07, $A9, $20 +$20, $A6, $06, $20, $0C, $04, $B0, $2C +$20, $14, $06, $D0, $F3, $20, $83, $08 +$4C, $2F, $08, $85, $B6, $E6, $B6, $D0 +$01, $E8, $86, $B7, $A4, $C1, $C0, $80 +$F0, $18, $20, $6B, $06, $A5, $2C, $A6 +$2D, $38, $E9, $02, $B0, $01, $CA, $85 +$2C, $4C, $48, $0B, $68, $85, $2C, $68 +$85, $2D, $60, $A5, $BF, $30, $FB, $A9 +$0D, $20, $09, $04, $AD, $11, $04, $29 +$7F, $85, $BF, $F0, $07, $20, $64, $0B +$C6, $BF, $D0, $F9, $A9, $0A, $4C, $61 +$0B, $AC, $12, $04, $84, $BF, $B0, $0B +$A9, $30, $85, $2C, $85, $C0, $84, $2D +$20, $80, $07, $45, $80, $85, $80, $20 +$06, $04, $A0, $00, $A6, $C0, $29, $7F +$F0, $F1, $C9, $7F, $F0, $ED, $C9, $13 +$F0, $DA, $C9, $0A, $F0, $D3, $CD, $10 +$04, $F0, $09, $CD, $0F, $04, $D0, $0A +$E0, $30, $D0, $16, $A6, $2C, $84, $BF +$A9, $0D, $E4, $C1, $30, $08, $A9, $07 +$20, $A6, $06, $4C, $B3, $08, $95, $00 +$E8, $E8, $CA, $86, $C0, $C9, $0D, $D0 +$BA, $20, $83, $08, $20, $95, $07, $85 +$BC, $20, $95, $07, $85, $BD, $60, $20 +$D6, $0A, $20, $6B, $06, $08, $20, $6D +$08, $85, $B8, $86, $B9, $A5, $BC, $85 +$B6, $A5, $BD, $85, $B7, $A2, $00, $28 +$D0, $0B, $20, $6D, $07, $CA, $CA, $CA +$20, $14, $06, $D0, $FA, $84, $28, $84 +$29, $20, $D6, $0A, $A9, $0D, $D1, $2C +$F0, $11, $E8, $E8, $E8, $E8, $C8, $D1 +$2C, $D0, $FA, $A5, $B6, $85, $28, $A5 +$B7, $85, $29, $A5, $B8, $85, $BC, $A5 +$B9, $85, $BD, $18, $A0, $00, $8A, $F0 +$6E, $10, $29, $65, $2E, $85, $B8, $A5 +$2F, $E9, $00, $85, $B9, $B1, $2E, $91 +$B8, $A6, $2E, $E4, $24, $D0, $06, $A5 +$2F, $C5, $25, $F0, $4A, $E8, $86, $2E +$D0, $02, $E6, $2F, $E6, $B8, $D0, $E5 +$E6, $B9, $D0, $E1, $65, $24, $85, $B8 +$85, $2E, $98, $65, $25, $85, $B9, $85 +$2F, $A5, $2E, $E5, $C6, $A5, $2F, $E5 +$C7, $90, $05, $C6, $2A, $4C, $14, $05 +$B1, $24, $91, $2E, $A6, $24, $D0, $02 +$C6, $25, $C6, $24, $A6, $2E, $D0, $02 +$C6, $2F, $CA, $86, $2E, $E4, $BC, $D0 +$E7, $A6, $2F, $E4, $BD, $D0, $E1, $A5 +$B8, $85, $24, $A5, $B9, $85, $25, $A5 +$28, $05, $29, $F0, $17, $A5, $28, $91 +$BC, $C8, $A5, $29, $91, $BC, $C8, $84 +$B6, $20, $14, $06, $08, $A4, $B6, $91 +$BC, $28, $D0, $F2, $4C, $CC, $04, $20 +$54, $05, $B5, $03, $29, $80, $F0, $02 +$A9, $FF, $85, $BC, $85, $BD, $48, $75 +$02, $95, $02, $68, $48, $75, $03, $95 +$03, $68, $55, $01, $85, $BB, $10, $03 +$20, $43, $0A, $A0, $11, $B5, $00, $15 +$01, $D0, $03, $4C, $14, $05, $38, $A5 +$BC, $F5, $00, $48, $A5, $BD, $F5, $01 +$48, $45, $BD, $30, $0A, $68, $85, $BD +$68, $85, $BC, $38, $4C, $32, $0A, $68 +$68, $18, $36, $02, $36, $03, $26, $BC +$26, $BD, $88, $D0, $D9, $A5, $BB, $10 +$0D, $A6, $C1, $38, $98, $F5, $00, $95 +$00, $98, $F5, $01, $95, $01, $60, $20 +$41, $0A, $20, $54, $05, $B5, $00, $75 +$02, $95, $02, $B5, $01, $75, $03, $95 +$03, $60, $20, $54, $05, $A0, $10, $B5 +$02, $85, $BC, $B5, $03, $85, $BD, $16 +$02, $36, $03, $26, $BC, $26, $BD, $90 +$0D, $18, $B5, $02, $75, $00, $95, $02 +$B5, $03, $75, $01, $95, $03, $88, $D0 +$E6, $60, $20, $95, $07, $AA, $B5, $00 +$B4, $01, $C6, $C1, $A6, $C1, $94, $00 +$4C, $87, $07, $A2, $7D, $20, $56, $05 +$B5, $01, $48, $B5, $00, $48, $20, $95 +$07, $AA, $68, $95, $00, $68, $95, $01 +$60, $20, $FD, $0A, $A5, $BC, $85, $2A +$A5, $BD, $85, $2B, $60, $A2, $2C, $D0 +$02, $A2, $2E, $B5, $00, $C9, $80, $B0 +$0D, $B5, $01, $D0, $09, $A5, $2C, $85 +$2E, $A5, $2D, $85, $2F, $60, $A5, $2C +$A4, $2E, $84, $2C, $85, $2E, $A5, $2D +$A4, $2F, $84, $2D, $85, $2F, $A0, $00 +$60, $A5, $28, $85, $BC, $A5, $29, $85 +$BD, $20, $9C, $05, $A5, $C6, $85, $26 +$A5, $C7, $85, $27, $60, $B1, $C6, $85 +$BC, $20, $08, $0B, $B1, $C6, $85, $BD +$E6, $C6, $D0, $02, $E6, $C7, $A5, $22 +$C5, $C6, $A5, $23, $E5, $C7, $B0, $E4 +$4C, $14, $05, $20, $24, $0B, $85, $BC +$98, $4C, $82, $07, $20, $FC, $08, $A5 +$BC, $85, $B6, $20, $FC, $08, $A5, $BD +$85, $B7, $A4, $BC, $20, $FC, $08, $A6 +$B7, $A5, $B6, $18, $6C, $BC, $00, $20 +$42, $0B, $20, $F9, $06, $4C, $87, $07 +$86, $2D, $E0, $00, $60, $A0, $02, $84 +$BC, $A0, $29, $84, $BD, $A0, $00, $B1 +$BC, $C9, $08, $D0, $03, $4C, $0B, $0A +$60, $20, $09, $04, $A9, $FF, $2C, $11 +$04, $30, $02, $A9, $00, $4C, $09, $04 +$24, $3A, $91, $27, $10, $E1, $59, $C5 +$2A, $56, $10, $11, $2C, $8B, $4C, $45 +$D4, $A0, $80, $BD, $30, $BC, $E0, $13 +$1D, $94, $47, $CF, $88, $54, $CF, $30 +$BC, $E0, $10, $11, $16, $80, $53, $55 +$C2, $30, $BC, $E0, $14, $16, $90, $50 +$D2, $83, $49, $4E, $D4, $E5, $71, $88 +$BB, $E1, $1D, $8F, $A2, $21, $58, $6F +$83, $AC, $22, $55, $83, $BA, $24, $93 +$E0, $23, $1D, $30, $BC, $20, $48, $91 +$49, $C6, $30, $BC, $31, $34, $30, $BC +$84, $54, $48, $45, $CE, $1C, $1D, $38 +$0D, $9A, $49, $4E, $50, $55, $D4, $A0 +$10, $E7, $24, $3F, $20, $91, $27, $E1 +$59, $81, $AC, $30, $BC, $13, $11, $82 +$AC, $4D, $E0, $1D, $89, $52, $45, $54 +$55, $52, $CE, $E0, $15, $1D, $85, $45 +$4E, $C4, $E0, $2D, $98, $4C, $49, $53 +$D4, $EC, $24, $00, $00, $00, $00, $0A +$80, $1F, $24, $93, $23, $1D, $30, $BC +$E1, $50, $80, $AC, $59, $85, $52, $55 +$CE, $38, $0A, $86, $43, $4C, $45, $41 +$D2, $2B, $84, $52, $45, $CD, $1D, $A0 +$80, $BD, $38, $14, $85, $AD, $30, $D3 +$17, $64, $81, $AB, $30, $D3, $85, $AB +$30, $D3, $18, $5A, $85, $AD, $30, $D3 +$19, $54, $2F, $30, $E2, $85, $AA, $30 +$E2, $1A, $5A, $85, $AF, $30, $E2, $1B +$54, $2F, $98, $52, $4E, $C4, $0A, $80 +$80, $12, $0A, $09, $29, $1A, $0A, $1A +$85, $18, $13, $09, $80, $12, $01, $0B +$31, $30, $61, $72, $0B, $04, $02, $03 +$05, $03, $1B, $1A, $19, $0B, $09, $06 +$0A, $00, $00, $1C, $17, $2F, $8F, $55 +$53, $D2, $80, $A8, $30, $BC, $31, $2A +$31, $2A, $80, $A9, $2E, $2F, $A2, $12 +$2F, $C1, $2F, $80, $A8, $30, $BC, $80 +$A9, $2F, $83, $AC, $38, $BC, $0B, $2F +$80, $A8, $52, $2F, $84, $BD, $09, $02 +$2F, $8E, $BC, $84, $BD, $09, $93, $2F +$84, $BE, $09, $05, $2F, $09, $91, $2F +$80, $BE, $84, $BD, $09, $06, $2F, $84 +$BC, $09, $95, $2F, $09, $04, $2F, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$20, $0D, $0F, $A0, $00, $20, $1D, $0F +$20, $2C, $0F, $C9, $43, $D0, $03, $4C +$85, $04, $C9, $57, $D0, $03, $4C, $BD +$04, $A2, $2F, $20, $1D, $0F, $4C, $F8 +$0C, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$4D, $4B, $48, $42, $43, $2D, $38, $2D +$52, $32, $20, $54, $49, $4E, $59, $20 +$42, $41, $53, $49, $43, $20, $36, $35 +$30, $32, $20, $50, $4F, $52, $54, $0D +$0A, $56, $65, $72, $73, $69, $6F, $6E +$3A, $20, $31, $2E, $30, $2E, $33, $2C +$20, $32, $2F, $32, $30, $2F, $32, $30 +$31, $36, $0D, $0A, $28, $4E, $4F, $54 +$45, $3A, $20, $55, $73, $65, $20, $55 +$50, $50, $45, $52, $20, $43, $41, $53 +$45, $2E, $29, $0D, $0A, $42, $6F, $6F +$74, $20, $28, $5B, $43, $5D, $6F, $6C +$64, $2F, $5B, $57, $5D, $61, $72, $6D +$29, $3F, $20, $07, $FF, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$86, $C3, $B1, $C2, $48, $C8, $B1, $C2 +$AA, $68, $A8, $8A, $60, $A2, $19, $A9 +$0D, $20, $31, $0F, $A9, $0A, $20, $31 +$0F, $CA, $D0, $FA, $60, $B9, $00, $0E +$C9, $FF, $F0, $07, $20, $31, $0F, $C8 +$4C, $1D, $0F, $60, $AD, $00, $E0, $F0 +$FB, $85, $FE, $C9, $FF, $F0, $1E, $C9 +$00, $F0, $1A, $C9, $91, $F0, $16, $C9 +$93, $F0, $12, $C9, $80, $F0, $0E, $4C +$50, $0F, $20, $F0, $FF, $A5, $FE, $60 +$A5, $FE, $8D, $00, $E0, $60, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 +$00, $00, $00, $00, $00, $00, $00, $00 diff --git a/test_char_io_01.65s b/test_char_io_01.65s index 343d122..18a4bd6 100644 --- a/test_char_io_01.65s +++ b/test_char_io_01.65s @@ -1,50 +1,50 @@ -; Basic test of char I/O emulation - - .ORG $0200 - -CHRGET = $E000 -PUTCH = $E000 -TXTBUF = $0400 -CR = $0D -NL = $0A - -START: LDX #$00 -PR1: LDA PROMPT,X ;print prompt - BEQ L0 - STA PUTCH - INX - BNE PR1 -L0: LDX #$00 -GETTXT: LDA CHRGET ;get text from input - BEQ GETTXT - CMP #CR - BEQ L1 - CMP #NL - BEQ L1 - STA PUTCH ;echo char - STA TXTBUF,X ;store char - INX - BNE GETTXT -L1: LDA #NL ; add line break - STA TXTBUF,X - STA PUTCH - INX - LDA #CR - STA TXTBUF,X - STA PUTCH - INX - LDA #$00 ; add null - STA TXTBUF,X - TAX -PRINT: LDA TXTBUF,X ; print to output - BEQ L2 - STA PUTCH - INX - BNE PRINT -L2: BRK - NOP - JMP START -PROMPT: .DB "Enter text:",0 - - +; Basic test of char I/O emulation + + .ORG $0200 + +CHRGET = $E000 +PUTCH = $E000 +TXTBUF = $0400 +CR = $0D +NL = $0A + +START: LDX #$00 +PR1: LDA PROMPT,X ;print prompt + BEQ L0 + STA PUTCH + INX + BNE PR1 +L0: LDX #$00 +GETTXT: LDA CHRGET ;get text from input + BEQ GETTXT + CMP #CR + BEQ L1 + CMP #NL + BEQ L1 + STA PUTCH ;echo char + STA TXTBUF,X ;store char + INX + BNE GETTXT +L1: LDA #NL ; add line break + STA TXTBUF,X + STA PUTCH + INX + LDA #CR + STA TXTBUF,X + STA PUTCH + INX + LDA #$00 ; add null + STA TXTBUF,X + TAX +PRINT: LDA TXTBUF,X ; print to output + BEQ L2 + STA PUTCH + INX + BNE PRINT +L2: BRK + NOP + JMP START +PROMPT: .DB "Enter text:",0 + + \ No newline at end of file diff --git a/test_char_io_01.dat b/test_char_io_01.dat index 7fdc22b..8767d98 100644 --- a/test_char_io_01.dat +++ b/test_char_io_01.dat @@ -1,15 +1,15 @@ -; I/O test for MKBASIC VM. -ORG -$0200 -$A2 $00 $BD $4E $02 $F0 $06 $8D -$00 $E0 $E8 $D0 $F5 $A2 $00 $AD -$00 $E0 $F0 $FB $C9 $0D $F0 $0D -$C9 $0A $F0 $09 $8D $00 $E0 $9D -$00 $04 $E8 $D0 $EA $A9 $0A $9D -$00 $04 $8D $00 $E0 $E8 $A9 $0D -$9D $00 $04 $8D $00 $E0 $E8 $A9 -$00 $9D $00 $04 $AA $BD $00 $04 -$F0 $06 $8D $00 $E0 $E8 $D0 $F5 -$00 $00 $EA $4C $00 $02 $45 $6E -$74 $65 $72 $20 $74 $65 $78 $74 -$3A $00 $00 $00 $00 $00 $00 $00 +; I/O test for MKBASIC VM. +ORG +$0200 +$A2 $00 $BD $4E $02 $F0 $06 $8D +$00 $E0 $E8 $D0 $F5 $A2 $00 $AD +$00 $E0 $F0 $FB $C9 $0D $F0 $0D +$C9 $0A $F0 $09 $8D $00 $E0 $9D +$00 $04 $E8 $D0 $EA $A9 $0A $9D +$00 $04 $8D $00 $E0 $E8 $A9 $0D +$9D $00 $04 $8D $00 $E0 $E8 $A9 +$00 $9D $00 $04 $AA $BD $00 $04 +$F0 $06 $8D $00 $E0 $E8 $D0 $F5 +$00 $00 $EA $4C $00 $02 $45 $6E +$74 $65 $72 $20 $74 $65 $78 $74 +$3A $00 $00 $00 $00 $00 $00 $00 diff --git a/testall.asm b/testall.asm index 197a441..a221200 100644 --- a/testall.asm +++ b/testall.asm @@ -1,925 +1,954 @@ - .ORG $4000 -start: -; EXPECTED FINAL RESULTS: $0210 = FF -; (any other number will be the -; test that failed) - -; initialize: - LDA #$00 - STA $0210 - ; store each test's expected - LDA #$55 - STA $0200 - LDA #$AA - STA $0201 - LDA #$FF - STA $0202 - LDA #$6E - STA $0203 - LDA #$42 - STA $0204 - LDA #$33 - STA $0205 - LDA #$9D - STA $0206 - LDA #$7F - STA $0207 - LDA #$A5 - STA $0208 - LDA #$1F - STA $0209 - LDA #$CE - STA $020A - LDA #$29 - STA $020B - LDA #$42 - STA $020C - LDA #$6C - STA $020D - LDA #$42 - STA $020E - - -; expected result: $022A = 0x55 -test00: - LDA #85 - LDX #42 - LDY #115 - STA $81 - LDA #$01 - STA $61 - LDA #$7E - LDA $81 - STA $0910 - LDA #$7E - LDA $0910 - STA $56,X - LDA #$7E - LDA $56,X - STY $60 - STA ($60),Y - LDA #$7E - LDA ($60),Y - STA $07ff,X - LDA #$7E - LDA $07ff,X - STA $07ff,Y - LDA #$7E - LDA $07ff,Y - STA ($36,X) - LDA #$7E - LDA ($36,X) - STX $50 - LDX $60 - LDY $50 - STX $0913 - LDX #$22 - LDX $0913 - STY $0914 - LDY #$99 - LDY $0914 - STY $2D,X - STX $77,Y - LDY #$99 - LDY $2D,X - LDX #$22 - LDX $77,Y - LDY #$99 - LDY $08A0,X - LDX #$22 - LDX $08A1,Y - STA $0200,X - -; CHECK test00: - LDA $022A - CMP $0200 - BEQ test00pass - JMP theend -test00pass: - LDA #$FE - STA $0210 - - -; expected result: $A9 = 0xAA -test01: - ; imm - LDA #85 - AND #83 - ORA #56 - EOR #17 - - ; zpg - STA $99 - LDA #185 - STA $10 - LDA #231 - STA $11 - LDA #57 - STA $12 - LDA $99 - AND $10 - ORA $11 - EOR $12 - - ; zpx - LDX #16 - STA $99 - LDA #188 - STA $20 - LDA #49 - STA $21 - LDA #23 - STA $22 - LDA $99 - AND $10,X - ORA $11,X - EOR $12,X - - ; abs - STA $99 - LDA #111 - STA $0110 - LDA #60 - STA $0111 - LDA #39 - STA $0112 - LDA $99 - AND $0110 - ORA $0111 - EOR $0112 - - ; abx - STA $99 - LDA #138 - STA $0120 - LDA #71 - STA $0121 - LDA #143 - STA $0122 - LDA $99 - AND $0110,X - ORA $0111,X - EOR $0112,X - - ; aby - LDY #32 - STA $99 - LDA #115 - STA $0130 - LDA #42 - STA $0131 - LDA #241 - STA $0132 - LDA $99 - AND $0110,Y - ORA $0111,Y - EOR $0112,Y - - ; idx - STA $99 - LDA #112 - STA $30 - LDA #$01 - STA $31 - LDA #113 - STA $32 - LDA #$01 - STA $33 - LDA #114 - STA $34 - LDA #$01 - STA $35 - LDA #197 - STA $0170 - LDA #124 - STA $0171 - LDA #161 - STA $0172 - LDA $99 - AND ($20,X) - ORA ($22,X) - EOR ($24,X) - - ; idy - STA $99 - LDA #96 - STA $40 - LDA #$01 - STA $41 - LDA #97 - STA $42 - LDA #$01 - STA $43 - LDA #98 - STA $44 - LDA #$01 - STA $45 - LDA #55 - STA $0250 - LDA #35 - STA $0251 - LDA #157 - STA $0252 - LDA $99 - LDY #$F0 - AND ($40),Y - ORA ($42),Y - EOR ($44),Y - - STA $A9 - -; CHECK test01 - LDA $A9 - CMP $0201 - BEQ test02 - LDA #$01 - STA $0210 - JMP theend - - -; expected result: $71 = 0xFF -test02: - LDA #$FF - LDX #$00 - - STA $90 - INC $90 - INC $90 - LDA $90 - LDX $90 - - STA $90,X - INC $90,X - LDA $90,X - LDX $91 - - STA $0190,X - INC $0192 - LDA $0190,X - LDX $0192 - - STA $0190,X - INC $0190,X - LDA $0190,X - LDX $0193 - - STA $0170,X - DEC $0170,X - LDA $0170,X - LDX $0174 - - STA $0170,X - DEC $0173 - LDA $0170,X - LDX $0173 - - STA $70,X - DEC $70,X - LDA $70,X - LDX $72 - - STA $70,X - DEC $71 - DEC $71 - -; CHECK test02 - LDA $71 - CMP $0202 - BEQ test03 - LDA #$02 - STA $0210 - JMP theend - - -; expected result: $01DD = 0x6E -test03: - LDA #$4B - LSR - ASL - - STA $50 - ASL $50 - ASL $50 - LSR $50 - LDA $50 - - LDX $50 - ORA #$C9 - STA $60 - ASL $4C,X - LSR $4C,X - LSR $4C,X - LDA $4C,X - - LDX $60 - ORA #$41 - STA $012E - LSR $0100,X - LSR $0100,X - ASL $0100,X - LDA $0100,X - - LDX $012E - ORA #$81 - STA $0100,X - LSR $0136 - LSR $0136 - ASL $0136 - LDA $0100,X - - ; rol & ror - - ROL - ROL - ROR - STA $70 - - LDX $70 - ORA #$03 - STA $0C,X - ROL $C0 - ROR $C0 - ROR $C0 - LDA $0C,X - - LDX $C0 - STA $D0 - ROL $75,X - ROL $75,X - ROR $75,X - LDA $D0 - - LDX $D0 - STA $0100,X - ROL $01B7 - ROL $01B7 - ROL $01B7 - ROR $01B7 - LDA $0100,X - - LDX $01B7 - STA $01DD - ROL $0100,X - ROR $0100,X - ROR $0100,X - -; CHECK test03 - LDA $01DD - CMP $0203 - BEQ test04 - LDA #$03 - STA $0210 - JMP theend - - -; expected result: $40 = 0x42 -test04: - LDA #$E8 ;originally:#$7C - STA $20 - LDA #$42 ;originally:#$02 - STA $21 - LDA #$00 - ORA #$03 - JMP jump1 - ORA #$FF ; not done -jump1: - ORA #$30 - JSR subr - ORA #$42 - JMP ($0020) - ORA #$FF ; not done -subr: - STA $30 - LDX $30 - LDA #$00 - RTS -final: - STA $0D,X - -; CHECK test04 - LDA $40 - CMP $0204 - BEQ test05 - LDA #$04 - STA $0210 - JMP theend - - -; expected result: $40 = 0x33 -test05: - LDA #$35 - - TAX - DEX - DEX - INX - TXA - - TAY - DEY - DEY - INY - TYA - - TAX - LDA #$20 - TXS - LDX #$10 - TSX - TXA - - STA $40 - -; CHECK test05 - LDA $40 - CMP $0205 - BEQ test06 - LDA #$05 - STA $0210 - JMP theend - - -; expected result: $30 = 9D -test06: - -; RESET TO CARRY FLAG = 0 - ROL - - LDA #$6A - STA $50 - LDA #$6B - STA $51 - LDA #$A1 - STA $60 - LDA #$A2 - STA $61 - - LDA #$FF - ADC #$FF - ADC #$FF - SBC #$AE - - STA $40 - LDX $40 - ADC $00,X - SBC $01,X - - ADC $60 - SBC $61 - - STA $0120 - LDA #$4D - STA $0121 - LDA #$23 - ADC $0120 - SBC $0121 - - STA $F0 - LDX $F0 - LDA #$64 - STA $0124 - LDA #$62 - STA $0125 - LDA #$26 - ADC $0100,X - SBC $0101,X - - STA $F1 - LDY $F1 - LDA #$E5 - STA $0128 - LDA #$E9 - STA $0129 - LDA #$34 - ADC $0100,Y - SBC $0101,Y - - STA $F2 - LDX $F2 - LDA #$20 - STA $70 - LDA #$01 - STA $71 - LDA #$24 - STA $72 - LDA #$01 - STA $73 - ADC ($41,X) - SBC ($3F,X) - - STA $F3 - LDY $F3 - LDA #$DA - STA $80 - LDA #$00 - STA $81 - LDA #$DC - STA $82 - LDA #$00 - STA $83 - LDA #$AA - ADC ($80),Y - SBC ($82),Y - STA $30 - -; CHECK test06 - LDA $30 - CMP $0206 - BEQ test07 - LDA #$06 - STA $0210 - JMP theend - - -; expected result: $15 = 0x7F -test07: - ; prepare memory - LDA #$00 - STA $34 - LDA #$FF - STA $0130 - LDA #$99 - STA $019D - LDA #$DB - STA $0199 - LDA #$2F - STA $32 - LDA #$32 - STA $4F - LDA #$30 - STA $33 - LDA #$70 - STA $AF - LDA #$18 - STA $30 - - ; imm - CMP #$18 - BEQ beq1 ; taken - AND #$00 ; not done -beq1: - ; zpg - ORA #$01 - CMP $30 - BNE bne1 ; taken - AND #$00 ; not done -bne1: - ; abs - LDX #$00 - CMP $0130 - BEQ beq2 ; not taken - STA $40 - LDX $40 -beq2: - ; zpx - CMP $27,X - BNE bne2 ; not taken - ORA #$84 - STA $41 - LDX $41 -bne2: - ; abx - AND #$DB - CMP $0100,X - BEQ beq3 ; taken - AND #$00 ; not done -beq3: - ; aby - STA $42 - LDY $42 - AND #$00 - CMP $0100,Y - BNE bne3 ; taken - ORA #$0F ; not done -bne3: - ; idx - STA $43 - LDX $43 - ORA #$24 - CMP ($40,X) - BEQ beq4 ; not taken - ORA #$7F -beq4: - ; idy - STA $44 - LDY $44 - EOR #$0F - CMP ($33),Y - BNE bne4 ; not taken - LDA $44 - STA $15 -bne4: - -; CHECK test07 - LDA $15 - CMP $0207 - BEQ test08 - LDA #$07 - STA $0210 - JMP theend - - -; expected result: $42 = 0xA5 -test08: - ; prepare memory - LDA #$A5 - STA $20 - STA $0120 - LDA #$5A - STA $21 - - ; cpx imm... - LDX #$A5 - CPX #$A5 - BEQ b1 ; taken - LDX #$01 ; not done -b1: - ; cpx zpg... - CPX $20 - BEQ b2 ; taken - LDX #$02 ; not done -b2: - ; cpx abs... - CPX $0120 - BEQ b3 ; taken - LDX #$03 ; not done -b3: - ; cpy imm... - STX $30 - LDY $30 - CPY #$A5 - BEQ b4 ; taken - LDY #$04 ; not done -b4: - ; cpy zpg... - CPY $20 - BEQ b5 ; taken - LDY #$05 ; not done -b5: - ; cpy abs... - CPY $0120 - BEQ b6 ; taken - LDY #$06 ; not done -b6: - ; bit zpg... - STY $31 - LDA $31 - BIT $20 - BNE b7 ; taken - LDA #$07 ; not done -b7: - ; bit abs... - BIT $0120 - BNE b8 ; taken - LDA #$08 ; not done -b8: - BIT $21 - BNE b9 ; not taken - STA $42 -b9: - -; CHECK test08 - LDA $42 - CMP $0208 - BEQ test09 - LDA #$08 - STA $0210 - JMP theend - - -; expected result: $80 = 0x1F -test09: - ; prepare memory - LDA #$54 - STA $32 - LDA #$B3 - STA $A1 - LDA #$87 - STA $43 - - ; BPL - LDX #$A1 - BPL bpl1 ; not taken - LDX #$32 -bpl1: - LDY $00,X - BPL bpl2 ; taken - LDA #$05 ; not done - LDX $A1 ; not done -bpl2: - - ; BMI - BMI bmi1 ; not taken - SBC #$03 -bmi1: - BMI bmi2 ; taken - LDA #$41 ; not done -bmi2: - - ; BVC - EOR #$30 - STA $32 - ADC $00,X - BVC bvc1 ; not taken - LDA #$03 -bvc1: - STA $54 - LDX $00,Y - ADC $51,X - BVC bvc2 ; taken - LDA #$E5 ; not done -bvc2: - - ; BVS - ADC $40,X - BVS bvs1 ; not taken - STA $0001,Y - ADC $55 -bvs1: - BVS bvs2 ; taken - LDA #$00 -bvs2: - - ; BCC - ADC #$F0 - BCC bcc1 ; not taken - STA $60 - ADC $43 -bcc1: - BCC bcc2 ; taken - LDA #$FF -bcc2: - - ; BCS - ADC $54 - BCS bcs1 ; not taken - ADC #$87 - LDX $60 -bcs1: - BCS bcs2 ; taken - LDA #$00 ; not done -bcs2: - STA $73,X - -; CHECK test09 - LDA $80 - CMP $0209 - BEQ test10 - LDA #$09 - STA $0210 - JMP theend - - -; expected result: $30 = 0xCE -test10: - -; RESET TO CARRY = 0 & OVERFLOW = 0 - ADC #$00 - - LDA #$99 - ADC #$87 - CLC - NOP - BCC t10bcc1 ; taken - ADC #$60 ; not done - ADC #$93 ; not done -t10bcc1: - SEC - NOP - BCC t10bcc2 ; not taken - CLV -t10bcc2: - BVC t10bvc1 ; taken - LDA #$00 ; not done -t10bvc1: - ADC #$AD - NOP - STA $30 - -; CHECK test10 - LDA $30 - CMP $020A - BEQ test11 - LDA #$0A - STA $0210 - JMP theend - - -; expected result: $30 = 0x29 -test11: - -; RESET TO CARRY = 0 & ZERO = 0 - ADC #$01 - - LDA #$27 - ADC #$01 - SEC - PHP - CLC - PLP - ADC #$00 - PHA - LDA #$00 - PLA - STA $30 - -; CHECK test11 - LDA $30 - CMP $020B - BEQ test12 - LDA #$0B - STA $0210 - JMP theend - - -; expected result: $33 = 0x42 -test12: - CLC - LDA #$42 - BCC runstuff - STA $33 - BCS t12end -runstuff: - LDA #$45 - PHA - LDA #$61 - PHA - SEC - PHP - CLC - RTI -t12end: - -; CHECK test12 - LDA $33 - CMP $020C - BEQ test13 - LDA #$0C - STA $0210 - JMP theend - - -; expected result: $21 = 0x6C (simulator) -; $21 = 0x0C (ours) -test13: - -; RESET TO CARRY = 0 & ZERO = 0 - ADC #$01 - - SEI - SED - PHP - PLA - STA $20 - CLI - CLD - PHP - PLA - ADC $20 - STA $21 - -; CHECK test13 - LDA $21 - CMP $020D - BEQ test14 - LDA #$0D - STA $0210 - JMP theend - - -; expect result: $60 = 0x42 -test14: - ; !!! NOTICE: BRK doesn't work in this - ; simulator, so commented instructions - ; are what should be executed... - ;JMP pass_intrp - LDA #$41 - STA $60 - ;RTI - ;pass_intrp: - ;LDA #$FF - ;STA $60 - ;BRK (two bytes) - INC $60 - -; CHECK test14 - LDA $60 - CMP $020E - BEQ suiteafinal - LDA #$0E - STA $0210 - JMP theend - -suiteafinal: - ; IF $0210 == 0xFE, INCREMENT - ; (checking that it didn't - ; happen to wander off and - ; not run our instructions - ; to say which tests failed...) - LDA #$FE - CMP $0210 - BNE theend - INC $0210 -theend: - BRK - ;JMP theend \ No newline at end of file +; Testing 6502 opcodes. +; Copied and adapted from AllSuiteA.asm from project hmc-6502: +; https://code.google.com/archive/p/hmc-6502/ +; EXPECTED FINAL RESULTS: $0210 = FF +; (any other number will be the test that failed) +; To build with cl65: +; cl65 -C testall_cl65.cfg -l --start-addr 16384 -t none -o tall.bin testall.asm +; then load to simulator from debug console with 'L B TALL.BIN' +; and execute with 'X 4000'. + + .segment "CODE1" + + .segment "CODE2" + + .ORG $4000 + +start: +; initialize: + LDA #$00 + STA $0210 + ; store each test's expected + LDA #$55 + STA $0200 + LDA #$AA + STA $0201 + LDA #$FF + STA $0202 + LDA #$6E + STA $0203 + LDA #$42 + STA $0204 + LDA #$33 + STA $0205 + LDA #$9D + STA $0206 + LDA #$7F + STA $0207 + LDA #$A5 + STA $0208 + LDA #$1F + STA $0209 + LDA #$CE + STA $020A + LDA #$29 + STA $020B + LDA #$42 + STA $020C + LDA #$6C + STA $020D + LDA #$42 + STA $020E + + +; expected result: $022A = 0x55 +test00: + LDA #85 + LDX #42 + LDY #115 + STA $81 + LDA #$01 + STA $61 + LDA #$7E + LDA $81 + STA $0910 + LDA #$7E + LDA $0910 + STA $56,X + LDA #$7E + LDA $56,X + STY $60 + STA ($60),Y + LDA #$7E + LDA ($60),Y + STA $07ff,X + LDA #$7E + LDA $07ff,X + STA $07ff,Y + LDA #$7E + LDA $07ff,Y + STA ($36,X) + LDA #$7E + LDA ($36,X) + STX $50 + LDX $60 + LDY $50 + STX $0913 + LDX #$22 + LDX $0913 + STY $0914 + LDY #$99 + LDY $0914 + STY $2D,X + STX $77,Y + LDY #$99 + LDY $2D,X + LDX #$22 + LDX $77,Y + LDY #$99 + LDY $08A0,X + LDX #$22 + LDX $08A1,Y + STA $0200,X + +; CHECK test00: + LDA $022A + CMP $0200 + BEQ test00pass + JMP theend +test00pass: + LDA #$FE + STA $0210 + + +; expected result: $A9 = 0xAA +test01: + ; imm + LDA #85 + AND #83 + ORA #56 + EOR #17 + + ; zpg + STA $99 + LDA #185 + STA $10 + LDA #231 + STA $11 + LDA #57 + STA $12 + LDA $99 + AND $10 + ORA $11 + EOR $12 + + ; zpx + LDX #16 + STA $99 + LDA #188 + STA $20 + LDA #49 + STA $21 + LDA #23 + STA $22 + LDA $99 + AND $10,X + ORA $11,X + EOR $12,X + + ; abs + STA $99 + LDA #111 + STA $0110 + LDA #60 + STA $0111 + LDA #39 + STA $0112 + LDA $99 + AND $0110 + ORA $0111 + EOR $0112 + + ; abx + STA $99 + LDA #138 + STA $0120 + LDA #71 + STA $0121 + LDA #143 + STA $0122 + LDA $99 + AND $0110,X + ORA $0111,X + EOR $0112,X + + ; aby + LDY #32 + STA $99 + LDA #115 + STA $0130 + LDA #42 + STA $0131 + LDA #241 + STA $0132 + LDA $99 + AND $0110,Y + ORA $0111,Y + EOR $0112,Y + + ; idx + STA $99 + LDA #112 + STA $30 + LDA #$01 + STA $31 + LDA #113 + STA $32 + LDA #$01 + STA $33 + LDA #114 + STA $34 + LDA #$01 + STA $35 + LDA #197 + STA $0170 + LDA #124 + STA $0171 + LDA #161 + STA $0172 + LDA $99 + AND ($20,X) + ORA ($22,X) + EOR ($24,X) + + ; idy + STA $99 + LDA #96 + STA $40 + LDA #$01 + STA $41 + LDA #97 + STA $42 + LDA #$01 + STA $43 + LDA #98 + STA $44 + LDA #$01 + STA $45 + LDA #55 + STA $0250 + LDA #35 + STA $0251 + LDA #157 + STA $0252 + LDA $99 + LDY #$F0 + AND ($40),Y + ORA ($42),Y + EOR ($44),Y + + STA $A9 + +; CHECK test01 + LDA $A9 + CMP $0201 + BEQ test02 + LDA #$01 + STA $0210 + JMP theend + + +; expected result: $71 = 0xFF +test02: + LDA #$FF + LDX #$00 + + STA $90 + INC $90 + INC $90 + LDA $90 + LDX $90 + + STA $90,X + INC $90,X + LDA $90,X + LDX $91 + + STA $0190,X + INC $0192 + LDA $0190,X + LDX $0192 + + STA $0190,X + INC $0190,X + LDA $0190,X + LDX $0193 + + STA $0170,X + DEC $0170,X + LDA $0170,X + LDX $0174 + + STA $0170,X + DEC $0173 + LDA $0170,X + LDX $0173 + + STA $70,X + DEC $70,X + LDA $70,X + LDX $72 + + STA $70,X + DEC $71 + DEC $71 + +; CHECK test02 + LDA $71 + CMP $0202 + BEQ test03 + LDA #$02 + STA $0210 + JMP theend + + +; expected result: $01DD = 0x6E +test03: + LDA #$4B + LSR + ASL + + STA $50 + ASL $50 + ASL $50 + LSR $50 + LDA $50 + + LDX $50 + ORA #$C9 + STA $60 + ASL $4C,X + LSR $4C,X + LSR $4C,X + LDA $4C,X + + LDX $60 + ORA #$41 + STA $012E + LSR $0100,X + LSR $0100,X + ASL $0100,X + LDA $0100,X + + LDX $012E + ORA #$81 + STA $0100,X + LSR $0136 + LSR $0136 + ASL $0136 + LDA $0100,X + + ; rol & ror + + ROL + ROL + ROR + STA $70 + + LDX $70 + ORA #$03 + STA $0C,X + ROL $C0 + ROR $C0 + ROR $C0 + LDA $0C,X + + LDX $C0 + STA $D0 + ROL $75,X + ROL $75,X + ROR $75,X + LDA $D0 + + LDX $D0 + STA $0100,X + ROL $01B7 + ROL $01B7 + ROL $01B7 + ROR $01B7 + LDA $0100,X + + LDX $01B7 + STA $01DD + ROL $0100,X + ROR $0100,X + ROR $0100,X + +; CHECK test03 + LDA $01DD + CMP $0203 + BEQ test04 + LDA #$03 + STA $0210 + JMP theend + + +; expected result: $40 = 0x42 +test04: + LDA #$E8 ;originally:#$7C + STA $20 + LDA #$42 ;originally:#$02 + STA $21 + LDA #$00 + ORA #$03 + JMP jump1 + ORA #$FF ; not done +jump1: + ORA #$30 + JSR subr + ORA #$42 + JMP ($0020) + ORA #$FF ; not done +subr: + STA $30 + LDX $30 + LDA #$00 + RTS +final: + STA $0D,X + +; CHECK test04 + LDA $40 + CMP $0204 + BEQ test05 + LDA #$04 + STA $0210 + JMP theend + + +; expected result: $40 = 0x33 +test05: + LDA #$35 + + TAX + DEX + DEX + INX + TXA + + TAY + DEY + DEY + INY + TYA + + TAX + LDA #$20 + TXS + LDX #$10 + TSX + TXA + + STA $40 + +; CHECK test05 + LDA $40 + CMP $0205 + BEQ test06 + LDA #$05 + STA $0210 + JMP theend + + +; expected result: $30 = 9D +test06: + +; RESET TO CARRY FLAG = 0 + ROL + + LDA #$6A + STA $50 + LDA #$6B + STA $51 + LDA #$A1 + STA $60 + LDA #$A2 + STA $61 + + LDA #$FF + ADC #$FF + ADC #$FF + SBC #$AE + + STA $40 + LDX $40 + ADC $00,X + SBC $01,X + + ADC $60 + SBC $61 + + STA $0120 + LDA #$4D + STA $0121 + LDA #$23 + ADC $0120 + SBC $0121 + + STA $F0 + LDX $F0 + LDA #$64 + STA $0124 + LDA #$62 + STA $0125 + LDA #$26 + ADC $0100,X + SBC $0101,X + + STA $F1 + LDY $F1 + LDA #$E5 + STA $0128 + LDA #$E9 + STA $0129 + LDA #$34 + ADC $0100,Y + SBC $0101,Y + + STA $F2 + LDX $F2 + LDA #$20 + STA $70 + LDA #$01 + STA $71 + LDA #$24 + STA $72 + LDA #$01 + STA $73 + ADC ($41,X) + SBC ($3F,X) + + STA $F3 + LDY $F3 + LDA #$DA + STA $80 + LDA #$00 + STA $81 + LDA #$DC + STA $82 + LDA #$00 + STA $83 + LDA #$AA + ADC ($80),Y + SBC ($82),Y + STA $30 + +; CHECK test06 + LDA $30 + CMP $0206 + BEQ test07 + LDA #$06 + STA $0210 + JMP theend + + +; expected result: $15 = 0x7F +test07: + ; prepare memory + LDA #$00 + STA $34 + LDA #$FF + STA $0130 + LDA #$99 + STA $019D + LDA #$DB + STA $0199 + LDA #$2F + STA $32 + LDA #$32 + STA $4F + LDA #$30 + STA $33 + LDA #$70 + STA $AF + LDA #$18 + STA $30 + + ; imm + CMP #$18 + BEQ beq1 ; taken + AND #$00 ; not done +beq1: + ; zpg + ORA #$01 + CMP $30 + BNE bne1 ; taken + AND #$00 ; not done +bne1: + ; abs + LDX #$00 + CMP $0130 + BEQ beq2 ; not taken + STA $40 + LDX $40 +beq2: + ; zpx + CMP $27,X + BNE bne2 ; not taken + ORA #$84 + STA $41 + LDX $41 +bne2: + ; abx + AND #$DB + CMP $0100,X + BEQ beq3 ; taken + AND #$00 ; not done +beq3: + ; aby + STA $42 + LDY $42 + AND #$00 + CMP $0100,Y + BNE bne3 ; taken + ORA #$0F ; not done +bne3: + ; idx + STA $43 + LDX $43 + ORA #$24 + CMP ($40,X) + BEQ beq4 ; not taken + ORA #$7F +beq4: + ; idy + STA $44 + LDY $44 + EOR #$0F + CMP ($33),Y + BNE bne4 ; not taken + LDA $44 + STA $15 +bne4: + +; CHECK test07 + LDA $15 + CMP $0207 + BEQ test08 + LDA #$07 + STA $0210 + JMP theend + + +; expected result: $42 = 0xA5 +test08: + ; prepare memory + LDA #$A5 + STA $20 + STA $0120 + LDA #$5A + STA $21 + + ; cpx imm... + LDX #$A5 + CPX #$A5 + BEQ b1 ; taken + LDX #$01 ; not done +b1: + ; cpx zpg... + CPX $20 + BEQ b2 ; taken + LDX #$02 ; not done +b2: + ; cpx abs... + CPX $0120 + BEQ b3 ; taken + LDX #$03 ; not done +b3: + ; cpy imm... + STX $30 + LDY $30 + CPY #$A5 + BEQ b4 ; taken + LDY #$04 ; not done +b4: + ; cpy zpg... + CPY $20 + BEQ b5 ; taken + LDY #$05 ; not done +b5: + ; cpy abs... + CPY $0120 + BEQ b6 ; taken + LDY #$06 ; not done +b6: + ; bit zpg... + STY $31 + LDA $31 + BIT $20 + BNE b7 ; taken + LDA #$07 ; not done +b7: + ; bit abs... + BIT $0120 + BNE b8 ; taken + LDA #$08 ; not done +b8: + BIT $21 + BNE b9 ; not taken + STA $42 +b9: + +; CHECK test08 + LDA $42 + CMP $0208 + BEQ test09 + LDA #$08 + STA $0210 + JMP theend + + +; expected result: $80 = 0x1F +test09: + ; prepare memory + LDA #$54 + STA $32 + LDA #$B3 + STA $A1 + LDA #$87 + STA $43 + + ; BPL + LDX #$A1 + BPL bpl1 ; not taken + LDX #$32 +bpl1: + LDY $00,X + BPL bpl2 ; taken + LDA #$05 ; not done + LDX $A1 ; not done +bpl2: + + ; BMI + BMI bmi1 ; not taken + SBC #$03 +bmi1: + BMI bmi2 ; taken + LDA #$41 ; not done +bmi2: + + ; BVC + EOR #$30 + STA $32 + ADC $00,X + BVC bvc1 ; not taken + LDA #$03 +bvc1: + STA $54 + LDX $00,Y + ADC $51,X + BVC bvc2 ; taken + LDA #$E5 ; not done +bvc2: + + ; BVS + ADC $40,X + BVS bvs1 ; not taken + STA $0001,Y + ADC $55 +bvs1: + BVS bvs2 ; taken + LDA #$00 +bvs2: + + ; BCC + ADC #$F0 + BCC bcc1 ; not taken + STA $60 + ADC $43 +bcc1: + BCC bcc2 ; taken + LDA #$FF +bcc2: + + ; BCS + ADC $54 + BCS bcs1 ; not taken + ADC #$87 + LDX $60 +bcs1: + BCS bcs2 ; taken + LDA #$00 ; not done +bcs2: + STA $73,X + +; CHECK test09 + LDA $80 + CMP $0209 + BEQ test10 + LDA #$09 + STA $0210 + JMP theend + + +; expected result: $30 = 0xCE +test10: + +; RESET TO CARRY = 0 & OVERFLOW = 0 + ADC #$00 + + LDA #$99 + ADC #$87 + CLC + NOP + BCC t10bcc1 ; taken + ADC #$60 ; not done + ADC #$93 ; not done +t10bcc1: + SEC + NOP + BCC t10bcc2 ; not taken + CLV +t10bcc2: + BVC t10bvc1 ; taken + LDA #$00 ; not done +t10bvc1: + ADC #$AD + NOP + STA $30 + +; CHECK test10 + LDA $30 + CMP $020A + BEQ test11 + LDA #$0A + STA $0210 + JMP theend + + +; expected result: $30 = 0x29 +test11: + +; RESET TO CARRY = 0 & ZERO = 0 + ADC #$01 + + LDA #$27 + ADC #$01 + SEC + PHP + CLC + PLP + ADC #$00 + PHA + LDA #$00 + PLA + STA $30 + +; CHECK test11 + LDA $30 + CMP $020B + BEQ test12 + LDA #$0B + STA $0210 + JMP theend + + +; expected result: $33 = 0x42 +test12: + CLC + LDA #$42 + BCC runstuff + STA $33 + BCS t12end +runstuff: + LDA #$45 + PHA + LDA #$61 + PHA + SEC + PHP + CLC + RTI +t12end: + +; CHECK test12 + LDA $33 + CMP $020C + BEQ test13 + LDA #$0C + STA $0210 + JMP theend + + +; expected result: $21 = 0x6C (simulator) +; $21 = 0x0C (ours) +test13: + +; RESET TO CARRY = 0 & ZERO = 0 + ADC #$01 + + SEI + SED + PHP + PLA + STA $20 + CLI + CLD + PHP + PLA + ADC $20 + STA $21 + +; CHECK test13 + LDA $21 + CMP $020D + BEQ test14 + LDA #$0D + STA $0210 + JMP theend + + +; expect result: $60 = 0x42 +test14: + ; !!! NOTICE: BRK doesn't work in this + ; simulator, so commented instructions + ; are what should be executed... + ;JMP pass_intrp + LDA #$41 + STA $60 + ;RTI + ;pass_intrp: + ;LDA #$FF + ;STA $60 + ;BRK (two bytes) + INC $60 + +; CHECK test14 + LDA $60 + CMP $020E + BEQ suiteafinal + LDA #$0E + STA $0210 + JMP theend + +suiteafinal: + ; IF $0210 == 0xFE, INCREMENT + ; (checking that it didn't + ; happen to wander off and + ; not run our instructions + ; to say which tests failed...) + LDA #$FE + CMP $0210 + BNE theend + INC $0210 +theend: + BRK + BRK + ;JMP theend + LDX #$FF + TXS + RTS + + .segment "KERN" + + .ORG $FF00 + + RTI + + .segment "VECT" + + .ORG $FFFA + + .BYTE $00,$FF,$00,$FF,$00,$FF + +;-------------------------- END \ No newline at end of file diff --git a/testall.dat b/testall.dat index 29cafa8..69896ee 100644 --- a/testall.dat +++ b/testall.dat @@ -1,195 +1,195 @@ -; Test 6502 emulation. -ORG -$4000 -$A9 $00 $8D $10 $02 $A9 $55 $8D -$00 $02 $A9 $AA $8D $01 $02 $A9 -$FF $8D $02 $02 $A9 $6E $8D $03 -$02 $A9 $42 $8D $04 $02 $A9 $33 -$8D $05 $02 $A9 $9D $8D $06 $02 -$A9 $7F $8D $07 $02 $A9 $A5 $8D -$08 $02 $A9 $1F $8D $09 $02 $A9 -$CE $8D $0A $02 $A9 $29 $8D $0B -$02 $A9 $42 $8D $0C $02 $A9 $6C -$8D $0D $02 $A9 $42 $8D $0E $02 -$A9 $55 $A2 $2A $A0 $73 $85 $81 -$A9 $01 $85 $61 $A9 $7E $A5 $81 -$8D $10 $09 $A9 $7E $AD $10 $09 -$95 $56 $A9 $7E $B5 $56 $84 $60 -$91 $60 $A9 $7E $B1 $60 $9D $FF -$07 $A9 $7E $BD $FF $07 $99 $FF -$07 $A9 $7E $B9 $FF $07 $81 $36 -$A9 $7E $A1 $36 $86 $50 $A6 $60 -$A4 $50 $8E $13 $09 $A2 $22 $AE -$13 $09 $8C $14 $09 $A0 $99 $AC -$14 $09 $94 $2D $96 $77 $A0 $99 -$B4 $2D $A2 $22 $B6 $77 $A0 $99 -$BC $A0 $08 $A2 $22 $BE $A1 $08 -$9D $00 $02 $AD $2A $02 $CD $00 -$02 $F0 $03 $4C $C0 $45 $A9 $FE -$8D $10 $02 $A9 $55 $29 $53 $09 -$38 $49 $11 $85 $99 $A9 $B9 $85 -$10 $A9 $E7 $85 $11 $A9 $39 $85 -$12 $A5 $99 $25 $10 $05 $11 $45 -$12 $A2 $10 $85 $99 $A9 $BC $85 -$20 $A9 $31 $85 $21 $A9 $17 $85 -$22 $A5 $99 $35 $10 $15 $11 $55 -$12 $85 $99 $A9 $6F $8D $10 $01 -$A9 $3C $8D $11 $01 $A9 $27 $8D -$12 $01 $A5 $99 $2D $10 $01 $0D -$11 $01 $4D $12 $01 $85 $99 $A9 -$8A $8D $20 $01 $A9 $47 $8D $21 -$01 $A9 $8F $8D $22 $01 $A5 $99 -$3D $10 $01 $1D $11 $01 $5D $12 -$01 $A0 $20 $85 $99 $A9 $73 $8D -$30 $01 $A9 $2A $8D $31 $01 $A9 -$F1 $8D $32 $01 $A5 $99 $39 $10 -$01 $19 $11 $01 $59 $12 $01 $85 -$99 $A9 $70 $85 $30 $A9 $01 $85 -$31 $A9 $71 $85 $32 $A9 $01 $85 -$33 $A9 $72 $85 $34 $A9 $01 $85 -$35 $A9 $C5 $8D $70 $01 $A9 $7C -$8D $71 $01 $A9 $A1 $8D $72 $01 -$A5 $99 $21 $20 $01 $22 $41 $24 -$85 $99 $A9 $60 $85 $40 $A9 $01 -$85 $41 $A9 $61 $85 $42 $A9 $01 -$85 $43 $A9 $62 $85 $44 $A9 $01 -$85 $45 $A9 $37 $8D $50 $02 $A9 -$23 $8D $51 $02 $A9 $9D $8D $52 -$02 $A5 $99 $A0 $F0 $31 $40 $11 -$42 $51 $44 $85 $A9 $A5 $A9 $CD -$01 $02 $F0 $08 $A9 $01 $8D $10 -$02 $4C $C0 $45 $A9 $FF $A2 $00 -$85 $90 $E6 $90 $E6 $90 $A5 $90 -$A6 $90 $95 $90 $F6 $90 $B5 $90 -$A6 $91 $9D $90 $01 $EE $92 $01 -$BD $90 $01 $AE $92 $01 $9D $90 -$01 $FE $90 $01 $BD $90 $01 $AE -$93 $01 $9D $70 $01 $DE $70 $01 -$BD $70 $01 $AE $74 $01 $9D $70 -$01 $CE $73 $01 $BD $70 $01 $AE -$73 $01 $95 $70 $D6 $70 $B5 $70 -$A6 $72 $95 $70 $C6 $71 $C6 $71 -$A5 $71 $CD $02 $02 $F0 $08 $A9 -$02 $8D $10 $02 $4C $C0 $45 $A9 -$4B $4A $0A $85 $50 $06 $50 $06 -$50 $46 $50 $A5 $50 $A6 $50 $09 -$C9 $85 $60 $16 $4C $56 $4C $56 -$4C $B5 $4C $A6 $60 $09 $41 $8D -$2E $01 $5E $00 $01 $5E $00 $01 -$1E $00 $01 $BD $00 $01 $AE $2E -$01 $09 $81 $9D $00 $01 $4E $36 -$01 $4E $36 $01 $0E $36 $01 $BD -$00 $01 $2A $2A $6A $85 $70 $A6 -$70 $09 $03 $95 $0C $26 $C0 $66 -$C0 $66 $C0 $B5 $0C $A6 $C0 $85 -$D0 $36 $75 $36 $75 $76 $75 $A5 -$D0 $A6 $D0 $9D $00 $01 $2E $B7 -$01 $2E $B7 $01 $2E $B7 $01 $6E -$B7 $01 $BD $00 $01 $AE $B7 $01 -$8D $DD $01 $3E $00 $01 $7E $00 -$01 $7E $00 $01 $AD $DD $01 $CD -$03 $02 $F0 $08 $A9 $03 $8D $10 -$02 $4C $C0 $45 $A9 $E8 $85 $20 -$A9 $42 $85 $21 $A9 $00 $09 $03 -$4C $D5 $42 $09 $FF $09 $30 $20 -$E1 $42 $09 $42 $6C $20 $00 $09 -$FF $85 $30 $A6 $30 $A9 $00 $60 -$95 $0D $A5 $40 $CD $04 $02 $F0 -$08 $A9 $04 $8D $10 $02 $4C $C0 -$45 $A9 $35 $AA $CA $CA $E8 $8A -$A8 $88 $88 $C8 $98 $AA $A9 $20 -$9A $A2 $10 $BA $8A $85 $40 $A5 -$40 $CD $05 $02 $F0 $08 $A9 $05 -$8D $10 $02 $4C $C0 $45 $2A $A9 -$6A $85 $50 $A9 $6B $85 $51 $A9 -$A1 $85 $60 $A9 $A2 $85 $61 $A9 -$FF $69 $FF $69 $FF $E9 $AE $85 -$40 $A6 $40 $75 $00 $F5 $01 $65 -$60 $E5 $61 $8D $20 $01 $A9 $4D -$8D $21 $01 $A9 $23 $6D $20 $01 -$ED $21 $01 $85 $F0 $A6 $F0 $A9 -$64 $8D $24 $01 $A9 $62 $8D $25 -$01 $A9 $26 $7D $00 $01 $FD $01 -$01 $85 $F1 $A4 $F1 $A9 $E5 $8D -$28 $01 $A9 $E9 $8D $29 $01 $A9 -$34 $79 $00 $01 $F9 $01 $01 $85 -$F2 $A6 $F2 $A9 $20 $85 $70 $A9 -$01 $85 $71 $A9 $24 $85 $72 $A9 -$01 $85 $73 $61 $41 $E1 $3F $85 -$F3 $A4 $F3 $A9 $DA $85 $80 $A9 -$00 $85 $81 $A9 $DC $85 $82 $A9 -$00 $85 $83 $A9 $AA $71 $80 $F1 -$82 $85 $30 $A5 $30 $CD $06 $02 -$F0 $08 $A9 $06 $8D $10 $02 $4C -$C0 $45 $A9 $00 $85 $34 $A9 $FF -$8D $30 $01 $A9 $99 $8D $9D $01 -$A9 $DB $8D $99 $01 $A9 $2F $85 -$32 $A9 $32 $85 $4F $A9 $30 $85 -$33 $A9 $70 $85 $AF $A9 $18 $85 -$30 $C9 $18 $F0 $02 $29 $00 $09 -$01 $C5 $30 $D0 $02 $29 $00 $A2 -$00 $CD $30 $01 $F0 $04 $85 $40 -$A6 $40 $D5 $27 $D0 $06 $09 $84 -$85 $41 $A6 $41 $29 $DB $DD $00 -$01 $F0 $02 $29 $00 $85 $42 $A4 -$42 $29 $00 $D9 $00 $01 $D0 $02 -$09 $0F $85 $43 $A6 $43 $09 $24 -$C1 $40 $F0 $02 $09 $7F $85 $44 -$A4 $44 $49 $0F $D1 $33 $D0 $04 -$A5 $44 $85 $15 $A5 $15 $CD $07 -$02 $F0 $08 $A9 $07 $8D $10 $02 -$4C $C0 $45 $A9 $A5 $85 $20 $8D -$20 $01 $A9 $5A $85 $21 $A2 $A5 -$E0 $A5 $F0 $02 $A2 $01 $E4 $20 -$F0 $02 $A2 $02 $EC $20 $01 $F0 -$02 $A2 $03 $86 $30 $A4 $30 $C0 -$A5 $F0 $02 $A0 $04 $C4 $20 $F0 -$02 $A0 $05 $CC $20 $01 $F0 $02 -$A0 $06 $84 $31 $A5 $31 $24 $20 -$D0 $02 $A9 $07 $2C $20 $01 $D0 -$02 $A9 $08 $24 $21 $D0 $02 $85 -$42 $A5 $42 $CD $08 $02 $F0 $08 -$A9 $08 $8D $10 $02 $4C $C0 $45 -$A9 $54 $85 $32 $A9 $B3 $85 $A1 -$A9 $87 $85 $43 $A2 $A1 $10 $02 -$A2 $32 $B4 $00 $10 $04 $A9 $05 -$A6 $A1 $30 $02 $E9 $03 $30 $02 -$A9 $41 $49 $30 $85 $32 $75 $00 -$50 $02 $A9 $03 $85 $54 $B6 $00 -$75 $51 $50 $02 $A9 $E5 $75 $40 -$70 $05 $99 $01 $00 $65 $55 $70 -$02 $A9 $00 $69 $F0 $90 $04 $85 -$60 $65 $43 $90 $02 $A9 $FF $65 -$54 $B0 $04 $69 $87 $A6 $60 $B0 -$02 $A9 $00 $95 $73 $A5 $80 $CD -$09 $02 $F0 $08 $A9 $09 $8D $10 -$02 $4C $C0 $45 $69 $00 $A9 $99 -$69 $87 $18 $EA $90 $04 $69 $60 -$69 $93 $38 $EA $90 $01 $B8 $50 -$02 $A9 $00 $69 $AD $EA $85 $30 -$A5 $30 $CD $0A $02 $F0 $08 $A9 -$0A $8D $10 $02 $4C $C0 $45 $69 -$01 $A9 $27 $69 $01 $38 $08 $18 -$28 $69 $00 $48 $A9 $00 $68 $85 -$30 $A5 $30 $CD $0B $02 $F0 $08 -$A9 $0B $8D $10 $02 $4C $C0 $45 -$18 $A9 $42 $90 $04 $85 $33 $B0 -$0A $A9 $45 $48 $A9 $61 $48 $38 -$08 $18 $40 $A5 $33 $CD $0C $02 -$F0 $08 $A9 $0C $8D $10 $02 $4C -$C0 $45 $69 $01 $78 $F8 $08 $68 -$85 $20 $58 $D8 $08 $68 $65 $20 -$85 $21 $A5 $21 $CD $0D $02 $F0 -$08 $A9 $0D $8D $10 $02 $4C $C0 -$45 $A9 $41 $85 $60 $E6 $60 $A5 -$60 $CD $0E $02 $F0 $08 $A9 $0E -$8D $10 $02 $4C $C0 $45 $A9 $FE -$CD $10 $02 $D0 $03 $EE $10 $02 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 +; Test 6502 emulation. +ORG +$4000 +$A9 $00 $8D $10 $02 $A9 $55 $8D +$00 $02 $A9 $AA $8D $01 $02 $A9 +$FF $8D $02 $02 $A9 $6E $8D $03 +$02 $A9 $42 $8D $04 $02 $A9 $33 +$8D $05 $02 $A9 $9D $8D $06 $02 +$A9 $7F $8D $07 $02 $A9 $A5 $8D +$08 $02 $A9 $1F $8D $09 $02 $A9 +$CE $8D $0A $02 $A9 $29 $8D $0B +$02 $A9 $42 $8D $0C $02 $A9 $6C +$8D $0D $02 $A9 $42 $8D $0E $02 +$A9 $55 $A2 $2A $A0 $73 $85 $81 +$A9 $01 $85 $61 $A9 $7E $A5 $81 +$8D $10 $09 $A9 $7E $AD $10 $09 +$95 $56 $A9 $7E $B5 $56 $84 $60 +$91 $60 $A9 $7E $B1 $60 $9D $FF +$07 $A9 $7E $BD $FF $07 $99 $FF +$07 $A9 $7E $B9 $FF $07 $81 $36 +$A9 $7E $A1 $36 $86 $50 $A6 $60 +$A4 $50 $8E $13 $09 $A2 $22 $AE +$13 $09 $8C $14 $09 $A0 $99 $AC +$14 $09 $94 $2D $96 $77 $A0 $99 +$B4 $2D $A2 $22 $B6 $77 $A0 $99 +$BC $A0 $08 $A2 $22 $BE $A1 $08 +$9D $00 $02 $AD $2A $02 $CD $00 +$02 $F0 $03 $4C $C0 $45 $A9 $FE +$8D $10 $02 $A9 $55 $29 $53 $09 +$38 $49 $11 $85 $99 $A9 $B9 $85 +$10 $A9 $E7 $85 $11 $A9 $39 $85 +$12 $A5 $99 $25 $10 $05 $11 $45 +$12 $A2 $10 $85 $99 $A9 $BC $85 +$20 $A9 $31 $85 $21 $A9 $17 $85 +$22 $A5 $99 $35 $10 $15 $11 $55 +$12 $85 $99 $A9 $6F $8D $10 $01 +$A9 $3C $8D $11 $01 $A9 $27 $8D +$12 $01 $A5 $99 $2D $10 $01 $0D +$11 $01 $4D $12 $01 $85 $99 $A9 +$8A $8D $20 $01 $A9 $47 $8D $21 +$01 $A9 $8F $8D $22 $01 $A5 $99 +$3D $10 $01 $1D $11 $01 $5D $12 +$01 $A0 $20 $85 $99 $A9 $73 $8D +$30 $01 $A9 $2A $8D $31 $01 $A9 +$F1 $8D $32 $01 $A5 $99 $39 $10 +$01 $19 $11 $01 $59 $12 $01 $85 +$99 $A9 $70 $85 $30 $A9 $01 $85 +$31 $A9 $71 $85 $32 $A9 $01 $85 +$33 $A9 $72 $85 $34 $A9 $01 $85 +$35 $A9 $C5 $8D $70 $01 $A9 $7C +$8D $71 $01 $A9 $A1 $8D $72 $01 +$A5 $99 $21 $20 $01 $22 $41 $24 +$85 $99 $A9 $60 $85 $40 $A9 $01 +$85 $41 $A9 $61 $85 $42 $A9 $01 +$85 $43 $A9 $62 $85 $44 $A9 $01 +$85 $45 $A9 $37 $8D $50 $02 $A9 +$23 $8D $51 $02 $A9 $9D $8D $52 +$02 $A5 $99 $A0 $F0 $31 $40 $11 +$42 $51 $44 $85 $A9 $A5 $A9 $CD +$01 $02 $F0 $08 $A9 $01 $8D $10 +$02 $4C $C0 $45 $A9 $FF $A2 $00 +$85 $90 $E6 $90 $E6 $90 $A5 $90 +$A6 $90 $95 $90 $F6 $90 $B5 $90 +$A6 $91 $9D $90 $01 $EE $92 $01 +$BD $90 $01 $AE $92 $01 $9D $90 +$01 $FE $90 $01 $BD $90 $01 $AE +$93 $01 $9D $70 $01 $DE $70 $01 +$BD $70 $01 $AE $74 $01 $9D $70 +$01 $CE $73 $01 $BD $70 $01 $AE +$73 $01 $95 $70 $D6 $70 $B5 $70 +$A6 $72 $95 $70 $C6 $71 $C6 $71 +$A5 $71 $CD $02 $02 $F0 $08 $A9 +$02 $8D $10 $02 $4C $C0 $45 $A9 +$4B $4A $0A $85 $50 $06 $50 $06 +$50 $46 $50 $A5 $50 $A6 $50 $09 +$C9 $85 $60 $16 $4C $56 $4C $56 +$4C $B5 $4C $A6 $60 $09 $41 $8D +$2E $01 $5E $00 $01 $5E $00 $01 +$1E $00 $01 $BD $00 $01 $AE $2E +$01 $09 $81 $9D $00 $01 $4E $36 +$01 $4E $36 $01 $0E $36 $01 $BD +$00 $01 $2A $2A $6A $85 $70 $A6 +$70 $09 $03 $95 $0C $26 $C0 $66 +$C0 $66 $C0 $B5 $0C $A6 $C0 $85 +$D0 $36 $75 $36 $75 $76 $75 $A5 +$D0 $A6 $D0 $9D $00 $01 $2E $B7 +$01 $2E $B7 $01 $2E $B7 $01 $6E +$B7 $01 $BD $00 $01 $AE $B7 $01 +$8D $DD $01 $3E $00 $01 $7E $00 +$01 $7E $00 $01 $AD $DD $01 $CD +$03 $02 $F0 $08 $A9 $03 $8D $10 +$02 $4C $C0 $45 $A9 $E8 $85 $20 +$A9 $42 $85 $21 $A9 $00 $09 $03 +$4C $D5 $42 $09 $FF $09 $30 $20 +$E1 $42 $09 $42 $6C $20 $00 $09 +$FF $85 $30 $A6 $30 $A9 $00 $60 +$95 $0D $A5 $40 $CD $04 $02 $F0 +$08 $A9 $04 $8D $10 $02 $4C $C0 +$45 $A9 $35 $AA $CA $CA $E8 $8A +$A8 $88 $88 $C8 $98 $AA $A9 $20 +$9A $A2 $10 $BA $8A $85 $40 $A5 +$40 $CD $05 $02 $F0 $08 $A9 $05 +$8D $10 $02 $4C $C0 $45 $2A $A9 +$6A $85 $50 $A9 $6B $85 $51 $A9 +$A1 $85 $60 $A9 $A2 $85 $61 $A9 +$FF $69 $FF $69 $FF $E9 $AE $85 +$40 $A6 $40 $75 $00 $F5 $01 $65 +$60 $E5 $61 $8D $20 $01 $A9 $4D +$8D $21 $01 $A9 $23 $6D $20 $01 +$ED $21 $01 $85 $F0 $A6 $F0 $A9 +$64 $8D $24 $01 $A9 $62 $8D $25 +$01 $A9 $26 $7D $00 $01 $FD $01 +$01 $85 $F1 $A4 $F1 $A9 $E5 $8D +$28 $01 $A9 $E9 $8D $29 $01 $A9 +$34 $79 $00 $01 $F9 $01 $01 $85 +$F2 $A6 $F2 $A9 $20 $85 $70 $A9 +$01 $85 $71 $A9 $24 $85 $72 $A9 +$01 $85 $73 $61 $41 $E1 $3F $85 +$F3 $A4 $F3 $A9 $DA $85 $80 $A9 +$00 $85 $81 $A9 $DC $85 $82 $A9 +$00 $85 $83 $A9 $AA $71 $80 $F1 +$82 $85 $30 $A5 $30 $CD $06 $02 +$F0 $08 $A9 $06 $8D $10 $02 $4C +$C0 $45 $A9 $00 $85 $34 $A9 $FF +$8D $30 $01 $A9 $99 $8D $9D $01 +$A9 $DB $8D $99 $01 $A9 $2F $85 +$32 $A9 $32 $85 $4F $A9 $30 $85 +$33 $A9 $70 $85 $AF $A9 $18 $85 +$30 $C9 $18 $F0 $02 $29 $00 $09 +$01 $C5 $30 $D0 $02 $29 $00 $A2 +$00 $CD $30 $01 $F0 $04 $85 $40 +$A6 $40 $D5 $27 $D0 $06 $09 $84 +$85 $41 $A6 $41 $29 $DB $DD $00 +$01 $F0 $02 $29 $00 $85 $42 $A4 +$42 $29 $00 $D9 $00 $01 $D0 $02 +$09 $0F $85 $43 $A6 $43 $09 $24 +$C1 $40 $F0 $02 $09 $7F $85 $44 +$A4 $44 $49 $0F $D1 $33 $D0 $04 +$A5 $44 $85 $15 $A5 $15 $CD $07 +$02 $F0 $08 $A9 $07 $8D $10 $02 +$4C $C0 $45 $A9 $A5 $85 $20 $8D +$20 $01 $A9 $5A $85 $21 $A2 $A5 +$E0 $A5 $F0 $02 $A2 $01 $E4 $20 +$F0 $02 $A2 $02 $EC $20 $01 $F0 +$02 $A2 $03 $86 $30 $A4 $30 $C0 +$A5 $F0 $02 $A0 $04 $C4 $20 $F0 +$02 $A0 $05 $CC $20 $01 $F0 $02 +$A0 $06 $84 $31 $A5 $31 $24 $20 +$D0 $02 $A9 $07 $2C $20 $01 $D0 +$02 $A9 $08 $24 $21 $D0 $02 $85 +$42 $A5 $42 $CD $08 $02 $F0 $08 +$A9 $08 $8D $10 $02 $4C $C0 $45 +$A9 $54 $85 $32 $A9 $B3 $85 $A1 +$A9 $87 $85 $43 $A2 $A1 $10 $02 +$A2 $32 $B4 $00 $10 $04 $A9 $05 +$A6 $A1 $30 $02 $E9 $03 $30 $02 +$A9 $41 $49 $30 $85 $32 $75 $00 +$50 $02 $A9 $03 $85 $54 $B6 $00 +$75 $51 $50 $02 $A9 $E5 $75 $40 +$70 $05 $99 $01 $00 $65 $55 $70 +$02 $A9 $00 $69 $F0 $90 $04 $85 +$60 $65 $43 $90 $02 $A9 $FF $65 +$54 $B0 $04 $69 $87 $A6 $60 $B0 +$02 $A9 $00 $95 $73 $A5 $80 $CD +$09 $02 $F0 $08 $A9 $09 $8D $10 +$02 $4C $C0 $45 $69 $00 $A9 $99 +$69 $87 $18 $EA $90 $04 $69 $60 +$69 $93 $38 $EA $90 $01 $B8 $50 +$02 $A9 $00 $69 $AD $EA $85 $30 +$A5 $30 $CD $0A $02 $F0 $08 $A9 +$0A $8D $10 $02 $4C $C0 $45 $69 +$01 $A9 $27 $69 $01 $38 $08 $18 +$28 $69 $00 $48 $A9 $00 $68 $85 +$30 $A5 $30 $CD $0B $02 $F0 $08 +$A9 $0B $8D $10 $02 $4C $C0 $45 +$18 $A9 $42 $90 $04 $85 $33 $B0 +$0A $A9 $45 $48 $A9 $61 $48 $38 +$08 $18 $40 $A5 $33 $CD $0C $02 +$F0 $08 $A9 $0C $8D $10 $02 $4C +$C0 $45 $69 $01 $78 $F8 $08 $68 +$85 $20 $58 $D8 $08 $68 $65 $20 +$85 $21 $A5 $21 $CD $0D $02 $F0 +$08 $A9 $0D $8D $10 $02 $4C $C0 +$45 $A9 $41 $85 $60 $E6 $60 $A5 +$60 $CD $0E $02 $F0 $08 $A9 $0E +$8D $10 $02 $4C $C0 $45 $A9 $FE +$CD $10 $02 $D0 $03 $EE $10 $02 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 diff --git a/testall.lst b/testall.lst new file mode 100644 index 0000000..2e7075f --- /dev/null +++ b/testall.lst @@ -0,0 +1,960 @@ +ca65 V2.13.2 - (C) Copyright 1998-2005 Ullrich von Bassewitz +Main file : testall.asm +Current file: testall.asm + +000000r 1 ; Testing 6502 opcodes. +000000r 1 ; Copied and adapted from AllSuiteA.asm from project hmc-6502: +000000r 1 ; https://code.google.com/archive/p/hmc-6502/ +000000r 1 ; EXPECTED FINAL RESULTS: $0210 = FF +000000r 1 ; (any other number will be the test that failed) +000000r 1 ; To build with cl65: +000000r 1 ; cl65 -C testall_cl65.cfg -l --start-addr 16384 -t none -o tall.bin testall.asm +000000r 1 ; then load to simulator from debug console with 'L B TALL.BIN' +000000r 1 ; and execute with 'X 4000'. +000000r 1 +000000r 1 .segment "CODE1" +000000r 1 +000000r 1 .segment "CODE2" +000000r 1 +000000r 1 .ORG $4000 +004000 1 +004000 1 start: +004000 1 ; initialize: +004000 1 A9 00 LDA #$00 +004002 1 8D 10 02 STA $0210 +004005 1 ; store each test's expected +004005 1 A9 55 LDA #$55 +004007 1 8D 00 02 STA $0200 +00400A 1 A9 AA LDA #$AA +00400C 1 8D 01 02 STA $0201 +00400F 1 A9 FF LDA #$FF +004011 1 8D 02 02 STA $0202 +004014 1 A9 6E LDA #$6E +004016 1 8D 03 02 STA $0203 +004019 1 A9 42 LDA #$42 +00401B 1 8D 04 02 STA $0204 +00401E 1 A9 33 LDA #$33 +004020 1 8D 05 02 STA $0205 +004023 1 A9 9D LDA #$9D +004025 1 8D 06 02 STA $0206 +004028 1 A9 7F LDA #$7F +00402A 1 8D 07 02 STA $0207 +00402D 1 A9 A5 LDA #$A5 +00402F 1 8D 08 02 STA $0208 +004032 1 A9 1F LDA #$1F +004034 1 8D 09 02 STA $0209 +004037 1 A9 CE LDA #$CE +004039 1 8D 0A 02 STA $020A +00403C 1 A9 29 LDA #$29 +00403E 1 8D 0B 02 STA $020B +004041 1 A9 42 LDA #$42 +004043 1 8D 0C 02 STA $020C +004046 1 A9 6C LDA #$6C +004048 1 8D 0D 02 STA $020D +00404B 1 A9 42 LDA #$42 +00404D 1 8D 0E 02 STA $020E +004050 1 +004050 1 +004050 1 ; expected result: $022A = 0x55 +004050 1 test00: +004050 1 A9 55 LDA #85 +004052 1 A2 2A LDX #42 +004054 1 A0 73 LDY #115 +004056 1 85 81 STA $81 +004058 1 A9 01 LDA #$01 +00405A 1 85 61 STA $61 +00405C 1 A9 7E LDA #$7E +00405E 1 A5 81 LDA $81 +004060 1 8D 10 09 STA $0910 +004063 1 A9 7E LDA #$7E +004065 1 AD 10 09 LDA $0910 +004068 1 95 56 STA $56,X +00406A 1 A9 7E LDA #$7E +00406C 1 B5 56 LDA $56,X +00406E 1 84 60 STY $60 +004070 1 91 60 STA ($60),Y +004072 1 A9 7E LDA #$7E +004074 1 B1 60 LDA ($60),Y +004076 1 9D FF 07 STA $07ff,X +004079 1 A9 7E LDA #$7E +00407B 1 BD FF 07 LDA $07ff,X +00407E 1 99 FF 07 STA $07ff,Y +004081 1 A9 7E LDA #$7E +004083 1 B9 FF 07 LDA $07ff,Y +004086 1 81 36 STA ($36,X) +004088 1 A9 7E LDA #$7E +00408A 1 A1 36 LDA ($36,X) +00408C 1 86 50 STX $50 +00408E 1 A6 60 LDX $60 +004090 1 A4 50 LDY $50 +004092 1 8E 13 09 STX $0913 +004095 1 A2 22 LDX #$22 +004097 1 AE 13 09 LDX $0913 +00409A 1 8C 14 09 STY $0914 +00409D 1 A0 99 LDY #$99 +00409F 1 AC 14 09 LDY $0914 +0040A2 1 94 2D STY $2D,X +0040A4 1 96 77 STX $77,Y +0040A6 1 A0 99 LDY #$99 +0040A8 1 B4 2D LDY $2D,X +0040AA 1 A2 22 LDX #$22 +0040AC 1 B6 77 LDX $77,Y +0040AE 1 A0 99 LDY #$99 +0040B0 1 BC A0 08 LDY $08A0,X +0040B3 1 A2 22 LDX #$22 +0040B5 1 BE A1 08 LDX $08A1,Y +0040B8 1 9D 00 02 STA $0200,X +0040BB 1 +0040BB 1 ; CHECK test00: +0040BB 1 AD 2A 02 LDA $022A +0040BE 1 CD 00 02 CMP $0200 +0040C1 1 F0 03 BEQ test00pass +0040C3 1 4C C0 45 JMP theend +0040C6 1 test00pass: +0040C6 1 A9 FE LDA #$FE +0040C8 1 8D 10 02 STA $0210 +0040CB 1 +0040CB 1 +0040CB 1 ; expected result: $A9 = 0xAA +0040CB 1 test01: +0040CB 1 ; imm +0040CB 1 A9 55 LDA #85 +0040CD 1 29 53 AND #83 +0040CF 1 09 38 ORA #56 +0040D1 1 49 11 EOR #17 +0040D3 1 +0040D3 1 ; zpg +0040D3 1 85 99 STA $99 +0040D5 1 A9 B9 LDA #185 +0040D7 1 85 10 STA $10 +0040D9 1 A9 E7 LDA #231 +0040DB 1 85 11 STA $11 +0040DD 1 A9 39 LDA #57 +0040DF 1 85 12 STA $12 +0040E1 1 A5 99 LDA $99 +0040E3 1 25 10 AND $10 +0040E5 1 05 11 ORA $11 +0040E7 1 45 12 EOR $12 +0040E9 1 +0040E9 1 ; zpx +0040E9 1 A2 10 LDX #16 +0040EB 1 85 99 STA $99 +0040ED 1 A9 BC LDA #188 +0040EF 1 85 20 STA $20 +0040F1 1 A9 31 LDA #49 +0040F3 1 85 21 STA $21 +0040F5 1 A9 17 LDA #23 +0040F7 1 85 22 STA $22 +0040F9 1 A5 99 LDA $99 +0040FB 1 35 10 AND $10,X +0040FD 1 15 11 ORA $11,X +0040FF 1 55 12 EOR $12,X +004101 1 +004101 1 ; abs +004101 1 85 99 STA $99 +004103 1 A9 6F LDA #111 +004105 1 8D 10 01 STA $0110 +004108 1 A9 3C LDA #60 +00410A 1 8D 11 01 STA $0111 +00410D 1 A9 27 LDA #39 +00410F 1 8D 12 01 STA $0112 +004112 1 A5 99 LDA $99 +004114 1 2D 10 01 AND $0110 +004117 1 0D 11 01 ORA $0111 +00411A 1 4D 12 01 EOR $0112 +00411D 1 +00411D 1 ; abx +00411D 1 85 99 STA $99 +00411F 1 A9 8A LDA #138 +004121 1 8D 20 01 STA $0120 +004124 1 A9 47 LDA #71 +004126 1 8D 21 01 STA $0121 +004129 1 A9 8F LDA #143 +00412B 1 8D 22 01 STA $0122 +00412E 1 A5 99 LDA $99 +004130 1 3D 10 01 AND $0110,X +004133 1 1D 11 01 ORA $0111,X +004136 1 5D 12 01 EOR $0112,X +004139 1 +004139 1 ; aby +004139 1 A0 20 LDY #32 +00413B 1 85 99 STA $99 +00413D 1 A9 73 LDA #115 +00413F 1 8D 30 01 STA $0130 +004142 1 A9 2A LDA #42 +004144 1 8D 31 01 STA $0131 +004147 1 A9 F1 LDA #241 +004149 1 8D 32 01 STA $0132 +00414C 1 A5 99 LDA $99 +00414E 1 39 10 01 AND $0110,Y +004151 1 19 11 01 ORA $0111,Y +004154 1 59 12 01 EOR $0112,Y +004157 1 +004157 1 ; idx +004157 1 85 99 STA $99 +004159 1 A9 70 LDA #112 +00415B 1 85 30 STA $30 +00415D 1 A9 01 LDA #$01 +00415F 1 85 31 STA $31 +004161 1 A9 71 LDA #113 +004163 1 85 32 STA $32 +004165 1 A9 01 LDA #$01 +004167 1 85 33 STA $33 +004169 1 A9 72 LDA #114 +00416B 1 85 34 STA $34 +00416D 1 A9 01 LDA #$01 +00416F 1 85 35 STA $35 +004171 1 A9 C5 LDA #197 +004173 1 8D 70 01 STA $0170 +004176 1 A9 7C LDA #124 +004178 1 8D 71 01 STA $0171 +00417B 1 A9 A1 LDA #161 +00417D 1 8D 72 01 STA $0172 +004180 1 A5 99 LDA $99 +004182 1 21 20 AND ($20,X) +004184 1 01 22 ORA ($22,X) +004186 1 41 24 EOR ($24,X) +004188 1 +004188 1 ; idy +004188 1 85 99 STA $99 +00418A 1 A9 60 LDA #96 +00418C 1 85 40 STA $40 +00418E 1 A9 01 LDA #$01 +004190 1 85 41 STA $41 +004192 1 A9 61 LDA #97 +004194 1 85 42 STA $42 +004196 1 A9 01 LDA #$01 +004198 1 85 43 STA $43 +00419A 1 A9 62 LDA #98 +00419C 1 85 44 STA $44 +00419E 1 A9 01 LDA #$01 +0041A0 1 85 45 STA $45 +0041A2 1 A9 37 LDA #55 +0041A4 1 8D 50 02 STA $0250 +0041A7 1 A9 23 LDA #35 +0041A9 1 8D 51 02 STA $0251 +0041AC 1 A9 9D LDA #157 +0041AE 1 8D 52 02 STA $0252 +0041B1 1 A5 99 LDA $99 +0041B3 1 A0 F0 LDY #$F0 +0041B5 1 31 40 AND ($40),Y +0041B7 1 11 42 ORA ($42),Y +0041B9 1 51 44 EOR ($44),Y +0041BB 1 +0041BB 1 85 A9 STA $A9 +0041BD 1 +0041BD 1 ; CHECK test01 +0041BD 1 A5 A9 LDA $A9 +0041BF 1 CD 01 02 CMP $0201 +0041C2 1 F0 08 BEQ test02 +0041C4 1 A9 01 LDA #$01 +0041C6 1 8D 10 02 STA $0210 +0041C9 1 4C C0 45 JMP theend +0041CC 1 +0041CC 1 +0041CC 1 ; expected result: $71 = 0xFF +0041CC 1 test02: +0041CC 1 A9 FF LDA #$FF +0041CE 1 A2 00 LDX #$00 +0041D0 1 +0041D0 1 85 90 STA $90 +0041D2 1 E6 90 INC $90 +0041D4 1 E6 90 INC $90 +0041D6 1 A5 90 LDA $90 +0041D8 1 A6 90 LDX $90 +0041DA 1 +0041DA 1 95 90 STA $90,X +0041DC 1 F6 90 INC $90,X +0041DE 1 B5 90 LDA $90,X +0041E0 1 A6 91 LDX $91 +0041E2 1 +0041E2 1 9D 90 01 STA $0190,X +0041E5 1 EE 92 01 INC $0192 +0041E8 1 BD 90 01 LDA $0190,X +0041EB 1 AE 92 01 LDX $0192 +0041EE 1 +0041EE 1 9D 90 01 STA $0190,X +0041F1 1 FE 90 01 INC $0190,X +0041F4 1 BD 90 01 LDA $0190,X +0041F7 1 AE 93 01 LDX $0193 +0041FA 1 +0041FA 1 9D 70 01 STA $0170,X +0041FD 1 DE 70 01 DEC $0170,X +004200 1 BD 70 01 LDA $0170,X +004203 1 AE 74 01 LDX $0174 +004206 1 +004206 1 9D 70 01 STA $0170,X +004209 1 CE 73 01 DEC $0173 +00420C 1 BD 70 01 LDA $0170,X +00420F 1 AE 73 01 LDX $0173 +004212 1 +004212 1 95 70 STA $70,X +004214 1 D6 70 DEC $70,X +004216 1 B5 70 LDA $70,X +004218 1 A6 72 LDX $72 +00421A 1 +00421A 1 95 70 STA $70,X +00421C 1 C6 71 DEC $71 +00421E 1 C6 71 DEC $71 +004220 1 +004220 1 ; CHECK test02 +004220 1 A5 71 LDA $71 +004222 1 CD 02 02 CMP $0202 +004225 1 F0 08 BEQ test03 +004227 1 A9 02 LDA #$02 +004229 1 8D 10 02 STA $0210 +00422C 1 4C C0 45 JMP theend +00422F 1 +00422F 1 +00422F 1 ; expected result: $01DD = 0x6E +00422F 1 test03: +00422F 1 A9 4B LDA #$4B +004231 1 4A LSR +004232 1 0A ASL +004233 1 +004233 1 85 50 STA $50 +004235 1 06 50 ASL $50 +004237 1 06 50 ASL $50 +004239 1 46 50 LSR $50 +00423B 1 A5 50 LDA $50 +00423D 1 +00423D 1 A6 50 LDX $50 +00423F 1 09 C9 ORA #$C9 +004241 1 85 60 STA $60 +004243 1 16 4C ASL $4C,X +004245 1 56 4C LSR $4C,X +004247 1 56 4C LSR $4C,X +004249 1 B5 4C LDA $4C,X +00424B 1 +00424B 1 A6 60 LDX $60 +00424D 1 09 41 ORA #$41 +00424F 1 8D 2E 01 STA $012E +004252 1 5E 00 01 LSR $0100,X +004255 1 5E 00 01 LSR $0100,X +004258 1 1E 00 01 ASL $0100,X +00425B 1 BD 00 01 LDA $0100,X +00425E 1 +00425E 1 AE 2E 01 LDX $012E +004261 1 09 81 ORA #$81 +004263 1 9D 00 01 STA $0100,X +004266 1 4E 36 01 LSR $0136 +004269 1 4E 36 01 LSR $0136 +00426C 1 0E 36 01 ASL $0136 +00426F 1 BD 00 01 LDA $0100,X +004272 1 +004272 1 ; rol & ror +004272 1 +004272 1 2A ROL +004273 1 2A ROL +004274 1 6A ROR +004275 1 85 70 STA $70 +004277 1 +004277 1 A6 70 LDX $70 +004279 1 09 03 ORA #$03 +00427B 1 95 0C STA $0C,X +00427D 1 26 C0 ROL $C0 +00427F 1 66 C0 ROR $C0 +004281 1 66 C0 ROR $C0 +004283 1 B5 0C LDA $0C,X +004285 1 +004285 1 A6 C0 LDX $C0 +004287 1 85 D0 STA $D0 +004289 1 36 75 ROL $75,X +00428B 1 36 75 ROL $75,X +00428D 1 76 75 ROR $75,X +00428F 1 A5 D0 LDA $D0 +004291 1 +004291 1 A6 D0 LDX $D0 +004293 1 9D 00 01 STA $0100,X +004296 1 2E B7 01 ROL $01B7 +004299 1 2E B7 01 ROL $01B7 +00429C 1 2E B7 01 ROL $01B7 +00429F 1 6E B7 01 ROR $01B7 +0042A2 1 BD 00 01 LDA $0100,X +0042A5 1 +0042A5 1 AE B7 01 LDX $01B7 +0042A8 1 8D DD 01 STA $01DD +0042AB 1 3E 00 01 ROL $0100,X +0042AE 1 7E 00 01 ROR $0100,X +0042B1 1 7E 00 01 ROR $0100,X +0042B4 1 +0042B4 1 ; CHECK test03 +0042B4 1 AD DD 01 LDA $01DD +0042B7 1 CD 03 02 CMP $0203 +0042BA 1 F0 08 BEQ test04 +0042BC 1 A9 03 LDA #$03 +0042BE 1 8D 10 02 STA $0210 +0042C1 1 4C C0 45 JMP theend +0042C4 1 +0042C4 1 +0042C4 1 ; expected result: $40 = 0x42 +0042C4 1 test04: +0042C4 1 A9 E8 LDA #$E8 ;originally:#$7C +0042C6 1 85 20 STA $20 +0042C8 1 A9 42 LDA #$42 ;originally:#$02 +0042CA 1 85 21 STA $21 +0042CC 1 A9 00 LDA #$00 +0042CE 1 09 03 ORA #$03 +0042D0 1 4C D5 42 JMP jump1 +0042D3 1 09 FF ORA #$FF ; not done +0042D5 1 jump1: +0042D5 1 09 30 ORA #$30 +0042D7 1 20 E1 42 JSR subr +0042DA 1 09 42 ORA #$42 +0042DC 1 6C 20 00 JMP ($0020) +0042DF 1 09 FF ORA #$FF ; not done +0042E1 1 subr: +0042E1 1 85 30 STA $30 +0042E3 1 A6 30 LDX $30 +0042E5 1 A9 00 LDA #$00 +0042E7 1 60 RTS +0042E8 1 final: +0042E8 1 95 0D STA $0D,X +0042EA 1 +0042EA 1 ; CHECK test04 +0042EA 1 A5 40 LDA $40 +0042EC 1 CD 04 02 CMP $0204 +0042EF 1 F0 08 BEQ test05 +0042F1 1 A9 04 LDA #$04 +0042F3 1 8D 10 02 STA $0210 +0042F6 1 4C C0 45 JMP theend +0042F9 1 +0042F9 1 +0042F9 1 ; expected result: $40 = 0x33 +0042F9 1 test05: +0042F9 1 A9 35 LDA #$35 +0042FB 1 +0042FB 1 AA TAX +0042FC 1 CA DEX +0042FD 1 CA DEX +0042FE 1 E8 INX +0042FF 1 8A TXA +004300 1 +004300 1 A8 TAY +004301 1 88 DEY +004302 1 88 DEY +004303 1 C8 INY +004304 1 98 TYA +004305 1 +004305 1 AA TAX +004306 1 A9 20 LDA #$20 +004308 1 9A TXS +004309 1 A2 10 LDX #$10 +00430B 1 BA TSX +00430C 1 8A TXA +00430D 1 +00430D 1 85 40 STA $40 +00430F 1 +00430F 1 ; CHECK test05 +00430F 1 A5 40 LDA $40 +004311 1 CD 05 02 CMP $0205 +004314 1 F0 08 BEQ test06 +004316 1 A9 05 LDA #$05 +004318 1 8D 10 02 STA $0210 +00431B 1 4C C0 45 JMP theend +00431E 1 +00431E 1 +00431E 1 ; expected result: $30 = 9D +00431E 1 test06: +00431E 1 +00431E 1 ; RESET TO CARRY FLAG = 0 +00431E 1 2A ROL +00431F 1 +00431F 1 A9 6A LDA #$6A +004321 1 85 50 STA $50 +004323 1 A9 6B LDA #$6B +004325 1 85 51 STA $51 +004327 1 A9 A1 LDA #$A1 +004329 1 85 60 STA $60 +00432B 1 A9 A2 LDA #$A2 +00432D 1 85 61 STA $61 +00432F 1 +00432F 1 A9 FF LDA #$FF +004331 1 69 FF ADC #$FF +004333 1 69 FF ADC #$FF +004335 1 E9 AE SBC #$AE +004337 1 +004337 1 85 40 STA $40 +004339 1 A6 40 LDX $40 +00433B 1 75 00 ADC $00,X +00433D 1 F5 01 SBC $01,X +00433F 1 +00433F 1 65 60 ADC $60 +004341 1 E5 61 SBC $61 +004343 1 +004343 1 8D 20 01 STA $0120 +004346 1 A9 4D LDA #$4D +004348 1 8D 21 01 STA $0121 +00434B 1 A9 23 LDA #$23 +00434D 1 6D 20 01 ADC $0120 +004350 1 ED 21 01 SBC $0121 +004353 1 +004353 1 85 F0 STA $F0 +004355 1 A6 F0 LDX $F0 +004357 1 A9 64 LDA #$64 +004359 1 8D 24 01 STA $0124 +00435C 1 A9 62 LDA #$62 +00435E 1 8D 25 01 STA $0125 +004361 1 A9 26 LDA #$26 +004363 1 7D 00 01 ADC $0100,X +004366 1 FD 01 01 SBC $0101,X +004369 1 +004369 1 85 F1 STA $F1 +00436B 1 A4 F1 LDY $F1 +00436D 1 A9 E5 LDA #$E5 +00436F 1 8D 28 01 STA $0128 +004372 1 A9 E9 LDA #$E9 +004374 1 8D 29 01 STA $0129 +004377 1 A9 34 LDA #$34 +004379 1 79 00 01 ADC $0100,Y +00437C 1 F9 01 01 SBC $0101,Y +00437F 1 +00437F 1 85 F2 STA $F2 +004381 1 A6 F2 LDX $F2 +004383 1 A9 20 LDA #$20 +004385 1 85 70 STA $70 +004387 1 A9 01 LDA #$01 +004389 1 85 71 STA $71 +00438B 1 A9 24 LDA #$24 +00438D 1 85 72 STA $72 +00438F 1 A9 01 LDA #$01 +004391 1 85 73 STA $73 +004393 1 61 41 ADC ($41,X) +004395 1 E1 3F SBC ($3F,X) +004397 1 +004397 1 85 F3 STA $F3 +004399 1 A4 F3 LDY $F3 +00439B 1 A9 DA LDA #$DA +00439D 1 85 80 STA $80 +00439F 1 A9 00 LDA #$00 +0043A1 1 85 81 STA $81 +0043A3 1 A9 DC LDA #$DC +0043A5 1 85 82 STA $82 +0043A7 1 A9 00 LDA #$00 +0043A9 1 85 83 STA $83 +0043AB 1 A9 AA LDA #$AA +0043AD 1 71 80 ADC ($80),Y +0043AF 1 F1 82 SBC ($82),Y +0043B1 1 85 30 STA $30 +0043B3 1 +0043B3 1 ; CHECK test06 +0043B3 1 A5 30 LDA $30 +0043B5 1 CD 06 02 CMP $0206 +0043B8 1 F0 08 BEQ test07 +0043BA 1 A9 06 LDA #$06 +0043BC 1 8D 10 02 STA $0210 +0043BF 1 4C C0 45 JMP theend +0043C2 1 +0043C2 1 +0043C2 1 ; expected result: $15 = 0x7F +0043C2 1 test07: +0043C2 1 ; prepare memory +0043C2 1 A9 00 LDA #$00 +0043C4 1 85 34 STA $34 +0043C6 1 A9 FF LDA #$FF +0043C8 1 8D 30 01 STA $0130 +0043CB 1 A9 99 LDA #$99 +0043CD 1 8D 9D 01 STA $019D +0043D0 1 A9 DB LDA #$DB +0043D2 1 8D 99 01 STA $0199 +0043D5 1 A9 2F LDA #$2F +0043D7 1 85 32 STA $32 +0043D9 1 A9 32 LDA #$32 +0043DB 1 85 4F STA $4F +0043DD 1 A9 30 LDA #$30 +0043DF 1 85 33 STA $33 +0043E1 1 A9 70 LDA #$70 +0043E3 1 85 AF STA $AF +0043E5 1 A9 18 LDA #$18 +0043E7 1 85 30 STA $30 +0043E9 1 +0043E9 1 ; imm +0043E9 1 C9 18 CMP #$18 +0043EB 1 F0 02 BEQ beq1 ; taken +0043ED 1 29 00 AND #$00 ; not done +0043EF 1 beq1: +0043EF 1 ; zpg +0043EF 1 09 01 ORA #$01 +0043F1 1 C5 30 CMP $30 +0043F3 1 D0 02 BNE bne1 ; taken +0043F5 1 29 00 AND #$00 ; not done +0043F7 1 bne1: +0043F7 1 ; abs +0043F7 1 A2 00 LDX #$00 +0043F9 1 CD 30 01 CMP $0130 +0043FC 1 F0 04 BEQ beq2 ; not taken +0043FE 1 85 40 STA $40 +004400 1 A6 40 LDX $40 +004402 1 beq2: +004402 1 ; zpx +004402 1 D5 27 CMP $27,X +004404 1 D0 06 BNE bne2 ; not taken +004406 1 09 84 ORA #$84 +004408 1 85 41 STA $41 +00440A 1 A6 41 LDX $41 +00440C 1 bne2: +00440C 1 ; abx +00440C 1 29 DB AND #$DB +00440E 1 DD 00 01 CMP $0100,X +004411 1 F0 02 BEQ beq3 ; taken +004413 1 29 00 AND #$00 ; not done +004415 1 beq3: +004415 1 ; aby +004415 1 85 42 STA $42 +004417 1 A4 42 LDY $42 +004419 1 29 00 AND #$00 +00441B 1 D9 00 01 CMP $0100,Y +00441E 1 D0 02 BNE bne3 ; taken +004420 1 09 0F ORA #$0F ; not done +004422 1 bne3: +004422 1 ; idx +004422 1 85 43 STA $43 +004424 1 A6 43 LDX $43 +004426 1 09 24 ORA #$24 +004428 1 C1 40 CMP ($40,X) +00442A 1 F0 02 BEQ beq4 ; not taken +00442C 1 09 7F ORA #$7F +00442E 1 beq4: +00442E 1 ; idy +00442E 1 85 44 STA $44 +004430 1 A4 44 LDY $44 +004432 1 49 0F EOR #$0F +004434 1 D1 33 CMP ($33),Y +004436 1 D0 04 BNE bne4 ; not taken +004438 1 A5 44 LDA $44 +00443A 1 85 15 STA $15 +00443C 1 bne4: +00443C 1 +00443C 1 ; CHECK test07 +00443C 1 A5 15 LDA $15 +00443E 1 CD 07 02 CMP $0207 +004441 1 F0 08 BEQ test08 +004443 1 A9 07 LDA #$07 +004445 1 8D 10 02 STA $0210 +004448 1 4C C0 45 JMP theend +00444B 1 +00444B 1 +00444B 1 ; expected result: $42 = 0xA5 +00444B 1 test08: +00444B 1 ; prepare memory +00444B 1 A9 A5 LDA #$A5 +00444D 1 85 20 STA $20 +00444F 1 8D 20 01 STA $0120 +004452 1 A9 5A LDA #$5A +004454 1 85 21 STA $21 +004456 1 +004456 1 ; cpx imm... +004456 1 A2 A5 LDX #$A5 +004458 1 E0 A5 CPX #$A5 +00445A 1 F0 02 BEQ b1 ; taken +00445C 1 A2 01 LDX #$01 ; not done +00445E 1 b1: +00445E 1 ; cpx zpg... +00445E 1 E4 20 CPX $20 +004460 1 F0 02 BEQ b2 ; taken +004462 1 A2 02 LDX #$02 ; not done +004464 1 b2: +004464 1 ; cpx abs... +004464 1 EC 20 01 CPX $0120 +004467 1 F0 02 BEQ b3 ; taken +004469 1 A2 03 LDX #$03 ; not done +00446B 1 b3: +00446B 1 ; cpy imm... +00446B 1 86 30 STX $30 +00446D 1 A4 30 LDY $30 +00446F 1 C0 A5 CPY #$A5 +004471 1 F0 02 BEQ b4 ; taken +004473 1 A0 04 LDY #$04 ; not done +004475 1 b4: +004475 1 ; cpy zpg... +004475 1 C4 20 CPY $20 +004477 1 F0 02 BEQ b5 ; taken +004479 1 A0 05 LDY #$05 ; not done +00447B 1 b5: +00447B 1 ; cpy abs... +00447B 1 CC 20 01 CPY $0120 +00447E 1 F0 02 BEQ b6 ; taken +004480 1 A0 06 LDY #$06 ; not done +004482 1 b6: +004482 1 ; bit zpg... +004482 1 84 31 STY $31 +004484 1 A5 31 LDA $31 +004486 1 24 20 BIT $20 +004488 1 D0 02 BNE b7 ; taken +00448A 1 A9 07 LDA #$07 ; not done +00448C 1 b7: +00448C 1 ; bit abs... +00448C 1 2C 20 01 BIT $0120 +00448F 1 D0 02 BNE b8 ; taken +004491 1 A9 08 LDA #$08 ; not done +004493 1 b8: +004493 1 24 21 BIT $21 +004495 1 D0 02 BNE b9 ; not taken +004497 1 85 42 STA $42 +004499 1 b9: +004499 1 +004499 1 ; CHECK test08 +004499 1 A5 42 LDA $42 +00449B 1 CD 08 02 CMP $0208 +00449E 1 F0 08 BEQ test09 +0044A0 1 A9 08 LDA #$08 +0044A2 1 8D 10 02 STA $0210 +0044A5 1 4C C0 45 JMP theend +0044A8 1 +0044A8 1 +0044A8 1 ; expected result: $80 = 0x1F +0044A8 1 test09: +0044A8 1 ; prepare memory +0044A8 1 A9 54 LDA #$54 +0044AA 1 85 32 STA $32 +0044AC 1 A9 B3 LDA #$B3 +0044AE 1 85 A1 STA $A1 +0044B0 1 A9 87 LDA #$87 +0044B2 1 85 43 STA $43 +0044B4 1 +0044B4 1 ; BPL +0044B4 1 A2 A1 LDX #$A1 +0044B6 1 10 02 BPL bpl1 ; not taken +0044B8 1 A2 32 LDX #$32 +0044BA 1 bpl1: +0044BA 1 B4 00 LDY $00,X +0044BC 1 10 04 BPL bpl2 ; taken +0044BE 1 A9 05 LDA #$05 ; not done +0044C0 1 A6 A1 LDX $A1 ; not done +0044C2 1 bpl2: +0044C2 1 +0044C2 1 ; BMI +0044C2 1 30 02 BMI bmi1 ; not taken +0044C4 1 E9 03 SBC #$03 +0044C6 1 bmi1: +0044C6 1 30 02 BMI bmi2 ; taken +0044C8 1 A9 41 LDA #$41 ; not done +0044CA 1 bmi2: +0044CA 1 +0044CA 1 ; BVC +0044CA 1 49 30 EOR #$30 +0044CC 1 85 32 STA $32 +0044CE 1 75 00 ADC $00,X +0044D0 1 50 02 BVC bvc1 ; not taken +0044D2 1 A9 03 LDA #$03 +0044D4 1 bvc1: +0044D4 1 85 54 STA $54 +0044D6 1 B6 00 LDX $00,Y +0044D8 1 75 51 ADC $51,X +0044DA 1 50 02 BVC bvc2 ; taken +0044DC 1 A9 E5 LDA #$E5 ; not done +0044DE 1 bvc2: +0044DE 1 +0044DE 1 ; BVS +0044DE 1 75 40 ADC $40,X +0044E0 1 70 05 BVS bvs1 ; not taken +0044E2 1 99 01 00 STA $0001,Y +0044E5 1 65 55 ADC $55 +0044E7 1 bvs1: +0044E7 1 70 02 BVS bvs2 ; taken +0044E9 1 A9 00 LDA #$00 +0044EB 1 bvs2: +0044EB 1 +0044EB 1 ; BCC +0044EB 1 69 F0 ADC #$F0 +0044ED 1 90 04 BCC bcc1 ; not taken +0044EF 1 85 60 STA $60 +0044F1 1 65 43 ADC $43 +0044F3 1 bcc1: +0044F3 1 90 02 BCC bcc2 ; taken +0044F5 1 A9 FF LDA #$FF +0044F7 1 bcc2: +0044F7 1 +0044F7 1 ; BCS +0044F7 1 65 54 ADC $54 +0044F9 1 B0 04 BCS bcs1 ; not taken +0044FB 1 69 87 ADC #$87 +0044FD 1 A6 60 LDX $60 +0044FF 1 bcs1: +0044FF 1 B0 02 BCS bcs2 ; taken +004501 1 A9 00 LDA #$00 ; not done +004503 1 bcs2: +004503 1 95 73 STA $73,X +004505 1 +004505 1 ; CHECK test09 +004505 1 A5 80 LDA $80 +004507 1 CD 09 02 CMP $0209 +00450A 1 F0 08 BEQ test10 +00450C 1 A9 09 LDA #$09 +00450E 1 8D 10 02 STA $0210 +004511 1 4C C0 45 JMP theend +004514 1 +004514 1 +004514 1 ; expected result: $30 = 0xCE +004514 1 test10: +004514 1 +004514 1 ; RESET TO CARRY = 0 & OVERFLOW = 0 +004514 1 69 00 ADC #$00 +004516 1 +004516 1 A9 99 LDA #$99 +004518 1 69 87 ADC #$87 +00451A 1 18 CLC +00451B 1 EA NOP +00451C 1 90 04 BCC t10bcc1 ; taken +00451E 1 69 60 ADC #$60 ; not done +004520 1 69 93 ADC #$93 ; not done +004522 1 t10bcc1: +004522 1 38 SEC +004523 1 EA NOP +004524 1 90 01 BCC t10bcc2 ; not taken +004526 1 B8 CLV +004527 1 t10bcc2: +004527 1 50 02 BVC t10bvc1 ; taken +004529 1 A9 00 LDA #$00 ; not done +00452B 1 t10bvc1: +00452B 1 69 AD ADC #$AD +00452D 1 EA NOP +00452E 1 85 30 STA $30 +004530 1 +004530 1 ; CHECK test10 +004530 1 A5 30 LDA $30 +004532 1 CD 0A 02 CMP $020A +004535 1 F0 08 BEQ test11 +004537 1 A9 0A LDA #$0A +004539 1 8D 10 02 STA $0210 +00453C 1 4C C0 45 JMP theend +00453F 1 +00453F 1 +00453F 1 ; expected result: $30 = 0x29 +00453F 1 test11: +00453F 1 +00453F 1 ; RESET TO CARRY = 0 & ZERO = 0 +00453F 1 69 01 ADC #$01 +004541 1 +004541 1 A9 27 LDA #$27 +004543 1 69 01 ADC #$01 +004545 1 38 SEC +004546 1 08 PHP +004547 1 18 CLC +004548 1 28 PLP +004549 1 69 00 ADC #$00 +00454B 1 48 PHA +00454C 1 A9 00 LDA #$00 +00454E 1 68 PLA +00454F 1 85 30 STA $30 +004551 1 +004551 1 ; CHECK test11 +004551 1 A5 30 LDA $30 +004553 1 CD 0B 02 CMP $020B +004556 1 F0 08 BEQ test12 +004558 1 A9 0B LDA #$0B +00455A 1 8D 10 02 STA $0210 +00455D 1 4C C0 45 JMP theend +004560 1 +004560 1 +004560 1 ; expected result: $33 = 0x42 +004560 1 test12: +004560 1 18 CLC +004561 1 A9 42 LDA #$42 +004563 1 90 04 BCC runstuff +004565 1 85 33 STA $33 +004567 1 B0 0A BCS t12end +004569 1 runstuff: +004569 1 A9 45 LDA #$45 +00456B 1 48 PHA +00456C 1 A9 61 LDA #$61 +00456E 1 48 PHA +00456F 1 38 SEC +004570 1 08 PHP +004571 1 18 CLC +004572 1 40 RTI +004573 1 t12end: +004573 1 +004573 1 ; CHECK test12 +004573 1 A5 33 LDA $33 +004575 1 CD 0C 02 CMP $020C +004578 1 F0 08 BEQ test13 +00457A 1 A9 0C LDA #$0C +00457C 1 8D 10 02 STA $0210 +00457F 1 4C C0 45 JMP theend +004582 1 +004582 1 +004582 1 ; expected result: $21 = 0x6C (simulator) +004582 1 ; $21 = 0x0C (ours) +004582 1 test13: +004582 1 +004582 1 ; RESET TO CARRY = 0 & ZERO = 0 +004582 1 69 01 ADC #$01 +004584 1 +004584 1 78 SEI +004585 1 F8 SED +004586 1 08 PHP +004587 1 68 PLA +004588 1 85 20 STA $20 +00458A 1 58 CLI +00458B 1 D8 CLD +00458C 1 08 PHP +00458D 1 68 PLA +00458E 1 65 20 ADC $20 +004590 1 85 21 STA $21 +004592 1 +004592 1 ; CHECK test13 +004592 1 A5 21 LDA $21 +004594 1 CD 0D 02 CMP $020D +004597 1 F0 08 BEQ test14 +004599 1 A9 0D LDA #$0D +00459B 1 8D 10 02 STA $0210 +00459E 1 4C C0 45 JMP theend +0045A1 1 +0045A1 1 +0045A1 1 ; expect result: $60 = 0x42 +0045A1 1 test14: +0045A1 1 ; !!! NOTICE: BRK doesn't work in this +0045A1 1 ; simulator, so commented instructions +0045A1 1 ; are what should be executed... +0045A1 1 ;JMP pass_intrp +0045A1 1 A9 41 LDA #$41 +0045A3 1 85 60 STA $60 +0045A5 1 ;RTI +0045A5 1 ;pass_intrp: +0045A5 1 ;LDA #$FF +0045A5 1 ;STA $60 +0045A5 1 ;BRK (two bytes) +0045A5 1 E6 60 INC $60 +0045A7 1 +0045A7 1 ; CHECK test14 +0045A7 1 A5 60 LDA $60 +0045A9 1 CD 0E 02 CMP $020E +0045AC 1 F0 08 BEQ suiteafinal +0045AE 1 A9 0E LDA #$0E +0045B0 1 8D 10 02 STA $0210 +0045B3 1 4C C0 45 JMP theend +0045B6 1 +0045B6 1 suiteafinal: +0045B6 1 ; IF $0210 == 0xFE, INCREMENT +0045B6 1 ; (checking that it didn't +0045B6 1 ; happen to wander off and +0045B6 1 ; not run our instructions +0045B6 1 ; to say which tests failed...) +0045B6 1 A9 FE LDA #$FE +0045B8 1 CD 10 02 CMP $0210 +0045BB 1 D0 03 BNE theend +0045BD 1 EE 10 02 INC $0210 +0045C0 1 theend: +0045C0 1 00 BRK +0045C1 1 00 BRK +0045C2 1 ;JMP theend +0045C2 1 A2 FF LDX #$FF +0045C4 1 9A TXS +0045C5 1 60 RTS +0045C6 1 +0045C6 1 .segment "KERN" +0045C6 1 +0045C6 1 .ORG $FF00 +00FF00 1 +00FF00 1 40 RTI +00FF01 1 +00FF01 1 .segment "VECT" +00FF01 1 +00FF01 1 .ORG $FFFA +00FFFA 1 +00FFFA 1 00 FF 00 FF .BYTE $00,$FF,$00,$FF,$00,$FF +00FFFE 1 00 FF +010000 1 +010000 1 ;-------------------------- END +010000 1 diff --git a/testall.o b/testall.o new file mode 100644 index 0000000..3aa7653 Binary files /dev/null and b/testall.o differ diff --git a/testall_cl65.cfg b/testall_cl65.cfg new file mode 100644 index 0000000..41507e2 --- /dev/null +++ b/testall_cl65.cfg @@ -0,0 +1,24 @@ +# +# This is configuration file for CL65 linker to produce +# binary image 64 kB long, which is to be loaded from +# address $0000. +# Code segment CODE1, 15 kB starts at $0400. +# Code segment CODE2, 49 kB starts at $4000. +# Kernel jump table segment KERN (250 B) starts at $FF00. +# Vectors segment start at $FFFA. +# +MEMORY { + RAM0: start = $0000, size = $400, fill = yes; + RAM1: start = $0400, size = $3C00, fill = yes; + RAM2: start = $4000, size = $BF00, fill = yes; + ROM0: start = $FF00, size = $FA, fill = yes; + ROM1: start = $FFFA, size = 6; +} + +SEGMENTS { + CODE1: load = RAM1, type = rw; + CODE2: load = RAM2, type = rw; + KERN: load = ROM0, type = ro; + VECT: load = ROM1, type = ro; +} + diff --git a/testbcd.dat b/testbcd.dat index 8675722..eadd04c 100644 --- a/testbcd.dat +++ b/testbcd.dat @@ -1,69 +1,69 @@ -; Program disassembly from $0400 to $0600 2/9/2016 -; Test BCD mode. -ORG -$0400 -$A0 $01 $8C $04 $03 $A9 $00 $8D -$07 $03 $8D $0A $03 $AD $0A $03 -$29 $0F $8D $0B $03 $AD $0A $03 -$29 $F0 $8D $0F $03 $09 $0F $8D -$10 $03 $AD $07 $03 $29 $0F $8D -$09 $03 $AD $07 $03 $29 $F0 $8D -$08 $03 $20 $5E $04 $20 $47 $05 -$20 $18 $05 $D0 $1D $20 $B1 $04 -$20 $54 $05 $20 $18 $05 $D0 $12 -$EE $07 $03 $D0 $D5 $EE $0A $03 -$D0 $BB $88 $10 $B8 $A9 $00 $8D -$04 $03 $00 $00 $00 $00 $F8 $C0 -$01 $AD $07 $03 $6D $0A $03 $8D -$02 $03 $08 $68 $8D $03 $03 $D8 -$C0 $01 $AD $07 $03 $6D $0A $03 -$8D $05 $03 $08 $68 $8D $06 $03 -$C0 $01 $AD $09 $03 $6D $0B $03 -$C9 $0A $A2 $00 $90 $06 $E8 $69 -$05 $29 $0F $38 $0D $08 $03 $7D -$0F $03 $08 $B0 $04 $C9 $A0 $90 -$03 $69 $5F $38 $8D $00 $03 $08 -$68 $8D $01 $03 $68 $8D $0D $03 -$60 $F8 $C0 $01 $AD $07 $03 $ED -$0A $03 $8D $02 $03 $08 $68 $8D -$03 $03 $D8 $C0 $01 $AD $07 $03 -$ED $0A $03 $8D $05 $03 $08 $68 -$8D $06 $03 $60 $C0 $01 $AD $09 -$03 $ED $0B $03 $A2 $00 $B0 $06 -$E8 $E9 $05 $29 $0F $18 $0D $08 -$03 $FD $0F $03 $B0 $02 $E9 $5F -$8D $00 $03 $60 $C0 $01 $AD $09 -$03 $ED $0B $03 $A2 $00 $B0 $04 -$E8 $29 $0F $18 $0D $08 $03 $FD -$0F $03 $B0 $02 $E9 $5F $E0 $00 -$F0 $02 $E9 $06 $8D $00 $03 $60 -$AD $02 $03 $CD $00 $03 $D0 $26 -$AD $03 $03 $4D $0C $03 $29 $80 -$D0 $1C $AD $03 $03 $4D $0D $03 -$29 $40 $D0 $12 $AD $03 $03 $4D -$0E $03 $29 $02 $D0 $08 $AD $03 -$03 $4D $01 $03 $29 $01 $60 $AD -$0D $03 $8D $0C $03 $AD $06 $03 -$8D $0E $03 $60 $20 $D4 $04 $AD -$06 $03 $8D $0C $03 $8D $0D $03 -$8D $0E $03 $8D $01 $03 $60 $AD -$00 $03 $08 $68 $8D $0C $03 $8D -$0E $03 $60 $20 $F4 $04 $AD $00 -$03 $08 $68 $8D $0C $03 $8D $0E -$03 $AD $06 $03 $8D $0D $03 $8D -$01 $03 $60 $AD $00 $03 $08 $68 -$8D $0C $03 $8D $0E $03 $60 $20 -$D4 $04 $AD $00 $03 $08 $68 $8D -$0C $03 $8D $0E $03 $AD $06 $03 -$8D $0D $03 $8D $01 $03 $60 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 - +; Program disassembly from $0400 to $0600 2/9/2016 +; Test BCD mode. +ORG +$0400 +$A0 $01 $8C $04 $03 $A9 $00 $8D +$07 $03 $8D $0A $03 $AD $0A $03 +$29 $0F $8D $0B $03 $AD $0A $03 +$29 $F0 $8D $0F $03 $09 $0F $8D +$10 $03 $AD $07 $03 $29 $0F $8D +$09 $03 $AD $07 $03 $29 $F0 $8D +$08 $03 $20 $5E $04 $20 $47 $05 +$20 $18 $05 $D0 $1D $20 $B1 $04 +$20 $54 $05 $20 $18 $05 $D0 $12 +$EE $07 $03 $D0 $D5 $EE $0A $03 +$D0 $BB $88 $10 $B8 $A9 $00 $8D +$04 $03 $00 $00 $00 $00 $F8 $C0 +$01 $AD $07 $03 $6D $0A $03 $8D +$02 $03 $08 $68 $8D $03 $03 $D8 +$C0 $01 $AD $07 $03 $6D $0A $03 +$8D $05 $03 $08 $68 $8D $06 $03 +$C0 $01 $AD $09 $03 $6D $0B $03 +$C9 $0A $A2 $00 $90 $06 $E8 $69 +$05 $29 $0F $38 $0D $08 $03 $7D +$0F $03 $08 $B0 $04 $C9 $A0 $90 +$03 $69 $5F $38 $8D $00 $03 $08 +$68 $8D $01 $03 $68 $8D $0D $03 +$60 $F8 $C0 $01 $AD $07 $03 $ED +$0A $03 $8D $02 $03 $08 $68 $8D +$03 $03 $D8 $C0 $01 $AD $07 $03 +$ED $0A $03 $8D $05 $03 $08 $68 +$8D $06 $03 $60 $C0 $01 $AD $09 +$03 $ED $0B $03 $A2 $00 $B0 $06 +$E8 $E9 $05 $29 $0F $18 $0D $08 +$03 $FD $0F $03 $B0 $02 $E9 $5F +$8D $00 $03 $60 $C0 $01 $AD $09 +$03 $ED $0B $03 $A2 $00 $B0 $04 +$E8 $29 $0F $18 $0D $08 $03 $FD +$0F $03 $B0 $02 $E9 $5F $E0 $00 +$F0 $02 $E9 $06 $8D $00 $03 $60 +$AD $02 $03 $CD $00 $03 $D0 $26 +$AD $03 $03 $4D $0C $03 $29 $80 +$D0 $1C $AD $03 $03 $4D $0D $03 +$29 $40 $D0 $12 $AD $03 $03 $4D +$0E $03 $29 $02 $D0 $08 $AD $03 +$03 $4D $01 $03 $29 $01 $60 $AD +$0D $03 $8D $0C $03 $AD $06 $03 +$8D $0E $03 $60 $20 $D4 $04 $AD +$06 $03 $8D $0C $03 $8D $0D $03 +$8D $0E $03 $8D $01 $03 $60 $AD +$00 $03 $08 $68 $8D $0C $03 $8D +$0E $03 $60 $20 $F4 $04 $AD $00 +$03 $08 $68 $8D $0C $03 $8D $0E +$03 $AD $06 $03 $8D $0D $03 $8D +$01 $03 $60 $AD $00 $03 $08 $68 +$8D $0C $03 $8D $0E $03 $60 $20 +$D4 $04 $AD $00 $03 $08 $68 $8D +$0C $03 $8D $0E $03 $AD $06 $03 +$8D $0D $03 $8D $01 $03 $60 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 + diff --git a/tinybasic.dat b/tinybasic.dat index fca0f34..d2f400d 100644 --- a/tinybasic.dat +++ b/tinybasic.dat @@ -1,774 +1,774 @@ -; Tiny Basic for MKBASIC 6502 emulator. -; Run address: $0CF0 -; I/O emulation: $E000 -ORG -$0400 -$4C $85 $04 $4C $BD $04 $4C $2C -$0F $4C $31 $0F $EA $18 $60 $5F -$18 $80 $00 $20 $86 $C3 $90 $05 -$86 $C3 $91 $C2 $60 $B1 $C2 $A0 -$00 $60 $62 $05 $64 $05 $D8 $05 -$05 $06 $33 $06 $FD $05 $9F $07 -$42 $0B $3F $0B $7A $07 $FC $08 -$95 $07 $9F $07 $9F $07 $BD $0A -$C1 $0A $8A $0A $9B $0A $E9 $0A -$61 $07 $51 $07 $41 $0A $52 $0A -$4F $0A $62 $0A $E7 $09 $CD $06 -$06 $07 $9F $07 $15 $08 $A7 $07 -$B7 $06 $BF $06 $83 $08 $A1 $06 -$9F $07 $9F $07 $A8 $08 $4F $0B -$4D $0B $07 $09 $AA $04 $37 $07 -$BD $04 $1B $0B $B1 $0A $20 $41 -$54 $20 $80 $70 $0B $A9 $00 $85 -$20 $85 $22 $A9 $1C $85 $21 $85 -$23 $A0 $01 $B1 $22 $AA $49 $FF -$91 $22 $D1 $22 $08 $8A $91 $22 -$E6 $22 $D0 $02 $E6 $23 $28 $F0 -$EA $88 $D8 $A5 $20 $6D $13 $04 -$85 $24 $98 $65 $21 $85 $25 $98 -$91 $20 $C8 $91 $20 $A5 $22 $85 -$C6 $85 $26 $A5 $23 $85 $C7 $85 -$27 $20 $87 $08 $AD $83 $04 $85 -$2A $AD $84 $04 $85 $2B $A9 $80 -$85 $C1 $A9 $30 $85 $C0 $A2 $00 -$86 $BE $86 $C2 $CA $9A $D8 $20 -$F9 $06 $20 $F2 $04 $4C $E6 $04 -$83 $65 $C9 $30 $B0 $7B $C9 $08 -$90 $0C $0A $AA $BD $1F $04 $48 -$BD $1E $04 $48 $08 $40 $65 $C1 -$AA $B1 $C1 $48 $B5 $00 $91 $C1 -$68 $95 $00 $60 $20 $87 $08 $A9 -$21 $20 $09 $04 $A5 $2A $38 $ED -$83 $04 $AA $A5 $2B $ED $84 $04 -$20 $A0 $07 $A5 $BE $F0 $12 $A9 -$7E $85 $2A $A9 $20 $85 $2B $20 -$A1 $06 $A6 $28 $A5 $29 $20 $A0 -$07 $A9 $07 $20 $09 $04 $20 $87 -$08 $A5 $26 $85 $C6 $A5 $27 $85 -$C7 $4C $CC $04 $A2 $7C $E4 $C1 -$90 $BA $A6 $C1 $E6 $C1 $E6 $C1 -$18 $60 $C6 $BD $A5 $BD $F0 $AC -$A5 $BC $85 $2A $A5 $BD $85 $2B -$60 $C9 $40 $B0 $43 $48 $20 $F9 -$06 $6D $83 $04 $85 $BC $68 $48 -$29 $07 $6D $84 $04 $85 $BD $68 -$29 $08 $D0 $DC $A5 $BC $A6 $2A -$85 $2A $86 $BC $A5 $BD $A6 $2B -$85 $2B $86 $BD $A5 $C6 $E9 $01 -$85 $C6 $B0 $02 $C6 $C7 $C5 $24 -$A5 $C7 $E5 $25 $90 $AA $A5 $BC -$91 $C6 $C8 $A5 $BD $91 $C6 $60 -$48 $4A $4A $4A $4A $29 $0E $AA -$68 $C9 $60 $29 $1F $B0 $02 $09 -$E0 $18 $F0 $07 $65 $2A $85 $BC -$98 $65 $2B $85 $BD $4C $FC $04 -$A5 $2C $85 $B8 $A5 $2D $85 $B9 -$20 $25 $06 $20 $14 $06 $51 $2A -$AA $20 $F9 $06 $8A $F0 $F1 $0A -$F0 $12 $A5 $B8 $85 $2C $A5 $B9 -$85 $2D $4C $64 $05 $20 $25 $06 -$C9 $0D $D0 $F6 $60 $20 $25 $06 -$C9 $5B $B0 $EE $C9 $41 $90 $EA -$0A $20 $87 $07 $A0 $00 $B1 $2C -$E6 $2C $D0 $02 $E6 $2D $C9 $0D -$18 $60 $20 $14 $06 $B1 $2C $C9 -$20 $F0 $F7 $C9 $3A $18 $10 $02 -$C9 $30 $60 $20 $25 $06 $90 $C2 -$84 $BC $84 $BD $A5 $BC $A6 $BD -$06 $BC $26 $BD $06 $BC $26 $BD -$18 $65 $BC $85 $BC $8A $65 $BD -$06 $BC $2A $85 $BD $20 $14 $06 -$29 $0F $65 $BC $85 $BC $98 $65 -$BD $85 $BD $20 $25 $06 $B0 $D4 -$4C $80 $07 $20 $FC $08 $A5 $BC -$05 $BD $F0 $48 $A5 $20 $85 $2C -$A5 $21 $85 $2D $20 $6D $07 $F0 -$12 $A5 $28 $C5 $BC $A5 $29 $E5 -$BD $B0 $08 $20 $14 $06 $D0 $FB -$4C $7C $06 $A5 $28 $45 $BC $D0 -$04 $A5 $29 $45 $BD $60 $20 $A6 -$06 $20 $F9 $06 $10 $F8 $E6 $BF -$30 $03 $4C $09 $04 $C6 $BF $60 -$C9 $22 $F0 $FB $20 $A6 $06 $20 -$14 $06 $D0 $F4 $4C $14 $05 $A9 -$20 $20 $A6 $06 $A5 $BF $29 $87 -$30 $E5 $D0 $F3 $60 $A2 $7B $20 -$56 $05 $E6 $C1 $E6 $C1 $E6 $C1 -$38 $B5 $03 $F5 $00 $95 $00 $B5 -$04 $F5 $01 $50 $04 $49 $80 $09 -$01 $30 $0A $D0 $04 $15 $00 $F0 -$02 $56 $02 $56 $02 $56 $02 $90 -$0C $A0 $00 $B1 $2A $E6 $2A $D0 -$02 $E6 $2B $09 $00 $60 $A5 $BE -$F0 $28 $20 $14 $06 $D0 $FB $20 -$6D $07 $F0 $1B $20 $4C $07 $20 -$0C $04 $B0 $09 $A5 $C4 $85 $2A -$A5 $C5 $85 $2B $60 $AD $83 $04 -$85 $2A $AD $84 $04 $85 $2B $4C -$14 $05 $85 $BF $4C $49 $05 $A5 -$20 $85 $2C $A5 $21 $85 $2D $20 -$6D $07 $F0 $EB $A5 $2A $85 $C4 -$A5 $2B $85 $C5 $A9 $01 $85 $BE -$60 $20 $6B $06 $F0 $BE $A5 $BC -$85 $28 $A5 $BD $85 $29 $4C $14 -$05 $20 $FD $0A $20 $FA $0A $20 -$74 $06 $D0 $EA $60 $20 $14 $06 -$85 $28 $20 $14 $06 $85 $29 $05 -$28 $60 $20 $FC $08 $20 $80 $07 -$A5 $BD $20 $87 $07 $A5 $BC $A6 -$C1 $CA $95 $00 $86 $C1 $E4 $C0 -$D0 $0D $4C $14 $05 $A6 $C1 $E0 -$80 $10 $F7 $B5 $00 $E6 $C1 $60 -$85 $BD $86 $BC $4C $B8 $07 $A6 -$C1 $B5 $01 $10 $08 $20 $41 $0A -$A9 $2D $20 $A6 $06 $20 $FC $08 -$A9 $1F $85 $B8 $85 $BA $A9 $2A -$85 $B9 $85 $BB $A6 $BC $A4 $BD -$38 $E6 $B8 $8A $E9 $10 $AA $98 -$E9 $27 $A8 $B0 $F4 $C6 $B9 $8A -$69 $E8 $AA $98 $69 $03 $A8 $90 -$F4 $8A $38 $E6 $BA $E9 $64 $B0 -$F9 $88 $10 $F6 $C6 $BB $69 $0A -$90 $FA $09 $30 $85 $BC $A9 $20 -$85 $BD $A2 $FB $86 $C3 $B5 $BD -$05 $BD $C9 $20 $F0 $09 $A0 $30 -$84 $BD $05 $BD $20 $A6 $06 $A6 -$C3 $E8 $D0 $E8 $60 $A5 $2D $48 -$A5 $2C $48 $A5 $20 $85 $2C $A5 -$21 $85 $2D $A5 $24 $A6 $25 $20 -$5B $08 $F0 $03 $20 $5B $08 $A5 -$2C $38 $E5 $B6 $A5 $2D $E5 $B7 -$B0 $42 $20 $6D $07 $F0 $3D $A6 -$28 $A5 $29 $20 $A0 $07 $A9 $20 -$20 $A6 $06 $20 $0C $04 $B0 $2C -$20 $14 $06 $D0 $F3 $20 $83 $08 -$4C $2F $08 $85 $B6 $E6 $B6 $D0 -$01 $E8 $86 $B7 $A4 $C1 $C0 $80 -$F0 $18 $20 $6B $06 $A5 $2C $A6 -$2D $38 $E9 $02 $B0 $01 $CA $85 -$2C $4C $48 $0B $68 $85 $2C $68 -$85 $2D $60 $A5 $BF $30 $FB $A9 -$0D $20 $09 $04 $AD $11 $04 $29 -$7F $85 $BF $F0 $07 $20 $64 $0B -$C6 $BF $D0 $F9 $A9 $0A $4C $61 -$0B $AC $12 $04 $84 $BF $B0 $0B -$A9 $30 $85 $2C $85 $C0 $84 $2D -$20 $80 $07 $45 $80 $85 $80 $20 -$06 $04 $A0 $00 $A6 $C0 $29 $7F -$F0 $F1 $C9 $7F $F0 $ED $C9 $13 -$F0 $DA $C9 $0A $F0 $D3 $CD $10 -$04 $F0 $09 $CD $0F $04 $D0 $0A -$E0 $30 $D0 $16 $A6 $2C $84 $BF -$A9 $0D $E4 $C1 $30 $08 $A9 $07 -$20 $A6 $06 $4C $B3 $08 $95 $00 -$E8 $E8 $CA $86 $C0 $C9 $0D $D0 -$BA $20 $83 $08 $20 $95 $07 $85 -$BC $20 $95 $07 $85 $BD $60 $20 -$D6 $0A $20 $6B $06 $08 $20 $6D -$08 $85 $B8 $86 $B9 $A5 $BC $85 -$B6 $A5 $BD $85 $B7 $A2 $00 $28 -$D0 $0B $20 $6D $07 $CA $CA $CA -$20 $14 $06 $D0 $FA $84 $28 $84 -$29 $20 $D6 $0A $A9 $0D $D1 $2C -$F0 $11 $E8 $E8 $E8 $E8 $C8 $D1 -$2C $D0 $FA $A5 $B6 $85 $28 $A5 -$B7 $85 $29 $A5 $B8 $85 $BC $A5 -$B9 $85 $BD $18 $A0 $00 $8A $F0 -$6E $10 $29 $65 $2E $85 $B8 $A5 -$2F $E9 $00 $85 $B9 $B1 $2E $91 -$B8 $A6 $2E $E4 $24 $D0 $06 $A5 -$2F $C5 $25 $F0 $4A $E8 $86 $2E -$D0 $02 $E6 $2F $E6 $B8 $D0 $E5 -$E6 $B9 $D0 $E1 $65 $24 $85 $B8 -$85 $2E $98 $65 $25 $85 $B9 $85 -$2F $A5 $2E $E5 $C6 $A5 $2F $E5 -$C7 $90 $05 $C6 $2A $4C $14 $05 -$B1 $24 $91 $2E $A6 $24 $D0 $02 -$C6 $25 $C6 $24 $A6 $2E $D0 $02 -$C6 $2F $CA $86 $2E $E4 $BC $D0 -$E7 $A6 $2F $E4 $BD $D0 $E1 $A5 -$B8 $85 $24 $A5 $B9 $85 $25 $A5 -$28 $05 $29 $F0 $17 $A5 $28 $91 -$BC $C8 $A5 $29 $91 $BC $C8 $84 -$B6 $20 $14 $06 $08 $A4 $B6 $91 -$BC $28 $D0 $F2 $4C $CC $04 $20 -$54 $05 $B5 $03 $29 $80 $F0 $02 -$A9 $FF $85 $BC $85 $BD $48 $75 -$02 $95 $02 $68 $48 $75 $03 $95 -$03 $68 $55 $01 $85 $BB $10 $03 -$20 $43 $0A $A0 $11 $B5 $00 $15 -$01 $D0 $03 $4C $14 $05 $38 $A5 -$BC $F5 $00 $48 $A5 $BD $F5 $01 -$48 $45 $BD $30 $0A $68 $85 $BD -$68 $85 $BC $38 $4C $32 $0A $68 -$68 $18 $36 $02 $36 $03 $26 $BC -$26 $BD $88 $D0 $D9 $A5 $BB $10 -$0D $A6 $C1 $38 $98 $F5 $00 $95 -$00 $98 $F5 $01 $95 $01 $60 $20 -$41 $0A $20 $54 $05 $B5 $00 $75 -$02 $95 $02 $B5 $01 $75 $03 $95 -$03 $60 $20 $54 $05 $A0 $10 $B5 -$02 $85 $BC $B5 $03 $85 $BD $16 -$02 $36 $03 $26 $BC $26 $BD $90 -$0D $18 $B5 $02 $75 $00 $95 $02 -$B5 $03 $75 $01 $95 $03 $88 $D0 -$E6 $60 $20 $95 $07 $AA $B5 $00 -$B4 $01 $C6 $C1 $A6 $C1 $94 $00 -$4C $87 $07 $A2 $7D $20 $56 $05 -$B5 $01 $48 $B5 $00 $48 $20 $95 -$07 $AA $68 $95 $00 $68 $95 $01 -$60 $20 $FD $0A $A5 $BC $85 $2A -$A5 $BD $85 $2B $60 $A2 $2C $D0 -$02 $A2 $2E $B5 $00 $C9 $80 $B0 -$0D $B5 $01 $D0 $09 $A5 $2C $85 -$2E $A5 $2D $85 $2F $60 $A5 $2C -$A4 $2E $84 $2C $85 $2E $A5 $2D -$A4 $2F $84 $2D $85 $2F $A0 $00 -$60 $A5 $28 $85 $BC $A5 $29 $85 -$BD $20 $9C $05 $A5 $C6 $85 $26 -$A5 $C7 $85 $27 $60 $B1 $C6 $85 -$BC $20 $08 $0B $B1 $C6 $85 $BD -$E6 $C6 $D0 $02 $E6 $C7 $A5 $22 -$C5 $C6 $A5 $23 $E5 $C7 $B0 $E4 -$4C $14 $05 $20 $24 $0B $85 $BC -$98 $4C $82 $07 $20 $FC $08 $A5 -$BC $85 $B6 $20 $FC $08 $A5 $BD -$85 $B7 $A4 $BC $20 $FC $08 $A6 -$B7 $A5 $B6 $18 $6C $BC $00 $20 -$42 $0B $20 $F9 $06 $4C $87 $07 -$86 $2D $E0 $00 $60 $A0 $02 $84 -$BC $A0 $29 $84 $BD $A0 $00 $B1 -$BC $C9 $08 $D0 $03 $4C $0B $0A -$60 $20 $09 $04 $A9 $FF $2C $11 -$04 $30 $02 $A9 $00 $4C $09 $04 -$24 $3A $91 $27 $10 $E1 $59 $C5 -$2A $56 $10 $11 $2C $8B $4C $45 -$D4 $A0 $80 $BD $30 $BC $E0 $13 -$1D $94 $47 $CF $88 $54 $CF $30 -$BC $E0 $10 $11 $16 $80 $53 $55 -$C2 $30 $BC $E0 $14 $16 $90 $50 -$D2 $83 $49 $4E $D4 $E5 $71 $88 -$BB $E1 $1D $8F $A2 $21 $58 $6F -$83 $AC $22 $55 $83 $BA $24 $93 -$E0 $23 $1D $30 $BC $20 $48 $91 -$49 $C6 $30 $BC $31 $34 $30 $BC -$84 $54 $48 $45 $CE $1C $1D $38 -$0D $9A $49 $4E $50 $55 $D4 $A0 -$10 $E7 $24 $3F $20 $91 $27 $E1 -$59 $81 $AC $30 $BC $13 $11 $82 -$AC $4D $E0 $1D $89 $52 $45 $54 -$55 $52 $CE $E0 $15 $1D $85 $45 -$4E $C4 $E0 $2D $98 $4C $49 $53 -$D4 $EC $24 $00 $00 $00 $00 $0A -$80 $1F $24 $93 $23 $1D $30 $BC -$E1 $50 $80 $AC $59 $85 $52 $55 -$CE $38 $0A $86 $43 $4C $45 $41 -$D2 $2B $84 $52 $45 $CD $1D $A0 -$80 $BD $38 $14 $85 $AD $30 $D3 -$17 $64 $81 $AB $30 $D3 $85 $AB -$30 $D3 $18 $5A $85 $AD $30 $D3 -$19 $54 $2F $30 $E2 $85 $AA $30 -$E2 $1A $5A $85 $AF $30 $E2 $1B -$54 $2F $98 $52 $4E $C4 $0A $80 -$80 $12 $0A $09 $29 $1A $0A $1A -$85 $18 $13 $09 $80 $12 $01 $0B -$31 $30 $61 $72 $0B $04 $02 $03 -$05 $03 $1B $1A $19 $0B $09 $06 -$0A $00 $00 $1C $17 $2F $8F $55 -$53 $D2 $80 $A8 $30 $BC $31 $2A -$31 $2A $80 $A9 $2E $2F $A2 $12 -$2F $C1 $2F $80 $A8 $30 $BC $80 -$A9 $2F $83 $AC $38 $BC $0B $2F -$80 $A8 $52 $2F $84 $BD $09 $02 -$2F $8E $BC $84 $BD $09 $93 $2F -$84 $BE $09 $05 $2F $09 $91 $2F -$80 $BE $84 $BD $09 $06 $2F $84 -$BC $09 $95 $2F $09 $04 $2F $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$EA $EA $EA $EA $EA $EA $EA $EA -$EA $EA $EA $EA $EA $20 $0D $0F -$A0 $00 $20 $1D $0F $20 $2C $0F -$C9 $43 $D0 $03 $4C $85 $04 $C9 -$57 $D0 $03 $4C $BD $04 $A2 $2F -$20 $1D $0F $4C $05 $0D $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$4F $4D $45 $47 $41 $20 $4D $49 -$43 $52 $4F $20 $53 $59 $53 $54 -$45 $4D $53 $0D $0A $4D $4B $48 -$42 $43 $2D $38 $2D $52 $31 $20 -$54 $49 $4E $59 $20 $42 $41 $53 -$49 $43 $20 $36 $35 $30 $32 $20 -$50 $4F $52 $54 $0D $0A $56 $65 -$72 $73 $69 $6F $6E $3A $20 $31 -$2E $30 $2E $32 $2C $20 $31 $2F -$31 $31 $2F $32 $30 $31 $32 $0D -$0A $28 $4E $4F $54 $45 $3A $20 -$55 $73 $65 $20 $63 $61 $70 $73 -$20 $66 $6F $72 $20 $42 $61 $73 -$69 $63 $29 $0D $0A $42 $6F $6F -$74 $20 $28 $5B $43 $5D $6F $6C -$64 $2F $5B $57 $5D $61 $72 $6D -$29 $3F $20 $07 $FF $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$86 $C3 $B1 $C2 $48 $C8 $B1 $C2 -$AA $68 $A8 $8A $60 $A2 $19 $A9 -$0D $20 $31 $0F $A9 $0A $20 $31 -$0F $CA $D0 $FA $60 $B9 $00 $0E -$C9 $FF $F0 $07 $20 $31 $0F $C8 -$4C $1D $0F $60 $AD $00 $E0 $F0 -$FB $85 $FE $C9 $FF $F0 $1E $C9 -$00 $F0 $1A $C9 $91 $F0 $16 $C9 -$93 $F0 $12 $C9 $80 $F0 $0E $4C -$50 $0F $20 $F0 $FF $A5 $FE $60 -$A5 $FE $8D $00 $E0 $60 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 -$00 $00 $00 $00 $00 $00 $00 $00 - +; Tiny Basic for MKBASIC 6502 emulator. +; Run address: $0CF0 +; I/O emulation: $E000 +ORG +$0400 +$4C $85 $04 $4C $BD $04 $4C $2C +$0F $4C $31 $0F $EA $18 $60 $5F +$18 $80 $00 $20 $86 $C3 $90 $05 +$86 $C3 $91 $C2 $60 $B1 $C2 $A0 +$00 $60 $62 $05 $64 $05 $D8 $05 +$05 $06 $33 $06 $FD $05 $9F $07 +$42 $0B $3F $0B $7A $07 $FC $08 +$95 $07 $9F $07 $9F $07 $BD $0A +$C1 $0A $8A $0A $9B $0A $E9 $0A +$61 $07 $51 $07 $41 $0A $52 $0A +$4F $0A $62 $0A $E7 $09 $CD $06 +$06 $07 $9F $07 $15 $08 $A7 $07 +$B7 $06 $BF $06 $83 $08 $A1 $06 +$9F $07 $9F $07 $A8 $08 $4F $0B +$4D $0B $07 $09 $AA $04 $37 $07 +$BD $04 $1B $0B $B1 $0A $20 $41 +$54 $20 $80 $70 $0B $A9 $00 $85 +$20 $85 $22 $A9 $1C $85 $21 $85 +$23 $A0 $01 $B1 $22 $AA $49 $FF +$91 $22 $D1 $22 $08 $8A $91 $22 +$E6 $22 $D0 $02 $E6 $23 $28 $F0 +$EA $88 $D8 $A5 $20 $6D $13 $04 +$85 $24 $98 $65 $21 $85 $25 $98 +$91 $20 $C8 $91 $20 $A5 $22 $85 +$C6 $85 $26 $A5 $23 $85 $C7 $85 +$27 $20 $87 $08 $AD $83 $04 $85 +$2A $AD $84 $04 $85 $2B $A9 $80 +$85 $C1 $A9 $30 $85 $C0 $A2 $00 +$86 $BE $86 $C2 $CA $9A $D8 $20 +$F9 $06 $20 $F2 $04 $4C $E6 $04 +$83 $65 $C9 $30 $B0 $7B $C9 $08 +$90 $0C $0A $AA $BD $1F $04 $48 +$BD $1E $04 $48 $08 $40 $65 $C1 +$AA $B1 $C1 $48 $B5 $00 $91 $C1 +$68 $95 $00 $60 $20 $87 $08 $A9 +$21 $20 $09 $04 $A5 $2A $38 $ED +$83 $04 $AA $A5 $2B $ED $84 $04 +$20 $A0 $07 $A5 $BE $F0 $12 $A9 +$7E $85 $2A $A9 $20 $85 $2B $20 +$A1 $06 $A6 $28 $A5 $29 $20 $A0 +$07 $A9 $07 $20 $09 $04 $20 $87 +$08 $A5 $26 $85 $C6 $A5 $27 $85 +$C7 $4C $CC $04 $A2 $7C $E4 $C1 +$90 $BA $A6 $C1 $E6 $C1 $E6 $C1 +$18 $60 $C6 $BD $A5 $BD $F0 $AC +$A5 $BC $85 $2A $A5 $BD $85 $2B +$60 $C9 $40 $B0 $43 $48 $20 $F9 +$06 $6D $83 $04 $85 $BC $68 $48 +$29 $07 $6D $84 $04 $85 $BD $68 +$29 $08 $D0 $DC $A5 $BC $A6 $2A +$85 $2A $86 $BC $A5 $BD $A6 $2B +$85 $2B $86 $BD $A5 $C6 $E9 $01 +$85 $C6 $B0 $02 $C6 $C7 $C5 $24 +$A5 $C7 $E5 $25 $90 $AA $A5 $BC +$91 $C6 $C8 $A5 $BD $91 $C6 $60 +$48 $4A $4A $4A $4A $29 $0E $AA +$68 $C9 $60 $29 $1F $B0 $02 $09 +$E0 $18 $F0 $07 $65 $2A $85 $BC +$98 $65 $2B $85 $BD $4C $FC $04 +$A5 $2C $85 $B8 $A5 $2D $85 $B9 +$20 $25 $06 $20 $14 $06 $51 $2A +$AA $20 $F9 $06 $8A $F0 $F1 $0A +$F0 $12 $A5 $B8 $85 $2C $A5 $B9 +$85 $2D $4C $64 $05 $20 $25 $06 +$C9 $0D $D0 $F6 $60 $20 $25 $06 +$C9 $5B $B0 $EE $C9 $41 $90 $EA +$0A $20 $87 $07 $A0 $00 $B1 $2C +$E6 $2C $D0 $02 $E6 $2D $C9 $0D +$18 $60 $20 $14 $06 $B1 $2C $C9 +$20 $F0 $F7 $C9 $3A $18 $10 $02 +$C9 $30 $60 $20 $25 $06 $90 $C2 +$84 $BC $84 $BD $A5 $BC $A6 $BD +$06 $BC $26 $BD $06 $BC $26 $BD +$18 $65 $BC $85 $BC $8A $65 $BD +$06 $BC $2A $85 $BD $20 $14 $06 +$29 $0F $65 $BC $85 $BC $98 $65 +$BD $85 $BD $20 $25 $06 $B0 $D4 +$4C $80 $07 $20 $FC $08 $A5 $BC +$05 $BD $F0 $48 $A5 $20 $85 $2C +$A5 $21 $85 $2D $20 $6D $07 $F0 +$12 $A5 $28 $C5 $BC $A5 $29 $E5 +$BD $B0 $08 $20 $14 $06 $D0 $FB +$4C $7C $06 $A5 $28 $45 $BC $D0 +$04 $A5 $29 $45 $BD $60 $20 $A6 +$06 $20 $F9 $06 $10 $F8 $E6 $BF +$30 $03 $4C $09 $04 $C6 $BF $60 +$C9 $22 $F0 $FB $20 $A6 $06 $20 +$14 $06 $D0 $F4 $4C $14 $05 $A9 +$20 $20 $A6 $06 $A5 $BF $29 $87 +$30 $E5 $D0 $F3 $60 $A2 $7B $20 +$56 $05 $E6 $C1 $E6 $C1 $E6 $C1 +$38 $B5 $03 $F5 $00 $95 $00 $B5 +$04 $F5 $01 $50 $04 $49 $80 $09 +$01 $30 $0A $D0 $04 $15 $00 $F0 +$02 $56 $02 $56 $02 $56 $02 $90 +$0C $A0 $00 $B1 $2A $E6 $2A $D0 +$02 $E6 $2B $09 $00 $60 $A5 $BE +$F0 $28 $20 $14 $06 $D0 $FB $20 +$6D $07 $F0 $1B $20 $4C $07 $20 +$0C $04 $B0 $09 $A5 $C4 $85 $2A +$A5 $C5 $85 $2B $60 $AD $83 $04 +$85 $2A $AD $84 $04 $85 $2B $4C +$14 $05 $85 $BF $4C $49 $05 $A5 +$20 $85 $2C $A5 $21 $85 $2D $20 +$6D $07 $F0 $EB $A5 $2A $85 $C4 +$A5 $2B $85 $C5 $A9 $01 $85 $BE +$60 $20 $6B $06 $F0 $BE $A5 $BC +$85 $28 $A5 $BD $85 $29 $4C $14 +$05 $20 $FD $0A $20 $FA $0A $20 +$74 $06 $D0 $EA $60 $20 $14 $06 +$85 $28 $20 $14 $06 $85 $29 $05 +$28 $60 $20 $FC $08 $20 $80 $07 +$A5 $BD $20 $87 $07 $A5 $BC $A6 +$C1 $CA $95 $00 $86 $C1 $E4 $C0 +$D0 $0D $4C $14 $05 $A6 $C1 $E0 +$80 $10 $F7 $B5 $00 $E6 $C1 $60 +$85 $BD $86 $BC $4C $B8 $07 $A6 +$C1 $B5 $01 $10 $08 $20 $41 $0A +$A9 $2D $20 $A6 $06 $20 $FC $08 +$A9 $1F $85 $B8 $85 $BA $A9 $2A +$85 $B9 $85 $BB $A6 $BC $A4 $BD +$38 $E6 $B8 $8A $E9 $10 $AA $98 +$E9 $27 $A8 $B0 $F4 $C6 $B9 $8A +$69 $E8 $AA $98 $69 $03 $A8 $90 +$F4 $8A $38 $E6 $BA $E9 $64 $B0 +$F9 $88 $10 $F6 $C6 $BB $69 $0A +$90 $FA $09 $30 $85 $BC $A9 $20 +$85 $BD $A2 $FB $86 $C3 $B5 $BD +$05 $BD $C9 $20 $F0 $09 $A0 $30 +$84 $BD $05 $BD $20 $A6 $06 $A6 +$C3 $E8 $D0 $E8 $60 $A5 $2D $48 +$A5 $2C $48 $A5 $20 $85 $2C $A5 +$21 $85 $2D $A5 $24 $A6 $25 $20 +$5B $08 $F0 $03 $20 $5B $08 $A5 +$2C $38 $E5 $B6 $A5 $2D $E5 $B7 +$B0 $42 $20 $6D $07 $F0 $3D $A6 +$28 $A5 $29 $20 $A0 $07 $A9 $20 +$20 $A6 $06 $20 $0C $04 $B0 $2C +$20 $14 $06 $D0 $F3 $20 $83 $08 +$4C $2F $08 $85 $B6 $E6 $B6 $D0 +$01 $E8 $86 $B7 $A4 $C1 $C0 $80 +$F0 $18 $20 $6B $06 $A5 $2C $A6 +$2D $38 $E9 $02 $B0 $01 $CA $85 +$2C $4C $48 $0B $68 $85 $2C $68 +$85 $2D $60 $A5 $BF $30 $FB $A9 +$0D $20 $09 $04 $AD $11 $04 $29 +$7F $85 $BF $F0 $07 $20 $64 $0B +$C6 $BF $D0 $F9 $A9 $0A $4C $61 +$0B $AC $12 $04 $84 $BF $B0 $0B +$A9 $30 $85 $2C $85 $C0 $84 $2D +$20 $80 $07 $45 $80 $85 $80 $20 +$06 $04 $A0 $00 $A6 $C0 $29 $7F +$F0 $F1 $C9 $7F $F0 $ED $C9 $13 +$F0 $DA $C9 $0A $F0 $D3 $CD $10 +$04 $F0 $09 $CD $0F $04 $D0 $0A +$E0 $30 $D0 $16 $A6 $2C $84 $BF +$A9 $0D $E4 $C1 $30 $08 $A9 $07 +$20 $A6 $06 $4C $B3 $08 $95 $00 +$E8 $E8 $CA $86 $C0 $C9 $0D $D0 +$BA $20 $83 $08 $20 $95 $07 $85 +$BC $20 $95 $07 $85 $BD $60 $20 +$D6 $0A $20 $6B $06 $08 $20 $6D +$08 $85 $B8 $86 $B9 $A5 $BC $85 +$B6 $A5 $BD $85 $B7 $A2 $00 $28 +$D0 $0B $20 $6D $07 $CA $CA $CA +$20 $14 $06 $D0 $FA $84 $28 $84 +$29 $20 $D6 $0A $A9 $0D $D1 $2C +$F0 $11 $E8 $E8 $E8 $E8 $C8 $D1 +$2C $D0 $FA $A5 $B6 $85 $28 $A5 +$B7 $85 $29 $A5 $B8 $85 $BC $A5 +$B9 $85 $BD $18 $A0 $00 $8A $F0 +$6E $10 $29 $65 $2E $85 $B8 $A5 +$2F $E9 $00 $85 $B9 $B1 $2E $91 +$B8 $A6 $2E $E4 $24 $D0 $06 $A5 +$2F $C5 $25 $F0 $4A $E8 $86 $2E +$D0 $02 $E6 $2F $E6 $B8 $D0 $E5 +$E6 $B9 $D0 $E1 $65 $24 $85 $B8 +$85 $2E $98 $65 $25 $85 $B9 $85 +$2F $A5 $2E $E5 $C6 $A5 $2F $E5 +$C7 $90 $05 $C6 $2A $4C $14 $05 +$B1 $24 $91 $2E $A6 $24 $D0 $02 +$C6 $25 $C6 $24 $A6 $2E $D0 $02 +$C6 $2F $CA $86 $2E $E4 $BC $D0 +$E7 $A6 $2F $E4 $BD $D0 $E1 $A5 +$B8 $85 $24 $A5 $B9 $85 $25 $A5 +$28 $05 $29 $F0 $17 $A5 $28 $91 +$BC $C8 $A5 $29 $91 $BC $C8 $84 +$B6 $20 $14 $06 $08 $A4 $B6 $91 +$BC $28 $D0 $F2 $4C $CC $04 $20 +$54 $05 $B5 $03 $29 $80 $F0 $02 +$A9 $FF $85 $BC $85 $BD $48 $75 +$02 $95 $02 $68 $48 $75 $03 $95 +$03 $68 $55 $01 $85 $BB $10 $03 +$20 $43 $0A $A0 $11 $B5 $00 $15 +$01 $D0 $03 $4C $14 $05 $38 $A5 +$BC $F5 $00 $48 $A5 $BD $F5 $01 +$48 $45 $BD $30 $0A $68 $85 $BD +$68 $85 $BC $38 $4C $32 $0A $68 +$68 $18 $36 $02 $36 $03 $26 $BC +$26 $BD $88 $D0 $D9 $A5 $BB $10 +$0D $A6 $C1 $38 $98 $F5 $00 $95 +$00 $98 $F5 $01 $95 $01 $60 $20 +$41 $0A $20 $54 $05 $B5 $00 $75 +$02 $95 $02 $B5 $01 $75 $03 $95 +$03 $60 $20 $54 $05 $A0 $10 $B5 +$02 $85 $BC $B5 $03 $85 $BD $16 +$02 $36 $03 $26 $BC $26 $BD $90 +$0D $18 $B5 $02 $75 $00 $95 $02 +$B5 $03 $75 $01 $95 $03 $88 $D0 +$E6 $60 $20 $95 $07 $AA $B5 $00 +$B4 $01 $C6 $C1 $A6 $C1 $94 $00 +$4C $87 $07 $A2 $7D $20 $56 $05 +$B5 $01 $48 $B5 $00 $48 $20 $95 +$07 $AA $68 $95 $00 $68 $95 $01 +$60 $20 $FD $0A $A5 $BC $85 $2A +$A5 $BD $85 $2B $60 $A2 $2C $D0 +$02 $A2 $2E $B5 $00 $C9 $80 $B0 +$0D $B5 $01 $D0 $09 $A5 $2C $85 +$2E $A5 $2D $85 $2F $60 $A5 $2C +$A4 $2E $84 $2C $85 $2E $A5 $2D +$A4 $2F $84 $2D $85 $2F $A0 $00 +$60 $A5 $28 $85 $BC $A5 $29 $85 +$BD $20 $9C $05 $A5 $C6 $85 $26 +$A5 $C7 $85 $27 $60 $B1 $C6 $85 +$BC $20 $08 $0B $B1 $C6 $85 $BD +$E6 $C6 $D0 $02 $E6 $C7 $A5 $22 +$C5 $C6 $A5 $23 $E5 $C7 $B0 $E4 +$4C $14 $05 $20 $24 $0B $85 $BC +$98 $4C $82 $07 $20 $FC $08 $A5 +$BC $85 $B6 $20 $FC $08 $A5 $BD +$85 $B7 $A4 $BC $20 $FC $08 $A6 +$B7 $A5 $B6 $18 $6C $BC $00 $20 +$42 $0B $20 $F9 $06 $4C $87 $07 +$86 $2D $E0 $00 $60 $A0 $02 $84 +$BC $A0 $29 $84 $BD $A0 $00 $B1 +$BC $C9 $08 $D0 $03 $4C $0B $0A +$60 $20 $09 $04 $A9 $FF $2C $11 +$04 $30 $02 $A9 $00 $4C $09 $04 +$24 $3A $91 $27 $10 $E1 $59 $C5 +$2A $56 $10 $11 $2C $8B $4C $45 +$D4 $A0 $80 $BD $30 $BC $E0 $13 +$1D $94 $47 $CF $88 $54 $CF $30 +$BC $E0 $10 $11 $16 $80 $53 $55 +$C2 $30 $BC $E0 $14 $16 $90 $50 +$D2 $83 $49 $4E $D4 $E5 $71 $88 +$BB $E1 $1D $8F $A2 $21 $58 $6F +$83 $AC $22 $55 $83 $BA $24 $93 +$E0 $23 $1D $30 $BC $20 $48 $91 +$49 $C6 $30 $BC $31 $34 $30 $BC +$84 $54 $48 $45 $CE $1C $1D $38 +$0D $9A $49 $4E $50 $55 $D4 $A0 +$10 $E7 $24 $3F $20 $91 $27 $E1 +$59 $81 $AC $30 $BC $13 $11 $82 +$AC $4D $E0 $1D $89 $52 $45 $54 +$55 $52 $CE $E0 $15 $1D $85 $45 +$4E $C4 $E0 $2D $98 $4C $49 $53 +$D4 $EC $24 $00 $00 $00 $00 $0A +$80 $1F $24 $93 $23 $1D $30 $BC +$E1 $50 $80 $AC $59 $85 $52 $55 +$CE $38 $0A $86 $43 $4C $45 $41 +$D2 $2B $84 $52 $45 $CD $1D $A0 +$80 $BD $38 $14 $85 $AD $30 $D3 +$17 $64 $81 $AB $30 $D3 $85 $AB +$30 $D3 $18 $5A $85 $AD $30 $D3 +$19 $54 $2F $30 $E2 $85 $AA $30 +$E2 $1A $5A $85 $AF $30 $E2 $1B +$54 $2F $98 $52 $4E $C4 $0A $80 +$80 $12 $0A $09 $29 $1A $0A $1A +$85 $18 $13 $09 $80 $12 $01 $0B +$31 $30 $61 $72 $0B $04 $02 $03 +$05 $03 $1B $1A $19 $0B $09 $06 +$0A $00 $00 $1C $17 $2F $8F $55 +$53 $D2 $80 $A8 $30 $BC $31 $2A +$31 $2A $80 $A9 $2E $2F $A2 $12 +$2F $C1 $2F $80 $A8 $30 $BC $80 +$A9 $2F $83 $AC $38 $BC $0B $2F +$80 $A8 $52 $2F $84 $BD $09 $02 +$2F $8E $BC $84 $BD $09 $93 $2F +$84 $BE $09 $05 $2F $09 $91 $2F +$80 $BE $84 $BD $09 $06 $2F $84 +$BC $09 $95 $2F $09 $04 $2F $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$EA $EA $EA $EA $EA $EA $EA $EA +$EA $EA $EA $EA $EA $20 $0D $0F +$A0 $00 $20 $1D $0F $20 $2C $0F +$C9 $43 $D0 $03 $4C $85 $04 $C9 +$57 $D0 $03 $4C $BD $04 $A2 $2F +$20 $1D $0F $4C $05 $0D $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$4F $4D $45 $47 $41 $20 $4D $49 +$43 $52 $4F $20 $53 $59 $53 $54 +$45 $4D $53 $0D $0A $4D $4B $48 +$42 $43 $2D $38 $2D $52 $31 $20 +$54 $49 $4E $59 $20 $42 $41 $53 +$49 $43 $20 $36 $35 $30 $32 $20 +$50 $4F $52 $54 $0D $0A $56 $65 +$72 $73 $69 $6F $6E $3A $20 $31 +$2E $30 $2E $32 $2C $20 $31 $2F +$31 $31 $2F $32 $30 $31 $32 $0D +$0A $28 $4E $4F $54 $45 $3A $20 +$55 $73 $65 $20 $63 $61 $70 $73 +$20 $66 $6F $72 $20 $42 $61 $73 +$69 $63 $29 $0D $0A $42 $6F $6F +$74 $20 $28 $5B $43 $5D $6F $6C +$64 $2F $5B $57 $5D $61 $72 $6D +$29 $3F $20 $07 $FF $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$86 $C3 $B1 $C2 $48 $C8 $B1 $C2 +$AA $68 $A8 $8A $60 $A2 $19 $A9 +$0D $20 $31 $0F $A9 $0A $20 $31 +$0F $CA $D0 $FA $60 $B9 $00 $0E +$C9 $FF $F0 $07 $20 $31 $0F $C8 +$4C $1D $0F $60 $AD $00 $E0 $F0 +$FB $85 $FE $C9 $FF $F0 $1E $C9 +$00 $F0 $1A $C9 $91 $F0 $16 $C9 +$93 $F0 $12 $C9 $80 $F0 $0E $4C +$50 $0F $20 $F0 $FF $A5 $FE $60 +$A5 $FE $8D $00 $E0 $60 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +$00 $00 $00 $00 $00 $00 $00 $00 +