
		; **********************************************
		; **                                          **
		; **  OPERATING SYSTEM ROM PART 1: C000-CBFF  **
		; **                                          **
		; **********************************************

		.org	$C000
		.segment "C000CBFF"

		.include "atari.inc"
		.include "gtia.inc"
		.include "pokey.inc"
		.include "antic.inc"
		.include "pia.inc"

		.import	E40C,E41C,E42C,E43C,E44C,E49B
		.import E510,E55C,E716,E7DE,E89E,E971

		.import	FE36

		.import init_parbus
		.import	SLFTST	
		.import SLFTSV,SIOV,CSOPIV,RBLOKV,DISKINV
		.import DISKIV,INTIV,INTINV,SIOINV
		.import CIOINV
		.import KEYBDV,SCRENV,EDITRV,CASETV,PRINTV
		.import V003,CHARSET1
		.import KIR
		.import	ISRSIR,ISRODN,ISRTD
		.import SELFS

		.if	(OS_REVISION=0)

		PHR=$C8C6
		.else
		.import	SELFS
		.import	VFR,VSR
		.import PHR
		.endif

		.export	C745,C8FC
		.export C991,C996,C99B,C9A0,C9A5,C9AA,CA29,CA57,CA61,CB56

		.if	(OS_REVISION=0)
CA29		= $CB5A
SIO		= $E74E
CB56		= $CB56
CA61		= $CA61
CA56		= $CA56
CA57		= $CA57
C9AA		= $C9AA
C9A5		= $C9A5
C9A0		= $C9A0
C99B		= $C99B
C996		= $C99B
C991		= $C991
C8FC		= $C8FC
		.else
		.export	parbus_init
		.endif

		.if	(OS_REVISION=4)
		.export	CB90
		.endif

		.export do_RTI
		.export SIO
		.export NMI_Handler,IRQ_Handler,RST_Handler
	
		.export	DISKI,DISKIN,SETVBL,VBLKI,VBLKD,INTIN,WARMS,COLDS

		; C000-C00C	  13	ROM identification
		; C00D-C017	  11	init interrupts
		; C018-C02B	  20	6502 NMI handler
		; C02C-C02F	   4	6502 IRQ handler
		; C030-C0DE	 175	default IRQ handler
		; C0DF-C0E1	   3	halt computer
		; C0E2-C271	 400	vblank stage 1
		; C272-C289	  24	set vblank
		; C28A-C28F	   6	end-vblank
		; C290-C2A9	  26	warmstart code
		; C2AA-C2C9	  32	6502 RESET handler: coldstart code
		; C2CA-C42D	 356	warm/coldstart continuation
		; C42E-C470	  67	boot process data
		; C471-C6A2	 562	boot code
		; C6A3-C932	 656	floppy disk code
		; C933-C96D	  59	SIO code
		; C96E-CA56	 233	parallel handler code
		; CA57-CB55	 255	selftest data
		; CB56-CB64	  15	checksum code
		; CB65-CBFF	 155	unused (zeros)
		; CC00-CFFF	1024    character set 2
		; 5000-57FF	2048	selftest ROM
		; D800-DFFF	2048	floating point package

		.include "rom1id.inc"
		.include "intin.inc"
		.include "6502-nmi.inc"

		; ********************************************
		; **                                        **
		; **  6502 Interrupt Request (IRQ) handler  **
		; **                                        **
		; ********************************************

IRQ_Handler:	cld			; clear decimal flag
		jmp	(VIMIRQ)	; engage immediate IRQ handler

		; ************************************
		; **                                **
		; ** Default Immediate IRQ handler  **
		; **                                **
		; ************************************

IMIRQ:		pha			; save A register
		lda	IRQST		; check IRQ status
		and	#%00100000	; serial input data ready?
		bne	@1		; no - other IRQ!

		; serial input ready IRQ

		lda	#%11011111	; disable interrupt notification
		sta	IRQEN
		lda	POKMSK		; enable interrupts
		sta	IRQEN
		jmp	(VSERIN)	; engage SERIN IRQ handler

		; other IRQ

@1:		txa			; save X register
		pha

		.if	(OS_REVISION>0)		
	
		lda	PDVS		; check parallel bus IRQ
		and	PDMSK
		beq	@2		; no - other IRQ!

		; parallel bus IRQ

		jmp	(VPIRQ)		; engage Parallel IRQ handler

		; other IRQ

@2:		.endif

		ldx	#6
@3:		lda	IRQMSK,X
		cpx	#5
		bne	@4
		and	POKMSK
		beq	@5
@4:		bit	IRQST
		beq	@6
@5:		dex
		bpl	@3
		jmp	C0A0

@6:		eor	#$FF
		sta	IRQEN
		lda	POKMSK
		sta	IRQEN
		cpx	#0
		bne	@7
		lda	KEYDIS
		bne	C0A0
@7:		lda	IRQOFS,X	; setup correct handler jump vector
		tax
		lda	$200,X
		sta	JVECK
		lda	$201,X
		sta	JVECK+1
		pla			; restore X register
		tax
		jmp	(JVECK)

		; *****************************
		; **                         **
		; **  break key IRQ Handler  **
		; **                         **
		; *****************************

BRKKY:		lda	#0
		sta	BRKKEY
		sta	SSFLAG
		sta	CRSINH
		sta	ATRACT
		pla
		rti
	
C0A0:		pla
		tax
		bit	PACTL
		bpl	@1
		lda	PORTA
		jmp	(VPRCED)

@1:		bit	PBCTL
		bpl	@2
		lda	PORTB
		jmp	(VINTER)

@2:		pla
		sta	JVECK
		pla
		pha
		and	#%00010000
		beq	@3
		lda	JVECK
		pha
		jmp	(VBREAK)

@3:		lda	JVECK
		pha

do_PLARTI:	pla
do_RTI:		rti

		; ***************************
		; **                       **
		; **  IRQ Dispatcher Data  **
		; **                       **
		; ***************************

		; Bit masks for IRQ interrupts

IRQMSK:		.byte	%10000000	; break key              LO PRIORITY
		.byte	%01000000	; keyboard               |
		.byte	%00000100	; timer 4                |
		.byte	%00000010	; timer 2                |
		.byte	%00000001	; timer 1                |
		.byte	%00001000	; serial output complete |
		.byte	%00010000	; serial output ready    |
		.byte	%00100000	; serial input ready     HI PRIORITY

		; Offsets from $200 of IRQ interrupt handler vectors

IRQOFS:		.byte	VBRKKY - $200	; break key              LO PRIORITY
		.byte	VKEYBD - $200	; keyboard               |
		.byte	VTIMR4 - $200	; timer 4                |
		.byte	VTIMR2 - $200	; timer 2                |
		.byte	VTIMR1 - $200	; timer 1                |
		.byte	VSEROC - $200	; serial output complete |
		.byte	VSEROR - $200	; serial output ready    |
		.byte	VSERIN - $200	; serial input ready     HI PRIORITY

		.include "halt.inc"
		.include "vblank.inc"
		.if	(OS_REVISION=0)
		.include "diski.inc"
		.include "diskin.inc"
		.endif
	
		; ******************
		; **              **
		; **  WARM START  **
		; **              **
		; ******************

WARMS:		sei
		lda	TRIG3
		cmp	GINTLK
		bne	COLDS
		ror
		bcc	@1
		jsr	check_cartr
		bne	COLDS
@1:		lda	COLDST
		bne	COLDS
		lda	#$FF
		bne	warm_cold

		; ********************************
		; **                            **
		; **  6502 Reset (RST) handler  **
		; **                            **
		; ********************************

RST_Handler:	sei			; disable interrupts

		.if	(OS_REVISION>0)
		ldx	#140		; wait about 0.1 second ...
@1:		dey
		bne	@1
		dex
		bne	@1
		.endif

		lda	PUPBT1		; check $33D..$33F = $5C,$93,$25?
		cmp	#$5C
		bne	COLDS
		lda	PUPBT2
		cmp	#$93
		bne	COLDS
		lda	PUPBT3
		cmp	#$25
		beq	WARMS

COLDS:		lda	#0

		; Warm- and cold-start continuation

warm_cold:	sta	WARMST
		.if	(OS_REVISION>0)
		sei
		.endif
		cld
		ldx	#$FF
		txs
		.if	(OS_REVISION=0)
		jsr	$C53D
		jsr	$C581
		.else
		jsr	boot_code
		.endif

		; order changed
	
		.if	(OS_REVISION<=1)
		lda	WARMST
		bne	@6
		lda	#1		; default: memory OK!
		sta	NGFLAG
		.else
		lda	#1		; default: memory OK!
		sta	NGFLAG
		lda	WARMST
		bne	@6
		.endif

		; This part: cold start only!

		lda	#0
		ldy	#8
		sta	RAMLO
		sta	RAMLO+1
@1:		lda	#$FF
		sta	(RAMLO),Y
		cmp	(RAMLO),Y
		beq	@2
		lsr	NGFLAG		; signal memory bad!
@2:		lda	#0
		sta	(RAMLO),Y
		cmp	(RAMLO),Y
		beq	@3
		lsr	NGFLAG		; signal memory bad!
@3:		iny
		bne	@1
		inc	RAMLO+1
		ldx	RAMLO+1
		cpx	TRAMSZ
		bne	@1
		lda	#<SELFS		; [$A:$B] = SELFTEST
		sta	DOSVEC
		lda	#>SELFS
		sta	DOSVEC+1

		lda	PORTB		; Verify ROMs
		and	#%01111111	; enable self test ROM
		sta	PORTB
		jsr	VFR
		bcs	@4
		jsr	VSR
		bcc	@5
@4:		lsr	NGFLAG
@5:		lda	PORTB		; disable self test ROM
		ora	#%10000000
		sta	PORTB

		lda	#$FF
		sta	COLDST
		bne	@10

		; this part: Warm start only!

@6:		ldx	#0

		.if	(OS_REVISION>0)	
		lda	DERRF
		beq	@7
		.byte	$8E		; stx APPMHI   (absolute)
		.word	APPMHI
		.byte	$8E		; stx APPMHI+1 (absolute)
		.word	APPMHI+1
		.endif

		txa			; clear $200-$3EC
@7:		sta	$200,X
		cpx	#$ED
		bcs	@8
		sta	$300,X
@8:		dex
		bne	@7

		ldx	#$10		; reset $10..$7F to zero
@9:		sta	0,X
		inx
		bpl	@9

		; Warm- and cold-start continuation

@10:		.if	(OS_REVISION>0)
		ldx	#0		; init BASICF
		lda	PORTB
		and	#%00000010
		beq	@11
		inx
@11:		stx	BASICF
		.endif

		lda	#$5C		; init power-up bytes
		sta	PUPBT1
		lda	#$93
		sta	PUPBT2
		lda	#$25
		sta	PUPBT3

		lda	#2		; init left margin
		sta	LMARGN
		lda	#39		; init right margin
		sta	RMARGN

		lda	PAL		; init keyboard timing & PALNTS flag
		and	#%00001110
		bne	@12
		lda	#5		; PAL
		ldx	#1
		ldy	#40
		bne	@13
@12:		lda	#6		; NTSC
		ldx	#0
		ldy	#48
@13:		sta	KEYREP		; PAL:  5 NTSC:  6
		stx	PALNTS		; PAL:  1 NTSC:  0
		sty	KRPDEL		; PAL: 40 NTSC:	48

		ldx	#$25		; init 19 vectors from $200 to $225
@14:		lda	def_vectors,X
		sta	$200,X
		dex
		bpl	@14

		.if	(OS_REVISION=0)
		jsr	$C5AE
		.endif

		ldx	#14		; init 5 3-byte device driver entries
@15:		lda	driver_entries,X
		sta	HATABS,X
		dex
		bpl	@15

		.if	(OS_REVISION=0)
		.byte	$ad,$32,$02
		.byte	$09,$04
		.byte	$8d,$0f,$d2
		.byte	$8d,$0a,$d4
		.byte	$8d,$0a,$d4
		.byte	$8d,$0a,$d4
		.byte	$a2,$03
		.byte	$bd,$04,$d2
		.byte	$0a,$2e,$0e,$03,$ca,$10,$f6
		.byte	$ad,$32,$02
		.byte	$8d,$0f,$d2
		.else
		jsr	init_vectors
		.endif

		cli

		.if	(OS_REVISION=0)
		.byte	$ad,$0e,$03
		.byte	$6a
		.byte	$b0,$19
		.endif

		lda	NGFLAG		; check if memory is ok
		bne	@16

		lda	PORTB		; NOT OK: enable SELFTEST ROM!
		and	#%01111111
		sta	PORTB

		lda	#2		; ...and go for self-test!
		sta	CHACT
		lda	#>CHARSET1
		sta	CHBAS
		.if	(OS_REVISION<=2)
		jmp	V003
		.else
		jmp	SLFTST
		.endif
	
@16:		ldx	#0		; memory ok.
		stx	TRAMSZ

		.if	(OS_REVISION=0)
		.byte	$ad,$13,$d0
		.byte	$6a
		.byte	$90,$14
		.endif

		ldx	RAMSIZ
		cpx	#>$B000
		bcs	@17
		ldx	BFFC
		bne	@17
		inc	TRAMSZ
		jsr	check_cartr
		jsr	@22		; jsr ($BFFE)

@17:		lda	#3		; open #0,12,0,"E:"
		ldx	#0
		sta	ICCOM,X
		lda	#<EDITOR
		sta	ICBAL,X
		lda	#>EDITOR
		sta	ICBAH,X
		lda	#12
		sta	ICAX1,X
		jsr	CIOV
		bpl	@18
		jmp	RST_Handler	; no go  -- hardware reset!

@18:		inx			; all ok -- settle down.
		bne	@18
		iny
		bpl	@18

		jsr	C66E
		lda	TRAMSZ
		beq	@19
		lda	BFFC+1
		ror
		bcc	@20
@19:		jsr	C58B
		.if	(OS_REVISION=59)
		nop
		nop
		nop
		.else
		jsr	PHR
		.endif
@20:		lda	#0
		.if     (OS_REVISION=59)
		jsr	$CBFA
		.else
		sta	COLDST
		.endif
		lda	TRAMSZ
		beq	@21		; beq (DOSVEC)
		lda	BFFC+1
		and	#%00000100
		beq	@21		; beq (BFFE)
		jmp	(BFFA)
@21:		jmp	(DOSVEC)
@22:		jmp	(BFFE)

		clc			; not used
		rts

		; BOOT PROCESS DATA

driver_entries:	.byte	"P"		; initial device driver entries
		.word	PRINTV
		.byte	"C"
		.word	CASETV
		.byte	"E"
		.word	EDITRV
		.byte	"S"
		.word	SCRENV
		.byte	"K"
		.word	KEYBDV

booterr_msg:	.byte	"BOOT ERROR",$9B

EDITOR:		.byte	"E:",$9B	; Editor device specification

def_vectors:	.word	do_RTI		; VDSLST ->     RTI
		.word	do_PLARTI	; VPRCED -> PLA,RTI
		.word	do_PLARTI	; VINTER -> PLA,RTI
		.word	do_PLARTI	; VBREAK -> PLA,RTI
		.word	KIR		; VKEYBD
		.word	ISRSIR		; VSERIN
		.word	ISRODN		; VSEROR
		.word	ISRTD		; VSEROC
		.word	do_PLARTI	; VTIMR1 -> PLA,RTI
		.word	do_PLARTI	; VTIMR2 -> PLA,RTI
		.word	do_PLARTI	; VTIMR4 -> PLA,RTI
		.word	IMIRQ		; VIMIRQ -> immediate IRQ
		.word	0		; CDTMV1 -> 0
		.word	0		; CDTMV2 -> 0
		.word	0		; CDTMV3 -> 0
		.word	0		; CDTMV4 -> 0
		.word	0		; CDTMV5 -> 0
		.word	VBLKI		; VVBLKI -> immediate VBLANK 
		.word	VBLKD		; VVBLKD -> deferred  VBLANK

boot_code:	lda	TRIG3
		ror
		bcc	@1
		lda	BFFC
		bne	@1
		lda	BFFC+1
		bpl	@1
		jmp	(BFFE)

@1:		.if	(OS_REVISION>0)
		jsr	init_chips
		lda	PORTB
		ora	#%00000010
		sta	PORTB

		lda	WARMST
		beq	@2
		lda	BASICF
		bne	C4A9
		beq	C4A1
@2:		.if	(OS_REVISION=4)
		jmp	CB65
		.else
		lda	CONSOL		; option key pressed?
		.endif
		and	#%00000100
		beq	C4A9		; no -- skip enable BASIC
C4A1:		lda	PORTB		; enable BASIC
		and	#%11111101
		sta	PORTB
		.endif

C4A9:		lda	#<$2800		; search 1st byte of ROM from $2800 up
		tay
		sta	RAMLO+1
		lda	#>$2800
		sta	TRAMSZ
@1:		lda	(TRAMSZ-1),Y
		eor	#$FF
		sta	(TRAMSZ-1),Y
		cmp	(TRAMSZ-1),Y
		bne	@2		; rts
		eor	#$FF
		sta	(TRAMSZ-1),Y
		cmp	(TRAMSZ-1),Y
		bne	@2		; rts
		inc	TRAMSZ
		bne	@1
@2:		rts

check_cartr:	lda	#0
		tax
		clc
@1:		adc	BFF0,X
		inx
		bne	@1
		cmp	CARTCK
		sta	CARTCK
		rts

init_chips:	lda	#0	; clear all of $D000..$D4FF, except $D301.
		tax
		sta	PBCTL
@1:		sta	$D000,X
		sta	$D400,X
		sta	$D200,X
		.if	(OS_REVISION>0)
		cpx	#1
		beq	@2
		.endif
		sta	$D300,X
@2:		inx
		bne	@1

		.if	(OS_REVISION>0)
		lda	#%00111100
		sta	PBCTL
		lda	#%11111111
		sta	PORTB
		lda	#%00111000
		sta	PACTL
		sta	PBCTL
		lda	#0
		sta	PORTA
		lda	#%11111111
		sta	PORTB
		lda	#%00111100
		sta	PACTL
		sta	PBCTL
		lda	PORTB
		lda	PORTA
		.endif
		lda	#%00100010
		sta	SKCTL
		lda	#160
		sta	$D205
		sta	$D207
		lda	#%00101000
		sta	AUDCTL
		lda	#$FF
		sta	SEROUT
		rts

init_vectors:	dec	BRKKEY

		lda	#<BRKKY		; init break key interrupt vector
		sta	VBRKKY
		lda	#>BRKKY
		sta	VBRKKY+1

		lda	TRAMSZ
		sta	RAMSIZ
		sta	HIMEM+1
		lda	#0
		sta	HIMEM

		lda	#<$700		; MEMLO = $700
		sta	MEMLO
		lda	#>$700
		sta	MEMLO+1

		jsr	E40C		; init devices
		jsr	E41C
		jsr	E42C
		jsr	E43C
		jsr	E44C

		jsr	CIOINV		; init cassette I/O
		jsr	SIOINV		; init serial I/O
		jsr	INTINV		; init vblank, copy GINTLK
		jsr	DISKIV		; init disk I/O

		.if	(OS_REVISION>0)
		lda	#<PIRQ
		sta	VPIRQ
		lda	#>PIRQ
		sta	VPIRQ+1
		jsr	init_parbus
		.endif

		lda	CONSOL
		and	#1
		eor	#1
		sta	CKEY
		rts

C58B:		lda	WARMST
		beq	@1
		lda	BOOTQ
		and	#1
		beq	do_RTS3		; rts
		jmp	ind_DOSINI	; jmp (DOSINI)

@1:		lda	#1
		sta	DUNIT
		lda	#'S'		; status
		sta	DCOMND
		jsr	DISKINV
		bmi	do_RTS3		; rts

C5A7:		lda	#0
		sta	DAUX2
		lda	#1
		sta	DAUX1
		lda	#<$400
		sta	DBUFLO
		lda	#>$400
		sta	DBUFHI

C5BB:		jsr	read128
		bpl	C5C9

C5C0:		jsr	C63E
		lda	CASSBT
		beq	C5A7
do_RTS3:	rts

C5C9:		ldx	#3
@1:		lda	$400,X
		sta	$240,X
		dex
		bpl	@1
		lda	BOOTAD
		sta	RAMLO
		lda	BOOTAD+1
		sta	RAMLO+1
		lda	$404
		sta	DOSINI
		lda	$405
		sta	DOSINI+1

C5E8:		ldy	#$7F		; copy lower half page 4
@1:		lda	$400,Y
		sta	(RAMLO),Y
		dey
		bpl	@1

		clc			; RAMLO += 128
		lda	RAMLO
		adc	#<$80
		sta	RAMLO
		lda	RAMLO+1
		adc	#>$80
		sta	RAMLO+1

		dec	DBSECT
		beq	@3		; we have read last sector!
		inc	DAUX1		; go for next sector...
@2:		jsr	read128
		bpl	C5E8
		jsr	C63E
		lda	CASSBT
		bne	C5C0
		beq	@2

@3:		lda	CASSBT
		beq	@4
		jsr	read128
@4:		jsr	@5
		bcs	C5C0
		jsr	ind_DOSINI	; jsr (DOSINI)
		inc	BOOTQ
		rts

@5:		clc			; [RAMLO] = BOOTAD+6
		lda	BOOTAD
		adc	#6
		sta	RAMLO
		lda	BOOTAD+1
		adc	#0
		sta	RAMLO+1
		jmp	(RAMLO)

ind_DOSINI:	jmp	(DOSINI)

		; display "BOOT ERROR" message

C63E:		ldx	#<booterr_msg
		ldy	#>booterr_msg
		txa
		ldx	#0
		sta	ICBAL,X
		tya
		sta	ICBAH,X
		lda	#9
		sta	ICCOM,X
		lda	#$FF
		sta	ICBLL,X
		jmp	CIOV

read128:	lda	CASSBT
		beq	@1
		jmp	RBLOKV
@1:		lda	#'R'		; read sector
		sta	DCOMND
		lda	#1
		sta	DUNIT
		jmp	DISKINV

C66E:		lda	WARMST
		beq	@1
		lda	BOOTQ
		and	#2
		beq	@2		; rts
		jmp	@3		; jmp (CASINI)

@1:		lda	CKEY
		beq	@2		; rts
		lda	#$80
		sta	FTYPE
		inc	CASSBT
		jsr	CSOPIV
		jsr	C5BB
		lda	#0
		sta	CASSBT
		sta	CKEY
		asl	BOOTQ
		lda	DOSINI		;  copy DOSINI -> CASINI
		sta	CASINI
		lda	DOSINI+1
		sta	CASINI+1
@2:		rts
@3:		jmp	(CASINI)

		.if	(OS_REVISION>0)
		.include "diski.inc"
		.include "diskin.inc"
		.endif
	
C745:		ldx	#5
@1:		lda	#0
		sta	$2C9,X
		dex
		bpl	@1

@2:		lda	#0
		sta	LCOUNT
		jsr	C7CF		; jsr (GBYTEA)
		ldy	#$9C
		bcs	@4		; rts
		sta	HIBYTE
		jsr	C7CF		; jsr (GBYTEA)
		ldy	#$9C
		bcs	@4		; rts
		sta	RECLEN
		lda	HIBYTE
		cmp	#11
		beq	C795

		rol
		tax
		lda	parbus_runaddr,X
		sta	RUNADR
		lda	parbus_runaddr+1,X
		sta	RUNADR+1

@3:		lda	RECLEN
		cmp	LCOUNT
		beq	@2
		jsr	C7CF		; jsr (GBYTEA)
		ldy	#$9C
		bcs	@4		; rts
		jsr	C7D2		; jsr (RUNADR)
		inc	LCOUNT
		bne	@3
@4:		rts

C795:		jsr	C7CF		; jsr (GBYTEA)
		ldy	#$9C
		bcs	@3
		sta	RUNADR
		jsr	C7CF		; jsr (GBYTEA)
		ldy	#$9C
		bcs	@3
		sta	RUNADR+1
		lda	RECLEN
		cmp	#1
		beq	@2
		bcc	@4
		clc
		lda	RUNADR
		adc	LOADAD
		tay
		lda	RUNADR+1
		adc	$2D2
@1:		sty	RUNADR
		sta	RUNADR+1
@2:		ldy	#1
@3:		rts
	
@4:		ldy	#0
		lda	#0
		beq	@1

C7CF:		jmp	(GBYTEA)
C7D2:		jmp	(RUNADR)

C7D5:		ldy	LCOUNT
		cpy	#1
		beq	@1
		bcs	Z9
		sta	RELADR
		sta	NEWADR
		bcc	do_RTS		; rts
@1:		sta	RELADR+1
		sta	NEWADR+1
		ldx	#0
		lda	HIBYTE
		beq	@2
		cmp	#10
		beq	@3
		ldx	#2
@2:		clc
		lda	RELADR
		adc	$2D1,X
		sta	NEWADR
		lda	RELADR+1
		adc	$2D2,X
		sta	NEWADR+1
@3:		clc
		lda	NEWADR
		adc	RECLEN
		pha
		lda	#0
		adc	NEWADR+1
		tay
		pla
		sec
		sbc	#2
		bcs	@4
		dey
@4:		pha
		tya
		cmp	$2CC,X
		pla
		bcc	@6
		bne	@5
		cmp	$2CB,X
		bcc	@6
@5:		sta	$2CB,X
		pha
		tya
		sta	$2CC,X
		pla
@6:		ldx	HIBYTE
		cpx	#1
		beq	do_RTS		; rts
		cpy	HIMEM+1
		bcc	do_RTS		; rts
		bne	@7
		cmp	HIMEM
		bcc	do_RTS		; rts
@7:		pla
		pla
		ldy	#$9D
do_RTS:		rts

Z9:		sec
		pha
		lda	LCOUNT
		sbc	#2
		clc
		adc	NEWADR
		sta	LTEMP
		lda	#0
		adc	NEWADR+1
		sta	LTEMP+1
		pla
		ldy	#0
		sta	(LTEMP),Y
		jmp	do_RTS		; rts

C86D:		clc
		adc	NEWADR
		sta	LTEMP
		lda	#0
		adc	NEWADR+1
		sta	LTEMP+1
		ldy	#0
		lda	(LTEMP),Y
		clc
		adc	LOADAD
		sta	(LTEMP),Y
		inc	LTEMP
		bne	@1
		inc	LTEMP+1
@1:		lda	(LTEMP),Y
		adc	LOADAD+1
		sta	(LTEMP),Y
		rts

C892:		ldx	#0
		ldy	HIBYTE
		cpy	#4
		bcc	@1
		ldx	#2
@1:		clc
		adc	NEWADR
		sta	LTEMP
		lda	#0
		adc	NEWADR+1
		sta	LTEMP+1
		ldy	#0
		lda	(LTEMP),Y
		clc
		adc	LOADAD,X
		sta	(LTEMP),Y
		rts

C8B5:		pha
		lda	LCOUNT
		ror
		pla
		bcs	lobit1
		clc			; superfluous
		adc	NEWADR
		sta	LTEMP
		lda	#0
		adc	NEWADR+1
		sta	LTEMP+1
		ldy	#0
		lda	(LTEMP),Y
		sta	HIBYTE
do_RTS2:	rts

lobit1:		clc
		adc	LOADAD
		lda	#0
		adc	LOADAD+1
		adc	HIBYTE
		ldy	#0
		sta	(LTEMP),Y
		beq	do_RTS2		; rts

		; Peripheral Device Handlers?

parbus_runaddr:	.word	C7D5,C7D5,C892,C892,C892,C892
		.word	C86D,C86D,C8B5,C8B5,C7D5,C795

		.if	(OS_REVISION=0)
		.byte	$a5,$08
		.byte	$f0,$25
		.byte	$a9,$e9
		.byte	$85,$4a
		.byte	$a9,$03
		.byte	$85,$4b
		.byte	$a0,$12
		.byte	$18,$b1,$4a,$aa,$c8,$71,$4a
		.byte	$f0,$26
		.byte	$b1,$4a,$85
		.byte	$4b,$86,$4a
		.byte	$20,$ea,$c9
		.byte	$d0,$1b
		.byte	$20,$30,$ca
		.byte	$b0,$16
		.byte	$90
		.byte	$e3
		.byte	$a9,$00
		.byte	$8d,$fb,$03
		.byte	$8d,$fc,$03
		.byte	$a9,$4f
		.byte	$d0,$2d
		.byte	$a9,$00
		.byte	$a8
		.byte	$20,$4b,$c9
		.byte	$10,$01
		.byte	$60
		.byte	$18
		.byte	$ad,$e7,$02
		.byte	$6d,$ea,$02
		.byte	$8d,$12,$03
		.byte	$ad,$e8,$02
		.byte	$6d,$eb,$02
		.byte	$8d,$13,$03
		.byte	$38
		.byte	$ad,$e5,$02,$ed,$12,$03
		.byte	$ad,$e6,$02
		.byte	$ed,$13,$03
		.byte	$b0,$09
		.byte	$a9,$4e
		.byte	$a8
		.byte	$20,$4b,$c9
		.byte	$4c,$fb,$c8
		.byte	$ad,$ec,$02
		.byte	$ae,$e7,$02,$8e,$ec,$02,$ae,$e8,$02,$8e,$ed,$02,$20,$6b
		.byte	$c9,$30,$e3,$38
		.byte	$20,$3a,$ca
		.byte	$b0,$dd
		.byte	$90,$b0
		.byte	$48
		.byte	$a2,$09
		.byte	$bd,$61
		.byte	$c9,$9d,$00,$03,$ca,$10,$f7,$8c,$0b,$03,$68,$8d,$0a,$03,$4c,$59
		.byte	$e4,$4f,$01,$40,$40,$ea,$02,$1e,$00,$04,$00,$8d,$13,$03,$a2,$00
		.byte	$8e,$12,$03,$ca,$8e,$15,$03,$ad,$ec,$02,$6a,$90,$08,$ee,$ec,$02
		.byte	$d0,$03,$ee,$ed,$02,$ad,$ec,$02,$8d,$d1,$02
		.byte	$ad,$ed,$02,$8d,$d2
		.byte	$02,$a9,$a3,$8d,$cf,$02,$a9,$c9,$8d,$d0,$02,$a9,$80,$8d,$d3,$02
		.byte	$4c,$0f,$c7,$ae,$15,$03,$e8,$8e,$15,$03,$f0,$08,$ae,$15,$03,$bd
		.byte	$7d,$03,$18,$60
		.byte	$a9,$80,$8d,$15,$03,$20,$c0,$c9,$10,$ee,$38,$60
		.byte	$a2,$0b,$bd,$de,$c9,$9d,$00,$03,$ca,$10,$f7,$ae,$12,$03,$8e,$0a
		.byte	$03,$e8,$8e,$12,$03,$ad,$13,$03,$8d,$00,$03,$4c,$59,$e4,$00,$01
		.byte	$26,$40,$fd,$03,$1e,$00,$80,$00,$00,$00,$a0,$11,$a9,$00,$18,$71
		.byte	$4a,$88,$10,$fb,$69,$00,$49,$ff,$60,$8c,$12,$03,$8d,$13,$03,$a9
		.byte	$e9,$85,$4a,$a9,$03,$85,$4b,$a0,$12,$b1,$4a,$aa,$c8,$b1,$4a,$cd
		.byte	$13,$03,$d0,$07,$ec,$12,$03,$d0,$02,$18,$60,$c9,$00,$d0,$06,$e0
		.byte	$00,$d0,$02,$38,$60,$86,$4a,$85,$4b,$20,$ea,$c9,$d0,$f5,$f0,$d7
		.byte	$38,$08,$b0,$28,$8d,$ed,$02,$8c,$ec,$02,$08,$a9,$00,$a8,$20,$f9
		.byte	$c9,$b0,$27,$a0,$12,$ad,$ec,$02,$91,$4a,$aa,$c8,$ad,$ed,$02,$91
		.byte	$4a,$86,$4a,$85,$4b
		.byte	$a9,$00,$91,$4a,$88,$91,$4a,$20,$9c,$ca,$90
		.byte	$0c,$ad,$ed,$02,$ac,$ec,$02,$20,$eb,$ca,$28,$38,$60,$28,$b0,$09
		.byte	$a9,$00,$a0,$10,$91,$4a,$c8,$91,$4a,$18,$a0,$10,$ad,$e7,$02,$71
		.byte	$4a,$8d,$e7,$02,$c8,$ad,$e8,$02,$71,$4a,$8d,$e8,$02,$a0,$0f,$a9
		.byte	$00,$91,$4a,$20,$ea,$c9,$a0,$0f,$91,$4a,$18,$60,$18,$a5,$4a,$69
		.byte	$0c,$8d,$12,$03,$a5,$4b,$69,$00,$8d,$13,$03,$6c,$12,$03,$48,$98
		.byte	$48,$8a,$a2,$00,$dd,$1a,$03,$f0,$1e,$e8,$e8,$e8,$e0,$22,$30,$f4
		.byte	$a2,$00,$a8,$a9,$00,$dd,$1a,$03,$f0,$13,$e8,$e8,$e8,$e0,$22,$30
		.byte	$f4,$68,$68,$a0,$ff,$38,$60,$68,$a8,$68,$e8,$38,$60,$98,$9d,$1a
		.byte	$03,$68,$9d,$1b,$03,$68,$9d,$1c,$03,$18,$60,$20,$f9,$c9,$b0,$3b
		.byte	$a8,$a5,$4a,$48,$a5,$4b,$48,$86,$4a,$84,$4b,$ad,$44,$02,$d0,$0f
		.byte	$a0,$10,$18,$b1,$4a,$c8,$71,$4a,$d0,$1f,$20,$ea,$c9,$d0,$1a,$a0
		.byte	$12,$b1,$4a,$aa,$c8,$b1,$4a,$a8,$68,$85,$4b,$68,$85,$4a,$98,$a0
		.byte	$13,$91,$4a,$88,$8a,$91,$4a,$18,$60,$68,$68,$38,$60,$a0,$00,$b1
		.byte	$24,$a4,$21,$20,$4b,$c9,$10,$03,$a0,$82,$60,$a9,$7f,$85,$20,$a9
		.byte	$ac,$85,$26,$a9,$fe,$85,$27,$ad,$ec,$02,$ae,$2e,$00,$9d,$4d,$03
		.byte	$a0,$00,$b1,$24,$9d,$4c,$03,$a0,$01,$60,$ae,$2e,$00,$bd,$4d,$03
		.byte	$20,$6b,$c9,$b0,$20,$18,$20,$3a,$ca,$b0,$1a,$ae,$2e,$00,$bd,$4c
		.byte	$03,$20,$16,$e7,$b0,$0f,$ae,$2e,$00,$9d,$40,$03,$85,$20,$a9,$03
		.byte	$85,$17,$4c,$5c,$e5,$4c,$10,$e5

		.include "checksum.inc"

		.else

C8FC:		lda	#$FF		; start self test!
		sta	COLDST
		lda	PORTB
		and	#%01111111
		sta	PORTB
		jmp	SLFTSV

parbus_init:	lda	#1
		sta	SHPDVS
@1:		lda	SHPDVS
		sta	PDVS
		lda	$D803		; ID number
		cmp	#$80
		bne	@2
		lda	$D80B		; ID number
		cmp	#$91
		bne	@2
		jsr	$D819		; jmp addr
@2:		asl	SHPDVS
		bne	@1
		lda	#0
		sta	PDVS
		rts

		; ******************
		; **              **
		; **  SERIAL I/O  **
		; **              **
		; ******************

		; !!! patched by XL-IT! !!!

SIO:		lda	#1		; start of critical timing region
		.byte	$8D		; sta CRITIC (absolute)
		.word	CRITIC

		lda	DUNIT		; save DUNIT
		pha
	
		lda	PDVMSK
		beq	@2

		ldx	#8
@1:		jsr	C9AF
		beq	@2
		txa			; save X
		pha
		jsr	$D805		; jmp instruction
		pla
		tax			; restore X
		bcc	@1
		lda	#0
		sta	SHPDVS
		sta	PDVS
		beq	@3		; skip to end-of-sio

		; "normal" SIO command
	
@2:		jsr	E971

@3:		pla			; restore DUNIT
		sta	DUNIT

		lda	#0		; end of critical timing region
		.byte	$8D		; sta CRITIC (absolute)
		.word	CRITIC

		sty	DSTATS
		ldy	DSTATS
		rts

		; ****************************
		; **                        **
		; **  PARALLEL IRQ HANDLER  **
		; **                        **
		; ****************************

PIRQ:		ldx	#8
@1:		ror
		bcs	@2
		dex
		bne	@1
@2:		lda	SHPDVS
		pha
		lda	BARREL-1,X
		sta	SHPDVS
		sta	PDVS
		jsr	$D808		; 'jmp'
		pla
		sta	SHPDVS
		sta	PDVS
		pla
		tax
		pla
		rti

C991:		ldy	#1
		jmp	C9DC
C996:		ldy	#3
		jmp	C9DC
C99B:		ldy	#5
		jmp	C9DC
C9A0:		ldy	#7
		jmp	C9DC
C9A5:		ldy	#9
		jmp	C9DC
C9AA:		ldy	#11
		jmp	C9DC

C9AF:		dex
		bpl	@1
		lda	#0
		sta	SHPDVS
		sta	PDVS
		rts

@1:		lda	PDVMSK
		and	BARREL,X
		beq	C9AF
		sta	SHPDVS
		sta	PDVS
		rts

C9CA:		lda	$D80D,Y		; open vector
		pha
		dey
		lda	$D80D,Y		; open vector
		pha
		lda	PPTMPA
		ldx	PPTMPX
		ldy	#146
		rts

C9DC:		sta	PPTMPA
		stx	PPTMPX

		.byte	$AD		; lda CRITIC (absolute)
		.word	CRITIC

		pha
		lda	#1

		.byte	$8D		; sta CRITIC (absolute)
		.word	CRITIC

		ldx	#8
@1:		jsr	C9AF
		beq	@2
		txa
		pha
		tya
		pha
		jsr	C9CA
		bcc	@4
		sta	PPTMPA
		pla
		pla
		jmp	@3

@2:		ldy	#130
@3:		lda	#0
		sta	SHPDVS
		sta	PDVS
		pla

		.byte	$8D		; sta CRITIC (absolute)
		.word	CRITIC

		lda	PPTMPA
		sty	PPTMPX
		ldy	PPTMPX
		rts

@4:		pla
		tay
		pla
		tax
		bcc	@1		; jmp @1

		; Barrel Shifter

BARREL:		.byte	%10000000
		.byte	%01000000
		.byte	%00100000
		.byte	%00010000
		.byte	%00001000
		.byte	%00000100
		.byte	%00000010
		.byte	%00000001

CA29:		.byte	$AE		; ldx ICAX5Z (absolute)
		.word	ICAX5Z

		lda	$34D,X
		.if	(OS_REVISION=59)
		nop
		nop
		nop
		.else
		jsr	E7DE
		.endif
		bcs	@1		; bcs E510
		clc
		.if	(OS_REVISION=59)
		nop
		nop
		nop
		.else
		jsr	E89E
		.endif
		bcs	@1

		.byte	$AE		; ldx ICAX5Z (absolute)
		.word	ICAX5Z

		lda	$34C,X
		jsr	E716
		bcs	@1		; bcs E510

		.byte	$AE		; ldx ICAX5Z (absolute)
		.word	ICAX5Z

		sta	IOCB,X
		sta	ICHIDZ
		lda	#3
		sta	ICCOMT
		jmp	E55C

@1:		jmp	E510

		; Some data, seems to be used by SELFTEST ROMS.

		.if	(OS_REVISION<=2)

CA57:		.byte	$00,$13,$16,$D1,$E4,$E4,$E8,$29,$EB,$EE

CA61:		.byte	$00,$00,$2D,$25,$2D,$2F,$32,$39	; '  MEMORY TEST   '
		.byte	$00,$34,$25,$33,$34,$00,$00,$00
		.byte	$32,$2F,$2D			; 'ROM'
		.byte	$32,$21,$2D			; 'RAM'
		.byte	$00,$00,$2B,$25,$39,$22,$2F,$21	; '  KEYBOARD TEST '
		.byte	$32,$24,$00,$34,$25,$33,$34,$00
		.byte	$00,$00,$B2,$91,$00,$92,$00,$93
		.byte	$00,$94,$00,$A8,$00,$A1,$00,$A2
		.byte	$00,$00,$00,$5B,$00,$11,$00,$12
		.byte	$00,$13,$00,$14,$00,$15,$00,$16
		.byte	$00,$17,$00,$18,$00,$19,$00,$10
		.byte	$00,$1C,$00,$1E,$00,$A2,$80,$B3
		.byte	$00,$00,$00,$FF,$FF,$00,$31,$00
		.byte	$37,$00,$25,$00,$32,$00,$34,$00
		.byte	$39,$00,$35,$00,$29,$00,$2F,$00
		.byte	$30,$00,$0D,$00,$1D,$00,$B2,$B4
		.byte	$00,$00,$00,$80,$DC,$80,$00,$21
		.byte	$00,$33,$00,$24,$00,$26,$00,$27
		.byte	$00,$28,$00,$2A,$00,$2B,$00,$2C
		.byte	$00,$1B,$00,$0B,$00,$0A,$00,$A3
		.byte	$00,$00,$00,$80,$B3,$A8,$80,$00
		.byte	$3A,$00,$38,$00,$23,$00,$36,$00
		.byte	$22,$00,$2E,$00,$2D,$00,$0C,$00
		.byte	$0E,$00,$0F,$00,$80,$B3,$A8,$80
		.byte	$00,$00,$00,$00,$00,$00,$00,$00
		.byte	$80,$B3,$80,$B0,$80,$A1,$80,$A3
		.byte	$80,$A5,$80,$80,$80,$A2,$80,$A1
		.byte	$80,$B2,$80,$00,$33,$00,$30,$00
		.byte	$21,$00,$23,$00,$25,$00,$00,$00
		.byte	$22,$00,$21,$00,$32,$00,$00,$33
		.byte	$28,$00,$22,$00,$33,$00,$5C,$00
		.byte	$36,$2F,$29,$23,$25		; 'VOICE'
		.byte	$00,$03

		.else

CA57:		.byte	$00,$13,$16,$cd,$e0,$e4,$e6,$25,$e7,$ea

CA61:		.byte	$00,$00,$2D,$25,$2D,$2F,$32,$39
		.byte	$00,$34,$25,$33,$34,$00,$00,$00
		.byte	$32,$2f,$2d,$32,$21,$2d,$00,$00
		.byte	$2b,$25,$39,$22,$2f,$21,$32,$24
		.byte	$00,$34,$25,$33,$34,$a8,$00,$00
		.byte	$b3,$00,$00,$f3,$00,$00,$AF,$00
		.byte	$00,$b2,$00,$00,$00,$5b,$00,$11
		.byte	$00,$12,$00,$13,$00,$14,$00,$15
		.byte	$00,$16,$00,$17,$00,$18,$00,$19
		.byte	$00,$10,$00,$1c,$00,$1e,$00,$a4
		.byte	$00,$a2,$00,$00,$00,$ff,$ff,$00
		.byte	$31,$00,$37,$00,$25,$00,$32,$00
		.byte	$34,$00,$39,$00,$35,$00,$29,$00
		.byte	$2f,$00,$30,$00,$0d,$00,$1d,$00
		.byte	$b2,$b4,$00,$00,$00,$80,$dc,$80
		.byte	$00,$21,$00,$33,$00,$24,$00,$26
		.byte	$00,$27,$00,$28,$00,$2a,$00,$2b
		.byte	$00,$2c,$00,$1b,$00,$0b,$00,$0a
		.byte	$00,$a3,$00,$00,$00,$80,$b3,$a8
		.byte	$80,$00,$3a,$00,$38,$00,$23,$00
		.byte	$36,$00,$22,$00,$2e,$00,$2d,$00
		.byte	$0c,$00,$0e,$00,$0f,$00,$b3,$a8
		.byte	$00,$48,$00,$00,$00,$00,$00,$00
		.byte	$00,$00,$80,$b3,$80,$b0,$80,$a1
		.byte	$80,$a3,$80,$a5,$80,$80,$80,$a2
		.byte	$80,$a1,$80,$b2,$80,$00,$33,$00
		.byte	$30,$00,$21,$00,$23,$00,$25,$00
		.byte	$00,$00,$22,$00,$21,$00,$32,$00
		.byte	$00,$33,$28,$00,$33,$28,$22,$00
		.byte	$5c,$00
		.byte	$36,$2F,$29,$23,$25		;  'VOICE'
		.byte	$00,$03,$00,$00,$00,$00
		.endif

		; 18-byte checksum!

CB56:		ldy	#17
		lda	#0
		clc
@1:		adc	(ZCHAIN),Y
		dey
		bpl	@1
		adc	#0
		eor	#$FF
		rts

		.if	(OS_REVISION=59)
		pha
		cmp	#$9B
		.byte	$f0,$1f
		cmp	#$7D
		.byte	$f0,$1e
		lda	$2A2
		sta	$CC
		.byte	$30,$05
		jsr	$F93C
		.byte	$f0,$15
		lda	$2BE
		.byte	$f0,$15
		.byte	$30,$13
		cmp	#$1B
		.byte	$90,$0f
		lda	$CF
		.byte	$f0,$06
		jmp	$E819
		jmp	$E829
		pla
		sta	$2FB
		rts

		jmp	$E881
		lda	$CF
		.byte	$d0,$0a
		lda	$54
		sta	$CE
		lda	$55
		sta	$CD
		inc	$CF
		lda	$CD
		cmp	$53
		.byte	$d0,$18
		ldx	$52
		dex
		stx	$CD
		lda	$CE
		cmp	#23
		.byte	$f0,$0d
		ldx	$2BF
		.byte	$e0,$04
		.byte	$d0,$04
		cmp	#3
		.byte	$f0,$02
		inc	$CE
		php
		inc	$CD
		asl	$2A2
		lda	#$FF
		sta	$2FB
		jsr	$F2BE
		plp
		.byte	$d0,$0a
		lda	#$FF
		jsr	$F2B0
		lda	#$FE
		jsr	$F2B0
		lda	$CC
		sta	$2A2
		pla
		jsr	$F2B0
		lda	#$1E
		ldx	$55
		cpx	$52
		.byte	$d0,$05
		jsr	$F2B0
		lda	#$1C
		sta	$2FB
		jmp	$F962
		sta	$244
		sta	$CF
		rts

		.elseif	(OS_REVISION>=4)

CB65:		lda	CONSOL
		ror
		and	#%00000011
		cmp	#1
		beq	@2
		eor	TRIG2
		beq	@1
		cmp	#3
		beq	@1
		jmp	C4A1
@1:		lda	PORTB
		and	#%10111111
		sta	PORTB
@2:		jmp	C4A9
		.res	10,0

CB90:		lda	CONSOL
		lsr
		bcc	CB90
		ldy	#0
@1:		sta	WSYNC
		iny
		bne	@1
@2:		lda	CONSOL
		lsr
		bcc	@3
		ldy	CH
		iny
		beq	@2
		jmp	FE36
@3:		iny
		rts

		.endif
		.endif

		.res ($CC00-*),0 ; next block starts at CC00; fill with zeroes.

		.end
