;----------------------------------------------------------------
; COLRBOOT.A86 - Puts a color message on last four sectors of disk
; and rewrites sector so message will display if the disk is booted.
; For A86V371 assembler 28 July 1994
; Revised for text 3 August 1994
; Minor revision 27 October 1994

; This will assemble with A86 VERSION 3.71
;	A86 COLRBOOT.A86

; JIM TUCKER	4/635 Brighton Road, Seacliff
;		South Australia, AUSTRALIA 5051 Phone: 61 8 377-1175
;		jtucker@adam.com.au

;----------------------------------------------------------------

lf	equ	10
cr	equ	13
eom	equ	'$'

;   BIOS LOADS BOOT SECTOR Entry:
;   CS:IP - 0:7C00h
;      DL - boot drive
;   ES:SI - Ptr to partition table boot entry (if hard disk)
;   All other registers undefined

bytes_per_sec   equ     word ptr [bp+0bh]
sec_per_cluster equ     byte ptr [bp+0dh]
reserved_sec    equ     word ptr [bp+0eh]
number_of_fats  equ     byte ptr [bp+10h]
root_size       equ     word ptr [bp+11h]
total_sec       equ     word ptr [bp+13h]
media_des_byte  equ     byte ptr [bp+15h]
sec_per_fat     equ     word ptr [bp+16h]
sec_per_track   equ     word ptr [bp+18h]
number_of_heads equ     word ptr [bp+1ah]
num_hidden_sec  equ     word ptr [bp+1ch]
total_sec_long  equ     word ptr [bp+20h]
drive_number    equ     word ptr [bp+24h]
reserved        equ     word ptr [bp+25h]
extended_flag   equ     word ptr [bp+26h]
vol_serial      equ     word ptr [bp+27h]
vol_name        equ     word ptr [bp+2bh]
boot_flag       equ     word ptr [bp+3feh]      ;OFFSET+512 for code

reloc_entry     equ     OFFSET boot_2 - 100h
boot_hard_msg	equ	7900h + OFFSET hard_msg
boot_floppy_msg	equ	7900h + OFFSET floppy_msg
boot_halt_msg	equ	7900h + OFFSET halt_msg

;--------------------------------------------------------------------
; Boot sector code. The existing BPB on the target disk is written here.
; The target disk *must* be DOS formatted to obtain this information.
;--------------------------------------------------------------------

		org	100h
ENTRY:          jmp     signon			;becomes jmp boot_1
BOOT_DATA       db	0			;NZ to prevent UNREG msg
		db      63 dup (0)              ;leave room for BPB
BOOT_DATAEND    =       $

BOOT_1:         cli
		cld
                mov     ax,7A00h
                xor     bx,bx
                mov     ss,bx                   ;SS:SP = 0:7A00
                mov     sp,ax
                sti
                push    si
                push    bp
                mov     bp,ax			;BP is new location

; This moves all code from 7A00 to 7C00h and jumps to BOOT_2 via RETF

		mov     ds,bx                   ;DS = 0
                mov     es,bx                   ;ES = 0
                mov     di,ax                   ;Move boot code
                mov     si,7C00h
                mov     cx,100h
                rep     movsw

                push    es                      ;Push re-entry segment
                mov     al,reloc_entry          ;  BOOT2 OFFSET on stack
                push    ax                      ;  and go there...
		retf

; The code is moved and we read the message to location 8000h
; Note MESG_LOC is the cluster number changed by installation for disk
; sizes other than 1.44M. (1.44 last sctr=2879, we use last eight sectors).

BOOT_2:		db	0B8h			;mov ax imm16 instruction
MESG_LOC	dw	2870			;changes with disk size
SKIP_MESG:	jmp	>l1			;*** NOPPED BY AUTOBOOT
		jmp	test_hard		;    AND NOFILE

L1:		call	maths			;do disk sums
		mov	bx,8000h		;where to put it
		
; This tries to read our message file (five times)

		mov	si,5
L1:		mov	dl,0			;drive zero
		mov	ax,0208h		;read eight sectors
		int	13h
		jnc	done
		xor	ax,ax
		int	13h
		dec	si
		jnz	l1

; Fall thru, if the read failed. We will not have the message code AAAAh
; and the message won't display anyway. Test for AAAAh (our code words)
; and if not found do not display anything. This prevents garbage
; display if the disk has been filled.

DONE:		mov	si,8000h		;where it is in memry
		lodsw				;get first word
		cmp	ax,0AAAAh		;us?
		je	>l1			;yes
		jmp	test_hard		;no message to write

; This writes the color message direct to the screen

L1:		mov	ah,0Fh			;get video mode
		int	10h
		push	ax
		mov	ah,0			;clear screen
		int	10h			;  by resetting mode
		pop	ax
		cmp	al,3
		mov	ax,0B800h
		jbe	>l1		
		mov	ah,0B0h			;(al is already zero)		
L1:		push	es			;get screen segment in es
		mov	es,ax
		xor	di,di
		push	di
		pop	ds
		mov	cx,25*80		;screen size
		repnz	movsw
		pop	es

; Note CURPOS can be modified on the command line by /Pnn

		db	0B6h			;mov dh imm8 instruction
CURPOS		db	21			;cursor line (Starts at 0)
		mov	dl,0			;  and column
		mov	bh,dl			;video page zero
		mov	ah,2			;position cursor
		int	10h

TEST_HARD:	mov	ah,10h			;test for hard disk
		mov	dl,80h			;first disk only
		int	13h			;if exist
		jc	>l4			;not found

; Note if the following JMP is nopped by installer we boot immediately
; from the hard drive.

BOOT_C:		jmp	>l9			;** NOPPED for autoboot
		push	bp
		jmp	boot_hard

L9:		push	bp
		mov	ah,0
		int	1ah
		db	81h,0C2h	;add dx imm16 opcode
TIMER_WORD	dw	0		;default = 1/18th secs
		inc	dx		;in case he makes it zero
					;  and clocks rolls over
		mov	bx,dx		;  during this op
L2:		int	1ah
		cmp	dx,bx
		jne	l2

		mov	si,boot_hard_msg	;wanna boot it?	
		call	bprint_msg

L21:		mov	ah,1			;clear kboard buffer
		int	16h			;  in case he hit keys
		jz	>l3			;  during time delay
		xor	ah,ah			;ah=0
		int	16h
		jmp	l21

L3:		xor	ah,ah			;BIOS get key
		int	16h
		or	al,20h
		cmp	al,'y'
		je	boot_hard		;yes
		cmp	al,'n'
		jne	l3

; Fall thru to boot from floppy

L4:		mov	si,boot_floppy_msg	;wants floopy boot
		call	bprint_msg
		mov	ah,0			;wait for a key
		int	16h
		call	clear_screen
		int	19h			;warm boot

; This reads drive C: sector zero into 7C00h and jumps there

BOOT_HARD:	call	clear_screen
		pop	bp
		call    boot_read_disk
		jc      boot_error

		cmp     boot_flag,0AA55h        ;Check for boot sig
                jne     boot_error
                pop     bp                      ;Restore BP from entry
                pop     si                      ;  Is BP for DR-DOS only?
		jmp     bx                      ;Jump to new boot rec

;Clear the screen

CLEAR_SCREEN:	mov	ah,0Fh		;get video mode
		int	10h
		mov	ah,0		;set video mode
		int	10h
		ret

BOOT_ERROR:	mov     si,boot_halt_msg        ;Print err message
BOOT_ERROR1:	call    bprint_msg
BOOT_HALT:	jmp     boot_halt               ;STOP!

;-----------------------------------------------------------------------
; BOOT_READ_DISK: Reads one sector from the hard disk
;		  CF - Clear if read successful.
;-----------------------------------------------------------------------

BOOT_READ_DISK: xor     ax,ax                   ;Read boot sector
		call	maths
		mov	bx,7C00h		;where to put it

L1:		mov     dl,80H			;80h is first hard disk
		mov     ax,0201h		;read one sector
                int     13h
                jnc     ret			;no error, exit
                xor     ax,ax                   ;reset disk before reading
                int     13h
                dec     si
                jnz     l1
                mov     si,boot_halt_msg	;read error message
                stc
		ret

; This does some calculations common to both disk reads

MATHS:		cwd
		div	sec_per_track
		inc	dx
		mov	bx,dx
		cwd
		div	number_of_heads
		xchg	ah,al
		mov	cl,6
		shl	al,cl
		xchg	cx,ax
		or	cl,bl
		mov	dh,dl
		mov	si,5
		ret

;--------------------------------------------------------------------
; BPRINT_MSG: - Prints a message to the screen
; Entry: DS:SI - Points to ASCIIZ message
;--------------------------------------------------------------------

BPRINT_MSG:	push    bx
                push    bp
L1:		lodsb
                or      al,al
                je      >l2
                mov     ah,0eh
                mov     bx,7h
                push    si
                int     10h
                pop     si
                jmp     l1
L2:		pop     bp
                pop     bx
                ret

HALT_MSG	db	'CANNOT BOOT - SYSTEM HALTED  ',0
FLOPPY_MSG	db	cr,lf
		db	'Non-System disk. Replace and ',cr,lf
		db	'press any key when ready     ',0
HARD_MSG	db	'Boot from hard disk (Y/N)?   ',0

BOOTCODE_END    = $
SPARE_DATA	= 2FEh-BOOTCODE_END		
		db	spare_data dup ' '
		org     2FEh
                dw      0AA55h

;****************************************************************
; START OF INSTALLATION CODE
;****************************************************************

IBM_SYS		db	'A:IBMBIO.COM',0
MS_SYS		db	'A:IO.SYS',0	
AUTOBOOT	db	'AUTOBOOT',0
NOFILE		db	'NOFILE',0
BLANK		db	'BLANK',0
TARGET_DISK	db      0
REGISTER_BYTE	db	?
VIDEO_SEG	dw	0B800h
OLD_VIDEO_SEG	dw	0B800h
MONO_SWITCH	db	0
VIDEO_MODE	db	?

SIGNON:		mov	dx,OFFSET hello
		mov	ah,9
		int	21h

		call	clear_buffers		;intialise to zero
		call	cmdline			;sort it out
		call	check_register		;/R to prevent display
		call	check_video		;/M for mono?
		call	check_curpos		;see if cursor positioned
		call	check_timer		;see if timer set
		call	check_color		;see if color for text
		call	check_filename		;want it displayed?
		call	read_file1		;check the filename etc
		call	read_file2		;read text file if any
		call	get_target		;handle A: or B:
		call	check_sys		;ensure not a system disk
		call	get_size		;how big is it?
		call	verify			;check sectors are free
		call	write_message		;write our message
		call	write_boot		;write the boot sector

		mov	dx,OFFSET done_message
		mov	ah,9
		int	21h
		mov	ax,4C00h
		int	21h

;----------------------------------------------------------------
; Clears buffers to zero bytes
;----------------------------------------------------------------

CLEAR_BUFFERS:	mov	di,TEXT_FILE_BUFFER
		mov	ax,0
		mov	cx,1000
		rep	stosw
		mov	ah,[103h]
		mov	register_byte,ah
		ret

;----------------------------------------------------------------
; Check registered
;----------------------------------------------------------------

CHECK_REGISTER: mov	si,OFFSET switch_buffer
L2:		lodsb
L3:		or	al,al			;end
		jz	ret			;yes
		cmp	al,'/'			;switch
		jne	l2			;no
		lodsb				;get
		cmp	al,'R'			;us?
		jne	l3			;no, maybe zero
		mov	register_byte,1		;set reg byte
		ret

;----------------------------------------------------------------
; CHECK_VIDEO: This checks if user wants mono display
;----------------------------------------------------------------

CHECK_VIDEO:	mov	ah,0Fh			;get current mode
		int	10h			;video
		mov	video_mode,al		;save current mode
		cmp	al,7			;is it mono?
		jne	>l1			;no
		mov	ax,0B000h
		mov	video_seg,ax		;change seg
		mov	old_video_seg,ax

L1:		mov	si,OFFSET switch_buffer
L2:		lodsb
L3:		or	al,al			;end
		jz	ret			;yes
		cmp	al,'/'			;switch
		jne	l2			;no
		lodsb				;get
		cmp	al,'M'			;us?
		jne	l3			;no, maybe zero
		mov	mono_switch,1		;set mono switch
		ret

;----------------------------------------------------------------
; CHECK_CURPOS: This checks for optional cursor position /Pnn
;----------------------------------------------------------------

TEN		dw	10
CHECK_CURPOS:	mov	si,OFFSET switch_buffer
L1:		lodsb				;get
L2:		or	al,al			;done?
		jz	ret			;yes
		cmp	al,'/'			;switch?
		jne	l1			;no
		lodsb				;get
		cmp	al,'P'			;us?
		jne	l2			;no, maybe zero

		mov	al,[si]			;get next
		or	al,al			;zero
		jz	bad_curpos		;error
		cmp	al,'='			;=?
		jne	>l2			;no, assume digit
		inc	si			;scrub it

L2:		xor	ax,ax			;arithmetic
		xor	bx,bx
		xor	dx,dx

L3:		mov	bl,[si]
		or	bl,bl
		jz	>l4
		cmp	bl,'/'
		je	>l4
		
		inc	si
		sub	bl,'0'
		jc	bad_curpos
		cmp	bl,9
		ja	bad_curpos
		mul	ten
		add	ax,bx
		jmp	l3

L4:		dec	al
		mov	curpos,al
		ret

BAD_CURPOS:	mov	dx,OFFSET bad_curpos_mesg
		jmp	error_message


;----------------------------------------------------------------
; CHECK_TIMER: This checks for optional time out /Tnn
;----------------------------------------------------------------

TICKS_PER_SEC	dw	18
CHECK_TIMER:	mov	si,OFFSET switch_buffer
L1:		lodsb				;get
L2:		or	al,al			;done?
		jz	ret			;yes
		cmp	al,'/'			;switch?
		jne	l1			;no
		lodsb				;get
		cmp	al,'T'			;us?
		jne	l2			;no, maybe zero

		mov	al,[si]			;get next
		or	al,al			;zero
		jz	bad_timer		;error
		cmp	al,'='			;=?
		jne	>l2			;no, assume digit
		inc	si			;scrub it

L2:		xor	ax,ax			;arithmetic
		xor	bx,bx
		xor	dx,dx

L3:		mov	bl,[si]
		or	bl,bl
		jz	>l4
		cmp	bl,'/'
		je	>l4
		
		inc	si
		sub	bl,'0'
		jc	bad_timer
		cmp	bl,9
		ja	bad_timer
		mul	ten
		add	ax,bx
		jmp	l3

L4:		cmp	ax,60
		jbe	>l5
		mov	dx,OFFSET too_long_mesg
		jmp	error_message
L5:		mul	ticks_per_sec
		mov	timer_word,ax
		ret

BAD_TIMER:	mov	dx,OFFSET bad_timer_mesg
		jmp	error_message

;----------------------------------------------------------------
; CHECK_COLOR: This tests for option text color in hex
;----------------------------------------------------------------

SIXTEEN		dw	16
CHECK_COLOR:	mov	si,OFFSET switch_buffer
L1:		lodsb				;get char
L2:		or	al,al			;end?
		jz	ret			;yes
		cmp	al,'/'			;switch?
		jne	l1			;no
		lodsb				;get next
		cmp	al,'C'			;us?
		jne	l2			;no

		mov	al,[si]			;next
		or	al,al			;end?
		jz	show_colors		;yes
		cmp	al,'='			;this?
		jne	>l2			;no, assume digit
		inc	si			;lose it

L2:		xor	ax,ax			;arithmetic
		xor	bx,bx
		xor	dx,dx

L3:		mov	bl,[si]
		or	bl,bl
		je	>l5
		cmp	bl,'/'
		je	>l5
		
		inc	si
		xchg	ax,bx
		call	caps
		xchg	bx,ax

		sub	bl,'0'
		jc	show_colors
		cmp	bl,9
		jbe	>l4

		sub	bl,7
		jc	show_colors
		cmp	bl,15
		ja	show_colors

L4:		mul	sixteen
		add	ax,bx
		jmp	l3

L5:		or	ax,ax
		jz	show_colors
		or	dx,dx
		jnz	show_colors
		or	ah,ah
		jnz	show_colors

		mov	text_color,al
		ret

SHOW_COLORS:	jmp	display_color_help

;----------------------------------------------------------------
; CHECK_FILENAME: This checks if user want filenames displayed
;----------------------------------------------------------------

FILENAME_SWITCH	db	0

CHECK_FILENAME:	mov	si,OFFSET switch_buffer
L1:		lodsb
		cmp	al,0
		je	ret
		cmp	al,'/'
		jne	l1
		lodsb
		cmp	al,'F'
		jne	l1

		mov	filename_switch,1
		ret

;----------------------------------------------------------------
; READ_FILE1: This reads the user file specified on the command line
;             If AUTOBOOT NOFILE or BLANK set NOPs in boot sector 
;----------------------------------------------------------------

LENGTH		dw	?
READ_FILE1:	test	W filename1
		if z	jmp help		;no file

; This checks for AUTOBOOT

		mov	si,filename1
		mov	di,OFFSET autoboot
		mov	cx,8
L1:		cmpsb
		jne	>l2
		loop	l1
		mov	di,OFFSET boot_c	;NO PROMPT FOR C
		mov	ax,9090h		;NOP NOP
		stosw
		mov	di,OFFSET skip_mesg	;NO MESSAGE DISPLAY
		stosw				;NOP NOP
		mov	W signature,0
		test	B drive1
		if z	jmp help	
		ret

; This checks for NOFILE

l2:		mov	si,filename1
		mov	di,OFFSET nofile
		mov	cx,6
L3:		cmpsb
		jne	>l4
		loop	l3
		mov	di,OFFSET skip_mesg	;NO MESSAGE DISPLAY
		mov	ax,9090h		;NOP NOP
		stosw
		mov	W signature,0
		test	B drive1
		if z	jmp help
		ret

; This checks for BLANK

l4:		mov	si,filename1
		mov	di,OFFSET blank
		mov	cx,5
L5:		cmpsb
		jne	>l1
		loop	l5

		mov	di,COLOR_FILE_BUFFER
		mov	cx,2000
		mov	ah,text_color
		mov	al,20h
		rep	stosw
		jmp	>l0

; No AUTOBOOT, NOFILE, BLANK so we must have a filename

L1:		mov 	dx,filename1		;open
		mov	ax,3D00h
		int	21h
		jnc	>l2
		mov	dx,OFFSET no_file_mesg
		jmp	error_message

L2:		mov	bx,ax			;get length
		mov	ax,4202h
		mov	cx,0
		mov	dx,0
		int	21h
		mov	length,ax
		jnc	>l3
		mov	dx,OFFSET bad_size_mesg
		jmp	error_message

L3:		cmp	ax,4000			;test length
		je	>l4
		mov	dx,OFFSET bad_size_mesg
		jmp	error_message

L4:		mov	ax,4200h		;rewind it
		mov	cx,0
		mov	dx,0
		int	21h

		mov	ax,3F00h		;read file
		mov	cx,length
		mov	dx,COLOR_FILE_BUFFER
		int	21h
		jnc	>l5
		mov	dx,OFFSET read_err_mesg
		jmp	error_message

L5:		mov	ah,3Eh			;close file
		int	21h

; Now insert the prompt blanks on the color screen

L0:		mov	ah,0			;put the prompt at /P
		mov	al,curpos
		cmp	al,24			;0-24
		ja	>l3			;off the screen

		mov	cl,al
		xor	dx,dx
		mov	bx,160			;bytes per line
		mul	bx
		mov	di,ax			;is here
		add	di,COLOR_FILE_BUFFER

		mov	ax,0720h
		cmp	cl,24			;remember 0-24
		je	>l2			;just do one
		cmp	cl,23			;two to do?
		je	>l1			;yes

		mov	cx,30
		rep	stosw
		add	di,100

L1:		mov	cx,30
		rep	stosw
		add	di,100

L2:		mov	cx,30
		rep	stosw

L3:		mov	dx,OFFSET reading_mesg
		call	print_message
		ret

;----------------------------------------------------------------
; READ_FILE2: This reads the SECOND file if specified
;----------------------------------------------------------------

GRID_NAME	db	'GRID',0
READ_FILE2:	test	W filename2
		jz	ret			;there isn't one
		
; Test if he is requesting a grid

		mov	si,filename2
		mov	di,OFFSET grid_name
		mov	cx,4
L1:		cmpsb
		jne	>l2
		loop	l1
		jmp	write_grid

L2:		mov	dx,filename2		;open file
		mov	ax,3d00h
		int	21h
		jnc	>l1
		mov	dx,OFFSET no_text_mesg
		jmp	error_message

L1:		mov	bx,ax			;get length
		mov	ax,4202h
		mov	cx,0
		mov	dx,0
		int	21h
		mov	length,ax
		jnc	>l2
		mov	dx,OFFSET bad_size_mesg
		jmp	error_message

L2:		cmp	ax,2000			;test for size
		jbe	>l3
		mov	dx,OFFSET bad_size_mesg2
		jmp	error_message

L3:		mov	ax,4200h		;rewind it
		mov	cx,0
		mov	dx,0
		int	21h

		mov	ax,3F00h		;read file
		mov	cx,length
		mov	dx,TEXT_FILE_BUFFER
		int	21h
		jnc	>l4
		mov	dx,OFFSET read_err_mesg
		jmp	error_message

L4:		mov	ah,3eh			;close file
		int	21h

		mov	dx,OFFSET reading_mesg2
		call	print_message
		jmp	overlay_text

; Now lay it on top of the color message

LINE_NUMBER	dw	0
BYTES_PER_LINE	dw	160
PROMPT_FLAG	db	0			;this is set if writing
TEXT_COLOR	db	07h			;set by /Cnn switch
CHAR_COUNT	db	0			;so we don't bust a line

WRITE_GRID:	mov	si,OFFSET grid		;lay down the grid
		call	overlay			;and come back for prompt

WRITE_PROMPT:	mov	ah,0			;put the prompt
		mov	al,curpos		; according to /P
		dec	ax			;prompt starts with a cr
		mov	line_number,ax		;force it here
		inc	prompt_flag
		mov	si,OFFSET grid_prompt	;source
		jmp	overlay			;and return to main

OVERLAY_TEXT:	mov	si,TEXT_FILE_BUFFER
OVERLAY:	mov	di,COLOR_FILE_BUFFER

L1:		lodsb				;get char from text buffer
		cmp	al,cr			;new line?
		je	>l3			;yes
		cmp	al,lf			;ignore lf
		je	l1
		cmp	al,0			;end of it?
		je	ret

		cmp	al,'_'
		jne	>l2
		add	di,2
		jmp	l1

L2:		inc	char_count
		cmp	char_count,80
		ja	l1

		stosb				;save it
		mov	al,text_color		;make it /Cnn
		test	prompt_flag		;unless it's the prompt...
		jz	>l21
		mov	al,07h
L21:		stosb
		jmp	l1			;do more		

L3:		mov	char_count,0
		inc	line_number		;new line
		mov	ax,line_number		;here
		cmp	ax,25			;past end?
		ja	ret
		mul	bytes_per_line		;position of next line
		mov	di,ax			;is here
		add	di,COLOR_FILE_BUFFER
		jmp	l1			;do more
		ret

;----------------------------------------------------------------
; GET_TARGET: This puts the target drive in TARGET_DISK and IO NAMES
; Return if A: (default) or error if <> B:
;----------------------------------------------------------------

GET_TARGET:	mov	al,drive1 B
		test	al
		if z	jmp display_file
		cmp	al,'A'
		je	ret
		cmp	al,'B'
		je	>l1
		mov	dx,OFFSET bad_target_mesg
		jmp	error_message

L1:		mov	target_disk,1
		mov	ibm_sys,'B'
		mov	ms_sys,'B'
		ret

;----------------------------------------------------------------
; CHECK_SYS: This checks if system is on the target disk by trying
; to open two files.
;----------------------------------------------------------------

CHECK_SYS:	mov	dx,OFFSET target_mesg
		call	print_message

		mov	dx,OFFSET ibm_sys	;check for ibmio.com	
		mov	ax,3D00h
		int	21h
		jnc	>l1
		mov	dx,OFFSET ms_sys	;check for io.sys
		mov	ax,3D00h
		int	21h
		jc	ret
L1:		mov	dx,OFFSET system_mesg
		jmp	error_message
		ret

;----------------------------------------------------------------
; GET_SIZE: This establishes the size of the target disk and the
; sector we will use for the color message
;----------------------------------------------------------------

GET_SIZE:	mov	dl,target_disk
		inc	dl
		mov	ah,36h
		int	21h
		mov	bx,dx
		xor	dx,dx			;sec per cluster
		mul	cx			;times bytes per sec
		cmp	dx,0
		jne	size_error
		mul	bx			;number of clusters

		add	ax,dx			;ah=ax al=dx
		cmp	ax,3E16h		;ie 0016:3E00=1457664
		je	size_144
		cmp	ax,240Bh
		je	size_720
		cmp	ax,8805h
		je	size_360
		cmp	ax,8612h
		je	size_12

SIZE_ERROR:	mov	dx,OFFSET wrong_disk_mesg
		jmp	error_message

SIZE_144:	mov	dx,OFFSET size_144_mesg		;2870 already there
		jmp	>l1
SIZE_720:	mov	mesg_loc,1360
		mov	dx,OFFSET size_720_mesg
		jmp	>l1
SIZE_360:	mov	mesg_loc,710
		mov	dx,OFFSET size_360_mesg
		jmp	>l1
SIZE_12:	mov	mesg_loc,2390
		mov	dx,OFFSET size_12_mesg

L1:		call	print_message
		ret

;----------------------------------------------------------------
; VERIFY: Sends a warning message if data .ne. F6h on target sector
; by doing an absolute read to the sector
;----------------------------------------------------------------

VERIFY:		mov	ax,signature W
		cmp	ax,0AAAAh
		jne	ret

		mov	al,target_disk
		mov	cx,1
		mov	dx,mesg_loc
		mov	bx,VERIFY_BUFFER
		int	25h
		pop	bx			;stack garbage
		jnc	>l1
		call	seterrmsg
		jmp	init_error

L1:		mov	si,VERIFY_BUFFER
		lodsw
		cmp	ax,0F6F6h
		je	ret

		mov	dx,OFFSET verify_mesg	;want to continue?
		call	print_message
L2:		mov	ah,8			;wait for a key
		int	21h
		or	al,20h
		cmp	al,'y'
		je	ret
		cmp	al,'n'
		jne	l2
		mov	dx,OFFSET abort_mesg
		jmp	error_message

;----------------------------------------------------------------
; WRITE_MESSAGE: This writes the message to the disk unless the
; signature has been zapped
;----------------------------------------------------------------

UNREG_MSG db ' '-64,'U'-64,'N'-64,'R'-64,'E'-64,'G'-64,'I'-64
	  db 'S'-64,'T'-64,'E'-64,'R'-64,'E'-64,'D'-64,' '-64

WRITE_MESSAGE:

; THIS WRITES AN UNREGISTERED MESSAGE

		test	register_byte
		jnz	>l2

		mov	di,OFFSET signature
		add	di,4000-26
		mov	ah,01Eh+80h
		mov	bx,OFFSET UNREG_MSG
		mov	cx,14
L1:		mov	al,[bx]
		inc	bx
		add	al,64
		stosw
		loop	l1

L2:		mov	ax,signature W
		cmp	ax,0AAAAh
		jne	ret

		mov	al,target_disk
		mov	cx,8			;8 sectors
		mov	dx,mesg_loc
		mov     bx,OFFSET signature
		int     26h                     ;DOS Absolute Disk Write
		pop	bx			;stack shit
		jnc	ret			;done
		call	seterrmsg
		jmp	init_error

;--------------------------------------------------------------------
; WRITE_BOOT: - Installs our boot record on the target diskette
; Exit:  	CF - Set if error
;        	DX - OFFSET of error message if CF set
;--------------------------------------------------------------------

WRITE_BOOT:	mov	dx,OFFSET install_mesg
		call	print_message

; This writes a new jump at start of our boot sector (100h)

		mov     di,OFFSET entry
                mov     al,0E9h                 ;JMP short opcode
                stosb
                mov     ax,OFFSET boot_1-OFFSET boot_data
                stosw

; Read the boot sector from the target disk into a buffer

		mov     al,target_disk		;Get target disk
                mov     cx,1                    ;read 1 sector
                xor     dx,dx                   ;Sector 0
                mov     si,dx
                mov     bx,TARGET_BOOT_SECTOR
                call    read_absolute
                jc      install_error

; This checks the JMP (short or long according to DOS version).

                mov     si,bx                   ;point to boot rec
                lodsb				;get opcode
                mov     dl,al
                lodsw				;get where to
                mov     bx,si			;next address
                cmp     dl,0EBh                 ;short JMP?
                jne     >l1			;no
                xor     ah,ah                   ;if short JMP clear
                jmp     >l2			;  high byte

L1:		cmp     dl,0E9h                 ;Check for long JMP
		je	>l2                
		mov     dx,OFFSET not_dos_mesg
		jmp	error_message

L2:		mov     dx,OFFSET cant_write_mesg
                dec     ax
                cmp     ax,OFFSET boot_dataend - OFFSET entry
		if a	jmp error_message

; This copies the boot data from target disk to our boot

		mov     si,bx
                mov     di,OFFSET boot_data     ;copy boot data to
                mov     cx,ax                   ;  boot rec
                rep     movsb

; This writes the boot sector to the target disk

		mov     al,target_disk		;Get target disk
                mov     bx,OFFSET entry
                mov     cx,1                    ;1 sector
		xor     dx,dx                   ;Sector 0
                xor     si,si
                call    write_absolute          ;Write new boot rec
		jc	install_error
		ret

INSTALL_ERROR:	call	seterrmsg
INIT_ERROR:	call	print_msg
		mov	ax,4C01h
		int	21h

;--------------------------------------------------------------------
; READ ABSOLUTE - Reads sectors from the disk.
; Entry:   AL - Drive to read
;          CX - Number of sectors to read.
;       SI,DX - Sector to start read (SI only used on huge disks)
;       DS:BX - Pointer to data buffer.
;--------------------------------------------------------------------

READ_ABSOLUTE:	push    bx
                push    cx
                push    ds
		int     25h                     ;DOS Absolute Disk Read
                pop     bx                      ;stack shit
                call    seterrmsg
                cld
		pop     ds
                pop     cx
                pop     bx
                ret

;--------------------------------------------------------------------
; WRITE ABSOLUTE - Writes sectors to the disk.
; Entry:   AL - Drive to write
;          CX - Number of sectors to write
;       SI,DX - Sector to start write (SI only used on huge disks)
;       DS:BX - Pointer to data buffer.
;--------------------------------------------------------------------

WRITE_ABSOLUTE:	push    bx
                push    cx
                push    ds
		int     26h                     ;DOS Absolute Disk Write
                pop     bx                      ;statck shit
                call    seterrmsg
                cld
		pop     ds
                pop     cx
                pop     bx
                ret

;----------------------------------------------------------------
; Sundry routines used by the above
;----------------------------------------------------------------

CAPS:		cmp	al,'a'
		jb	ret
		cmp	al,'z'
		ja	ret
		and	al,5Fh
		ret

PRINT_MESSAGE:	push	ax
		mov	ah,9
		int	21h
		pop	ax
		ret

HELP:		JMP	DISPLAY_SCREEN

ERROR_MESSAGE:	call	print_message
		mov	ax,4C01h
		int	21h

;----------------------------------------------------------------
; MESSAGE DATA
;----------------------------------------------------------------

NO_FILE_MESG	db	'Color file not found',7,cr,lf,eom
NO_TEXT_MESG	db	'Text file not found',7,cr,lf,eom
BAD_TARGET_MESG	db	'Invalid target drive',7,cr,lf,eom
SYSTEM_MESG	db	'Target contains system files. Aborted.',7,cr,lf,eom
TARGET_MESG	db	'Verifying target disk',cr,lf,eom
WRONG_DISK_MESG db	'Wrong size disk',7,cr,lf,eom
VERIFY_MESG	db	'WARNING! Message sector may contain data. Continue (Y/N)?',7,cr,lf,eom
ABORT_MESG	db	'Aborted as user request',cr,lf,eom
SIZE_144_MESG	db	'1.44Mb disk detected',cr,lf,eom
SIZE_720_MESG	db	'720Kb disk detected',cr,lf,eom
SIZE_360_MESG	db	'360Kb disk detected',cr,lf,eom
SIZE_12_MESG	db	'1.2Mb disk detected',cr,lf,eom
READING_MESG	db	'Reading color file',cr,lf,eom
READING_MESG2	db	'Reading text file',cr,lf,eom
BAD_SWITCH_MESG db	'Invalid switch',7,cr,lf,eom
BAD_CURPOS_MESG db	'Invalid cursor /P position',cr,lf,eom
BAD_TIMER_MESG	db	'Invalid timer /T value',7,cr,lf,eom
TOO_LONG_MESG	db	'Timer delay must not exceed 60 seconds',7,cr,lf,eom
BAD_COLOR_MESG	db	'Invalid color /C specified',7,cr,lf,eom
NOT_DOS_MESG	db	'Target diskette not a DOS formatted disk',7,cr,lf,eom
CANT_WRITE_MESG db	'Cannot write code on target disk',7,cr,lf,eom
INSTALL_MESG	db	'Installing boot sector',cr,lf,eom
BAD_SIZE_MESG	db	'Bad color file size (must be 4000 bytes)',7,cr,lf,eom
BAD_SIZE_MESG2	db	'Bad text file size (maximum 2000 bytes)',7,cr,lf,eom
READ_ERR_MESG	db	'Error reading data file',7,cr,lf,eom
WRITE_ERROR	db	'Error writing data to sector address',7,cr,lf,eom
DONE_MESSAGE	db	'Disk modified OK',cr,lf,eom

HELLO	db	cr,lf
	db	'COLRBOOT V1.0 þ Release November 1994 JIM TUCKER',cr,lf
	db	'Copyright (c) 1994 JIM TUCKER. All rights reserved',cr,lf,eom

;----------------------------------------------------------------
; This is the display stuff
;----------------------------------------------------------------

CURSOR_SIZE	dw	?
CURSOR_POS	dw	?

;----------------------------------------------------------------
; This moves the COLOR_HELP screen to the OUTPUT screen
;----------------------------------------------------------------

DISPLAY_COLOR_HELP:
		mov	si,OFFSET color_help
		mov	di,OFFSET output_screen
		mov	cx,2000
		rep	movsw
		jmp	display_screen

;----------------------------------------------------------------
; This moves the FILE (and any overlay) to the OUTPUT screen 
;----------------------------------------------------------------

DISPLAY_FILE:	call	write_prompt		; put prompt on screen
		mov	si,COLOR_FILE_BUFFER	; get the file
		mov	di,OFFSET output_screen	
		mov	cx,2000
		rep	movsw
		test	filename_switch		; /F switch?
		jz	display_screen		; no

		mov	si,filename1		; display filename
		mov	di,OFFSET output_screen
		add	di,4000-40
		mov	ah,0Eh		
L1:		lodsb
		test	al
		jz	display_screen
		stosw
		jmp	l1		

;----------------------------------------------------------------
; Here to display the contents of the OUTPUT screen
;----------------------------------------------------------------

; This saves the current screen - we can overwrite the file buffer
; DS:SI is the screen, ES:DI is the buffer

DISPLAY_SCREEN:	mov	di,COLOR_FILE_BUFFER
		mov	ax,video_seg		; current video
                mov     ds, ax                  ; place in DS
                xor     si, si                  ; zero SI
                mov     cx, 2000
                rep	movsw			; store chars and color
		mov	ds,cs			; done, restore DS

; Save the cursor info

		mov	bh,0			; page zero
		mov	ah,3			; get cursor info
		int	10h
		mov	cursor_pos,dx		; save it for restore
		mov	cursor_size,cx

; Hide the cursor

		mov	ah,2
		mov	bh,0
		mov	dx,1A00h
		int	10h

		test	mono_switch
		jz	>l1
		mov	ah,0
		mov	al,7
		int	10h
		mov	ax,video_seg
		mov	old_video_seg,ax
		mov	video_seg,0B000h

; This WRITES the OUTPUT screen to the VIDEO SEGMENT

L1:		mov	ax,video_seg
		mov	es,ax
		mov	si,offset OUTPUT_SCREEN
		xor	di,di
		mov	cx,2000
		rep	movsw
		mov	es,cs

L1:		mov	ah,01h		;wait for a keystroke
		int	016h
		jz	l1
		mov	ah,0		;clear keyboard buffer
		int	016h

; Restore the screen

		mov	al,video_mode
		mov	ah,0
		int	10h
		mov	ax,old_video_seg
		mov	video_seg,ax

; DS:SI is the buffer, ES:DI is the screen

L1:		mov	si,COLOR_FILE_BUFFER
		mov	ax,video_seg
		mov	es,ax
		xor	di,di
		mov	cx,2000
		rep	movsw
		mov	es,cs		

; Put the cursor back

		mov	bh,0
		mov	dx,cursor_pos
		mov	ah,2
		int	10h
		mov	cx,cursor_size
		mov	ah,1
		int	10h

		mov	ax,4C00h
		int	21h

;----------------------------------------------------------------
; The following are messages returned by absolute and read and write.

DOSERR_TBL      dw      OFFSET  doserr_00
                dw      OFFSET  doserr_01
                dw      OFFSET  doserr_02
                dw      OFFSET  doserr_03
                dw      OFFSET  doserr_04
                dw      OFFSET  doserr_05
                dw      OFFSET  doserr_06
                dw      OFFSET  doserr_07
                dw      OFFSET  doserr_08
                dw      OFFSET  doserr_09
                dw      OFFSET  doserr_10
                dw      OFFSET  doserr_11
                dw      OFFSET  doserr_12
                dw      OFFSET  doserr_unk
DOSERR_TBLEND   =       $

doserr_00       db      "Disk Write Protected",0
doserr_01       db      "Unknown Unit",0
doserr_02       db      "Drive not ready",0
doserr_03       db      "Unknown Command",0
doserr_04       db      "CRC Data Error",0
doserr_05       db      "Bad request structure",0
doserr_06       db      "Disk Seek error",0
doserr_07       db      "Not a DOS disk",0
doserr_08       db      "Sector not found",0
doserr_09       db      "Printer out of paper",0
doserr_10       db      "Disk Write fault",0
doserr_11       db      "Disk Read fault",0
doserr_12       db      "General failure",0
doserr_unk      db      "Unknown DOS error",0

;--------------------------------------------------------------------
; SETERRMSG:  Assigns a DOS error message to the value in AL
; Entry: AL - Error code
;        CF - Set if error
; Exit:  SI - Points to error message
;--------------------------------------------------------------------

SETERRMSG:	push    bx
                pushf
                jnc     >l2
                mov     bx,ax
                xor     bh,bh
                shl     bx,1
                cmp     bx,OFFSET doserr_tblend - OFFSET doserr_tbl
                jbe     >l1
                mov     bx,26
L1:		mov     si,[bx+doserr_tbl]
L2:		popf
                pop     bx
                ret

;----------------------------------------------------------------
; PRINT_MSG: Prints ASCIIZ message to screen appending crlf
; Entry: DS:SI - Points to ASCIIZ message
;----------------------------------------------------------------

CRLF_MSG        db      13,10,0
PRINT_MSG:	call    print_line
                mov     si,OFFSET crlf_msg
                call    print_line
                ret

;----------------------------------------------------------------
; PRINT_LINE: Prints a line to the screen
; Entry: DS:SI - Points to ASCIIZ message
;----------------------------------------------------------------

PRINT_LINE:	lodsb
                or      al,al
                je      >l1
                mov     dl,al
                mov     ah,02
                int     21h
                jmp     short print_line
L1:		ret

; If you do not have the latest version of A86 catenate these files
; to this file.

INCLUDE CMDLINE.A86
INCLUDE CBDATA.A86

; END COLRBOOT.A86
