;---------------------------------------------------------------
;  SOLOAD.ASM - Sol Pogram Loader
;
;  CP/M stub to load older Sol-20 programs that run at zero
;  and were typically loaded and run from cassette.
;
;  The binary of this program is inserted immediately before
;  the first byte of the original Sol-20 program to make the
;  file an executable CP/M program. The length of the payload
;  binary should be patched at location 3-4 in the resulting
;  exectuable. A cold boot of CP/M is typically required after
;  running these orignal programs since they clobber page zero. 
;
;  Rev	   Date	     By		Desc
;  1.0	 11/22/15  M Douglas	Original
;  1.1	 11/23/15  M Douglas	
;	Include load address as a parameter in the two bytes
;	following the load length. If the move is to a higher
;	address than 013Fh (the payload symbol), then 
;	loadAdr must be > loadLen + 013Fh.
;---------------------------------------------------------------

; Equates

BDOS	equ	5		;BDOS jump vector
SOLOS	equ	0c000h		;SOLOS location

; This loader stub is run by CP/M at 100h

	org	0100h
	jmp	start		;jump to program entry point

; Patch the length of the "payload" binary into the two
;   bytes at location 3-4. Patch the load location into
;   locations 5-6.

loadLen	dw	0570h		;size of program to load/move
loadAdr	dw	0000h		;load location

;---------------------------------------------------------------
;  start - relocate the "mover" portion of this program up 
;     to high memory (just under the BDOS) so that it can
;     move the payload to the location specified in loadAdr.
;---------------------------------------------------------------
start	lhld	BDOS+1		;hl->BDOS entry point
	dcr	h		;h=msb of relocated mover
	mvi	l,mover and 0ffh  ;l=lsb of relocated mover
	push	h		;save relocated addr on stack

	mov	a,h		;a=msb of relocated mover
	sta	movJmp+2	;patch (relocate) the one jump instruction

	lxi	b,mover		;bc->mover code
	mvi	d,movEnd-mover  ;d=number of bytes to move
	
; reloc - relocate the "mover" code to high memory as pointed to by hl

reloc	ldax	b		;move a byte
	mov	m,a
	inx	h		;bump pointers
	inx	b
	dcr	d		;decrement count
	jnz	reloc
	ret			;jump to relocated mover in high memory

;---------------------------------------------------------------
; mover - move the payload binary to (loadAdr), then jump
;   to it with registers and stack set up the same as when EX
;   is executed in SOLOS. This block of code is relocated and
;   runs in high memory just below the BDOS.
;---------------------------------------------------------------
mover	lhld	loadLen		;get number of bytes to move in de
	xchg
	lhld	loadAdr		;hl->destination
	push	h		;save load address on stack
	lxi	b,payLoad	;bc->source

; movLoop - move the payload to the address in loadAdr

movLoop	ldax	b		;move payload
	mov	m,a
	inx	h		;bump pointers
	inx	b
	dcx	d		;decrement and test count
	mov	a,d
	ora	e
movJmp	jnz	movLoop		;this jump patched for relocation

; program moved to address loadAdr. Jump to it with registers and the
;    stack set up the same way as when an EXECUTE command is issued
;    in SOLOS: A valid RET address is present on the stack, the
;    address of SOLOS is in hl, and the address of the called routine
;    is immediately above the stack

	pop	d		;de->load and entry address
	lxi	sp,SOLOS+0c00h	;use typical SOLOS stack location
	lxi	h,SOLOS		;hl->SOLOS
	push	h		;push a RET to SOLOS on stack
	push	d		;push entry address on stack
	ret			;jump to program

movEnd	equ	$		;end of the mover code,
payload	equ	$		;start of the payload binary

	end

