Atom Kernel Routines part 2


; F802 Print A as two hex digits. A destroyed.

F802_print_hex_byte:

F802  48        pha 		; save A
F803  4a        lsr A
F804  4a        lsr A
F805  4a        lsr A
F806  4a        lsr A
F807  20 0b f8  jsr $F80B_print_hex_nibble	
F80A  68        pla		; restore A to get low nibble, drop through

F80B_print_hex_nibble:

F80B  29 0f     and #$0F	; clear high nibble
F80D  c9 0a     cmp #10		; if >= 10 
F80F  90 02     bcc $F813
F811  69 06     adc #6		; then add six
F813  69 30     adc #'0'		; add ASCII ZERO $30
F815  4c f4 ff  jmp $FFF4_OSWRCH	; vectored print character

; Data from $F818 to $F84E (55 bytes)
F818  .BYTE 20, 76, f8, a2, 00, c9, 22, f0, 06, e8  ;  v...."...
F822  .BYTE d0, 1b, 4c, 7d, fa, c8, b9, 00, 01, c9  ; ..L}......
F82C  .BYTE 0d, f0, f5, 9d, 40, 01, e8, c9, 22, d0  ; ....@...".
F836  .BYTE f0, c8, b9, 00, 01, c9, 22, f0, e8, a9  ; ......"...
F840  .BYTE 0d, 9d, 3f, 01, a9, 40, 85, c9, a9, 01  ; ..?..@....
F84A  .BYTE 85, ca, a2, c9, 60                      ; ....`
F84F  a0 00     ldy #$00
F851  b5 00     lda $00,X
F853  99 c9 00  sta $00C9,Y
F856  e8        inx 
F857  c8        iny 
F858  c0 0a     cpy #$0A
F85A  90 f5     bcc $F851
F85C  a0 ff     ldy #$FF
F85E  a9 0d     lda #$0D
F860  c8        iny 
F861  c0 0e     cpy #$0E
F863  b0 07     bcs $F86C
F865  d1 c9     cmp ($C9),Y
F867  d0 f7     bne $F860
F869  c0 00     cpy #$00
F86B  60        rts 
F86C  20 d1 f7  jsr $F7D1_Print_ASCII_string
F86F  .byte	"NAME", 
	ea	NOP
	00	BRK
; search buffer for non-space char
F875  c8        iny 
F876  b9 00 01  lda INPUT_LINE_BUFFER,Y
F879  c9 20     cmp #SP
F87B  f0 f8     beq $F875
F87D  60        rts 

F87E _ascii_to_bin:

; Convert ASCII hex char in A to binary. A destroyed. Returns C=1 if char was not ASCII '0' to '9'
F87E_ascii_to_bin  c9 30     cmp #$30
F880  90 0f     bcc $F891
F882  c9 3a     cmp #$3A
F884  90 08     bcc $F88E
F886  e9 07     sbc #$07
F888  90 07     bcc $F891
F88A  c9 40     cmp #$40
F88C  b0 02     bcs $F890
F88E  29 0f     and #$0F
F890  60        rts
F891  38        sec 
F892  60        rts 

; Data from $F893 to $F89D (11 bytes)
F893  .BYTE a9, 00, 95, 00, 95, 01, 95, 02, 20, 76
F89D  .BYTE f8

F89E Converts ASCII hex string at INPUT_LINE_BUFFER,Y to 16 bit binary in 0,X and 1,X. Uses 2,X. Destroys A. 
Returns with Y pointing to first non-hex character, 
Z=1 if first character is not ASCII '0' to '9'
F89E  b9 00 01  lda INPUT_LINE_BUFFER,Y
F8A1  20 7e f8  jsr $F87E_ascii_to_bin
F8A4  b0 15     bcs $F8BB
F8A6  0a        asl A
F8A7  0a        asl A
F8A8  0a        asl A
F8A9  0a        asl A
F8AA  94 02     sty $02,X
F8AC  a0 04     ldy #$04
F8AE  0a        asl A
F8AF  36 00     rol $00,X
F8B1  36 01     rol $01,X
F8B3  88        dey 
F8B4  d0 f8     bne $F8AE
F8B6  b4 02     ldy $02,X
F8B8  c8        iny 
F8B9  d0 e3     bne $F89E
F8BB  b5 02     lda $02,X
F8BD  60        rts 

F8BE  .BYTE "CAT", fa, 2a, 
F8C3  .BYTE "LOAD", f9  ; .*.
F8C8  .BYTE "XSAVE", fa, bb, 
F8CF  .BYTE "RUN", fa, 20
F8D4  .BYTE "MON", fa, 1a
F8D9  .BYTE "NOMON", fa, 19, 
F8E0  .BYTE "FLOAD", f9, 55
F8E7  .BYTE "DOS", 0d, e0, 00, f9, 26

F8EF_OSCLI: ; Operating System Command Line Interpreter

Interpret string starting at INPUT_LINE_BUFFER as an Operating System command.
Uses all registers. Legal commands are: 'CAT', 'LOAD', 'SAVE', 'RUN', 'MON', 'NOMON', 'FLOAD' and 'DOS'.
The latter causes a jump to E000

F8EF  a2 ff     ldx #$FF
F8F1  d8        cld 
F8F2  a0 00     ldy #$00
F8F4  84 dd     sty $DD
F8F6  20 76 f8  jsr $F876
F8F9  88        dey 
F8FA  c8        iny 
F8FB  e8        inx 
F8FC  bd be f8  lda $F8BE_str_CAT,X
F8FF  30 18     bmi $F919
F901  d9 00 01  cmp INPUT_LINE_BUFFER,Y
F904  f0 f4     beq $F8FA
F906  ca        dex 
F907  e8        inx 
F908  bd be f8  lda $F8BE_str_CAT,X
F90B  10 fa     bpl $F907
F90D  e8        inx 
F90E  b9 00 01  lda INPUT_LINE_BUFFER,Y
F911  c9 2e     cmp #$2E
F913  d0 dd     bne $F8F2
F915  c8        iny 
F916  ca        dex 
F917  b0 e3     bcs $F8FC
F919  85 ca     sta $CA
F91B  bd bf f8  lda $F8BF_str_AT,X
F91E  85 c9     sta $C9
F920  18        clc 
F921  a2 00     ldx #$00
F923  6c c9 00  jmp ($00C9)
F926  20 d1 f7  jsr $F7D1_Print_ASCII_string
	.byte	"COM?"
	ea	NOP
F92E  00        brk
F92F  20 8e fb  jsr $FB8E
F932  50 fa     bvc $F92E
F934  f0 f9     beq $F92F
F936  20 2b fc  jsr $FC2B
F939  a0 00     ldy #$00
F93B  20 d4 ff  jsr $FFD4_OSBGET
F93E  91 cb     sta ($CB),Y
F940  e6 cb     inc $CB
F942  d0 02     bne $F946
F944  e6 cc     inc $CC
F946  a2 d4     ldx #$D4
F948  20 08 fa  jsr $FA08
F94B  d0 ee     bne $F93B
F94D  38        sec 
F94E  66 dd     ror $DD
F950  18        clc 
F951  66 dd     ror $DD
F953  28        plp 
F954  60        rts

; Data from $F955 to $F96D (25 bytes)
F955  .BYTE 38, 66, dd, 20, 18, f8, a2, cb, 20, 93  ; 8f. .... .
F95F  .BYTE f8, f0, 04, a9, ff, 85, cd, 20, 76, fa  ; ....... v.
F969  .BYTE a2, c9, 6c, 0c, 02    

F96E_LOAD: ; Load cassette file.

;Enter with X pointing to the first of five data bytes in zero page RAM:  ; 
;0,X and 1,X pointing to the file name string, 
;2,X and 3,X pointing to the first byte to be loaded.
;4,X bit 7 should be 0 to use the file's start address
F96E  08        php 
F96F  78        sei 
F970  20 4f f8  jsr $F84F
F973  08        php 
F974  20 3e fc  jsr $FC3E
F977  28        plp 
F978  f0 b5     beq $F92F
F97A  a9 00     lda #$00
F97C  85 d0     sta $D0
F97E  85 d1     sta $D1
F980  20 a2 f9  jsr $F9A2
F983  90 c9     bcc $F94E
F985  e6 d0     inc $D0
F987  e6 cc     inc $CC
F989  d0 f5     bne $F980
F98B  18        clc 
F98C  90 c0     bcc $F94E
F98E  20 f4 ff  jsr $FFF4_OSWRCH
F991  c8        iny 
F992  b9 ed 00  lda $00ED,Y
F995  c9 0d     cmp #$0D
F997  d0 f5     bne $F98E
F999  c8        iny 
F99A  20 fd f7  jsr $F7FD
F99D  c0 0e     cpy #$0E
F99F  90 f8     bcc $F999
F9A1  60        rts 
F9A2  a9 00     lda #$00
F9A4  85 dc     sta $DC
F9A6  20 8e fb  jsr $FB8E
F9A9  50 f8     bvc $F9A3	branch to data???
F9AB  d0 f5     bne $F9A2
F9AD  20 c9 fb  jsr $FBC9
F9B0  08        php 
F9B1  20 e2 fb  jsr $FBE2
F9B4  28        plp 
F9B5  f0 10     beq $F9C7
F9B7  a5 db     lda $DB
F9B9  29 20     and #$20
F9BB  05 ea     ora $EA
F9BD  d0 e3     bne $F9A2
F9BF  20 92 f9  jsr $F992
F9C2  20 ed ff  jsr $FFED
F9C5  d0 db     bne $F9A2
F9C7  a2 02     ldx #$02
F9C9  a5 dd     lda $DD
F9CB  30 13     bmi $F9E0
F9CD  b5 cf     lda $CF,X
F9CF  d5 d8     cmp $D8,X
F9D1  b0 08     bcs $F9DB
F9D3  a9 05     lda #$05
F9D5  20 40 fc  jsr $FC40
F9D8  20 3e fc  jsr $FC3E
F9DB  d0 c5     bne $F9A2
F9DD  ca        dex 
F9DE  d0 ed     bne $F9CD
F9E0  20 2b fc  jsr $FC2B
F9E3  24 db     bit $DB
F9E5  50 0b     bvc $F9F2
F9E7  88        dey 
F9E8  c8        iny 
F9E9  20 d4 ff  jsr $FFD4_OSBGET
F9EC  91 cb     sta ($CB),Y
F9EE  c4 d8     cpy $D8
F9F0  d0 f6     bne $F9E8
F9F2  a5 dc     lda $DC
F9F4  85 ce     sta $CE
F9F6  20 d4 ff  jsr $FFD4_OSBGET
F9F9  c5 ce     cmp $CE
F9FB  f0 08     beq $FA05
F9FD  20 d1 f7  jsr $F7D1_Print_ASCII_string
FA00  53        .byte	"SUM"
FA03	ea	NOP
	00	BRK
FA05  26 db     rol $DB
FA07  60        rts 
FA08  f6 00     inc $00,X
FA0A  d0 02     bne $FA0E
FA0C  f6 01     inc $01,X
FA0E  b5 00     lda $00,X
FA10  d5 02     cmp $02,X
FA12  d0 04     bne $FA18	; rts
FA14  b5 01     lda $01,X
FA16  d5 03     cmp $03,X
FA18  60        rts 
; Data from $FA19 to $FA85 (109 bytes)
FA19  .BYTE ca, 20, 76, fa, 86, ea, 60, 20, 58, f9  ; . v...` X.
FA23  .BYTE 24, dd, 70, 4c, 6c, d6, 00, 08, 20, 76  ; $.pLl... v
FA2D  .BYTE fa, 20, 3e, fc, 20, 8e, fb, 70, 02, 28  ; . >. ..p.(
FA37  .BYTE 60, f0, 0a, a0, 00, 20, 99, f9, 20, ec  ; `.... .. .
FA41  .BYTE f7, d0, 19, 20, c9, fb, 20, e2, fb, 20  ; ... .. .. 
FA4B  .BYTE 92, f9, 20, ec, f7, 26, db, 10, 09, e8  ; .. ..&....
FA55  .BYTE 20, f1, f7, b5, fd, 20, 02, f8, 20, ed  ;  .... .. .
FA5F  .BYTE ff, d0, cf, 4c, ed, ff, 20, 93, f8, f0  ; ...L.. ...
FA69  .BYTE 13, 60, a2, cb, 20, 65, fa, 20, 76, fa  ; .`.. e. v.
FA73  .BYTE 6c, cb, 00, 20, 76, f8, c9, 0d, f0, a2  ; l.. v.....
FA7D  .BYTE 20, d1, f7, 53, 59, 4e, 3f, 	ea	NOP
	00	BRK      ;  ..SYN?..
FA86  38        sec 
FA87  a5 d1     lda $D1
FA89  e5 cf     sbc $CF
FA8B  48        pha 
FA8C  a5 d2     lda $D2
FA8E  e5 d0     sbc $D0
FA90  a8        tay 
FA91  68        pla 
FA92  18        clc 
FA93  65 cb     adc $CB
FA95  85 cd     sta $CD
FA97  98        tya 
FA98  65 cc     adc $CC
FA9A  85 ce     sta $CE
FA9C  a0 04     ldy #$04
FA9E  b9 ca 00  lda $00CA,Y
FAA1  20 d1 ff  jsr $FFD1_OSBPUT
FAA4  88        dey 
FAA5  d0 f7     bne $FA9E
FAA7  b1 cf     lda ($CF),Y
FAA9  20 d1 ff  jsr $FFD1_OSBPUT
FAAC  e6 cf     inc $CF
FAAE  d0 02     bne $FAB2
FAB0  e6 d0     inc $D0
FAB2  a2 cb     ldx #$CB
FAB4  20 08 fa  jsr $FA08
FAB7  d0 ee     bne $FAA7
FAB9  28        plp 
FABA  60        rts 

FABB  20 18 f8  jsr $F818
FABE  a2 cb     ldx #$CB
FAC0  20 65 fa  jsr $FA65
FAC3  a2 d1     ldx #$D1
FAC5  20 65 fa  jsr $FA65
FAC8  a2 cd     ldx #$CD
FACA  20 93 f8  jsr $F893
FACD  08        php 
FACE  a5 cb     lda $CB
FAD0  a6 cc     ldx $CC
FAD2  28        plp 
FAD3  d0 04     bne $FAD9
FAD5  85 cd     sta $CD
FAD7  86 ce     stx $CE
FAD9  85 cf     sta $CF
FADB  86 d0     stx $D0
FADD  20 76 fa  jsr $FA76
FAE0  a2 c9     ldx #$C9
FAE2  6c 0e 02  jmp (SAVVEC)      

FAE5
SAVE:
;Save cassette file

Enter with X pointing to the first of 10 data bytes in zero page RAM:  ; 
0,X and 1,X pointing to the file name string, 
2,X and 3,X pointing to the reload address
4,X and 5,X pointing to the execution address
6,X and 7,X pointing to the first byte to be saved
8,X and 9,X pointing to the last byte to be saved plus one
FAE5  08        php 
FAE6  78        sei 
FAE7  20 4f f8  jsr $F84F
FAEA  08        php 
FAEB  a9 06     lda #$06
FAED  20 40 fc  jsr $FC40
FAF0  a2 07     ldx #$07
FAF2  20 7a fb  jsr $FB7A
FAF5  28        plp 
FAF6  f0 8e     beq $FA86
FAF8  a2 04     ldx #$04
FAFA  b5 ce     lda $CE,X
FAFC  95 d2     sta $D2,X
FAFE  ca        dex 
FAFF  d0 f9     bne $FAFA
FB01  86 d0     stx $D0
FB03  86 d1     stx $D1
FB05  a5 d5     lda $D5
FB07  d0 02     bne $FB0B
FB09  c6 d6     dec $D6
FB0B  c6 d5     dec $D5
FB0D  18        clc 
FB0E  66 d2     ror $D2
FB10  38        sec 
FB11  a2 ff     ldx #$FF
FB13  a5 d5     lda $D5
FB15  e5 d3     sbc $D3
FB17  85 cf     sta $CF
FB19  a5 d6     lda $D6
FB1B  e5 d4     sbc $D4
FB1D  08        php 
FB1E  66 d2     ror $D2
FB20  28        plp 
FB21  90 06     bcc $FB29
FB23  18        clc 
FB24  f0 03     beq $FB29
FB26  86 cf     stx $CF
FB28  38        sec 
FB29  66 d2     ror $D2
FB2B  e8        inx 
FB2C  20 3b fb  jsr $FB3B
FB2F  e6 d0     inc $D0
FB31  e6 d4     inc $D4
FB33  e6 cc     inc $CC
FB35  26 d2     rol $D2
FB37  b0 d5     bcs $FB0E
FB39  28        plp 
FB3A  60        rts 

FB3B  a2 07     ldx #$07
FB3D  20 7a fb  jsr $FB7A
FB40  86 dc     stx $DC
FB42  a0 04     ldy #$04
FB44  a9 2a     lda #$2A
FB46  20 d1 ff  jsr $FFD1_OSBPUT
FB49  88        dey 
FB4A  d0 f8     bne $FB44
FB4C  b1 c9     lda ($C9),Y
FB4E  20 d1 ff  jsr $FFD1_OSBPUT
FB51  c8        iny 
FB52  c9 0d     cmp #$0D
FB54  d0 f6     bne $FB4C
FB56  a0 08     ldy #$08
FB58  b9 ca 00  lda $00CA,Y
FB5B  20 d1 ff  jsr $FFD1_OSBPUT
FB5E  88        dey 
FB5F  d0 f7     bne $FB58
FB61  20 81 fb  jsr $FB81
FB64  24 d2     bit $D2
FB66  50 0b     bvc $FB73
FB68  88        dey 
FB69  c8        iny 
FB6A  b1 d3     lda ($D3),Y
FB6C  20 d1 ff  jsr $FFD1_OSBPUT
FB6F  c4 cf     cpy $CF
FB71  d0 f6     bne $FB69
FB73  a5 dc     lda $DC
FB75  20 d1 ff  jsr $FFD1_OSBPUT
FB78  a2 04     ldx #$04
FB7A  8e 02 b0  stx PPI_PC
FB7D  a2 78     ldx #$78
FB7F  d0 02     bne $FB83
FB81  a2 1e     ldx #$1E

FB83_wait_x_60ths_of_a_second:

: Returns with X=0. Other registers preserved
FB83  20 66 fe  jsr $FE66_wait_for_flyback_start
FB86  ca        dex 
FB87  d0 fa     bne FB83_wait_x_60ths_of_a_second
FB89  60        rts 

FB8A  a2 06     ldx #$06
FB8C  d0 f5     bne $FB83
FB8E  2c 01 b0  bit PPI_PB	; loop
FB91  10 fb     bpl $FB8E
FB93  50 f9     bvc $FB8E
FB95  a0 00     ldy #$00
FB97  85 c3     sta $C3
FB99  a9 10     lda #$10
FB9B  85 c2     sta $C2
FB9D  2c 01 b0  bit PPI_PB
FBA0  10 0f     bpl $FBB1
FBA2  50 0d     bvc $FBB1
FBA4  20 bd fc  jsr $FCBD
FBA7  b0 ec     bcs $FB95
FBA9  c6 c3     dec $C3
FBAB  d0 f0     bne $FB9D
FBAD  c6 c2     dec $C2
FBAF  d0 ec     bne $FB9D
FBB1  70 01     bvs $FBB4
FBB3  60        rts 

FBB4  a0 04     ldy #$04
FBB6  08        php 
FBB7  20 e4 fb  jsr $FBE4
FBBA  28        plp 
FBBB  a0 04     ldy #$04
FBBD  a9 2a     lda #$2A
FBBF  d9 d3 00  cmp $00D3,Y
FBC2  d0 03     bne $FBC7
FBC4  88        dey 
FBC5  d0 f8     bne $FBBF
FBC7  60        rts 

FBC8  c8        iny 			; loop
FBC9  20 d4 ff  jsr $FFD4_OSBGET
FBCC  99 ed 00  sta $00ED,Y
FBCF  c9 0d     cmp #$0D
FBD1  d0 f5     bne $FBC8
FBD3  a0 ff     ldy #$FF
FBD5  c8        iny 
FBD6  b1 c9     lda ($C9),Y
FBD8  d9 ed 00  cmp $00ED,Y
FBDB  d0 ea     bne $FBC7		; rts
FBDD  c9 0d     cmp #$0D
FBDF  d0 f4     bne $FBD5
FBE1  60        rts 

FBE2  .BYTE a0, 08
FBE4  20 d4 ff  jsr $FFD4_OSBGET
FBE7  99 d3 00  sta $00D3,Y
FBEA  88        dey 
FBEB  d0 f7     bne $FBE4
FBED  60        rts 

FBEE
BGET:
; Get byte from tape

Return with it in A. X and Y preserved
Byte added to checksum at 00DC
FBEE  86 ec     stx $EC
FBF0  84 c3     sty $C3
FBF2  08        php 
FBF3  78        sei 
FBF4  a9 78     lda #$78
FBF6  85 c0     sta $C0
FBF8  20 bd fc  jsr $FCBD
FBFB  90 f7     bcc $FBF4
FBFD  e6 c0     inc $C0
FBFF  10 f7     bpl $FBF8
FC01  a9 53     lda #$53
FC03  85 c4     sta $C4
FC05  a2 00     ldx #$00
FC07  ac 02 b0  ldy PPI_PC
FC0A  20 cd fc  jsr $FCCD
FC0D  f0 00     beq $FC0F
FC0F  f0 01     beq $FC12
FC11  e8        inx 
FC12  c6 c4     dec $C4
FC14  d0 f4     bne $FC0A
FC16  e0 0c     cpx #$0C
FC18  66 c0     ror $C0
FC1A  90 e5     bcc $FC01
FC1C  a5 c0     lda $C0
FC1E  28        plp 
FC1F  a4 c3     ldy $C3
FC21  a6 ec     ldx $EC
FC23  48        pha 
FC24  18        clc 
FC25  65 dc     adc $DC
FC27  85 dc     sta $DC
FC29  68        pla 
FC2A  60        rts 
FC2B  a5 cd     lda $CD
FC2D  30 08     bmi $FC37
FC2F  a5 d4     lda $D4
FC31  85 cb     sta $CB
FC33  a5 d5     lda $D5
FC35  85 cc     sta $CC
FC37  60        rts 

FC38
FIND:

Prints 'PLAY TAPE' if flag C=1, or 'RECORD TAPE' if C=0.
Then waits for a key press before returning.
Returns with A=13, X and Y destroyed.
FC38  b0 04     bcs $FC3E
FC3A  a9 06     lda #$06
FC3C  d0 02     bne $FC40
FC3E  a9 04     lda #$04

Print 'REWIND TAPE', then waits for a key press
before returning with A=13. X and Y destroyed.
FC40  a2 07     ldx #$07
FC42  8e 02 b0  stx PPI_PC
FC45  24 ea     bit $EA
FC47  d0 2d     bne $FC76
FC49  c9 05     cmp #$05
FC4B  f0 16     beq $FC63
FC4D  b0 09     bcs $FC58

FC4F  20 d1 f7  jsr $F7D1_Print_ASCII_string
FC52  .BYTE "PLAY", 
FC56  d0 15     bne $FC6D

FC58  20 d1 f7  jsr $F7D1_Print_ASCII_string
FC5B	.byte "RECORD", d0, LF, 
FC63	20 d1 f7  jsr $F7D1_Print_ASCII_string
FC66  .BYTE "REWIND"
	ea	NOP	; end string
FC6D	20 d1 f7  jsr $F7D1_Print_ASCII_string
FC70  .BYTE " TAPE", 
	ea	NOP	; end string
	20 e3 ff  jsr FFE3
FC7A  .BYTE ed, ff, 

FC7C
BPUT:
; Put byte to tape.

; All registers preserved. Byte added to checksum at 00DC.
86, ec, 84, c3, 08, 78, 48, 
FC83  20 23 fc  jsr $FC23
FC86  85 c0     sta $C0
FC88  20 d8 fc  jsr $FCD8
FC8B  a9 0a     lda #$0A
FC8D  85 c1     sta $C1
FC8F  18        clc 
FC90  90 0a     bcc $FC9C
FC92  a2 07     ldx #$07
FC94  8e 02 b0  stx PPI_PC
FC97  20 da fc  jsr $FCDA
FC9A  30 13     bmi $FCAF
FC9C  a0 04     ldy #$04
FC9E  a9 04     lda #$04
FCA0  8d 02 b0  sta PPI_PC
FCA3  20 d8 fc  jsr $FCD8
FCA6  ee 02 b0  inc PPI_PC
FCA9  20 d8 fc  jsr $FCD8
FCAC  88        dey 
FCAD  d0 ef     bne $FC9E
FCAF  38        sec 
FCB0  66 c0     ror $C0
FCB2  c6 c1     dec $C1
FCB4  d0 da     bne $FC90
FCB6  a4 c3     ldy $C3
FCB8  a6 ec     ldx $EC
FCBA  68        pla 
FCBB  28        plp 
FCBC  60        rts 

FCBD  a2 00     ldx #$00
FCBF  ac 02 b0  ldy PPI_PC
FCC2  e8        inx 
FCC3  f0 07     beq $FCCC
FCC5  20 cd fc  jsr $FCCD
FCC8  f0 f8     beq $FCC2
FCCA  e0 08     cpx #$08
FCCC  60        rts 

FCCD  84 c5     sty $C5
FCCF  ad 02 b0  lda PPI_PC
FCD2  a8        tay 
FCD3  45 c5     eor $C5
FCD5  29 20     and #$20
FCD7  60        rts 

FCD8  a2 00     ldx #$00
FCDA  a9 10     lda #$10
FCDC  2c 02 b0  bit PPI_PC
FCDF  f0 fb     beq $FCDC
FCE1  2c 02 b0  bit PPI_PC
FCE4  d0 fb     bne $FCE1
FCE6  ca        dex 
FCE7  10 f3     bpl $FCDC
FCE9  60        rts 

; print character 
FCEA  c9 06     cmp #ACK	; (CTRL-F, 6)	Start screen* 
FCEC  f0 1d     beq FD0B_start_screen
FCEE  c9 15     cmp #NAK 	; (CTRL-U, 21)	End screen
FCF0  f0 1f     beq FD11_nak_handler
FCF2  a4 e0     ldy VE0_cursor_position_in_VDU_line
FCF4  30 23     bmi FD19_rts
FCF6  c9 1b     cmp #ESC	; (CTRL-[, 27)	Escape
FCF8  f0 11     beq FD0B_start_screen
FCFA  c9 07     cmp #BELL	; (CTRL-G, 7)	Bleep
FCFC  f0 1c     beq FD1A_bleep_handler
FCFE  20 44 fd  jsr $FD44
FD01  a2 0a     ldx #LF		; (CTRL-J, 10)	Linefeed
FD03  20 c5 fe  jsr $FEC5
FD06  d0 21     bne $FD29
FD08  4c b7 fe  jmp $FEB7
FD0B_start_screen:
FD0B  18        clc		; clear carry
FD0C  a2 00     ldx #$00	; clear A
FD0E  8e 00 b0  stx PPI_PA	; clear PPI_port_a, sets graphic mode zero (text)
FD11_nak_handler:
FD11  a2 02     ldx #$02
FD13  08        php 
FD14  16 de     asl VDE_p_start_of_line_containing_cursor,X
FD16  28        plp 
FD17  76 de     ror VDE_p_start_of_line_containing_cursor,X
FD19_rts:
FD19  60        rts 

FD1A_bleep_handler:

All registers destroyed.
FD1A  a9 05     lda #$05
FD1C  a8        tay 
FD1D  8d 03 b0  sta PPI_CTRL
FD20  ca        dex 
FD21  d0 fd     bne $FD20
FD23  49 01     eor #$01
FD25  c8        iny 
FD26  10 f5     bpl $FD1D
FD28  60        rts 

; convert from ascii to 6847VDG characters
FD29  c9 20     cmp #$20		; is A > $20
FD2B  90 17     bcc $FD44		; skip fwd, else
FD2D  69 1f     adc #$1F		; add $20 (nb includes carry=1)
FD2F  30 02     bmi $FD33		; if D7 set, 
FD31  49 60     eor #$60		; xor 0110_0000
; moves a line of chars during flyback
; this is no longer needed with snow-free display!
FD33  20 6b fe  jsr $FE6B_wait_for_flyback			; wait for snow-free time
FD36  91 de     sta (VDE_p_start_of_line_containing_cursor),Y
FD38  c8        iny 
FD39  c0 20     cpy #characters_per_line
FD3B  90 05     bcc $FD42
FD3D  20 ec fd  jsr $FDEC_scroll_screen_up
FD40  a0 00     ldy #$00
FD42  84 e0     sty VE0_cursor_position_in_VDU_line

FD44  48        pha 
FD45  20 6b fe  jsr $FE6B_wait_for_flyback
FD48  b1 de     lda (VDE_p_start_of_line_containing_cursor),Y
FD4A  45 e1     eor $E1
FD4C  91 de     sta (VDE_p_start_of_line_containing_cursor),Y
FD4E  68        pla 
FD4F  60        rts 
; Data from $FD50 to $FDEB (156 bytes)
FD50  .BYTE 20, 35, fe, a9, 20, 20, 6b, fe, 91, de  ;  5..  k...
FD5A  .BYTE 10, e6, 20, 35, fe, 4c, 42, fd, 20, ec  ; .. 5.LB. .
FD64  .BYTE fd, a4, e0, 10, d9, a0, 80, 84, e1, a0  ; ..........
FD6E  .BYTE 00, 8c, 00, b0, a9, 20, 99, 00, 80, 99  ; ..... ....
FD78  .BYTE 00, 81, c8, d0, f7, a9, 80, a0, 00, 85  ; ..........
FD82  .BYTE df, 84, de, f0, bb, 20, 3a, fe, 4c, 42  ; ..... :.LB
FD8C  .BYTE fd, 18, a9, 10, 85, e6, a2, 08, 20, 13  ; ........ .
FD96  .BYTE fd, 4c, 44, fd, a5, e7, 49, 60, 85, e7  ; .LD...I`..
FDA0  .BYTE b0, 09, 29, 05, 2e, 01, b0, 2a, 20, ea  ; ..)....* .
FDAA  .BYTE fc, 4c, 9a, fe, a4, e0, 20, 6b, fe, b1  ; .L.... k..
FDB4  .BYTE de, 45, e1, 30, 02, 49, 60, e9, 20, 4c  ; .E.0.I`. L
FDBE  .BYTE e9, fd, a9, 5f, 49, 20, d0, 23, 45, e7  ; ..._I .#E.
FDC8  .BYTE 2c, 01, b0, 30, 02, 49, 60, 4c, df, fd  ; ,..0.I`L..
FDD2  .BYTE 69, 39, 90, f2, 49, 10, 2c, 01, b0, 30  ; i9..I.,..0
FDDC  .BYTE 02, 49, 10, 18, 69, 20, 2c, 01, b0, 70  ; .I..i ,..p
FDE6  .BYTE 02, 29, 1f, 4c, 60, fe                  ; .).L`.

FDEC_scroll_screen_up:

FDEC  a5 de     lda $DE		; VDE_p_start_of_line_containing_cursor lsb
FDEE  a4 df     ldy $DF		; VDE_p_start_of_line_containing_cursor msb
FDF0  c0 81     cpy #$81	; 
FDF2  90 38     bcc $FE2C
FDF4  c9 e0     cmp #$E0
FDF6  90 34     bcc $FE2C
FDF8  a4 e6     ldy VE6_lines_remaining_if_VDU_in_page_mode
FDFA  30 0c     bmi $FE08
FDFC  88        dey 
FDFD  d0 07     bne $FE06
FDFF  20 71 fe  jsr $FE71_scan_key
FE02  b0 fb     bcs $FDFF
FE04  a0 10     ldy #lines_per_screen
FE06  84 e6     sty VE6_lines_remaining_if_VDU_in_page_mode
FE08  a0 20     ldy #characters_per_line			; 32 characters per line
FE0A  20 66 fe  jsr $FE66_wait_for_flyback_start	; prevents screen tearing
FE0D  b9 00 80  lda VRAM,Y				; scroll 1st 256 bytes one line up
FE10  99 e0 7f  sta VRAM-lines_per_screen,Y
FE13  c8        iny 
FE14  d0 f7     bne $FE0D
FE16  20 6b fe  jsr $FE6B_wait_for_flyback
FE19  b9 00 81  lda VRAM+256,Y				; scroll 2nd 256 bytes one line up
FE1C  99 e0 80  sta VRAM+256-lines_per_screen,Y
FE1F  c8        iny 
FE20  d0 f7     bne $FE19
FE22  a0 1f     ldy #$1F
FE24  a9 20     lda #SP
FE26  91 de     sta (VDE_p_start_of_line_containing_cursor),Y
FE28  88        dey 
FE29  10 fb     bpl $FE26
FE2B  60        rts 
FE2C  69 20     adc #characters_per_line
FE2E  85 de     sta VDE_p_start_of_line_containing_cursor	; lsb
FE30  d0 02     bne FE34_rts
FE32  e6 df     inc VDE_p_start_of_line_containing_cursor+1	; msb
FE34  60        rts 
; Data from $FE35 to $FE54 (32 bytes)
FE35  .BYTE 88, 10, 19, a0, 1f, a5, de, d0, 0b, a6  ; ..........
FE3F  .BYTE df, e0, 80, d0, 05, 

FD44
Invert character at current cursor position. 
See page zero RAM locations DE to E0. A and Y destroyed.
68, 68, 4c, 65, fd  ; .....hhLe.
FE49  .BYTE e9, 20, 85, de, b0, 02, c6, df, 60,

FE52
WRCH:

; Write ASCII character in A to printer and VDU (if enabled).
; Control characters recognised and acted upon. All registers preserved.
FE52  20 fb fe  jsr $FEFB_write_ASCII_char

FE55
WRCH_to_vdu:

; As FE52_WRCH but does not write to printer.
FE55  08        php 
FE56  48        pha 
FE57  d8        cld 
FE58  84 e5     sty $E5
FE5A  86 e4     stx $E4
FE5C  20 ea fc  jsr $FCEA
FE5F  68        pla 
FE60  a6 e4     ldx $E4

F6E2_Plot_mode_0:

FE62  a4 e5     ldy $E5
FE64  28        plp 
FE65  60        rts 

Wait_for_start_of_VDU_flyback:

; Wait for start of VDU fly-back (blanking) period. All registers preserved.

FE66_wait_for_flyback_start:

FE66  2c 02 b0  bit PPI_PC	; wait until 
FE69  10 fb     bpl $FE66_wait_for_flyback_start	;

FE6B_wait_for_flyback:

FE6B  2c 02 b0  bit PPI_PC	; wait until flyback begins
FE6E  30 fb     bmi FE6B_wait_for_flyback
FE70  60        rts		; now have whole flyback time to use

FE71_scan_key:

;  Scan key (except for CTRL, SHIFT, RPT and BRK).
; Returns with flag C-1 if no key pressed, 
; else C=0 and Y = key number. All registers destroyed.
FE71  a0 3b     ldy #$3B
FE73  18        clc 
FE74  a9 20     lda #$20
FE76  a2 0a     ldx #$0A
FE78  2c 01 b0  bit PPI_PB
FE7B  f0 08     beq $FE85
FE7D  ee 00 b0  inc PPI_PA
FE80  88        dey 
FE81  ca        dex 
FE82  d0 f4     bne $FE78
FE84  4a        lsr A
FE85  08        php 
FE86  48        pha 
FE87  ad 00 b0  lda PPI_PA
FE8A  29 f0     and #$F0
FE8C  8d 00 b0  sta PPI_PA
FE8F  68        pla 
FE90  28        plp 
FE91  d0 e3     bne $FE76
FE93  60        rts 

FE94
RDCH:

Wait for key press then return with its ASCII code in A. X and Y preserved.
FE94  08        php 
FE95  d8        cld 
FE96  86 e4     stx $E4
FE98  84 e5     sty $E5

FE9A  2c 02 b0  bit PPI_PC
FE9D  50 05     bvc $FEA4
FE9F  20 71 fe  jsr $FE71_scan_key_scan_keys
FEA2  90 f6     bcc $FE9A
FEA4  20 8a fb  jsr $FB8A
FEA7  20 71 fe  jsr $FE71_scan_key_scan_keys
FEAA  b0 fb     bcs $FEA7
FEAC  20 71 fe  jsr $FE71_scan_key_scan_keys
FEAF  b0 f6     bcs $FEA7
FEB1  98        tya 
FEB2  a2 17     ldx #$17
FEB4  20 c5 fe  jsr $FEC5
FEB7  bd e3 fe  lda $FEE3,X
FEBA  85 e2     sta $E2
FEBC  a9 fd     lda #$FD
FEBE  85 e3     sta $E3
FEC0  98        tya 
FEC1  6c e2 00  jmp ($00E2)
FEC4  ca        dex 
FEC5  dd cb fe  cmp $FECB,X
FEC8  90 fa     bcc $FEC4
FECA  60        rts 

; Data from $FECB to $FEFA (48 bytes)
;00000000
;00001000
;00001001
;00001010
;00001100
;00001101
;00001110
;00001111
;00011110
;01111111
;00000000
;00000001
;00000101
FECB  .BYTE 00, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 1e  ; ..........
FED5  .BYTE 7f, 00, 01, 05, 06, 08, 0e, 0f, 10, 11  ; ..........
FEDF  .BYTE 1c, 20, 21, 3b, 44, 5c, 38, 62, 87, 69  ; . !;D\8b.i
FEE9  .BYTE 40, 8d, 92, 7d, 50, df, d2, 9a, a2, e2  ; @..}P.....
FEF3  .BYTE ae, c0, df, d8, d6, c8, c6, c2          ; ........

FEFB_write_ascii_char:

FEFB:	; Write ASCII character in A to printer (if enabled).
If A=02 (STX), enable printer.
If A=03 (ETX), disable printer.
All registers preserved.
FPGA project seemed to get stuck in a loop trying to access the VIA.
FEFB  48        pha 		; save char on stack
FEFC  c9 02     cmp #STX	; start of text?
FEFE  f0 27     beq $FF27	; yes, skip forward
FF00  c9 03     cmp #ETX	; end of text?
FF02  f0 34     beq $FF38	; yes, skip forward
FF04  c5 fe     cmp $FE		; 
FF06  f0 2e     beq $FF36	; yes, pull a and return
FF08  ad 0c b8  lda VIA_RC	; read Peripheral control reg
FF0B  29 0e     and #$0E	; read bits xxxx 111x
FF0D  f0 27     beq $FF36	; if clear,  pull a and return
FF0F  68        pla		; get char from stack
FF10  2c 01 b8  bit VIA_R1	; read Port A to flags only (not register)
FF13  30 fb     bmi $FF10	; if bit 7 = BUSY = true then wait
FF15  8d 01 b8  sta VIA_R1	; write char to Port A
FF18  48        pha 
FF19  ad 0c b8  lda VIA_RC	; read Peripheral control reg
FF1C  29 f0     and #$F0	; preserve upper nibble
FF1E  09 0c     ora #$0C	; lower nibble = 1100
FF20  8d 0c b8  sta VIA_RC	; write Peripheral control reg
FF23  09 02     ora #$02	; lower nibble = 1110
FF25  d0 0c     bne $FF33
FF27  a9 7f     lda #$7F
FF29  8d 03 b8  sta VIA_R3
FF2C  ad 0c b8  lda VIA_RC	; read Peripheral control reg
FF2F  29 f0     and #$F0	; preserve upper nibble
FF31  09 0e     ora #$0E	; lower nibble = 1110
FF33  8d 0c b8  sta VIA_RC	; write Peripheral control reg
FF36  68        pla 
FF37  60        rts 

; ETX_handler:	; end of text by doing a reset?
FF38  ad 0c b8  lda VIA_RC	; read Peripheral control reg
FF3B  29 f0     and #$F0
FF3D  b0 f4     bcs $FF33	; fall through to reset???

do_reset:

FF3F  a2 17     ldx #$17		; x = size of FF9A_table;
LFF41:
      bd 9a ff  lda FF9A_table,X	;  do {
FF44  9d 04 02  sta $0204,X		; 	$204[X] = FF9A_table[X]
FF47  ca        dex			; 	X--
FF48  10 f7     bpl LFF41		; } until X = -1 ; // i.e. FF
FF4A  9a        txs 			; S = $FF
FF4B  8a        txa 			; A = $FF
FF4C  e8        inx 			; X = 0
FF4D  86 ea     stx VEA_nomon		; clears these locations
FF4F  86 e1     stx VE1_cursor_on	; 0=cursor off, 1 = cursor on 
FF51  86 e7     stx VE7_shift_lock	; Bits 5,6,= 1 for shift lock, else 0 
FF53  a2 33     ldx #$33		; X = size of array = 51 to 0 = 26 x 2 -1
LFF55:
FF55  9d eb 02  sta P_array_space,X	; fill with $FF
FF58  ca        dex 
FF59  10 fa     bpl LFF55
FF5B  a9 0a     lda #LF
FF5D  85 fe     sta VFE_char_not_printed
FF5F  a9 8a     lda #$8A		; free workspace
FF61  8d 03 b0  sta PPI_CTRL		; set PPI control register
FF64  a9 07     lda #$07
FF66  8d 02 b0  sta PPI_PC		; set PPI port c to 0000_0111
FF69  20 d1 f7  jsr $F7D1_Print_ASCII_string
FF6C
 	.byte ACK	; Start screen* 
 	.byte FF	; Formfeed	Clears the screen, moves the cursor to the top left-hand corner, 
			;		and sets the VDU to character mode.
 	.byte SI	; Page mode off *
	.byte "ACORN ATOM" 	; the sign-on message
	.byte LF, LF, CR

May be data or code?
FF7C  a9 82     lda #$82
FF7E  85 12     sta $12
FF80  58        cli 
FF81  a9 55     lda #$55
FF83  8d 01 29  sta $2901
FF86  cd 01 29  cmp $2901
FF89  d0 0c     bne $FF97
FF8B  0a        asl A
FF8C  8d 01 29  sta $2901
FF8F  cd 01 29  cmp $2901
FF92  d0 03     bne $FF97
FF94  4c b2 c2  jmp $C2B2
FF97  4c b6 c2  jmp $C2B6

; This data table used to initialise vectors during start up
; Data from $FF9A to $FFD3 (58 bytes)

FF9A_table

	.word ;	vector		default
			;    (NMIVEC);	NMI routine
			;    (BRKVEC);	?
	a000,		; p_ (IRQVEC) ptr to another ROM?
	F8EF_CLI, 	; p_ (CLIVEC)  OSCLI:
	FE52_WRCH,	; p_ (WRCVEC) OSWRCH:
	FE94_RDCH,	; p_ (RDCVEC) OSRDCH:
	F96E_LOAD,	; p_ (LODVEC) OSLOAD:
	FAE5_SAVE,	; p_ (SAVVEC) OSSAVE:
	c2ac_RDRVEC,	; p_ (RDRVEC)
	c2ac_STRVEC,	; p_ (STRVEC)
	FBEE_BGET,	; p_ (BGTVEC) OSBGET:
	FC7C_BPUT,	; p_ (BPTVEC) OSBPUT:
	FC38_FIND,	; p_ (FNDVEC) OSFIND:
	C278_SHUT,	; p_ (SHTVEC) OSSHUT:  ; normally calls C278_SHUT (RTS)

FFB2  85 ff     sta $FF
FFB4  68        pla 
FFB5  48        pha 
FFB6  29 10     and #$10

 

FFB8  d0 06     bne $FFC0
FFBA  a5 ff     lda $FF
FFBC  48        pha 
FFBD  6c 04 02  jmp (VEC_IRQ)
FFC0  a5 ff     lda $FF
FFC2  28        plp
FBC3  08        php 
FFC4  6c 00 02  jmp (VEC_NMI)
; NMI routine
FFC7  48        pha 
FFC8  6c 00 02  jmp (VEC_NMI)
OSSHUT:  ; normally calls C278_SHUT (RTS)
FFCB  6c 1a 02  jmp (SHTVEC)
OSFIND:  ; normally calls FC38_FIND
FFCE  6c 18 02  jmp (FNDVEC)
FFD1
OSBPUT:  ; normally calls FC7C_BPUT
FFD1  6c 16 02  jmp (BPTVEC)
FFD4
OSBGET:  ; normally calls FBEE_BGET
FFD4_OSBGET  6c 14 02  jmp (BGTVEC)
OSSTAR: 
FFD7  6c 12 02  jmp (STRVEC)
OSRDAR:
FFDA  6c 10 02  jmp (RDRVEC)
FFDD
OSSAVE:  ; normally calls FAE5_SAVE
FFDD  6c 0e 02  jmp (SAVVEC)
FFE0
OSLOAD:  ; normally calls F96E_LOAD
FFE0  6c 0c 02  jmp (LODVEC)
FFE3
OSRDCH:  ; normally calls FE94_RDCH
FFE3  6c 0a 02  jmp (RDCVEC)
FFE6
OSECHO:  ; normally calls FE94_RDCH then FE52_WRCH
FFE6  20 e3 ff  jsr $FFE3_OSRDCH
FFE9
OSASCI:  ; normally calls FE52_WRCH
FFE9  c9 0d     cmp #$0D
FFEB  d0 07     bne $FFF4_OSWRCH
FFED
OSCRLF:  ; normally calls FE52_WRCH to print CR/LF
FFED  a9 0a     lda #LF
FFEF  20 f4 ff  jsr $FFF4_OSWRCH
FFF2  a9 0d     lda #CR
OSWRCH:
FFF4  6c 08 02  jmp (WRCVEC)
FFF7
OSCLI:  ; normally calls F8EF_CLI
FFF7  6c 06 02  jmp (CLIVEC)
NMI_vector:  ; normally contains FFC7
;FFFA
	.word $ffc7
Reset_vector:  ; normally contains FF3F
;FFFC  
	.word $ff3f 
IRQ_BRK_vector:  ; normally contains FFB2
;FFFE
	.word $ffb2 

Note: #C014 input routine in #100. Y register must be zero.

Temporal order:

jumps via Reset_vector to do_reset