;MOVCPM.ASM	BY DIGITAL RESEARCH
;DISASSEMBLED 3 DEC 84 RHP
;CONVERTED FOR DIGITAL RESEARCH 'MAC' 
;MACROASSEMBLER 7 DEC 84 RHP
;
	ORG	00100H
;
; EQUATES
;
WBOOT	EQU	00000H
BDOS	EQU	00005H		;BDOS JUMP ENTRY POINT
BDOSADR EQU	00006H		;ADDRESS OF BOTTOM OF BDOS
FILNAM	EQU	0005DH		;START OF FILE NAME IN FCB1+1
FCB2	EQU	0006DH		;START OF FCB 2 +1
STACK	EQU	00800H
CODEST	EQU	00900H		;START OF CPM CODE (BOOT)
SERNO	EQU	01200H		;LOCATION OF SER# IN THE CCP
CPMLG	EQU	01700H		;LENGTH OF CPM CODE
PRSTRG	EQU	009H
;
;PROGRAM START
;
START:	JMP	BEGIN		;GO TO REAL START OF PROGRAM
;
;COPYRIGHT NOTICE
;
	DB	'COPYRIGHT (C) DIGITAL RESEARCH, 1979     '
;
BEGIN:	LXI	SP,STACK	;SET STACK AT 800H
	LXI	D,FILNAM	;POINT AT FILE NAME  
	LDAX	D 		;GET CHARACTER
	CPI	020H		;IS IT A SPACE?
	JZ	RAMCHK
	CPI	03FH		;IS IT A ? (WILDCARD)
 	JZ	RAMCHK
;
;CHECK FOR 2 ASCII NUMBERS AND CONVERT TO HEX
;
	LXI	H,00000H
ASCHEX:	LDAX	D		;GET CHARACTER
	INX	D		;BUMP TO NEXT CHAR
	CPI	020H		;IS IT A SPACE?
	JZ	BADMM
	ORA	A
	JZ	BADMM
	SBI	030H		;NUMBER 0-9?
	CPI	00AH
	JNC	PMSG1		;PRINT BAD MEMORY SIZE
;
;MULTIPLY HL BY 10
;
	DAD	H		;X2
	PUSH	H		;SAVE X2
	DAD	H		;X4
	DAD	H		;X8
	POP	B		;GET THE X2
	DAD	B		;X2+X8=X10
	MOV	C,A		;SAVE CHAR IN C
	MVI	B,000H		;CLEAR B TO ZERO
	DAD	B		;UPDATE HEX NO.
	JMP	ASCHEX		;LOOP TIL DONE
;
BADMM:	MOV	A,H
	ORA	A
	JNZ	PMSG1		;PRINT BAD MEMORY SIZE
	MOV	A,L
	CPI	010H
	JC	PMSG1		;PRINT BAD MEMORY SIZE
	MVI	L,000H
	MOV	H,A
	DAD	H
	DAD	H
	JMP	SVHIRM
;
PMSG1:	LXI	D,MESSG1	;INVALID MEMORY SIZE
	CALL	PRINT
	JMP	WBOOT
;
MESSG1:	DB	00DH, 00AH
	DB	'INVALID MEMORY SIZE$'
;
RAMCHK:	LXI	H,00000H
RAMLUP:	INR	H
	JZ	HIRAM
;
;SCAN MEMORY TO CHECK FOR RAM
;
	MOV	A,M		;GET A CHARACTER
	CMA			;INVERT IT
	MOV	M,A		;PUT IT BACK
	CMP	M		;SET Z FLAG IF = ELSE NOT RAM
	CMA			;RIGHT SIDE UP
	MOV	M,A		;PUT IT BACK THE WAY IT WAS
	JZ	RAMLUP		;IF RAM, KEEP LOOKING
;
;IF HERE, THEN HL=END OF RAM
;
HIRAM:	MOV	A,H		;ROUND OFF HI RAM ADDR 
	ANI	0FCH		; TO NEAREST K
	MOV	H,A
;
SVHIRM:	PUSH	H		;SAVE HI RAM ADDR ON STACK
;
	LHLD	BDOSADR		;MOVE BDOS ADDR TO STOR1
	SHLD	STORE1    
	POP	H		;GET HI RAM ADDR AGAIN
	PUSH	H		;BUT LEAVE IT ON THE STACK TOO
	MOV	A,H		;GET HI BYTE OF RAM ADDR
	RRC			;CHANGE TO UNITS OF K
	RRC
	ANI	03FH		;<64K?
	JNZ	SETMSZ		;SMALL ENOUGH
	MVI	A,040H		;ELSE SET TO 64K
SETMSZ:	MOV	B,A		;SAVE SIZE IN B
	LXI	H,SCPMSZ	;POINT TO CPM SZ MSG
	MVI	A,030H		;FILL WITH 00 ASCII  
	MOV	M,A		;STORE 0
	INX	H		;NEXT LOCATION
	MOV	M,A		;STORE 0
SIZLUP:	LXI	H,SECCHR	;POINT TO SECOND CHAR
	INR	M		;INCREMENT MEMORY
	MOV	A,M		;READ THE CHAR
	CPI	03AH		;ASCII 9 OR LESS?
	JC	SZLP1
	MVI	M,030H		;SET TO ASCII 0
	DCX	H		;POINT TO HI CHAR
	INR	M		;INCREMENT MEMORY
SZLP1:	DCR	B		;HAS MEM SIZE IN K
	JNZ	SIZLUP
	LXI	D,MESSG4	;POINT TO CONSTRUCTING CPM MSG
	CALL	PRINT		;PRINT CONSTRUCTING CPM MSG
;
	LXI	H,STACK+1	;POINT TO BOTTOM OF STACK
;
	MOV	C,M		;GET MEMORY SIZE IN BC
	INX	H
	MOV	B,M
;
	PUSH	B		;PUT MEMORY SIZE ON TOP OF STACK
;
	LXI	H,CODEST	;POINT TO START OF CODE TO MOVE
UPDCD:	LXI	D,SMALLK

	MOV	A,B		;IS BC = 0?
	ORA	C		;WHERE BC = MEMORY SIZE
	JZ	WHAT2		;IF SO GOTO WHAT2

	DCX	B		;DECREMENT MEM PTR
	PUSH	B		;SAVE MEMORY POINTER
	MVI	C,00FH
	PUSH	H		;SAVE CODE POINTER
NOT16:	LDAX	D
	CMP	M
	JNZ	INCOD
	INX	D
	INX	H
	DCR	C		;COUNT 16
	JZ	WHAT1
	JMP	NOT16
;
	DB	001H		;DUMMY BYTE
;
SDELY:	XRA	A
DELUP:	DCR	A		;SMALL DELAY HERE
	JNZ	DELUP
;
	LXI	H,076F3H	;LOAD STORE1 WITH F376H
	SHLD	STORE1    
;
	LXI	H,CHCALL	;CHANGE INSTRUCTION TO CALL
	MVI	M,0CDH
;
	LXI	D,ADRCH+1	;NOW POINTS TO CHSER
	LXI	H,00005H	;POINT TO SYNCH ERROR MSG
	DAD	D		;NEW ADDRESS
	XCHG			;PUT MSG PTR IN DE
	JMP	PRINT		;PRINT SYNCH ERROR MSG
;
INCOD:	POP	H
	INX	H
	POP	B
	JMP	UPDCD
;
WHAT1:	POP	H
	POP	B
	DCX	H
	LXI	D,SECCHR
	LDAX	D
	MOV	M,A
	DCX	H
	DCX	D
	LDAX	D
	MOV	M,A
WHAT2:	LXI	B,STORE1
	LDAX	B
	CPI	006H
	MVI	A,000H
	JNZ	CHADR
	STAX	B
	POP	B
	POP	H
	PUSH	B
	MOV	A,B
	ADI	003H
	MOV	B,A
	MOV	A,L
	SUB	C
	MOV	L,A
	MOV	A,H
	SBB	B
	MOV	H,A
	SHLD	STORE2    
	XCHG	
	LXI	H,CODEST
	POP	B
	PUSH	B
	LDA	FCB2
	CPI	020H
	JZ	SHOVE
	DAD	B
	JMP	MOVDUN
;
CHADR:	LXI	H,SDELY
	SHLD	HANG+1    
	JMP	HANG
;
SHOVE:	MOV	A,B		;CHECK BYTES TO MOVE COUNT
	ORA	C		;THROUGH YET?
	JZ	MOVDUN		;DONE MOVING
	DCX	B		;COUNT-1
	MOV	A,M		;GET BYTE TO MOVE
	STAX	D		;POINT TO DESTINATION
	INX	D		;NEXT DEST.
	INX	H		;NEXT BYTE
	JMP	SHOVE		;LOOP TIL DONE
;
MOVDUN:	POP	B
	PUSH	H
	LHLD	STORE2
	XCHG	
	LXI	H,START
	DAD	D
	LDA	FCB2
	CPI	020H
	JZ	RLCLP
	LXI	D,CODEST
RLCLP:	MOV	A,B		;CHECK BIT COUNTR 
	ORA	C		;RLOC DONE?
ADRCH:	JZ	CHSER
	JMP	MOREL
;
MESSG2:	DB	00DH, 00AH
	DB	'SYNCRONIZATION ERROR$'
;
MOREL:	DCX	B		;DROP THE BYTE COUNT
	MOV	A,E		;IS DE ADDR MOD 8 BYTES?
	ANI	007H		;IF SO NEED NEXT BIT MAP BYTE
	JNZ	SAMBYT		;STILL ON SAM BIT MAP BYTE
;
;GET NEXT MAP BYTE VIA POINTER ON STACK
;
	XTHL			;SAVE HL & GET MAP PTR
	MOV	A,M		;GET MAP BYTE
	INX	H		;POINT TO NEXT BYTE
	XTHL			;REPLACE POINTER ON STACK
	MOV	L,A		;MAP BYTE TO HOLDINO REG.
;
SAMBYT:	MOV	A,L		;GET CURRENT BIT MAP BYTE
	RAL			;SHIFT ONE BIT
	MOV	L,A		;SAVE FOR NEXT PASS
	JNC	NOFFST	;0=NO OFFSET NEEDED
	LDAX	D		;GET DEST BYTE
	ADD	H		;ADD THE OFFSET
	STAX	D		;PUT IT BACK
	JMP	NOFFST		;
;
NOFFST:	INX	D		;BUMP MOVED CODE BYTE COUNTER
	JMP	RLCLP		;BACK FOR MORE BYTES
;
;MATCH SERIAL NO OF MOVCPM AND CCP
;
CHSER:	POP	D		;CLEAN UP STACK
	LXI	D,SERNO		;POINT TO SER NO IN CCP
	LHLD	STORE1		;GET LOCAL SER NO
	MVI	C,006H		;CHECK 6 CHAR OF SERIAL NO.
LOOP6:	LDAX	D		;GET CHAR OF SER NO
	CMP	M		;COMPARE LOCAL SER NO
	JNZ	CHADR		;NO MATCH CHANGE THE JUMP ADDR
	INX	H		;NEXT CHAR LOC
	INX	D		;NEXT CHAR CCP
	DCR	C		;EXT CHAR COUNT
	JNZ	LOOP6		;IF C <> 0 THEN KEEP LOOPING
;
;HERE IMPLIES MATCHED SERIAL NUMBERS
;
	LDA	FCB2	;GET CHAR FROM FILE CONT BLK 2
	CPI	020H		;IS IT A SPACE?
	JZ	CBOOT		;YEAH, GOTO CBOOT
	MVI	B,080H		;SET COUNTER
	LXI	H,CODEST	;POINT TO CODE START ADDR
MOVLUP:	MOV	A,M		;GET A CHAR OF CODE
	ORA	A		;SET FLAGS
	JNZ	BINDEC		;SOMETHING THERE
	INX	H		;TRY NEXT ADDR
	DCR	B		;COUNT DOWN
	JNZ	MOVLUP		;STILL COUNTING, THEN LOOP
	XCHG	
	LHLD	STACK+1		;LOAD HL WITH ADDR OF ?
	LXI	B,0FF80H	;LOAD BC WITH 80FFH
	DAD	B
	MOV	B,H		;PUT HL IN BC
	MOV	C,L
	LXI	H,CODEST	;POINT TO START OF CODE
MVBYT:	MOV	A,B		;CHK BYTE CNT
	ORA	C		;ALL MOVED YET?
	JZ	BINDEC
	DCX	B		;DEC BYTES TO MOVE CNT
	LDAX	D		;READ FROM DE
	MOV	M,A		;PLACE IN HL
	INX	D		;NEXT DE
	INX	H		;NEXT HL
	JMP	MVBYT		;LOOP TIL DONE
;
	DB	001H		;DUMMY BYTE
;
HANG:	JMP	HANG		;OR JUMP A01FF
;
BINDEC:	LXI	H,STACK+1	;LOAD BC FROM TOP OF STACK
;
	MOV	C,M		;LOAD BC FROM BOTTOM OF STACK
	INX	H
	MOV	B,M
;
	LXI	H,CODEST	;POINT TO CODE START
	DAD	B		;CALCULATE MEMORY SIZE
	MOV	B,H		;UPDATE MSIZE IN K
	LXI	H,SIZE1	;POINT TO 1ST CHAR OF SIZE
	MVI	A,030H		;LOAD ASCII 0
	MOV	M,A		;LOAD IT IN 1ST CHAR
	INX	H		;POINT TO 2ND CHAR
	MOV	M,A		;A ZERO THERE TOO
NUMLUP:	DCR	B		;DECR MEMORY SIZE IN K
	JZ	PTSIZ
	LXI	H,SIZE2	;POINT TO SECOND CHAR
	INR	M		;INCR THE VALUE THERE
	MOV	A,M		;GET THE VALUE
	CPI	03AH		;IS IT OVER 9?
	JC	NUMLUP	;ELSE LOOP TO INCREASE
	MVI	M,030H	;OR BACK TO 0 & BUMP 1ST#
	DCX	H		;POINT TO 1ST
	INR	M		;BUMP IT 10K
	JMP	NUMLUP		;BACK TO 1K LOOP
;
PTSIZ:	LHLD	SCPMSZ		;POINT TO CPM SIZE
	SHLD	CPMSZ    	;GET IT
	LXI	D,MESSG3	;POINT TO SYSGEN MSG
	CALL	PRINT		;PRINT SYSGEN MESSAGE
	JMP	WBOOT
;
MESSG3:	DB	00DH, 00AH
	DB	'READY FOR "SYSGEN" OR'
	DB	00DH, 00AH
	DB	'"SAVE '
SIZE1:	DB	'0'
SIZE2:	DB	'0'
	DB	' CPM'
CPMSZ:	DB	'00'
	DB	'.COM"$'
;
CBOOT:	LXI	D,CPMLG		;LOAD THE LENGTH OF CPM
	LHLD	STORE2		;GET THE LOCATION OF CPM
	DAD	D		;CALC THE START OF BIOS 
	PCHL			;JUMP TO COLD BOOT
;
PRINT:	MVI	C,PRSTRG	;PREPARE TO PRINT A STRING
CHCALL:	JMP	BDOS		; GO DO IT
;
STORE1:	NOP
	NOP
;
STORE2:	NOP
	NOP
;
MESSG4:	DB	00DH, 00AH
	DB	'CONSTRUCTING '
SCPMSZ:	DB	'0' 
SECCHR:	DB	'0' 
SMALLK:	DB	'k' 
	DB	' CP/M vers 2.2$'
;
	END

		;Label cross reference
		;WBOOT      Z013D   Z0191   X033D
		;BDOS       Z0212   X0377
		;BDOSADR    Y01A6
		;FILNAM     Z012F
		;FCB2       Y024E   Y027A   Y02D4
		;START      T0276
		;BEGIN      START
		;ASCHEX     A015C
		;BADMM      A0144   A0148
		;PMSG1      A014F   A0161   A0167
		;MESSG1     T0172
		;RAMCHK     A0135   A013A
		;RAMLUP     A019E
		;HIRAM      A0195
		;SVHIRM     A016F
		;SETMSZ     A01B3
		;SIZLUP     A01D0
		;SZLP1      A01C8
		;UPDCD      A021D
		;NOT16      A01FB
		;SDELY      T025A
		;DELUP      A0201
		;INCOD      A01F2
		;WHAT1      A01F8
		;WHAT2      A01E8
		;CHADR      A0234   A02CB
		;SHOVE      A0253   A026D
		;MOVDUN     A0257   A0265
		;RLCLP      A027F   A02BD
		;ADRCH+1    T020F
		;MOREL      A028A
		;SAMBYT     A02A8
		;NOFFST     A02B3   A02B9
		;CHSER      A0287
		;LOOP6      A02D1
		;MOVLUP     A02E8
		;MVBYT      A0302
		;HANG       A0260
		;HANG+1     D025D
		;BINDEC     A02E3   A02FA
		;NUMLUP     A0327   A032E
		;PTSIZ      A031D
		;MESSG3     T0337
		;SIZE1      T0314
		;SIZE2      T0320
		;CPMSZ      D0334
		;CBOOT      A02D9
		;PRINT      A0175   A01D6   A0217   A033A
		;CHCALL     T020A
		;STORE1     D01A9   D0207   T022C   D02C4
		;STORE2     D0245   D0272   D0370
		;MESSG4     T01D3
		;SCPMSZ     T01B9   D0331
		;SECCHR     T01C1   T0223
		;SMALLK     T01E3
		;STACK      Z012C
		;STACK+1    Z01D9   Y02EC   Z0309
		;CODEST     Z01E0   Z0249   Z0282   Z02DE
		;           Z02F5   Z030F
		;SERNO      Z02C1
		;CPMLG      Z036D
		;Z76F3	    Z0204
		;ZFF80	    Z02EF