ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее-ACPMUG °1BPRINT БSM4PRNT БSM& RELOC БSMNRTE БSM7SEDIT БSM !"SPACE БSM~#$%&'()*+,-./012SPAT БSM:3456789: CPI 1AH ;EOF? JZ DONE ;YES CPI CR ;CR? JZ CRET ;YES CPI LF ;LF? JZ LFEED ;YES CPI TAB ;TAB? JZ TABMOV ;YES CPI SPACE ;ODD CONTROL CHR? JNC LOOPX ;NO, PRINT CHR. JMP LOOP ;YES, DROP IT TABMOV: LXI H,COL ;POINT TO COLUMN TBLP: MVI A,ND ;OUTPUT TO CONSOLE OR CP/M LIST DEVICE ;10/15/77 ;********************************; ;********************************; ; MISCELLANEOUS EQUATES ; ;********************************; MAXLN EQU 56 ;LINES/PAGE NULLS EQU 12 ;NULLS AFTERееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееE IN OBJECT DB '/ PRINT UTILITY VERS. 1.1 /' IF FORM DB ' HARDWARE FF /' ENDIF IF NOT FORM DB ' LF TO PAGE TOP /' ENDIF IF NOT ODEV-5 DB ' OUT TO LST: /' ENDIF IF NOT ODEV-2 DB ' OUT TO CON: /' ENDIF PRINT: LXI SP,STACK LXI DееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееTRAIN БSM;<=TREAD БSM>?@AVBIOS31 БSMЂBCDEFGHIJKLMNOPQVBIOS31 БSMRXSTAT ГOMSеTRAIN HEX TUееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее TO PAGE TOP LF EQU 0AH ; FF EQU 0CH ; CR EQU 0DH ; TAB EQU 09H ; SPACE EQU 20H ; RUBOUT EQU 7FH ;USED AS FF NULL. MAY CAUSE PROBLEM ;TO SOME PRINTERS ODEV EQU 5 ;CON:=2 LST:=5 FORM EQU 0H ;SET 0FFFFH FOR 0CH A FORM FEED BOOT EQU 0000H ;REBOOT ENTRY POINT CPM EQU 0005H ;CPM ENTRY POINT TBUF EQU 0080H ;TRANSIENT PROGRAM BUFFER TFCB EQU 005CH ;TRANSIENT PROGRAM FCB OPEN EQU 15 ;OPEN FUNCTION CODE READ EQU 20 ;READ FUNCTION CODE LINES EQU 7 ;LINESееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее,TFCB ;POINT TO FCB CALL FOPEN ;OPEN FILE JC ERR ;IF ERROR, EXIT ; IF FORM ;DO IF HARDWARE CALL TOF ;PRINT HEADING ENDIF ; IF NOT FORM;IF NO HARDWARE, ASSUME THERE CALL TOF3 ENDIF ; LOOP: CALL GETBT ;GET A BYTE JC ERR ;ERROR ;********************************; ; FILE PRINT UTILITY ; ;********************************; ;********************************; ;VERSION 1.1 ;ORIGINAL CODED BY JEFF KRAVITZ ;MODIFIED BY A. GOLD ;CONDITIONAL ASSEMBLY FOR HARDWARE Aееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее ;SET 0 FOR 'S TO PAGE TOP ;TO DEVICE THAT NEEDS LINE-FEEDS ; ;********************************; ;********************************; ; MAIN LOOP ; ;********************************; ORG 100H JMP PRINT ;PUT A CLUееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееSPACE ;PRINT ONE SPACE CALL PBYT MOV A,M ;GET COLUMN ANI 07H ;MODULO 8 JNZ TBLP ;IF NOT AT TAB STOP, KEEP TYPEIN JMP LOOP LOOPX: CALL PBYT ;PRINT BYTE JMP LOOP CRET: XRA A STA COL MVI A,CR JMP LOOPX LFEED: LDA LINE ;GET LINE COUNT *********************; ; MISCELLANEOUS SUBROUTINES ; ;********************************; ;********************************; ; C P H L ; ; ROUTINE TO COMPARE HL VS DE ; ;********************************; CPHL: MOV A,VI B,NULLS ;RUBOUT COUNT DLP2: MVI A,RUBOUT CALL PBYT DCR B JNZ DLP2 ENDIF ; IF NOT FORM DONE: LXI H,LINE ;POINT TO CURRENT LINE MVI A,MAXLN SUB M ;LINES LEFT TO PRINT ADI LINES ;PLUS LINE TO PAGE TOP MOV B,A DLP2: MVI A,LF ; CACR B ;DCREMENT COUNT JNZ TOF2 ;PRINT 'N' 'S ENDIF ; ; TOF3: LXI H,FMSG ;POINT TO MESSAGE CALL PSTRNG ;PRINT STRING LXI H,TFCB+1;POINT TO NAME MVI B,8 ;SIZE OF NAME CALL PCNT ;PRINT COUNT MVI A,SPACE ;PRINT A SPACE CALL PBYT LXI H,TR ; ;********************************; GETBT: LXI H,TBUF+128 XCHG ;BUFFER END ADDR. IN DE LHLD INPTR ;CURRENT POINTER IN HL CALL CPHL ;TEST FOR END OF BUFFER JZ GETB2 ;YES, READ GETB1: MOV A,M ;GET BYTE INX H ;BUMP POINTER SHLD INPTRDONE POP B POP H RET PSTRNG: MOV A,M ;GET BYTE CPI '$' ;STRING END? RZ ;YES, DONE CALL PBYT ;PRINT BYTE INX H ;BUMP POINTER JMP PSTRNG ;LOOP PCNT: MOV A,M ;GET BYTE CALL PBYT ;PRINT IT INX H ;BUMP POINTER DCR B ;DECREMENT COUNT CPI MAXLN ;PAGE OVERFLOW? JZ NEWPG ;YES INR A ;BUMP LINE COUNT STA LINE MVI A,LF JMP LOOPX ;CONTINUE NEWPG: MVI A,CR CALL PBYT ;PRINT CR CALL TOF JMP LOOP ; ; IF FORM ;ROUTINE TO FORM FEED WITH 0CH TOF: MVI A,FF ;FORM FEED CALL OPEN A DISK FILE ; ; ; ; INPUT: DE=A(FCB) ; ; OUTPUT: CARRY=ERROR ; ;********************************; FOPEN: MVI C,OPEN ;OPEN CODE CALL CPM ;ISSUE OPEN CPI 0FFH ;ERROR? JZ FOERR ;YES LL PBYT DCR B ;DCREMENT COUNT JNZ DLP2 ;PRINT 'N' LINES TO PAGE TOP ENDIF ; JMP BOOT ;EXIT ERR: LXI D,ERMSG MVI C,09H ;WRITE MSG CALL CPM JMP BOOT ;********************************; ; F O P E N ; ; ROUTINE TOFCB+9;POINT TO TYPE MVI B,03 ;SIZE OF TYPE CALL PCNT ;PRINT COUNT LXI H,PMSG ;POINT TO MESSAGE CALL PSTRNG ;PRINT STRING LDA PAGE ;GET PAGE NUMBER INR A ;BUMP IT STA PAGE ;SAVE IT CALL DEC ;CONVERT TO DECIMAL LXI H,DECWRK;POINT TO DEC STR ;SAVE POINTER ORA A ;RESET CARRY RET GETB2: MVI C,READ ;READ CODE LXI D,TFCB ;FCB ADDRESS CALL CPM ;ISSUE READ CPI 00 ;ERROR? JNZ IERR ;YES LXI H,TBUF ;RESET BUFFER POINTER SHLD INPTR JMP GETB1 ;CONTINUE IERR: STC RET ;*********** JNZ PCNT RET DEC: LXI H,DECWRK MVI C,100 CALL DIGIT MVI C,10 CALL DIGIT MVI C,1 CALL DIGIT RET DIGIT: MVI M,'0' DI0: SUB C JM DI1 INR M JMP DI0 DI1: ADD C INX H RET IF FORM DONE: MVI A,FF ;FORM FEED CALL PBYT MPBYT MVI B,NULLS ;NUMBER OF RUBOUTS TOF2: MVI A,RUBOUT CALL PBYT DCR B ;DCREMENT COUNT JNZ TOF2 ;PRINT 'N' RUBOUTS ENDIF ; ; IF NOT FORM;ROUTINE TO PAGE TOP WITH 'S TOF: MVI B,LINES ;NUMBER OF LINES TOF2: MVI A,LF ; CALL PBYT D XRA A ;CLEAR CARRY RET FOERR: STC RET ;********************************; ; G E T B T ; ; ROUTINE TO READ A BYTE ; ; ; ; OUTPUTS: A=BYTE ; ; CARRY=ERRO: PUSH H PUSH B PUSH PSW MOV E,A MVI C,ODEV CALL CPM ;PRINT POP PSW CPI SPACE ;NON-PRINTING? JC PBY2 ;YES, DONT BUMP COL LXI H,COL ;INCREMENT COLUMN INR M PBY2: MVI C,11 ;GET CONSOLE STATUS CALL CPM CPI 00 ;BREAK? JNZ BOOT ;YES, ING MVI B,3 CALL PCNT ;PRINT PAGE NUMBER MVI A,CR ;PRINT CR CALL PBYT MVI A,LF CALL PBYT ;PRINT LF MVI A,LF CALL PBYT ;AND SECOND MVI A,LF CALL PBYT ;AND A THIRD XRA A STA LINE ;RESET LINE COUNT STA COL ;RESET COLUMN RET PBYTH CMP D RNZ MOV A,L CMP E RET ;********************************; ; D A T A ; ;********************************; COL: DB 0 ;COLUMN COUNTER LINE: DB 0 ;LINE COUNTER PAGE: DB 0 ;PAGE COUNTER FMSG: DB CR,'FILE: $' SUB C JM DI1 INR M JMP DI0 DI1: ADD C INX H RET DONE: MVI A,0CH ;FORM FEED CALL PBYT MVI B,NULLS ;RUBOUT COUNT DLP2: MVI A,7FH CALL PBYT DCR B JNZ DLP2 JMP BOOT ;EXIT ERR: LXI D,ERMSG MVI C,09H ;WRITE MSG CALL CPM JMPNUE CRET2: MVI A,0DH CALL PBYT ;PRINT CR CALL TOF JMP LOOP TOF: MVI A,0CH ;FORM FEED CALL PBYT MVI B,NULLS ;NUMBER OF RUBOUTS TOF2: MVI A,7FH ;RUBOUT CALL PBYT DCR B ;DCREMENT COUNT JNZ TOF2 ;PRINT 'N' RUBOUTS LXI H,FMSG ;POINT TO ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееXI H,COL ;INCREMENT COLUMN INR M PBY2: MVI C,11 ;GET CONSOLE STATUS CALL CPM CPI 00 ;BREAK? JNZ BOOT ;YES, DONE POP B POP H RET PSTRNG: MOV A,M ;GET BYTE CPI '$' ;STRING END? RZ ;YES, DONE CALL PBYT ;PRINT BYTE INX H ;BUMP POINTER GETBT ;GET A BYTE JC ERR ;ERROR CPI 1AH ;EOF? JZ DONE ;YES CPI 0DH ;CR? JZ CRET ;YES CPI 09H ;TAB? JNZ LOOPX ;NO, CONTINUE LXI H,COL ;POINT TO COLUMN TBLP: MVI A,' ' ;PRINT ONE SPACE CALL PBYT MOV A,M ;GET COLUMN ANI 07H ;MODULO 8 PMSG: DB ' PAGE $' ERMSG: DB 'ERROR',0DH,0AH,'$' DS 32 STACK EQU $ INPTR: DW TBUF+128;INPUT POINTER DECWRK: DB '000' END PRINT  MESSAGE CALL PSTRNG ;PRINT STRING LDA PAGE ;GET PAGE NUMBER INR A ;BUMP IT STA PAGE ;SAVE IT CALL DEC ;CONVERT TO DECIMAL LXI H,DECWRK ;POINT TO DEC STRING MVI B,3 CALL PCNT ;PRINT PAGE NUMBER MVI A,0DH ;PRINT CR CALL PBYT MVI A,0AH MESSAGE CALL PSTRNG ;PRINT STRING LXI H,TFCB+1 ;POINT TO NAME MVI B,8 ;SIZE OF NAME CALL PCNT ;PRINT COUNT MVI A,' ' ;PRINT A SPACE CALL PBYT LXI H,TFCB+9 ;POINT TO TYPE MVI B,03 ;SIZE OF TYPE CALL PCNT ;PRINT COUNT LXI H,PMSG ;POINT TO;********************************; ; FILE PRINT UTILITY ; ;********************************; ;********************************; ; MISCELLANEOUS EQUATES ; ;********************************; MAXLN EQU 56 ;LINES/PAGE NULLS EQ JMP PSTRNG ;LOOP PCNT: MOV A,M ;GET BYTE CALL PBYT ;PRINT IT INX H ;BUMP POINTER DCR B ;DECREMENT COUNT JNZ PCNT RET DEC: LXI H,DECWRK MVI C,100 CALL DIGIT MVI C,10 CALL DIGIT MVI C,1 CALL DIGIT RET DIGIT: MVI M,'0' DI0:JNZ TBLP ;IF NOT AT TAB STOP, KEEP TYPEIN JMP LOOP LOOPX: CALL PBYT ;PRINT BYTE JMP LOOP CRET: LDA LINE ;GET LINE COUNT CPI MAXLN ;PAGE OVERFLOW? JZ CRET2 ;YES INR A ;BUMP LINE COUNT STA LINE XRA A STA COL MVI A,0DH JMP LOOPX ;CONTIееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее CALL PBYT ;PRINT LF MVI A,0AH CALL PBYT XRA A STA LINE ;RESET LINE COUNT STA COL ;RESET COLUMN RET PBYT: PUSH H PUSH B PUSH PSW MOV E,A MVI C,05 CALL CPM ;PRINT POP PSW CPI 20H ;NON-PRINTING? JC PBY2 ;YES, DONT BUMP COL L********************************; ; MAIN LOOP ; ;********************************; ORG 100H PRINT: LXI SP,STACK LXI D,TFCB ;POINT TO FCB CALL FOPEN ;OPEN FILE JC ERR ;IF ERROR, EXIT CALL TOF ;PRINT HEADING LOOP: CALL U 12 ;NULLS AFTER A FORM FEED BOOT EQU 0000H ;REBOOT ENTRY POINT CPM EQU 0005H ;CPM ENTRY POINT TBUF EQU 0080H ;TRANSIENT PROGRAM BUFFER TFCB EQU 005CH ;TRANSIENT PROGRAM FCB OPEN EQU 15 ;OPEN FUNCTION CODE READ EQU 20 ;READ FUNCTION CODE ; BOOT ;********************************; ; F O P E N ; ; ROUTINE TO OPEN A DISK FILE ; ; ; ; INPUT: DE=A(FCB) ; ; OUTPUT: CARRY=ERROR ; ;***************************AND GO BACK FOR NEXT DIGIT ; ; TESTNO: MOV A,H ;GET HIGH BYTE OF NUMBER OF K SPECIFIED ORA A ;IF IT'S NOT ZERO, NUMBER WAS 256 OR BIGGER JNZ INVAL ; AND THEREFORE NOT A VALID MEMORY SIZE MOV A,L ;GET LOW BYTE CPI 16 ;SYSTEM MUST BE AT LEAST 16K T 900H, AND A ; RELOCATION TABLE, PRESENTLY BEGINNING AT 2100H. ; ; ORG 100H ; ; LOCATIONS OF INFORMATION FROM COMMAND LINE, PUT IN DEFAULT BUFFERS ; BY CCP: ; NAME1 EQU 5DH ;FIRST "FILENAME" (NO. OF K) NAME2 EQU 6DH ;2ND "FILENAME" (BLANK OR *) END OF BUFFER JZ GETB2 ;YES, READ GETB1: MOV A,M ;GET BYTE INX H ;BUMP POINTER SHLD INPTR ;SAVE POINTER ORA A ;RESET CARRY RET GETB2: MVI C,READ ;READ CODE LXI D,TFCB ;FCB ADDRESS CALL CPM ;ISSUE READ CPI 00 ;ERROR? JNZ IERR ;YES LXICPI ' ' JZ TESTNO ;FINISHED GETTING NUMBER IF BLANK OR NULL ORA A ;TEST FOR NULL (0) JZ TESTNO SUI '0' ;SUBTRACT ASCII 0; THIS CONVERTS DIGIT TO NUMBER CPI 10 ;MAKE SURE IT WAS REALLY A DIGIT (0-9) JNC INVAL ;JUMP IF NOT DAD H ;DOUBLE ACCUMULееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее*****; FOPEN: MVI C,OPEN ;OPEN CODE CALL CPM ;ISSUE OPEN CPI 0FFH ;ERROR? JZ FOERR ;YES XRA A ;CLEAR CARRY RET FOERR: STC RET ;********************************; ; G E T B T ; ; ROUTINE TO READ A BYTE ; ; CR EQU 0DH LF EQU 0AH ; ; ; ; FIRST: JMP START ; ; ; ; ORG 012CH ; START: LXI SP,800H ; ; LXI D,NAME1 LDAX D ;GET FIRST CHAR. OF WHAT IS ASSUMED TO BE NO. OF K CPI ' ' JZ UNSPEC ;JUMP IF NO NUMBER TYPED IN COMMAND CPI '?' JZ UN ; ENTRY EQU 5 ;LOCATION OF JUMP TO BDOS REBOOT EQU 0 ;LOCATION TO JUMP TO FOR REBOOT SYSTEM EQU 900H ;WHERE RELOC'S COPY OF SYSTEM RESIDES SERIAL EQU 1300H ;START OF SERIAL NUMBER IN THAT SYSTEM SIZE EQU 801H ;WHERE LENGTH OF SYSTEM IS STORED ; ; H,TBUF ;RESET BUFFER POINTER SHLD INPTR JMP GETB1 ;CONTINUE IERR: STC RET ;********************************; ; MISCELLANEOUS SUBROUTINES ; ;********************************; ;********************************; ; C P H L ATED VALUE PUSH H ;SAVE RESULT DAD H ;DOUBLE IT AGAIN DAD H ;AND AGAIN POP B ;NOW GET RESULT SAVE ABOVE AND ADD TO VALUE DAD B ;WE HAVE NOW MULTIPLIED VALUE BY 10 MOV C,A ;NOW ADD TO IT THE VALUE OF THE NEW DIGIT MVI B,0 DAD B JMP DIGIT ;; RELOC.ASM ; ; ; THIS IS A REGENERATED SOURCE TEXT OF THE PROGRAM PORTION OF ; RELOC.COM. IT GENERATES THE SAME CODE (EXACTLY) AS IS FOUND ; IN LOCATIONS 100-102 AND 12C-393 (HEX) OF RELOC.COM. RELOC.COM ; ALSO CONTAINS A COPY OF CP/M, BEGINNING A ; ; OUTPUTS: A=BYTE ; ; CARRY=ERROR ; ;********************************; GETBT: LXI H,TBUF+128 XCHG ;BUFFER END ADDR. IN DE LHLD INPTR ;CURRENT POINTER IN HL CALL CPHL ;TEST FORSPEC ;RECOGNIZE BLANK OR QUESTION MARK AS NO-NUMBER ; ; ; IF WE ARE HERE, THERE IS A DECIMAL NUMBER AT 5DH WAITING TO BE READ ; LXI H,0 ;H WILL CONTAIN THE VALUE OF THE NUMBER DIGIT: LDAX D ;GET NEXT DIGIT (ASCII) INX D ;INCREMENT DIGIT POINTER B 0 ;COLUMN COUNTER LINE: DB 0 ;LINE COUNTER PAGE: DB 0 ;PAGE COUNTER FMSG: DB 0DH,0AH,'FILE: $' PMSG: DB ' PAGE $' ERMSG: DB 'ERROR',0DH,0AH,'$' DS 32 STACK EQU $ INPTR: DW TBUF+128;INPUT POINTER DECWRK: DB '000' END PRINT  ; ; ROUTINE TO COMPARE HL VS DE ; ;********************************; CPHL: MOV A,H CMP D RNZ MOV A,L CMP E RET ;********************************; ; D A T A ; ;********************************; COL: D JC INVAL ; SO ERROR IF <16. ; ; ; NOW MULTIPY NO. OF K BY 1024 TO GET SPECIFIED MEMORY SIZE ; MVI L,0 ;L WAS SAVED IN A ABOVE MOV H,A ;THIS MULTIPLIES BY 256 DAD H ;MULTIPLY BY 2 DAD H ;MULTIPLY BY 2 AGAIN JMP PUTK ;GO TO NEXT SECTION WITH ;SET LOW BYTE OF BDOS ADDRESS TO ZERO, SO ADDRESS IS THAT OF SERIAL NUMBER ; ; ; ; POP B ;GET SYSTEM LENGTH POP H ;GET MEMORY SIZE IN BYTES MOV A,L ;SUBTRACT B FROM H TO GET MSIZE-LENGTH SUB C ; THIS IS ADDRESS NEW SYSTEM WILL RUN FROM MOV L,CONTINUES THROUGH 900+LENGTH ; ; LXI H,SYSTEM SEARCH: LXI D,CPMMSG+17 MOV A,B ORA C JZ NOFIND ;EXIT IF SEARCH COMPLETED WITHOUT FINDING STRING DCX B ;DECREMENT SEARCH COUNT AND SAVE ON STACK PUSH B ; MVI C,15 ;SET STRING LENGTH FOR COMPACK CMP M ;NOW READ BACK AND COMPARE CMA ;RESTORE MEMORY BEFORE JUMPING MOV M,A JZ PAGE ;KEEP LOOPING IF MEMORY VALID FOUND: MOV A,H ;L IS STILL ZERO, SO HL IS NUMBER OF BYTES OF MEMORY, ANI 0FCH ; TRUNCATED TO NEAREST 256. NOW ZERO BITS 0,1 OF GOTIT: POP H ;STRING FOUND- GET ITS LOCATION POP B ;CLEAN UP STACK DCX H ;POINT TO 2ND DIGIT OF NUMBER OF K IN STRING LXI D,CPMMSG+16 LDAX D ;GET ASCII NUMBER OF K FROM STRING, AND PUT IT INTO STRING JUST FOUND MOV M,A DCX H DCX D LDAX D ' MVI M,'0' ;ELSE SET IT TO ASCII 0 AND INCREMENT HIGH DIGIT. DCX H INR M CNV1A: DCR B ;DECREMENT REMAINDER OF NUMBER BEING CONVERTED JNZ CNVRT1 ; AND CONTINUE IN LOOP IF NOT YET ZERO ; ; LXI D,CPMMSG CALL MSG ;OUTPUT "CONSTRUCTING . . ." MH=MEMORY SIZE IN BYTES ; ; INVAL: LXI D,INVMSG CALL MSG ;OUTPUT "INVALID MEMORY SIZE" MESAGE TO CONSOLE JMP REBOOT ;REBOOT SYSTEM ; ; INVMSG: DB CR,LF,'INVALID MEMORY SIZE$' ; ; ; COME HERE IF MEMORY SIZE WAS NOT SPECIFIED IN COMMAND LINE ; ; ; DB 1 SYNERR: XRA A SYNE1: DCR A JNZ SYNE1 LXI H,76F3H SHLD BDOS ;PUT "DI,HLT" AT BDOS, WHERE "CALL ENTRY" WILL RETURN LXI H,SYSCAL MVI M,0CDH ;CHANGE INSTRUCTION AT SYSCAL FROM "JMP" TO "CALL" LXI D,SYNMSG-5 LXI H,5 DAD D XCHG RE LOOP PUSH H ;SAVE CURRENTLY SEARCH ADDRESS ON STACK COMPR: LDAX D ;LOOP TO COMPARE STRINGS- D POINTS TO ONE, H TO THE OTHER CMP M JNZ NEWLOC ;GO TRY NEXT MEMORY POSITION IF COMPARISON FAILED INX D INX H DCR C JZ GOTIT JMP COMPR ; ; ;H TO MOV H,A ; TRUNCATE TO A MULTIPLE OF 1024 PUTK: PUSH H ;SAVE TRUNCATED MEMORY SIZE ON STACK ; LHLD ENTRY+1 ;GET STARTING ADDRESS OF PRESENT BDOS FROM THE JUMP AT LOC. 5 SHLD BDOS ;SAVE IT FOR LATER USE ; POP H ;GET MEMORY SIZE AGAIN PUSH H MOV M,A ; ; ; ; NOFIND: LXI B,BDOS ;GET LOW BYTE OF CURRENT BDOS ADDRESS LDAX B CPI 6 ;THIS BYTE IS NORMALLY 06, BUT IS CHANGED BY DDT AND RESTORED ON RETURN TO SYSTEM MVI A,0 JNZ SYNC1 ;GIVE SYNCHRONIZATION ERROR IF BYTE IS NOT 06 STAX B ESSAGE TO CONSOLE ; ; LXI H,SIZE ;GET LENGTH OF SYSTEM IN BYTES MOV C,M INX H MOV B,M PUSH B ;SAVE LENGTH IN B AND ON STACK ; ; ; SEARCH RELOC'S COPY OF THE SYSTEM FOR THE STRING "K CP/M VERS 1.3". THE ; SEARCH PRESENTLY BEGINS AT 900H AND UNSPEC: LXI H,0 ;SET UP TO FIND MEMORY SIZE PAGE: INR H ;POINT TO 1ST LOCATION OF NEXT PAGE JZ FOUND ;GET OUT OF LOOP IF WE FOUND 256 PAGES OF MEMORY (WHY?) MOV A,M ;GET 1ST BYTE OF PAGE POINTED TO BY H CMA ;COMPLEMENT IT MOV M,A ; AND PUT IT BA ;THIS GETS "SYNC. ERROR" MESSAGE ADDRESS IN D JMP MSG ;OUTPUT MESSAGE AND THEN HANG. ; ; ; ; NEWLOC: POP H ;GET SEARCH POINTER AGAIN INX H ;INCREMENT IT POP B ;RESTORE REMAINING SEARCH COUNT JMP SEARCH ;GO BACK TO LOOK FOR STRING AGAIN ; ;' ;SET IT TO ASCII 00 MOV M,A INX H MOV M,A CNVRT1: LXI H,CPMMSG+16 ;LOOP TO CONVERT NO. OF K TO DECIMAL ASCII (2 DIGITS) INR M ;INCREMENT LOW DIGIT MOV A,M ;GET ITS NEW VALUE CPI '9'+1 JC CNV1A ;CONTINUE LOOP IF STILL IN THE RANGE '0' TO '9 ; BUT LEAVE IT ON STACK TOP MOV A,H ;TAKE NUMBER OF PAGES AND DIVIDE BY 4 (INTEGER) RRC ;TO GET NUMBER OF K. RRC ANI 3FH MOV B,A ;SAVE NUMBER OF K IN B LXI H,CPMMSG+15 ;POINT TO OF NUMBER OF K (ASCII) IN "CONSTRUCTING" MESSAGE TEXT MVI A,'0A MOV A,H SBB B MOV H,A SHLD NEWSYS ;SAVE THIS ADDRESS AT NEWSYS AND IN D XCHG ; ; ; ; LXI H,SYSTEM ;POINT TO BEGINNING OF SYSTEM LOADED WITH RELOC.COM PUSH B ;SAVE LENGTH ; LDA NAME2 ;GET 2ND ITEM IN COMMAND LINE CPI ' ' ;IF BLANK, ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее ; ; ; IF SYSTEM WAS PUT AT EXECUTION ADDRESS, GO THERE ; LDA NAME2 CPI ' ' JZ SYSGO ; ; ; IF 900-97F IS ALL ZEROES, THEN MOVE THE WHOLE SYSTEM DOWN 80H BYTES ; FROM 980 TO 900 ; ; MVI B,80H LXI H,SYSTEM TEST1: MOV A,M ORA A JNZ NOELOCATION. ; MSIZE-LENGTH+100H IS ADDED TO EACH ADDRESS ; MARKED BY A '1' IN THE RELOCATION BIT TABLE. ; ; REL1: POP B ;GET LENGTH PUSH H ;SAVE TABLE ADDRESS LHLD NEWSYS XCHG ;ADDRESS OF NEW SYSTEM IN D LXI H,100H DAD D ;H IS NOW NEWSYS+10GE LXI D,ENDMSG CALL MSG ;OUTPUT MESSAGE TO CONSOLE JMP REBOOT ;RETURN TO CP/M ; ; ; ; ENDMSG: DB CR,LF,'READY FOR "SYSGEN" OR',CR,LF DB '"SAVE 00 CPM00.COM"$' ; ; ; ; SYSGO: LXI D,1600H LHLD NEWSYS DAD D PCHL ;JUMP TO NEW SYSTEMLOCATION IN NEW SYSTEM ADD H ;ADD HIGH BYTE OF 100H+EXECUTION ADDRESS STAX D ; AND PUT BACK IN NEW SYSTEM JMP REL5 REL5: INX D ;POINT TO NEXT BYTE OF NEW SYSTEM JMP REL2 ; ; ; ; FINISH: POP D ;CLEAN UP STACK ; ; ; COMPARE SERIAL NUMBER OFSYSTEM IS TO BE PLACED AT ITS EXECUTION ADDRESS JZ EXEC DAD B ;SET H TO POINT TO FIRST LOC. AFTER SYSTEM (START OF RELOCATION TABLE) JMP REL1 ; ; ; ; SYNC1: LXI H,SYNERR ;SET JUMP AT SYNC2 TO GO TO SYNERR SHLD SYNC2+1 JMP SYNC2 ; ; ; ; 1 SYNC2: JMP SYNC2 ; ; NOMOVE: LXI H,SIZE MOV C,M INX H MOV B,M ;B = LENGTH LXI H,900H DAD B MOV B,H ;C IS ALREADY ZERO- NOW B IS NUMBER OF PAGES IN NEW SYSTEM ; ; ; PUT NUMBER OF PAGES IN THE NEW SYSTEM INTO THE "SAVE NN . . ." MESSAGEMOVE INX H DCR B JNZ TEST1 ; XCHG ;D IS 980H LHLD SIZE ;GET SYSTEM LENGTH LXI B,-80H DAD B MOV B,H MOV C,L ;BC = LENGTH-128 LXI H,900H MOVE: MOV A,B ORA C JZ NOMOVE DCX B LDAX D MOV M,A INX D INX H JMP MOVE ; ; DB0H ; ; LDA NAME2 ;GET 2ND COMMAND ITEM AGAIN CPI ' ' JZ REL2 LXI D,SYSTEM ;IF NOT A SPACE, SET D TO PUT NEW SYSTEM IN PLACE FOR SYSGEN REL2: MOV A,B ORA C JZ FINISH ;JUMP IF COUNT HAS REACHED ZERO JMP REL3 ; ; SYNMSG: DB CR,LF,'SYNCRON ; ; ; ; MSG: MVI C,9 SYSCAL: JMP ENTRY BDOS DW 0 NEWSYS DW 0 ; CPMMSG: DB CR,LF,'CONSTRUCTING 00K CP/M VERS 1.3$' ; ; ; ; END  NEW SYSTEM WITH THAT OF SYSTEM CURRENTLY RUNNING. ; ; LXI D,SERIAL ;ADDRESS OF SERIAL NUMBER IN RELOC.COM LHLD BDOS ;ADDRESS OF SERIAL NO. IN CURRENT SYSTEM MVI C,6 ;LOOP COUNT SERLP: LDAX D CMP M JNZ SYNC1 INX H INX D DCR C JNZ SERLP; IF 2ND ITEM IN COMMAND WAS BLANK, THEN COME HERE TO MOVE A COPY ; OF THE SYSTEM FROM 900 TO ITS EVENTUAL EXECUTION ADDRESS. ; ; EXEC: MOV A,B ORA C JZ REL1 DCX B MOV A,M STAX D INX D INX H JMP EXEC ; ; ; ; ; LOOP TO PERFORM THE R TEXT ; LXI H,ENDMSG+31 MVI A,30H MOV M,A INX H MOV M,A PUTN: DCR B JZ PUTK2 LXI H,ENDMSG+32 INR M MOV A,M CPI '9'+1 JC PUTN MVI M,30H DCX H INR M JMP PUTN ; ; PUTK2: LHLD CPMMSG+15 SHLD ENDMSG+37 ;PUT NO. OF K IN MESSAMOV A,M ;GET THE BYTE THERE INX H ;INCREMENT TABLE ADDRESS XTHL ;PUT IT BACK ON STACK MOV L,A REL4: MOV A,L ;TEST NEXT BIT OF CURRENT TABLE BYTE RAL MOV L,A JNC REL5 ;IF NOT SET, CONTINUE IN LOOP LDAX D ;GET HIGH BYTE OF ADDRESS AT CURRENT IZATION ERROR$' ; ; REL3: DCX B ;DECREMENT BYTE COUNT MOV A,E ;GET LOW BYTE OF CURRENT ADDRESS IN NEW SYSTEM ANI 7 ;IF IT IS A MULTIPLE OF 8, WE NEED TO GET ANOTHER JNZ REL4 ; BYTE OF THE RELOCATION TABLE XTHL ;GET H=CURRENT ADDRESS IN TABLE ;REF NO. AB27 ;PROGRAM TITLE REAL TIME EXECUTIVE ; ; ; ; REAL TIME EXECUTIVE ; ; ; THE REAL TIME EXECUTIVE IS DESIGNED TO PERFORM THE NECESSARY ; SCHEDULING AND TASK INITIALIZATION AND TERMINATION THAT CAN BE ; FOUND IN REAL-TIME ENVIRONMEN QCLOK ADI DELAY CALL QPERQ ENDM ; ;THE FOLLOWING EQUATES ARE REQUIRED BY THE EXECUTIVE ; BRAM EQU 04000Q NRAMS EQU 02 QTSTK EQU BRAM+0300Q QSYS EQU BRAM+0400Q QQUEP EQU BRAM+0200Q QCLOK EQU BRAM QQUE EQU QCLOK+1 QSTAK EQU QQUE+2 ; ;THE ; INRET MACRO INTERRUPT RETURN WITH PSW RESTORE ; PEREQ MACRO CALLS QPERQ TO SCHEDULE A TASK FOR TIMED ENTRY ; PARAMETERS: ADDRESS, TIME ; PERDY MACRO CALLS QPERQ TO SCHEDULE A TASK FOR DELAYED ENTRY ; PARAMETERS: ADDRESS, DELAY ; QCLKI ROUTINERESCHEDULES ITSELF. A LARGER TIME BASE WOULD REQUIRE CHANGING THE ; CLOCK AND PERIODIC REQUEST ROUTINES TO HANDLE MORE CLOCK CELLS. ; ; THE EXECUTIVE HAS 6 ROUTINES OR PARTS, 8 EQUATES, AND 5 OPTIONAL ; MACROS. THE EQUATES DEFINE THE STORAGE AREAS USLEASE NOTE THAT THE EQUATES CAN BE CHANGED TO FIT A DIFFERENT MEMORY ; CONFIGURATION AND THAT THE MAIN USER ROUTINE IS CURRENTLY LABELED ACQRE. ; ; ; ; ; ;THE FOLLOWING MACROS ARE REQUIRED BY THE EXECUTIVE ; INITR MACRO ADDR LXI D,ADDR CALL QI ; NRAMS EQU DEFINES THE NUMBER OF 256 BYTE RAM BLOCKS ; QTSTK EQU DEFINES THE LOCATION OF THE TIME STACK ; QSYS EQU DEFINES THE LOCATION OF THE SYSTEM STACK ; QQUEP EQU DEFINES THE LOCATION OF THE DISPATCH QUEUE ; QCLOK EQU DEFINES THETS. IT IS NOT DESIGNED TO HANDLE ; A TIME SLICE ENVIRONMENT (I.E. TIMESHARING NETWORK). ; ; THE EXECUTIVE SHOULD BE USED AS A CONTROL PROGRAM FOR THE ; VARIOUS APPLICATION TASKS A USER MIGHT WISH TO RUN. IT WILL SCHEDULE ; TASKS ON A LIFO QUEUE FOR ACK ; IN INCREASING TIME ORDER. ADDRESS IN D,E; TIME IN A ; QINIT ROUTINE ADDS A ROUTINE TO THE DISPATCH QUEUE. ADDRESS IN ; D,E. ; QDSPC ROUTINE TERMINATES A ROUTINE BY EXITING TO THE NEXT ROUTINE ; ON THE DISPATCH QUEUE. ; QWAIT ROUTINE I UPDATES THE CLOCK CELL AND CHECKS THE TOP OF THE ; TIME STACK FOR TIMED ENTRIES ; QPERQ ROUTINE SCHEDULES A TASK TO BE ACTIVATED AT A LATER TIME, ; DOESN'T ALLOW A TASK TO BE SCHEDULED TWICE FOR ; THE SAME ACTIVATION TIME, MAINTAINS THE TIME STEY THE SYSTEM, THE ; ROUTINES HANDLE THE VARIOUS FUNCTIONS, AND THE MACROS PROVIDE A MEDIUM ; FOR USER CALLS TO THE SYSTEM. DEFINITIONS ARE PROVIDED IN TABLE #1. ; ; PLEASE NOTE THAT ALL THE STACKS AND QUEUES IN THE ; SYSTEM GROW DOWNWARD IN MEMORY TNIT ENDM TERM MACRO JMP QDSPC ENDM ; ;THESE MACROS ARE REQUIRED BY THE APPLICATIONS PROGRAM ; INRET MACRO POP PSW EI RET ENDM PEREQ MACRO ADDR,TIME LXI D,ADDR MVI A,TIME CALL QPERQ ENDM PERDY MACRO ADDR,DELAY LXI D,ADDR LDA CLOCK CELL ; QQUE EQU HOLDS THE CURRENT QUEUE POINTER (2 CELLS) ; QSTAK EQU HOLDS THE CURRENT TIME STACK POINTER (2 CELLS) ; INITR MACRO CALLS QINIT WITH THE ROUTINE ADDRESS AS PARAMETER ; TERM MACRO CALLS QDSPC (TERMINATES A ROUINE) EXECUTION OR ON A TIME STACK FOR EXECUTION ; AT A LATER TIME. THE CLOCK IS CURRENTLY SET UP ON AN 8-BIT WRAP- ; AROUND WITH THE CLOCK INTERRUPT FORCING AN RST 7. A SMALLER TIME ; BASE CAN BE USED BY SCHEDULING A ROUTINE THAT RESETS THE CLOCK, THEN ; DLES WHEN THE SYSTEM IS NOT BULD ALWAYS BE ; LAST ON THE DISPATCH QUEUE, IT RESCHEDULES ITSELF. ; QINTP ROUTINE INITIALIZES THE PROCESSOR BY CLEARING RAM, SETTING ; UP POINTERS, AND SCHEDULING THE SYSTEM WAIT AND MAIN ; USER ROUTINES. ; ; ; PI- ; SIONS FOR ANOTHER PRIORITY SCHEME. THIS IMPLIES THAT ONCE STARTED A ; ROUTINE OR TASK RUNS UNTIL COMPLETION ESCEPT FOR INTERRUPT PROCESSING. ; ; ; ; ; ; ; TABLE #1 ; ; NAME TYPE FUNCTION ; ; BRAM EQU DEFINES THE BASE OF RAM MEMORY O BE CONSISTENT WITH INTEL. THE ; TIME STACK REQUIRES 3 BYTES PER ENTRY AND HAS A CELL OR ALL BINARY ONES ; AT THE TOP TO PREVENT IT FROM RUN-AWAY IN CASE IT IS EMPTY. THE DISPATCH ; QUEUE REQUIRES 2 BYTES PER ENTRY, IS LIFO IN DESIGN, AND HAS NO PROVFIRST 64D CELLS ARE THE INTERCTORS ; DI ;PWER JMP QINTP ;UP ; ;THIS IS THE CLOCK INTERRUPT ROUTINE. ;IT UPDATES THE CLOCK IN 116 CYCLES, TO ACTIVATE ;A TASK REQUIRES 237 CYCLES + INIT TIME. ; ORG 70Q ;RESTART 7 QCLKI: PUSH PSW ;SAVE PUSH H LXI D,SYMTB ;POINT DE TO TABLE DAD D ;POINT HL TO PROPER ENTRY LABEL MOV A,M ;GET FIRST CHAR ORA A ;END OF TABLE? RZ ;RETURN TO CALLER IF SO ; PRINT EXISTING LABEL MVI B,5 ;MAX LABEL LENGTH PRINT MOV A,M ;GET CHAR OF LABEL ORA A ;END OF SHORD,M ;QUEUE INX H ;ALTER SHLD QQUE ;POINTER XCHG ;AND EI ;EXIT TO PCHL ;NEW TASK ; ;SYSTEM WAIT ROUTINE, ALWAYS LAST ON THE QUEUE. ;IT WAITS UNTIL SOMETHING HAPPENS. ; QWAIT: INITR QWAIT ;RE-INIT HLT ;WAIT TERM ; ;PROCESSOR INITIALITIME IN A. THE BEST CASE EXECUTION ;IS 117 CYCLES, TO UNSTACK AND INSERT ONCE IS 329 CYCLES. ;ALL REGS ARE DESTROYED. ; QPERQ: MVI B,0 ;GET TIME DI ;STACK POINTER LHLD QSTAK ;CHECK TOP QCOMP: CMP M ;OF STACK JC QASTK ;LOWER JZ QADEQ ;EQUAL * * * * * * * * * * * * * * * TYPE EQU 409CH ;TYPE ASCII FROM A KEYIN EQU 408EH ;KEYIN ASCII TO A ; ; PLACE THE ENTRY NUMBER FROM THE ; SYMBOL TABLE AT WHICH YOU WANT TO ; START EDITING INTO THE FOLLOWING ; WORD (0 FOR START OF TABLE) BBUF EQU 386 ;STACK POP PSW DCX H ;THEN MOV M,A ;TRY JMP QSTKP ;AGAIN QPREX: SHLD QSTAK ;SAVE EI ;POINTER RET ;AND EXIT ; ;INITIALIZER ROUTINE, ADDRESS IS PASSED IN D,E. ;DESTROYS H,L. EXECUTION 74 CYCLES. ; QINIT: DI ;ADD LHLD QQUE ;PROGRAM ;REGS LXI H,QCLOK ;INCREMENT INR M ;CLOCK MOV A,M ;CHECK LHLD QSTAK ;TOP OF CMP M ;STACK JC QCLEX ;NONE READY PUSH D ; QCLP: INX H ;POP MOV E,M ;ROUTINE INX H ;AND MOV D,M ;ADD INX H ;TO PUSH H ;DISPATCH CALL QINIT ;QUEUE POP LD QQUE ;QUEUE LXI SP,QSYS ;FINISH INITR QWAIT ;INIT ; ;BEGINNING OF APPLICATION ROUINES ; ACQRE: END *NRAMS DCX B ;BYTES CMP B JNZ QCLRL LXI H,QTSTK ;FIX MVI M,0FFH ;TIME SHLD QSTAK ;STACK LXI H,QQUEP ;DISPATCH SHZATION ROUTINE ; QINTP: LXI H,BRAM ;CLEAR XRA A ;RAM LXI B,(NRAMS SHL 8)+0FFH ;FROM BRAM QCLRL: MOV M,A ;FOR INX H ;256*NRAMS DCX B ;BYTES CMP B JNZ QCLRL LXI H,QTSTK ;FIX MVI M,0FFH ;TIME SHLD QSTAK ;STACK LXI H,QQUEP ;DISPATCH SHMOV C,A ;HIGHER THAN MOV A,F PUSH PSW ;STACK INX H ;REMOVE IT MOV A,M ;AND PUSH PSW ;SAVE IT INX H MOV A,M ;ADJUST PUSH PSW ;POINTER INX H ;AND MOV A,C ;TRY INR B ;AGAIN JMP QCOMP QADEQ: INX H ;TIME MOV A,E ;EQUAL CMP M ;CHEC8H ;PTCO PARM BUFFER+2 ; SYMTB EQU 0C002H ;SYMBOL TABLE START ORG 3600H LHLD BBUF ;GET TABLE ENTRY # MOV D,H ;MOVE ENTRY # MOV E,L ;..TO D,E ; MULTIPLY ENTRY BY 7 BYTES/ENTRY DAD H ;TIMES 2 DAD D ;TIMES 3 DAD H ;TIMES 6 DAD D ;TIMES 7 DCX H ;TO MOV M,D ;DISPATCH QUEUE MOV M,E ; SHLD QQUE EI RET ; ;DISPATCHER ROUTINE, ENTRANCE UPON TASK TERMINATION. ;LIFO PRIORITY WITH EXIT TO NEXT TASK. (73 CYCLES). ; QDSPC: DI ;GET LHLD QQUE ;NEXT MOV E,M ;TASK INX H ;PROM MOV H ; CMP M ;ANY MORE JNC QCLP ;YES POP D SHLD QSTAK QCLEX: POP H ;RESTORE INRET ;REGS & EXIT ; ;THIS IS THE PERIODIC REQUEST ROUTINE. IT MANIPULATES THE ;STACK AND THEREFORE MASKS OFF INTERUPTS. PARAMETERS ARE ;ROUTINE ADDRESS IN D,E AND ;CP/M NOTE - EDITED FOR CP/M ASSEMBLER BY A.R.G. ;SEE DISASSM1.ASM FOR MAIN PROGRAM BY ;WARD CHRISTENSEN ; ; *@2C0 1 * * * * * * * * * * * * * * * * * SYMBOL TABLE EDIT ROUTINE * * FOR USE WITH * * 8 0 8 0 DISASSEMBLER * *STACK QASTK: DCX H ;ADD REQUEST MOV M,D ;TO TOP DCX H ;OF TIME MOV M,E ;STACK DCX H ;ADJUST MOV M,A ;POINTER QSTKP: DCR B ;ANYTHING TO JM QPREX ;RESTORE POP PSW ;YES DCX H ;RESTORE MOV M,A ;REQUEST POP PSW ;TO DCX H ;TIME MOV M,AK ADDRESS JNZ QRELD ;NOT EQUAL INX H ;CHECK REST MOV A,D ;OF CMP M ;ADDRESS JZ QEQAD ;EQUAL DCX H ;NOT EQUAL QRELD: DCX H ;RESTORE POINTER MOV A,M ;TIME, AND JMP QASTK ;ADD TO STACK QEQAD: DCX H ;RESTORE DCX H ;POINTER JMP QSTKP ;POP T LABEL? JZ ENDP ;..YES - END OF PRINT CALL TYPE ;TYPE THE CHAR INX H ;POINT TO NEXT DCR B ;DONE? JNZ PRINT ;NO ; END OF LABEL ENDP MOV A,B ;GET LABEL RESIDUAL COUNT ADD L ;ADD TO H,L MOV L,A ;MOVE IT BACK JNC NC ;SKIP ADD IF NO CARRY INT/2 STA THETA1 MVI A,3*PI/2 STA THETA2 LXI H,32 * X1INIT SHLD X1 SHLD T1X LXI H,32 * Y1INIT SHLD Y1 SHLD T1Y LXI H,32 * X2INIT SHLD X2 LXI H,32 * Y2INIT SHLD Y2 LXI H,0 SHLD VX1 SHLD VY1 SHLD VX2 SHLD VY2 EI JMP STARTBLE, RETURN ABORT POP H ;DELETE PUSHED H RET ; RETURN TO CALLER LE CPI 10 ;ALPHA HEX? JC HEXNU ;NO, NUMBER ADI 7 ;FUDGE FOR ALPHA HEX HEXNU ADI '0' ;MAKE PRINTABLE JMP TYPE ;PRINT NIBHAR CPI 7FH ;DEL CHAR? (BACKSPACE?) JNZ NOTBS ;..NO ; PROCESS BACKSPACE DCX H ;BACK UP 1 CHAR INR D ;ADJUST COUNT ; PRINT DELETED CHAR IN SLASHES MVI A,'/' CALL TYPE MOV A,M ;GET DELETED CHAR CALL TYPE MVI A,'/' CALL TYPE JMP INPLP LXI H,INT7 SHLD 71Q RESTART: DI MVI C,ESC CALL TYOUT MVI C,FF CALL TYOUT IN 0FFH ANI 1 JZ RS1 MVI C,ESC CALL TYOUT MVI C,112 CALL TYOUT RS1: MVI A,1 OUT 8 ;ENABLE TEKTRONIX IN AND OUT INTERRUPTS XRA A STA BUFSW STA TLCE ; ; HEX OUTPUT ROUTINES ; ;---> HEX OUTPUT W/BLANK XOB CALL XO ;PRINT HEX JMP SPACE ;..THEN SPACE ;---> HEX OUTPUT XO PUSH PSW ;SAVE INCOMING A REG RAR ; SHIFT RAR ; ..LEFT NIBBLE RAR ; ..INTO THE RAR ; ..THE RIGHT NIBBLE CALL NIBO H INR H ;ADD IN CARRY NC CALL SPACE ;PRINT A SPACE ; PRINT HEX LABEL VALUE MOV A,M ;FIRST CHAR CALL XO ;PRINT IN HEX INX H ;POINT TO SECOND CHAR MOV A,M ;SECOND CHAR CALL XOB ;SECOND CHAR LXI D,-6 ;BACK HL UP TO DAD D ;..START OF LABEL ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее NOTBS CPI 13 ;C/R? JZ ENDLB ;YES - END OF LABEL MOV M,A ;STORE CHAR INTO TABLE INX H ;POINT TO NEXT POSITION DCR D ;5 CHARS? JNZ INPLP ;NO - GO GET MORE MVI A,13 ;GET ASCII C/R CALL TYPE ;C/R ; END OF ;LABEL, PAD W/0'S IF < 5 CHARS ENDLB MIFE1 STA RSTAR1 STA RSTAR2 STA HIT1 STA HIT2 STA MTHRUST1 STA MTHRUST2 STA VTHETA1 STA VTHETA2 LXI H,BUF1 SHLD OUTBUF SHLD BPOINT MVI M,0 INX H MVI M,13 LXI H,BUF2 SHLD CURBUF LXI H,BUF3 SHLD MIDBUF MVI M,13 MVI A,PIBL ;PRINT LEFT NIBBLE POP PSW ;RESTORE CHAR ;---> PRINT 1 HEX NIBBLE ; (NIBBLE IS HALF A BYTE) NIBBL ANI 15 ;ISOLATE NIBBLE CPI 10 ;ALPHA HEX? JC HEXNU ;NO, NUMBER ADI 7 ;FUDGE FOR ALPHA HEX HEXNU ADI '0' ;MAKE PRINTABLE JMP TYPE ;PRINT NIB PUSH H ;SAVE START OF LBL ADDR ; ; READ NEW LABEL INTO TABLE ; MVI D,5 ;MAX LABEL LENGTH INPLP CALL KEYIN ;GET CHAR FOR LABEL CPI 'X'-40H ;CTL-X? JZ ABORT ;RETURN IF CTL-X PUSH PSW ;SAVE THE CHAR CALL TYPE ;ECHO IT POP PSW ;RESTORE THE C; ; SPACEWAR FOR IMSAI 8080 AND TEKTRONIX 4013 (9600 BAUD). ; ; COPYRIGHT (C) 1977 ; BY JEFFREY L. ZURKOW ; ; ORG 100H ; ; DI LXI H,0 DAD SP SHLD SPSAVE LXI SP,STACK LDA 70Q STA SAVE71 LHLD 71Q SHLD SAVE72 MVI A,0C3H STA 70Q COUNT? JNZ PADLB ;STORE MORE UNTIL DONE NOLAB POP H ;RESTORE START OF LBL ADDR LXI D,7 ;5 FOR LABEL, 2 FOR VALUE DAD D ;POINT TO NEXT LABEL JMP LABEL ;LOOP FOR NEXT LABEL ; ; ROUTINE TO PRINT A SPACE ; SPACE MVI A,' ' JMP TYPE ;TYPE THE SPAOV A,D ;GET RESIDUAL LABEL COUNT ORA A ;ZERO? JZ NOLAB ;YES - DON'T STORE THE ZERO CPI 5 ;NO LABEL CHANGE? JZ NOLAB ;YES - LEAVE ALONE XRA A ;GET A ZERO MOV M,A ;STORE INTO TABLE PADLB INX H ;POINT TO NEXT POSITION DCR D ;STILL MORE RESIDUAL ; ; SAVE71: DB 0 SAVE72: DW 0 BPOINT: DW 0 ; ; GLOBAL EQUATES ; ====== ======= ; ; TEKSTAT EQU 3 TEKDATA EQU 2 PI EQU 200Q THRUST EQU 0FH ;MAIN THRUST MAGNITUDE TSPEED EQU 09H ;TORPEDO SPEED TLIFE EQU 20H ;TORPEDO LIFETIME ESC EQU ENERATES A POINT FROM POLAR COORDINATES, WITH ORIGIN ; AT (X,Y) AND THE WHOLE COORDINATE SYSTEM ROTATED BY THETA ; ABOUT THE ORIGIN. CALL POINT WITH THE RADIUS IN B, ; THE ANGLE IN C, AND HL POINTING TO THE MEMORY BUFFER WHERE ; THE RESULTS ARE TO BE LAY2 DCR M JZ RESTART LXI H,RSTAR1 MOV A,M CPI SMAX*4 JNC ST4 INR A MOV M,A ; ST4: LDA TLIFE1 ORA A JZ ST6 LHLD X2 XCHG LHLD T1X CALL NBRHD JNZ ST5 LHLD Y2 XCHG LHLD T1Y CALL NBRHD JNZ ST5 XRA A STA TLIFE1 CAB 0 OUTBUF: DW 0 MIDBUF: DW 0 CURBUF: DW 0 ; ; ; ; ; ; START: LHLD CURBUF ST0: CALL SHIP1 CALL TORP1 CALL SHIP2 CALL TORP2 MVI M,13 ; LXI H,RATE INR M ; DI LHLD CURBUF XCHG LHLD MIDBUF SHLD CURBUF XCHG SHLD MIDBUF MORA A RNZ STA MTHRUST2 INR A STA HIT2 STA RSTAR2 MVI A,DELAY STA DELAY2 RET ; ; ; ; LEAVE: DI LHLD SPSAVE SPHL MVI A,13 CALL TYOUT MVI A,10 CALL TYOUT LDA SAVE71 STA 70Q LHLD SAVE72 SHLD 71Q XRA A OUT 8 RET ;T1X LHLD Y1 SHLD T1Y ; ; ST2A: LDA TLIFE2 ORA A JZ ST2B LHLD T2X XCHG LHLD VT2X DAD D MOV A,H ANI 7FH MOV H,A SHLD T2X ; LHLD T2Y XCHG LHLD VT2Y DAD D MOV A,H ANI 7FH MOV H,A SHLD T2Y JMP ST3A ; ST2B: LHLD X227 FF EQU 12 FRATE EQU 07H RRATE EQU 01H DELTA EQU 0FFH EXRATE EQU 03H SMAX EQU 14 X1INIT EQU 150 Y1INIT EQU 150 X2INIT EQU 875 Y2INIT EQU 640 THETA0 EQU PI/2 DELAY EQU 100 SIZE EQU 3 ; ; ; ; ; KEYBOARD SHIP CONTROL CHARACTER LHLD T2Y CALL NBRHD JNZ ST7 XRA A STA TLIFE2 CALL KILL1 ; ST7: LHLD X2 XCHG LHLD T2X CALL NBRHD JNZ ST8 LHLD Y2 XCHG LHLD T2Y CALL NBRHD JNZ ST8 XRA A STA TLIFE2 CALL KILL2 ; ST8: LHLD X1 XCHG LHLD X2 CALL NBRLL KILL2 ; ST5: LHLD X1 XCHG LHLD T1X CALL NBRHD JNZ ST6 LHLD Y1 XCHG LHLD T1Y CALL NBRHD JNZ ST6 XRA A STA TLIFE1 CALL KILL1 ; ST6: LDA TLIFE2 ORA A JZ ST8 LHLD X1 XCHG LHLD T2X CALL NBRHD JNZ ST7 LHLD Y1 XCHGVI A,1 STA BUFSW EI ; ; ; ROTATION INTEGRATORS ; LDA RATE ANI RRATE JNZ ST1 ; LDA THETA1 MOV B,A LDA VTHETA1 ADD B STA THETA1 ; LDA THETA2 MOV B,A LDA VTHETA2 ADD B STA THETA2 ; ST1: LHLD X1 XCHG LHLD VX1 DAD D ; ; ; NBRHD: MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A JP NB1 CMA MOV H,A MOV A,L CMA MOV L,A INX H NB1: LXI D,NOT DELTA MOV A,D ANA H MOV H,A MOV A,E ANA L ORA H RET ; ; ; ; ; POINT ; ===== ; ; POINT G SHLD T2X LHLD Y2 SHLD T2Y ; ; ST3A: LDA RATE ANI EXRATE JNZ ST4 LDA HIT2 ORA A JZ ST3B LXI H,DELAY2 DCR M JZ RESTART LXI H,RSTAR2 MOV A,M CPI SMAX*4 JNC ST3B INR A MOV M,A ; ST3B: LDA HIT1 ORA A JZ ST4 LXI H,DES ; ======== ==== ======= ========== ; ; LEFT1C EQU 'A' RT1C EQU 'S' FOR1C EQU 'D' TORP1C EQU 'F' ; LEFT2C EQU 'J' RT2C EQU 'K' FOR2C EQU 'L' TORP2C EQU ';' ; CTRLC EQU 03 ; ; ; ; OUTPUT BUFFER STUFF ; ====== ====== ===== ; ; BUFSW: DHD JNZ ST9 LHLD Y1 XCHG LHLD Y2 CALL NBRHD JNZ ST9 CALL KILL1 CALL KILL2 ; ST9: JMP START ; ; ; ; KILL1: LDA HIT1 ORA A RNZ STA MTHRUST1 INR A STA HIT1 STA RSTAR1 MVI A,DELAY STA DELAY2 RET ; ; KILL2: LDA HIT2 MOV H,A SHLD Y2 ; LDA TLIFE1 ORA A JZ ST2 LHLD T1X XCHG LHLD VT1X DAD D MOV A,H ANI 7FH MOV H,A SHLD T1X ; LHLD T1Y XCHG LHLD VT1Y DAD D MOV A,H ANI 7FH MOV H,A SHLD T1Y ; JMP ST2A ; ; ST2: LHLD X1 SHLD MOV A,H ANI 7FH MOV H,A SHLD X1 ; LHLD Y1 XCHG LHLD VY1 DAD D MOV A,H ANI 7FH MOV H,A SHLD Y1 ; LHLD VX2 XCHG LHLD X2 DAD D MOV A,H ANI 7FH MOV H,A SHLD X2 ; LHLD VY2 XCHG LHLD Y2 DAD D MOV A,H ANI 7FHPUT. ON RETURN, THE BUFFER WILL CONTAIN ; FIVE NEW BYTES, STARTING AT THE PREVIOUS (HL): 4 BYTES ARE ; THE TEK 4013 COORDINATES OF THE FINAL POINT, Y FIRST, ; AND THE FIFTH IS A ZERO BYTE TO ALLOW PROPER SETTLING TIME FOR ; THE VECTOR GENERATOR IN TH,29 INX H MVI C,PI/2 CALL STARB1 MVI C,3*PI/2 CALL STARB1 MVI M,29 INX H MVI C,7*PI/4 CALL STARB1 MVI C,3*PI/4 CALL STARB1 POP B RET ; STARB1: LDA RSTAR MOV B,A CALL POINT RNC POP B POP H RET ; ; ; ; ; ; INT7:RA A JZ SHP2A LDA RATE ANI FRATE JNZ SHP2A MVI A,THRUST STA MAG CALL RESOLVE LHLD VX SHLD VX2 LHLD VY SHLD VY2 ; SHP2A: LDA T2GO ORA A JZ SHP2B XRA A STA T2GO MVI A,TLIFE STA TLIFE2 CALL FIRE LHLD VX SHLD VT2X LH 4013 FORMAT POP B XCHG ;SAVE RESULT POP H ;GET BUFFER ADDRESS MOV M,D ;SAVE FIRST BYTE INX H MOV M,E ;SAVE SECOND BYTE INX H PUSH H PUSH B MOV A,C CALL COS ;GET COSINE(THETA+PHI) POP B ;GET R AGAIN MOV E,A ;SET UP FOR MULTIPLY X H MVI M,0 INX H MOV M,E INX H RET ; ; ; ; ; TORP2: MVI M,29 INX H PUSH H LHLD T2Y CALL TEKY XCHG POP H MOV M,D INX H MOV M,E INX H PUSH H LHLD T2X CALL TEKX XCHG POP H MOV M,D INX H MOV M,E INX H XRB ; PUSH H MVI M,29 INX H MVI B,5*SIZE MVI C,0 CALL POINT JC BLANK1 MVI B,4*SIZE MVI C,200Q LDA MTHRUST1 ORA A JZ SHP1A MVI B,6*SIZE SHP1A: CALL POINT JC BLANK1 MVI M,29 INX H MVI B,5*SIZE MVI C,9AH CALL POINT JC BE 4013. HL WILL POINT TO THE BYTE ; AFTER THE NUL (ZERO) BYTE. ; ; POINT: PUSH H ;SAVE BUFFER ADDRESS LDA THETA ;GET SHIP ANGLE ADD C ;ADD ANGLE FOR THIS POINT MOV C,A PUSH B ;SAVE RADIUS (R) AND NEW ANGLE CALL SIN POP B ;GET R AGAIN (SIN VI B,5*SIZE MVI C,9AH CALL POINT JC BLANK2 MVI B,5*SIZE MVI C,0 CALL POINT JC BLANK2 LDA MTHRUST2 ORA A JZ SHP2C MVI M,29 INX H MVI B,3*SIZE MVI C,PI CALL POINT JC BLANK2 MVI B,5*SIZE MVI C,PI CALL POINT JC BLANK2 SLD VY SHLD VT2Y ; LHLD X SHLD T2X LHLD Y SHLD T2Y ; SHP2B: POP H LDA HIT2 ORA A LDA RSTAR2 JNZ STARB PUSH H MVI M,29 INX H MVI B,5*SIZE MVI C,0 CALL POINT JC BLANK2 MVI B,5*SIZE MVI C,66H CALL POINT JC BLANK2 M CALL MUL CALL SHIFT XCHG LHLD X DAD D MOV A,H RLC JC ERASE2 CALL TEKX XCHG POP H MOV M,D INX H MOV M,E INX H XRA A ; MOV M,A ; INX H ; MOV M,A ; INX H ORA A RET ERASE1: POP B ERASE2: POP H STC RET ; ; ; ; SA A MOV M,A INX H MOV M,A INX H MOV M,E INX H RET ; ; ; ; ; STARB: PUSH H STA RSTAR MVI M,29 INX H MVI C,0 CALL STARB1 MVI C,PI CALL STARB1 MVI M,29 INX H MVI C,5*PI/4 CALL STARB1 MVI C,PI/4 CALL STARB1 MVI MLANK1 MVI B,5*SIZE MVI C,66H CALL POINT JC BLANK1 POP B ;CLEAR STACK RET BLANK1: POP H RET ; ; ; ; SHIP2: PUSH H LDA THETA2 STA THETA LHLD X2 SHLD X LHLD Y2 SHLD Y LHLD VX2 SHLD VX LHLD VY2 SHLD VY LDA MTHRUST2 OCLOBBERED B) PUSH B ; BUT LEAVE IT ON STACK. MOV E,A ;PUT SINE IN E FOR MULTIPLIER CALL MUL ;THIS GETS R*SIN(THETA+PHI) IN HL CALL SHIFT ;THIS SCALES THE RESULT XCHG ;NOW ADD Y LHLD Y DAD D MOV A,H RLC JC ERASE1 CALL TEKY ;CONVERT TOHP2C: POP B RET BLANK2: POP H RET ; ; ; ; TORP1: MVI M,29 INX H PUSH H LHLD T1Y CALL TEKY XCHG POP H MOV M,D INX H MOV M,E INX H PUSH H LHLD T1X CALL TEKX XCHG POP H MOV M,D INX H MOV M,E INX H MVI M,0 INY SHLD VY1 ; SHP1B: LDA T1GO ORA A JZ SHP1C XRA A STA T1GO MVI A,TLIFE STA TLIFE1 CALL FIRE LHLD VX SHLD VT1X LHLD VY SHLD VT1Y ; LHLD X SHLD T1X LHLD Y SHLD T1Y SHP1C: POP H ; LDA HIT1 ORA A LDA RSTAR1 JNZ STARHIP1: PUSH H LDA THETA1 STA THETA LHLD X1 SHLD X LHLD Y1 SHLD Y LHLD VX1 SHLD VX LHLD VY1 SHLD VY LDA MTHRUST1 ORA A JZ SHP1B LDA RATE ANI FRATE JNZ SHP1B MVI A,THRUST STA MAG CALL RESOLVE LHLD VX SHLD VX1 LHLD V PUSH PSW PUSH H IN TEKSTAT ANI 2 JNZ INPUT LHLD BPOINT MOV A,M CPI 13 JZ BUFEND OUT TEKDATA INX H SHLD BPOINT ; EXIT7: POP H POP PSW EI RET ; BUFEND: LDA BUFSW ORA A JZ BUFEN1 PUSH D XRA A STA BUFSW LHLD MIDBUF VE ROTATED MULTIPLIER JC NEXT ;JUMP IF B(K)=B(K-1)=1 MOV A,L ;SUBTRACT MULTIPLICAND FROM PARTIAL PRODUCT SUB E MOV L,A MOV A,H SBB D MOV H,A JMP NEXT ; LBS: DAD D ;ADD MULTIPLICAND TO PARTIAL PRODUCT JMP NEXT ; ; ; ; ; ; ; ; ; 2 Y DW 390*32 X DW 514*32 VX DW 0 VY DW 0 THETA DB 0 THETA1 DB 0 THETA2 DB 0 VTHETA1 DB 0 VTHETA2 DB 0 MTHRUST1 DB 0 MTHRUST2 DB 0 VX1 DW 0 VY1 DW 0 VX2 DW 0 VY2 DW 0 X2 DW 400*32 Y2 DW 250*32 T1X DW 0 T1Y DW 0 VT1X DW 0 VT1Y DW 0 T2OV H,A LDA HIT2 ORA A MOV A,H JNZ INP2 LXI H,VTHETA2 CPI LEFT2C JZ LEFT CPI RT2C JZ RIGHT LXI H,MTHRUST2 CPI FOR2C JZ FORWD CPI TORP2C JZ FIRE2 ; INP2: JMP EXIT7 ; LEFT: INR M JMP EXIT7 ; RIGHT: DCR M JMP EXIT7 ; FORIGN BIT THRU D POS: ; ORA A ;CLEAR CARRY=B(-1) MVI C,8 ;STEP COUNT MOV A,B ;GET MULTIPLIER RAL ;SET UP TO BEGIN WITH BIT 7 ; LOOP: JC HBS ;JUMP IF B(K)=1 RLC ;TEST B(K-1) MOV B,A ;SAVE ROTATED MULTIPLIER JC LBS ;JUMP IF B(K-1)=0 ; NEXW1 MVI D,0FFH FORW1: LHLD VX DAD D SHLD VX POP PSW CALL SIN MOV E,A LDA MAG MOV B,A CALL MUL MOV E,H MVI D,0 MOV A,H RLC JNC FORW2 MVI D,0FFH FORW2: LHLD VY DAD D SHLD VY RET ; ; ; ; SHIFT: MOV A,L RRC RRC A XCHG LHLD OUTBUF SHLD MIDBUF XCHG SHLD OUTBUF POP D ; BUFEN1: LHLD OUTBUF MOV A,M OUT TEKDATA INX H SHLD BPOINT LXI H,TLIFE1 MOV A,M ORA A JZ BUFEN2 DCR A MOV M,A ; BUFEN2: INX H MOV A,M ORA A JZ EXIT7 DCR A MOITHM TO MULTIPLY ; TWO 8-BIT TWO'S-COMPLEMENT NUMBERS AND GENERATE ; A 16-BIT TWO'S-COMPLEMENT PRODUCT. ARGUMENTS ; ARE PASSED IN B AND E, AND THE PRODUCT IS RETURNED ; IN HL. ALL REGISTERS AND FLAGS ARE CLOBBERED ; EXCEPT E. ON RETURN, C IS ZERO, X DW 0 T2Y DW 0 VT2X DW 0 VT2Y DW 0 TLIFE1 DB 0 TLIFE2 DB 0 RATE DB 0 MAG DB 0 SPSAVE DW 0 BUF1 DS 150 BUF2 DS 150 BUF3 DS 150 STACK DS 256 ; ; ; ; ; MULTIPLICATION ROUTINE ; ============== ======= ; ; ; THIS ROUTINE USES BOOTH'S ALGORWD: MOV A,M ANI 1 XRI 1 MOV M,A JMP EXIT7 ; FIRE1: LDA TLIFE1 ORA A JNZ EXIT7 INR A STA T1GO JMP EXIT7 ; ; FIRE2: LDA TLIFE2 ORA A JNZ EXIT7 INR A STA T2GO JMP EXIT7 ; ; ; ; FIRE: LDA THETA PUSH PSW CALL COS MOV T: DCR C ;DECREMENT STEP COUNT RZ ;FINISHED IF C=0 DAD H ;SHIFT PRODUCT LEFT ONE PLACE MOV A,B ;GET MULTIPLIER AGAIN RRC ;RESTORE CARRY CHANGED BY DAD INSTR. MOV A,B ;ONCE AGAIN GET MULTIPLIER JMP LOOP ; HBS: RLC ;TEST B(K-1) MOV B,A ;SANI 3FH MOV L,A MOV A,H RRC RRC ANI 0C0H ORA L MOV L,A MOV A,H RLC RRC RAR RLC RRC RAR MOV H,A RET ; RSTAR DB 0 RSTAR1 DB 0 RSTAR2 DB 0 HIT1: DB 0 HIT2: DB 0 T1GO DB 0 T2GO DB 0 DELAY2 DB 0 Y1 DW 390*32 X1 DW 514*3V M,A JMP EXIT7 ; INPUT: IN TEKDATA ANI 7FH CPI CTRLC JZ LEAVE MOV H,A LDA HIT1 ORA A MOV A,H JNZ INP1 LXI H,VTHETA1 CPI LEFT1C JZ LEFT CPI RT1C JZ RIGHT LXI H,MTHRUST1 CPI FOR1C JZ FORWD CPI TORP1C JZ FIRE1 INP1: ME IS INTACT, AND ; THE SIGN BIT OF E HAS BEEN EXTENDED THROUGH D. ; ; ; MUL: LXI H,0 ;CLEAR PRODUCT MOV A,E ;GET MULTIPLICAND MVI D,0 ;CLEAR HIGH BYTE OF MULTIPLICAND RLC ;TEST MULTIPLICAND SIGN BIT JNC POS MVI D,0FFH ;IF NEGATIVE, EXTEND SHLD Y DAD D SHLD Y POP D MVI B,TSPEED CALL MUL CALL SHIFT XCHG LHLD VY DAD D SHLD VY RET ; ; ; ; ; RESOLVE: LDA THETA PUSH PSW CALL COS MOV E,A LDA MAG MOV B,A CALL MUL MOV E,H MVI D,0 MOV A,H RLC JNC FORE,A PUSH D MVI B,5*SIZE CALL MUL CALL SHIFT XCHG LHLD X DAD D SHLD X POP D MVI B,TSPEED CALL MUL CALL SHIFT XCHG LHLD VX DAD D SHLD VX POP PSW CALL SIN MOV E,A PUSH D MVI B,5*SIZE CALL MUL CALL SHIFT XCHG LSINE AND COSINE ROUTINE ; ======================= ; ; ; THIS ROUTINE FINDS SIN(X) AND COS(X) BY A TABLE ; LOOK-UP. ARGUMENTS ARE PASSED IN A AND VALUES ; RETURNED THERE. THE VALUE RETURNED IS AN EIGHT- ; BIT NUMBER IN TWO'S COMPLEMENT FORM, SUCH TMORY MVI B,VDMPG ;# PAGES IN VDM MVI A,' ' CLR: MVI C,00 CL2: MOV M,A INX H DCR C JNZ CL2 DCR B JNZ CLR LXI H,TBUF ;CLEAR BUFFER TO SPACES MVI B,128 ;BUFFER SIZE MVI A,' ' CL3: MOV M,A INX H DCR B JNZ CL3 LXI D,MSG1 LXI H,V TWO RESULTING ; BYTES IN H AND L. TEKY APPENDS THE PROPER HIGH-ORDER ; OCTAL DIGIT (IN EACH BYTE) FOR Y-COORDINATES, AND ; TEKX DOES THE SAME FOR X-COORDINATES. ; ; ; TEKX: MVI B,40H DB 11H TEKY: MVI B,60H MOV C,H MOV A,H RRC RRC ANI 4AH,050H,056H,05CH DB 062H,067H,06DH,073H,078H,07EH,083H,086H DB 08EH,093H,098H,09DH,0A2H,0A7H,0ACH,0B0H DB 0B5H,0B9H,0BDH,0C2H,0C6H,0CAH,0CDH,0D1H DB 0D5H,0D8H,0DBH,0DEH,0E2H,0E4H,0E7H,0EAH DB 0ECH,0EFH,0F1H,0F3H,0F5H,0F6H,0F8H,0FAH DB 0* VECTRS: JMP GETVEC DS 42 WBOOTE EQU VECTRS+3 CSTS EQU VECTRS+6 CI EQU VECTRS+9 CO EQU VECTRS+12 LO EQU VECTRS+15 PO EQU VECTRS+18 RI EQU VECTRS+21 HOME EQU VECTRS+24 SELDSK EQU VECTRS+27 SETTRK EQU VECTRS+30 SETSEC EQU VECTRS+33 SETDMA EQUQ4 ;JUMP IF 4TH QUADRANT SUI 200Q ;SUBTRACT PI FROM ARGUMENT JMP Q1 ;NOW TREAT AS FIRST QUADRANT ; Q4: CMA ;NEGATE ARGUMENT INR A JMP Q1 ; ; ; ; ; ; ; ; OUTPUT CHARACTER TO SCOPE ; ====== ========= == ===== ; ; CALL WITH CHARACTER IN HAT ; SIN(0) YIELDS 7F HEX AND SIN(PI/2) YIELDS FF. ; ANGLES ARE REPRESENTED AS BINARY FRACTIONS OF ; 2 PI; THAT IS, PI=80H, PI/2 = 40H, AND SO FORTH. ; THERE ARE SEPARATE ENTRY POINTS FOR SINE AND ; COSINE. THE TABLE USED IS ONLY FOR THE FIRST ; QUееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее1FH ORI 20H MOV H,A MOV A,L RLC RLC RLC ANI 7 MOV L,A MOV A,C RLC RLC RLC ANI 18H ORA L ORA B MOV L,A RET ; ; ; ; ; ; ; END FBH,0FCH,0FDH,0FEH,0FFH,0FFH,0FFH,0FFH DB 0FFH ; ; ; ; ; COSINE ENTRY POINT ; ====== ===== ===== ; COS: ADI 100Q ; ; ; SINE ENTRY POINT ; ==== ===== ===== ; ; SIN: MVI C,1 ;CLEAR FLAG MOV B,A ;SAVE ARGUMENT RLC ;TEST BIT 7 JC Q34 ; VECTRS+36 READ EQU VECTRS+39 WRITE EQU VECTRS+42 GETVEC: LXI D,WBOOTE LHLD 1 MVI B,42 GETVE1: MOV A,M STAX D INX H INX D DCR B JNZ GETVE1 ; ;**** ; MAIN PROGRAM ;**** MAIN: LXI SP,STACK ;SET STACK LXI H,VDMLC ;POINT TO VDM MEC. ; CLOBBERS A AND FLAGS. ; ; TYOUT: IN TEKSTAT RRC JNC TYOUT MOV A,C OUT TEKDATA RET ; ; ; ; ; TEKX AND TEKY ; ============= ; ; THESE ROUTINES TAKE A 10-BIT QUANTITY IN HL, CONVERT IT ; TO TEKTRONIX 4013 COORDINATES, AND LEAVE THEADRANT AND CONTAINS 8-BIT UNSIGNED VALUES OF ; SIN(X). ONE BIT OF PRECISION IS LOST WHEN THESE ; ARE CONVERTED TO SIGNED 8-BIT NUMBERS. ; ; ; SINE TABLE ; ========== ; SINES: DB 000H,006H,00CH,013H,019H,01FH,025H,02CH DB 032H,038H,03EH,044H,0;*********************************; ; SECTOR PATCH UTILITY ; ;*********************************; ORG 100H ;**** ; MISC. EQUATES ;**** TBUF EQU 0080H VDMLC EQU 0CC00H VDMLN EQU 64 VDMPG EQU 4 ;***** ; OBTAIN BIOS VECTORS ;****NTRY ADDRESS MOV A,M ;GET VALUE FROM TABLE ORA A ;CLEAR CARRY RAR ;DIVIDE BY TWO DCR C ;TEST FLAG RZ ;RETURN IF RESULT POSITIVE CMA ;NEGATE RESULT INR A RET ; Q34: MVI C,2 ;SET FLAG RLC ;TEST BIT 6 MOV A,B ;GET ARGUMENT BACK JC SET- QUADRANT 3 OR 4 RLC ;TEST BIT 6 MOV A,B ;GET ARGUMENT BACK JNC Q1 ;JUMP IF 1ST QUADRANT MVI A,200Q ;BIT 6 SET- 2ND QUADRANT SUB B ;TAKE SIN(PI-X) Q1: LXI H,SINES ;GET START OF SINE TABLE MVI D,0 ;GET OFFSET IN DE MOV E,A DAD D ;GET EDMLC+VDMLN MVI B,64 CALL MOVTG ;MOV MSG1 TO SCREEN MVI A,00 ;CLEAR VDM I/O PORT OUT 0C8H STA CURDK ;SET DISK TO DRIVE 0 CALL HOME ;RESTORE HEAD XRA A STA CURTK ;SET CURTK BYTE INR A STA CURSC ;SET CURRENT SECTOR LXI H,VDMLC+(2*VDMLN) CURDK NWDS1: LDA CURDK DCX H CALL HXO CALL READR RET NWTRK: LXI H,VDMLC+(2*VDMLN)+OF2 CALL GETEM JC NWTR2 MOV A,B CPI 4DH JNC NWTRK STA CURTK NWTR2: LDA CURTK DCX H CALL HXO MOV A,C CPI 20H JZ NWDSK CALL READR RET READ SECTOR RET ;MOVE HEAD NXSEC: LDA CURSC CPI 26 ;END OF CURTK JNC NXS2 ;YES INR A STA CURSC XRA A RET NXS2: MVI A,01 STA CURSC STC RET NXTRK: LDA CURTK CPI 76 CMC RC ;ERROR INR A STA CURTK RET PVSEC: LDA CURSC D,M XCHG LXI D,LOOP PUSH D PCHL CONIN: CALL CI ANI 7FH CPI 3 JZ 0 RET ;**** ; DISPLAY ROUTINE ;**** DSPLY: LXI D,TBUF LXI H,VDMLC+(4*VDMLN) MVI B,80H CALL MOVE LXI H,VDMLC+(2*VDMLN) LXI D,MSG2 MVI B,64 ;MOVE MESSAGE ADD A ADD A ADD A ADD C MOV B,A JMP HXI1 HXC: CALL CONIN MOV C,A CPI '0' RC CPI '9'+1 JNC HXA ORI 80H MOV C,M DCX H MOV M,C INX H MOV M,A ANI 0FH RET HXA: ANI 5FH CPI 'A' JC HXC CPI 'F'+1 JNC HXC ORI 80H CALL SETDMA LDA CURDK MOV C,A CALL SELDSK LDA CURSC MOV C,A CALL SETSEC LDA CURTK MOV C,A CALL SETTRK RET WRITR: CALL SETUP CALL WRITE RET NEXTR: CALL NXSEC ;BUMP TO NEXT SECTOR CC NXTRK ;BUMP TO NEXT CURTK MVI A,'+' LXI D,MSG2 MVI B,64 CALL MOVTG JMP LOOP1 LOOP: CALL DSPLY ;DISPLAY PARAMETERS LOOP1: CALL CONIN ;READ CONSOLE CPI 'A' JC LOOP2 ANI 5FH LOOP2: LXI H,2020H ;CLEAR ERROR FLAG SHLD VDMLC+(15*VDMLN) LXI H,CMDTB ;POINT TO COMMAND TABLE MVIVE BYTE IN B RRC RRC RRC RRC ;GET HI ORDER 4 BITS CALL HXN ;CONVERT TO HEX ASCII INX H ;BUMP MEM ADDRESS MOV A,B ;GET BYTE AGAIN CALL HXN ;CONVERT INX H ;BUMP MEM ADDRESS RET HXN: ANI 0FH ;GET 4 BITS ORI 30H ;CONVERT TO ASCII CP CPI 01+1 JC PVS2 DCR A STA CURSC XRA A RET PVS2 MVI A,26 STA CURSC STC RET PVTRK: LDA CURTK CPI 00+1 RC DCR A STA CURTK RET MOVTG: LDAX D ORI 80H MOV M,A DCR B INX H INX D JNZ MOVTG RET HXO: MOV B,A ;SATO SCREEN CALL MOVTG LXI H,VDMLC+(2*VDMLN)+OF1 ;OFFSET TO FIELD1 LDA CURSC CALL HXO ;DISPLAY SECTOR NUMBER LXI H,VDMLC+(2*VDMLN)+OF2 ;OFFSET TO FIELD2 LDA CURTK CALL HXO ;DISPLAY CURTK NUMBER LXI H,VDMLC+(2*VDMLN)+OF3 ;OFFSET TO FIELD3 LD MOV C,M DCX H MOV M,C INX H MOV M,A SUI 37H ANI 0FH RET GETEM: MVI M,'?'+80H INX H MVI M,'?'+80H CALL HXI RC MOV A,B ANA A RET NWDSK: LXI H,VDMLC+(2*VDMLN)+OF3 CALL GETEM JC NWDS1 MOV A,B CPI 2 JNC NWDSK STA JC ERR ;ERROR CALL READR RET PREVR: CALL PVSEC ;BUMP TO PREV. SECTOR CC PVTRK MVI A,'-' JC ERR CALL READR RET HDOUT: CALL PVTRK ;DECREMENT CURTK CALL READR ;READ SECTOR RET ;EXIT HDIN: CALL NXTRK ;INCREMENT CURTK CALL READR ; C,NCMDS ;NUMBER OF COMMANDS CMLP: CMP M ;COMMAND FOUND? JZ CMOK INX H INX H INX H DCR C ;ANY COMMANDS LEFT? JNZ CMLP ;YES, KEEP LOOKING ERR: LXI H,VDMLC+(15*VDMLN) MOV M,A INX H MVI M,'?' JMP LOOP CMOK: INX H MOV E,M INX H MOVI 3AH ;A-F? JC HXN1 ;NO, CONTINUE ADI 07 ;COMPENSATE HXN1: MOV M,A ;STORE BYTE RET MOVE: LDAX D MOV M,A INX H INX D DCR B JNZ MOVE RET HXI: LXI B,0 CALL HXC RC MOV B,A HXI1: CALL HXC CMC RNC MOV C,A MOV A,B ADD A ER DCR C ;DECREMENT BYTE COUNT JNZ DL3 ;LOOP LXI H,VDMLC+(14*VDMLN) MVI B,64 CALL BLANKIT RET BLANKIT:MVI M,' ' INX H DCR B JNZ BLANKIT RET ;**** ; READ ROUTINE ;**** READR: CALL SETUP CALL READ RET SETUP: LXI B,TBUFA CURDK CALL HXO ;DISPLAY DISK NUMBER LXI H,VDMLC+(2*VDMLN)+OF4 CALL STAT CALL HXO LXI H,VDMLC+(8*VDMLN) LXI D,TBUF ;POINT TO BUFFER MVI C,128 ;BUFFER SIZE DL3: LDAX D ;GET BYTE FROM BUFFER CALL HXO ;DISPLAY BYTE INX D ;BUMP BUFFER POINTNWSEC: LXI H,VDMLC+(2*VDMLN)+OF1 CALL GETEM JC NWSC2 XRA A ADD B JZ NWSEC CPI 1BH JNC NWSEC STA CURSC NWSC2: LDA CURSC DCX H CALL HXO MOV A,C CPI 20H JZ NWTRK CALL READR RET GETBNO: LXI H,VDMLC+(14*VDMLN) LXI D,MSGI MVLHLD BOI5 SHLD SHED+36BH LHLD BOI6 SHLD SHED+36DH LHLD FRA1 SHLD SHED+3A0H LHLD FRA2 SHLD SHED+3A2H SHLD SHED+3A4H SHLD SHED+3A6H LHLD FRA3 SHLD SHED+3A8H LHLD FRA4 SHLD SHED+3AAH LHLD FRA5 SHLD SHED+3ACH LXI B,-21H LXI H,ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее: CALL GETBNO RC LDA BYTENO MOV C,A MVI B,0 LXI H,TBUF DAD B XCHG LXI H,VDMLC+(4*VDMLN) DAD B ASCPA1: MVI M,'?'+80H CALL CONIN CPI 20H RC MOV M,A STAX D INX H INX D LDA BYTENO INR A CPI 128 RNC STA BYTENO JMP AS4 CALL SMO1 LXI D,59 MVI B,2 CALL SMO1 LXI D,60 MVI B,1 CALL SMO1 LXI D,62 MVI B,1 CALL SMO1 JMP ENGIN SMO1: DAD D SMO2: MVI M,SMOKE INX H DCR B JNZ SMO2 RET ENGIN: LXI H,SHED+322H MVI M,16H LXI H,SHED+325H MVI M,EN EQU $-MSGI OF1 EQU (MSG2A-MSG2)-3 OF2 EQU (MSG2B-MSG2)-3 OF3 EQU (MSG2C-MSG2)-3 OF4 EQU (MSG2D-MSG2)-3 DS 64 STACK EQU $ CURSC: DB 00 ;CURRENT SECTOR CURTK: DB 00 ;CURRENT TRACK CURDK: DB 00 ;CURRENT DISK BYTENO: DB 0 ;***************I B,MSGILEN CALL MOVTG CALL GETEM RC MOV A,B CPI 129 JNC GETBNO DCR A JM GETBNO STA BYTENO MVI B,MSGILEN+3 LXI H,VDMLC+(14*VDMLN) CALL BLANKIT ANA A RET HEXPAT: CALL GETBNO RC LDA BYTENO MOV C,A MVI B,0 LXI H,TBUF ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееCPA1 CMDTB: DB 'R' DW READR DB 'W' DW WRITR DB 'A' DW ASCPAT DB 'H' DW HEXPAT DB '+' ;READ NEXT SECTOR DW NEXTR DB 0AH DW NEXTR DB '-' ;READ PREV SECTOR DW PREVR DB 'D' ;SELECT DISK DRIVE DW NWDSK DB 'I' ;STEP HEAD IN D07H LXI H,SHED+327H MVI M,6EH LHLD CAB1 SHLD SHED+32AH LHLD CAB2 SHLD SHED+32CH LHLD CAB3 SHLD SHED+32EH LHLD BOI1 SHLD SHED+361H LHLD BOI2 SHLD SHED+363H LHLD BOI3 SHLD SHED+365H SHLD SHED+367H LHLD BOI4 SHLD SHED+369H ****************** ; GET DISK STATUS ;********************************* STAT: SUB A OUT 0C0H ;REQUEST STATUS FROM CONTROLLER IN 0C0H ;GET STATUS RET ;AND RETURN END  DAD B XCHG ADD A MOV C,A LXI H,VDMLC+(8*VDMLN) DAD B HEXPA1: CALL GETEM JC HEXPA2 MOV A,B STAX D HEXPA2: LDAX D DCX H CALL HXO MOV A,C CPI ' ' RNZ INX D LDA BYTENO INR A CPI 128 RNC STA BYTENO JMP HEXPA1 ASCPAT ORG 100H TRAIN: XRA A OUT 0C8H LXI H,SHED LXI B,2048 EMPTY: MVI M,20H INX H DCX B XRA A XRA B JNZ EMPTY LXI H,CLOUD LXI D,0 MVI B,15 CALL SMO1 LXI D,43 MVI B,13 CALL SMO1 LXI D,48 MVI B,9 CALL SMO1 LXI D,52 MVI B,' DB ' ' DB ' ' MSG2: DB 'SECTOR ' MSG2A: DB 'TRACK ' MSG2B: DB 'DRIVE ' MSG2C: DB 'STATUS ' MSG2D: DB ' ' DB ' ' MSGI: DB ' BYTE # ' MSGILW HDIN DB 'O' ;STEP HEAD OUT DW HDOUT DB 'Q' ;QUIT (EXIT TO CP/M) DW 0 DB 'S' ;SPECIFIC SECTOR DW NWSEC DB 'T' DW NWTRK ;SPECIFIC TRACK DB 'C' ;CLEAR ALL AND RESTART EXAM DW MAIN NCMDS EQU ($-CMDTB)/3 MSG1: DB ' SPAT VERSION 1.0 SHED+3DEH RAILS: MVI M,19H INX B INX H XRA A XRA B JNZ RAILS HOSTL: LXI H,RRY XCHG LXI H,SHED FIRE: MOV A,M INX H XCHG MOV M,A INX H MOV A,H XCHG CPI 0D0H JNZ FIRE CALL TRAVL JMP HOSTL TRAVL: LXI B,64*13 CHOO: PUSFPNT CALL CPHL RZ ;NO MORE CHARS LHLD EPNT MOV A,M ;GET BYTE INX H ;BUMP POINTER CALL WRAP SHLD EPNT ;SAVE LHLD BPNT ;DISK BUFFER POINTER MOV M,A ;STORE BYTE CPI 1AH ;CONTROL Z? JZ FINIS ;DONE INX H ;BUMP POINTER SHLD BPNT LXI ;BEGIN MESSAGE MVI C,WCONB ;WRITE CONSOLE BUFFER CALL CPM ;WRITE START MESSAGE MVI C,RCON ;WAIT FOR CR CALL CPM CPI 0DH ;CR? JZ BEGIN ;START PROCESS CPI 03H ;CONTROL C? JZ BOOT ;REBOOT JMP SETUP ;START AGAIN BEGIN: LXI D,CRLF MVI C,5FH JMP AXL1 NXT3: CPI 12H JNZ AXLE LXI D,112DH JMP AXL1 WORK: LXI B,3000 OIL: DCX B XRA A XRA B JNZ OIL RET QUIT: JMP 0000 RRY EQU 0CC00H SMOKE EQU 6FH CAB1: DW 1001H CAB2: DW 5D10H CAB3: DW 207EH BOI1: DW 0A28H BOI2: DW 1I 0DH ;TEST FOR CR JNZ GB2 LHLD FPNT MVI M,0AH ;ADD LF AFTER CR INX H ;BUMP POINTER CALL WRAP ;WRAP POINTER SHLD FPNT ;SAVE POINTER GB3: MVI C,13H ;STOP READER CALL CONOUT RET PUTBUF: LDA BCNT ;GET DISK BUFFER COUNT CPI 128 ;FULL? JееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееH B CALL STROK CALL TURN POP B DCX B XRA A XRA B JNZ CHOO RET STROK: LXI H,0CC01H MVI C,0D0H COAL: MOV A,M DCX H MOV M,A INX H INX H MOV A,H CMP C JNZ COAL RET TURN: LXI H,0CC00H HISS: MOV A,M INX H CPI 6 JNZSG CALL CPM JMP BOOT FINIS: LXI D,TFCB MVI C,WRITE CALL CPM CPI 00 JNZ ERR LXI D,TFCB MVI C,CLOSE CALL CPM CPI 0FFH JZ ERR JMP BOOT GETBUF: MVI C,11H ;START READER CHAR CALL CONOUT ;START READER GB2: CALL CONIN CPI 07FHWCONB CALL CPM LXI D,TFCB ;POINT TO INITIALIZED FCB MVI C,CREATE ;SET UP TO CREATE CALL CPM CPI 0FFH ;SUCCESSFULL? JZ ERR ;NO, ERROR LOOP1: CALL GETBUF ;GET BUFFER CALL PUTBUF ;PUT BUFFER JMP LOOP1 ;CONTINUE ERR: MVI C,WCONB LXI D,EM90AH BOI3: DW 0A0AH BOI4: DW 5B0AH BOI5: DW 3939H BOI6: DW 205DH FRA1: DW 2006H FRA2: DW 2D11H FRA3: DW 2011H FRA4: DW 2D6FH FRA5: DW 206FH TIES: DW 1919H SHED: NOP CLOUD EQU $+0172H END NZ PB2 ;NO,CONTINUE LXI D,TFCB ;FCB ADDRESS MVI C,WRITE ;WRITE BLOCK CALL CPM CPI 00 ;OK? JNZ ERR ;ERROR MVI A,00 STA BCNT ;ZERO BUFFER COUNT LXI H,TBUF ;BUFFER POINTER SHLD BPNT PB2: LHLD EPNT ;GET EMPTY POINTER XCHG ;INTO DE LHLD ;********************************; ; PAPER TAPE TO DISK COPY ; ;********************************; ORG 100H SETUP: LXI SP,STACK LXI H,IOBUF ;GET ADDRESS OF CIRC. BUFFER SHLD FPNT ;SET FILL POINTER SHLD EPNT ;SET EMPTY POINTER LXI D,BGMSG HISS FOUND: INX H AXLE: MOV A,M CPI 11H JNZ NEXT1 LXI D,147EH AXL1: MVI B,7 AXL2: MOV M,D DCR B JZ WORK INX H MOV M,E INX H DCR B JNZ AXL2 NEXT1: CPI 14H JNZ NXT2 LXI D,132DH JMP AXL1 NXT2: CPI 13H JNZ NXT3 LXI D,12 ;RUBOUT? JZ GB2 ;IGNORE CPI 00H ;NULL? JZ GB2 ;IGNORE CPI 0AH ;LF? JZ GB2 ;IGNORE LHLD FPNT ;GET FILL POINTER MOV M,A ;STORE CHAR INX H ;BUMP FILL POINTER CALL WRAP SHLD FPNT ;SAVE CPI 1AH ;TEST FOR CONTROL Z JZ GB3 ;YES, DONE CPееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееH,BCNT INR M ;BUMP B COUNT JMP PUTBUF WRAP: PUSH D PUSH B PUSH PSW PUSH H XCHG LXI H,IOBUF+4096 CALL CPHL JNZ WRAPX LXI H,IOBUF XTHL WRAPX: POP H POP PSW POP B POP D RET CPHL: MOV A,D CMP H RNZ MOV A,E CMP L RNT DISK NUMBER DUMMY EQU DISKNO+1 ;MUST BE 0 FOR DOUBLE ADD ORG PATCH ;ORIGIN OF THIS PROGRAM CBASE EQU (MSIZE-16)*1024 ;BIAS FOR SYSTEMS>16K CPMB EQU CBASE+2900H ;BASE OF CP/M BDOS EQU CBASE+3206H ;BASE OF RESIDENT CODE CPML EQU $-CPMB ;LENGTH***************; ;NOTE : MSIZE DETERMINES WHERE THIS CBIOS IS LOCATED MSIZE EQU 31 ;CP/M MEMORY SIZE IN KBYTES PATCH EQU MSIZE*1024-2*256 ;START OF THE CBIOS ;***********************************************; ; ; I/O DEVICE VALUES ; ADDRESS TBASE EQU 0100H ;TRANSIENT PROGRAM BASE CBASE EQU 2900H ;CCP BASE ADDRESS CPM EQU 0005H ;CPM ENTRY POINT ;***********************************; ; CP/M FUNCTION CODES ; ;***********************************; SRSET EQU 00 ;SY; TRACK = LAST SELECTED TRACK ; SECTOR = LAST SELECTED SECTOR ; DMAAD = LAST SELECTED DMA ADDRESS ; DISKNO = LAST SELECTED DISK NUMBER ;(NOTE THAT ALL ARE BYTE VALUES EXCEPT FOR DMAAD) ; ;************************************************ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееET CONOUT: MOV E,C MVI C,WPUN CALL CPM RET CONIN: MVI C,RRDR CALL CPM RET FPNT: DW IOBUF EPNT: DW IOBUF BPNT: DW TBUF BCNT: DB 00 BGMSG: DB 'SET UP DISK, PAPER TAPE, TYPE RETURN $' EMSG: DB 'I/O ERROR $' CRLF: DB 0DH,0AH,'$' DSTA PORT CRTS EQU 05H ;CRT STATUS PORT CRTDA EQU 02H ;CRT DATA AVAIL BIT CRTBE EQU 01H ;CRT BUFFER EMPTY BIT TTYMD EQU 0CEH ;TTY MODE BYTE TTYCM EQU 017H ;TTY COMMAND BYTE CRTMD EQU 0CEH ;CRT MODE BYTE CRTCM EQU 017H ;CRT COMMAND BYTE ;******* ;***********************************************; IOBYT EQU 0003H ;I/O CONTROL BYTE TTYD EQU 02H ;TELETYPE DATA PORT TTYS EQU 03H ;TELETYPE STATUS PORT TTYDA EQU 02H ;TTY DATA AVAIL BIT TTYBE EQU 01H ;TTY BUFER EMPTY BIT CRTD EQU 04H ;CRT DASTEM RESET RCON EQU 01 ;READ CONSOLE WCON EQU 02 ;WRITE CONSOLE RRDR EQU 03 ;READ READER WPUN EQU 04 ;WRITE PUNCH WLST EQU 05 ;WRITE LIST ISTAT EQU 07 ;GET IOSTATUS SSTAT EQU 08 ;SET IOSTATUS WCONB EQU 09 ;WRITE CONSOLE BUFFER RCONB EQU 10 ;READ C*; SCRAT EQU 40H ;START OF SCRATCH AREA TRACK EQU SCRAT ;CURRENT TRACK ON DRIVE 0 TRAK1 EQU TRACK+1 ;CURRENT TRACK ON DRIVE 1 SECTOR EQU SCRAT+2 ;CURRENTLY SELECTED SECTOR DMAAD EQU SCRAT+3 ;CURRENT DMA ADDRESS DISKNO EQU SCRAT+5 ;CURRE;***********************************************; ; ; CBIOS FOR IMSAI WITH SIO2-2 AND TELETYPE ; INCLUDES IOBYTE FUNCTION ; AND DRIVER FOR PROCESSOR TECHNOLOGY VDM ; WRITTEN BY JEFF KRAVITZ, 05/21/77 ; ;******************************** 32 STACK EQU $ IOBUF: DS 4096 ;***********************************; ; CP/M STANDARD EQUATES ; ;***********************************; BOOT EQU 0000H ;WARM START ADDRESS TFCB EQU 005CH ;DEFAULT FCB ADDRESS TBUF EQU 0080H ;DEFAULT BUFFER*****************************************; ; ; MISC EQUATES ; ;************************************************; ;*************************************************; ; ; WE WILL USE A SCRATCH AREA STARTING AT 40H ; FOR HOLDING THE VALUES OF: 19 ;DELETE FILE READ EQU 20 ;READ RECORD WRITE EQU 21 ;WRITE RECORD CREATE EQU 22 ;CREATE FILE RENAM EQU 23 ;RENAME FILE LOGIN EQU 24 ;GET LOGIN IDISK EQU 25 ;GET DISK NUMBER SDMA EQU 26 ;SET DMA VECTOR IALLOC EQU 27 ;GET ALLOCATION VECTOR END ONSOLE BUFFER CSTAT EQU 11 ;CHECK CONSOLE STATUS LHEAD EQU 12 ;LIFT DISK HEAD RSDSK EQU 13 ;RESET DISK SYSTEM SDISK EQU 14 ;SELECT DISK OPEN EQU 15 ;OPEN FILE CLOSE EQU 16 ;CLOSE FILE SFRST EQU 17 ;SEARCH FIRST SNEXT EQU 18 ;SEARCH NEXT FDELT EQU OF CP/M NSECTS EQU CPML/128 ;# OF SECTORS TO LOAD ;************************************************; ; ; JUMP VECTOR FOR INDIVIDUAL SUBROUTINES ; ;************************************************; JMP SCPM ;COLD START WBOTE: JMP WBOOT ;WARM FOR SELECTED DISK LXI D,TRACK LHLD DISKNO DAD D HOMEL: MVI M,00 ;SET CURRENT TRACK PTR BACK TO 0 IN 127 ;READ FDC STATUS ANI 4 ;TEST TRACK 0 BIT RNZ ;RETURN IF AT 0 STC ;DIRECTION=OUT CALL STEP ;STEP ONE TRACK JMP HOMEL ;LOOP ; SEH CALL SETTRK ;TRACK ADDR SET FROM REG C POP H POP D POP B JMP LOAD1 ;FOR ANOTHER SECTOR ; ; END OF LOAD OPERATION, SET PARAMETERS AND GO TO CP/M GOCPM: LXI SP,80H MVI A,0C3H ;C3 IS A JMP INSTRUCTION STA 0 ;FOR JMP TO WBOOT LXI H,WBOTE ;FUNCTION ; ;************************************************; WBOOT: ;READ THE DISK UNTIL ALL SECTORS LOADED LXI SP,80H ;STACK BELOW BUFFER MVI C,0 ;SELECT DISK 0 CALL SELDSK CALL HOME ;GO TO TRACK 00 MVI B,NSECTS ;B = # SECTORS TO LOAD MVPMSG ;POINT TO STARTUP MESSAGE MVI C,09 ;WRITE BUFFER CALL BDOS ;CALL BDOS JMP GOCPM ;CONTINUE INITIALIZATION CPMSG: DB 0DH,0AH,'CP/M V1-3.5 L0.1 31K$' ;*************************************************; ; ; ; I/O DRIVERS FOR THE DISK ; ;**SS LXI D,128 ;DMA=DMA+128 DAD D ;NEW DMA ADDRESS IS IN H,L POP D ;RECALL SECTOR ADDRESS POP B ;GET NUM. SECTORS & TRACK DCR B ;SECTORS=SECTORS-1 JZ GOCPM ;GOTO CPM WHEN DONE ; ; MORE SECTORS REMAIN TO LOAD, CHECK FOR TRACK CHANGE INR D MO START JMP CONST ;CONSOLE STATUS JMP CONIN ;CONSOLE CHARACTER IN JMP CONOUT ;CONSOLE CHARACTER OUT JMP LIST ;LIST CHARACTER OUT JMP PUNCH ;PUNCH CHARACTER OUT JMP READER ;READER CHARACTER OUT JMP HOME ;MOVE HEAD TO HOME JMP SELDSK IN LOCATION 4) IN C LDA 04H MOV C,A EI ;ENABLE INTERRUPTS JMP CPMB ;GO TO CP/M FOR FURTHER PROCESSING ;**********************************************; ; ; COLD START ROUTINE ; ;**********************************************; SCPM: XRA AWBOOT ENTRY POINT SHLD 1 ;SET ADDRESS FIELD FOR JMP AT 0 ; STA 5 ;FOR JMP TO BDOS LXI H,BDOS ;BDOS ENTRY POINT SHLD 6 ;ADDRESS FIELD OF JUMP AT 5 TO BDOS ; LXI B,80H ;DEFAULT DMA ADDRESS IS 80H CALL SETDMA ; ;PUT ACTIVE DISK NUMBER (STORED I C,0 ;C HAS THE CURRENT TRACK NUMBER MVI D,2 ;D HAS THE NEXT SECTOR TO READ ; NOTE THAT WE BEGIN BY READING TRACK 0, SECTOR 2 SINCE SECTOR 1 ; CONTAINS THE COLD START LOADER, WHICH IS SKIPPED IN A WARM START LXI H,CPMB ;BASE OF CP/M (INITIAL LOAD PO***********************************************; HOME: ;MOVE TO THE TRACK 00 POSITION OF CURRENT DRIVE LDA DISKNO ;SELECTED DISK MOV C,A ;FOLLOW PARAMETER CONVENTIONS CALL SELDSK ;ROUTINE TO SELECT THE DISK ;SET UP H,L TO POINT TO WORD WITH TRACKV A,D ;SEC=27?,IF SO,CHANGE TRACKS CPI 27 JC LOAD1 ;CARRY GENERATED IF SECTOR<27 ; ; END OF CURRENT TRACK, GO TO NEXT TRACK MVI D,1 ;1ST SEC OF NEXT TRACK INR C ;TRACK=TRACK+1 ; ; SAVE REGISTER STATE, AND CHANGE TRACKS PUSH B PUSH D PUSH ;SELECT DISK JMP SETTRK ;SET TRACK NUMBER JMP SETSEC ;SET SECTOR NUMBER JMP SETDMA ;SET DMA ADDRESS JMP READ ;READ DISK JMP WRITE ;WRITE DISK ;************************************************; ; ; INDIVIDUAL SUBROUTINES TO PERFORM EACH ;INITIALIZE IOBYT STA IOBYT MVI A,0AAH ;DUMMY MODE BYTE OUT TTYS ;CLEAR TTY MVI A,040H ;RESET COMMAND OUT TTYS MVI A,TTYMD OUT TTYS MVI A,TTYCM OUT TTYS ;SET UP TTY USART LXI SP,80H ;SET STACK CALL DSINT ;INITIALIZE DISPLAY LXI D,C B,C PUSH B ;REPLACE ON STACK CALL SETDMA ;SET DMA ADDRESS FROM B,C ; ; DRIVE SET TO 0, TRACK SET, SECTOR SET, DMA ADDRESS SET CALL READ ORA A ;ANY ERRORS? JNZ WBOOT ;RETRY IF ERROR ; ; NO ERROR, MOVE TO NEXT SECTOR POP H ;RECALL DMA ADDREINT) LOAD1: ;LOAD ONE MORE SECTOR PUSH B ;SAVE SECTOR COUNT, CURRENT TRACK PUSH D ;SAVE NEXT SECTOR TO READ PUSH H ;SAVE DMA ADDRESS MOV C,D ;GET SECTOR ADDRESS TO REG. C CALL SETSEC ;SET SECTOR ADDRESS FROM REG. C POP B ;RECALL DMA ADDRESS TOLDSK: ;SELECT DISK GIVEN BY REGISTER C ;MAKE SURE DUMMY IS 0 (FOR USE IN DOUBLE ADD TO H,L) XRA A STA DUMMY MOV A,C STA DISKNO RRC ;PUT INTO BITS 4,5 RRC RRC RRC ORI 08 ;ENABLE DISK SELECT OUT 127 ;SELECT THE DISK RET ; SETTRK: ;SSTEP: ;STEP HEAD OUT TOWARDS ZERO ;IF CARRY IS SET; ELSE ;STEP IN ; H,L POINT TO CORRECT TRACK INDICATOR WORD PUSH PSW ;SAVE DIRECTION STWAIT: IN 127 ;INPUT FDC STATUS ANI 2 ;TEST STEP READY BIT JZ STWAIT ;WAIT FOR STEP READY(MAX 10 MSDDRESS DCX H ;SAVE AND REPLACE 3 BYTES BELOW ;BUF WITH TRACK,SECTOR,ADDRESS MARK MOV B,M MVI A,0FBH ;ADDRESS MARK MOV M,A DCX H MOV C,M LDA SECTOR ;NOTE THAT INVALID SECTOR NUMBER ;WILL RESULT IN HEAD UNLOADED ;ERROR, SO DONT CHEC MVI A,18D CALL DELAY RET ;END OF SETTRK ROUTINE ; DELAY: ;ROUTINE TO DELAY C(A) MILLISECONDS MVI C,82H ;ADJUST FOR 1 MSEC LOOP DELAY ;THIS IS THE VALUE FOR OUR IMSAI LDXA: DCR C JNZ LDXA ;LOOP 1 MSEC DCR A JNZ DELAY RET ;END OF NOUT ;SET ERROR RETURN FOR OPERATING SYSTEM MVI A,1 RET REDO: ;D STILL HAS READ/WRITE FLAG POP PSW ;GET ERROR CODE ANI 0E0H ;RETRY IF NOT TRACK ERROR JNZ TRYAGN ;WAS A TRACK ERROR SO NEED TO RESEEK PUSH D ;SAVE READ/WRITE INDICATOR ;FIGURE HAVE SAVED THE DISK NUMBER IN 'DISKNO' (0,1) ; THE TRACK NUMBER IN 'TRACK' (0-76) ; THE SECTOR NUMBER IN 'SECTOR' (1-26) ; THE DMA ADDRESS IN 'DMAAD' (3-3F80H) ;D STILL HAS R/W FLAG MVI A,10D ;SET ERROR COUNT STA ERRORS ;RETRY SOME FAILURES 10 ET TRACK GIVEN BY REGISTER C ;FIRST REFERENCE CORRECT TRACK INDICATOR ACCORDING TO ;SELECTED DISK LXI D,TRACK ;ADDRESS OF TRACK FOR DISK 0 LHLD DISKNO ;FIND OUT WHICH DISK IS SELECTED DAD D MOV A,C ;DESIRED TRACK CMP M RZ ;WE ARE ALREADY ON OR IOF JZ RWWAIT MOV M,E ;RESTORE 3 BYTES BELOW BUF INX H MOV M,C INX H MOV M,B IN 127 ;TEST FOR ERRORS ANI 0F0H RZ ;A WILL BE 0 IF NO ERRORS ;COME HERE ON ERROR FROM DISK PUSH PSW ;SAVE ERROR CONDITION ;CHECK FOR 10 ERRORS LXI H,EK MOV M,A DCX H MOV E,M POP PSW MOV M,A MOV A,H ;SET UP FDC DMA ADDRESS OUT 126 ;HIGH BYTE MOV A,L OUT 125 ;LOW BYTE MOV A,D ;GET R/W FLAG OUT 127 ;START DISK READ/WRITE RWWAIT: IN 127 ;READ FDC STATUS ANI 0F8H ;TEST FOR ANY ERROR DELAY ROUTINE ; SETSEC: ;SET SECTOR GIVEN BY REGISTER C MOV A,C STA SECTOR RET ; SETDMA: ;SET DMA ADDRESS GIVEN BY REGISTERS B AND C MOV L,C ;LOW ORDER ADDRESS MOV H,B ;HIGH ORDER ADDRESS SHLD DMAAD ;SAVE THE ADDRESS RET ; ; ERRORS: DB OUT THE DESIRED TRACK LXI D,TRACK LHLD DISKNO ;SELECTED DISK DAD D ;POINT TO CORRECT TRACK INDICATOR MOV A,M ;DESIRED TRACK PUSH PSW ;SAVE IT CALL HOME POP PSW MOV C,A CALL SETTRK POP D ;GET READ/WRITE INDICATOR JMP TRYAGN ; ; ; TIMES ;BEFORE GIVING UP TRYAGN: ;FIRST WE HAVE TO FIGURE OUT WHICH DRIVE IS SELECTED ;AND WHICH TRACK IS DESIRED LXI B,TRACK LHLD DISKNO DAD B ;H,L POINT TO CORRECT TRACK INDICATOR MOV A,M PUSH PSW ;NEED IT LATER LHLD DMAAD ;GET BUFFER ATHE TRACK SETTKX: CALL STEP ;STEP TRACK-CARRY HAS DIRECTION ;STEP WILL UPDATE TRACK INDICATOR MOV A,C CMP M ;ARE WE WHERE WE WANT TO BE JNZ SETTKX ;NOT YET ;HAVE STEPPED ENOUGH SEEKRT: ;DELAY 18 MSEC FOR FINAL STEP TIME AND HEAD SETTLE TIMERRORS DCR M JNZ REDO ;NOT TEN YET. DO A RETRY ;WE HAVE TOO MANY ERRORS. PRINT OUT HEX NUMBER FOR LAST ;RECEIVED ERROR TYPE. CPM WILL PRINT PERM ERROR MESSAGE. POP PSW ;GET CODE RRC RRC RRC RRC ;MAKE IT ASCII ORI 030H MOV C,A CALL CO MVI D,80H ;SET WRITE COMMAND ; WAITIO: ;ENTER HERE FROM READ AND WRITE TO PERFORM THE ACTUAL I/O ;OPERATION. RETURN A 00H IN REGISTER A IF THE OPERATION COMPLETES ;PROPERLY, AND 01H IF AN ERROR OCCURS DURING THE READ OR WRITE ; ;IN THIS CASE, WE 0 ;KEEP TRACK OF NUMBER OF ERRORS READ: ;PERFORM READ OPERATION. ;THIS IS SIMILAR TO WRITE, SO SET UP READ COMMAND AND USE ;COMMON CODE IN WRITE MVI D,40H ;SET READ FLAG JMP WAITIO ;TO PERFORM THE ACTUAL I/O ; WRITE: ;PERFORM A WRITE OPERATION EC) POP PSW ;GET DIRECTION TO STEP JC OUTX INR M ;INCREMENT CURRENT TRACK BYTE MVI A,4 ;SET DIRECTION = IN DOSTEP: OUT 127 ;SET DIRECTION BIT IN FDC ORI 2 OUT 127 ;PULSE STEP BIT ANI 0FDH OUT 127 ;TURN OFF PULSE RET ; OUTX: DCR M ; MVI A,' ' D1002: MOV M,A INX H DCR B JNZ D1002 INR C MVI A,DSPSIZ CMP C JNZ D1001 CALL CSON RET DSWRT: LDA CHR LHLD DSPLOC MOV M,A CALL CSRGT IN 0FFH ;READ SWITCHES ORA A ;TEST RZ ;ZERO, RUN FULL SPEED MOV H,A ;PUT SULATE TABLE ENTRY ADDRESS MOV A,M ;GET TABLE ENTRY INX H MOV H,M MOV L,A ;INTO HL POP D ;RESTORE DE XTHL ;PUT EXIT ADDR ON STACK, RESTORE HL RET ;EXIT TO ROUTINE ;****************************************************; ; ; PHYSICAL I/O INE DW NULST ;NULL STATUS ROUTINE ; ; CONSOLE INPUT ; CONIN: LDA IOBYT ;GET IOBYT CALL IOCAL ;EXIT TO SELECTED ROUTINE DW TTYIN ;TTY INPUT ROUTINE DW CRTIN ;CRT INPUT ROUTINE DW RDRIN ;READER INPUT ROUTINE DW NULIN ;NULL INPUT ROUTINE , IGNORE IT JNC CO4 ;IGNORE CHARS>7F CPI 20H ;OTHER CONTROL CHAR JC CO4 ;YES, IGNORE STA CHR CALL DSWRT ;DISPLAY CHARACTER CO4: POP H POP D POP B POP PSW RET COCR: CALL CSRET JMP CO4 COLF: CALL CSDWN JMP CO4 COBS: CALL CSLFT JDER: LDA IOBYT ;GET IOBYT RRC ;SHIFT BITS RRC CALL IOCAL ;EXIT TO SELECTED ROUTINE DW TTYIN ;TTY INPUT ROUTINE DW CRTIN ;CRT INPUT ROUTINE DW RDRIN ;READER INPUT ROUTINE DW NULIN ;NULL INPUT ROUTINE ;**************************************UPDATE TRACK BYTE XRA A ;SET DIRECTION = OUT JMP DOSTEP ;*************************************************; ; ; PERIPHERAL I/O DRIVERS ; ;*************************************************; ; ; CONSOLE STATUS ; CONST: CALL CONS ;GET DEVIC ;STRIP PARITY RET TTYOUT: IN TTYS ;GET TTY STATUS ANI TTYBE ;TEST FOR XMIT BUFFER EMPTY JZ TTYOUT ;WAIT TIL READY MOV A,C ;GET OUTPUT CHAR OUT TTYD ;OUTPUT CHAR RET CRTST: CALL TTYST RET CRTIN: CALL TTYIN ;CRT KEYBOARD = TTY RET ROUTINES ; ;***************************************************; TTYST: IN TTYS ANI TTYDA ;TEST FOR TTY DATA AVAIL. RET ;EXIT WITH ZERO IF NOT AVAIL TTYIN: CALL TTYST ;TEST FOR CHAR AVAIL JZ TTYIN ;NOT YET, WAIT IN TTYD ;GET DATA ANI 7FH ; ; CONSOLE OUTPUT ; CONOUT: LDA IOBYT ;GET IOBYT CALL IOCAL ;EXIT TO SELECTED ROUTINE DW TTYOUT ;TTY OUTPUT ROUTINE DW CRTOUT ;CRT OUTPUT ROUTINE DW PRTOUT ;PRINTER OUTPUT ROUTINE DW NULOUT ;NULL OUTPUT ROUTINE ; ; LISTING OUTPUT ; LMP CO4 COFF: CALL CSHOM CALL DSERS JMP CO4 DSINT: LXI H,VDMLC SHLD DSPLOC MVI A,0 STA CURVRT STA CURHOR CALL DSERS CALL CSON MVI A,00 OUT 0C8H ;SET UP VDM PORT RET DSERS: LHLD DSPLOC LDA CURVRT MOV C,A D1001: MVI B,LINSIZ*************; ; ; I/O DISPATCHER ; ;***************************************************; IOCAL: RLC ;SHIFT BITS ANI 06H ;MASK BITS XTHL ;SAVE HL, GET TABLE ADDRESS PUSH D ;SAVE DE MOV E,A ;GET SELECTION VALUE IN A MVI D,0 DAD D ;CALCE STATUS ORA A ;SET FLAGS RZ ;ZERO IF NO CHAR AVAIL MVI A,0FFH ;FF IF CHAR OK RET CONS: LDA IOBYT ;GET IOBYT CALL IOCAL ;EXIT TO SELECTED ROUTINE DW TTYST ;TELETYPE STATUS ROUTIE DW CRTST ;CRT STATUS ROUTINE DW RDRST ;READER STATUS ROUT;EXIT CRTOUT: MOV A,C PUSH PSW ;SAVE A PUSH B PUSH D PUSH H ;SAVE REGS CPI 0DH ;CARRIAGE RETURN? JZ COCR ;YES CPI 0AH ;LF? JZ COLF ;YES CPI 08H ;BACKSPACE? JZ COBS CPI 0CH ;FORM FEED? JZ COFF ;YES CPI 7FH ;RUBOUT? JZ CO4 ;YESLDA IOBYT ;GET IOBYT RRC RRC RRC ;SHIFT BITS RRC CALL IOCAL ;EXIT TO SELECTED ROUTINE DW TTYOUT ;TTY OUTPUT ROUTINE DW CRTOUT ;CRT OUTPUT ROUTIE DW PUNOUT ;PUNCH OUTPUT ROUTINE DW NULOUT ;NULL OUTPUT ROUTINE ; ; READER INPUT ; REAIST: LDA IOBYT ;GET IOBYT RLC RLC ;SHIFT BITS CALL IOCAL ;EXIT TO SELECTED ROUTINE DW TTYOUT ;TTY OUTPUT ROUTINE DW CRTOUT ;CRT OUTPUT ROUTINE DW PRTOUT ;PRINTER OUTPUT ROUTINE DW NULOUT ;NULL OUTPUT ROUTINE ; ; PUNCH OUTPUT ; PUNCH: WITCHES IN H MVI L,0 DLLP: DCX H ;CHECK HL MOV A,H ORA L JNZ DLLP RET DSSCR: LXI H,VDMLC MOV D,H MOV E,L LXI B,LINSIZ DAD B MVI B,DSPSIZ-1 D7003: MVI C,LINSIZ D7004: MOV A,M STAX D INX H INX D DCR C JNZ D7004 DCR B Jееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее0 MOV H,A SHLD DSPLOC XRA A STA CURHOR CALL CSON RET CSDWN: CALL CSOFF LDA CURVRT CPI DSPSIZ-1 JNZ D4001 CALL DSSCR CALL CSON RET D4001: LDA CURVRT INR A STA CURVRT LHLD DSPLOC LXI B,LINSIZ DAD B SHLD DSPLOC CALL Cт~·В # ВH!lН_lНdаХНУНюяКWУНюяКxжюВ4С!ЂлХНГ4d Н*а щЙ NO FILES ON DISK $С!аЇ2Т2С"П:С<2С~юеКы:Т<2Т~~·Ві:СН0±НdГы=жшС НБсЙЕХх=o&)))))а# еЕ^НБб# ВC« НсСБЙМЕ НБЙ K BYTES LEFT $00H NOT ALLOCATED $00H LINKED BLOCK $ $ NULL FILE $ FILES $Н?????????????яНпВщННЛG@Н±°Г‰!НNES ; ;**************************************************; END ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее CSLFT: CALL CSOFF LDA CURHOR CPI 00 JNZ D3001 CALL CSON RET D3001: DCR A STA CURHOR LHLD DSPLOC DCX H SHLD DSPLOC CALL CSON RET CSRET: CALL CSOFF LHLD DSPLOC LDA CURHOR MOV B,A MOV A,L SUB B MOV L,A MOV A,H SBI ГЧ! Ц0шю РT])))_Г! Н/юР))))…oГЦ0ю ШЦЙЕxН>БyGНGxжЖ0ю:w#Ш+Жw#ЙЇГa>0Гa> 2Ф"Х`i|·тv>-НґНМрШН›ьН›њяН›цяН›яяН›*ХЙЕ/|ТћлНМxБю0Кї Ђе*Хw#"ХбЙЂтЗђГ± КГЙ}/o|/g#Й­!9"а 1а Н!а  хжЂw#сВоВл!а 004BH DSPSIZ EQU 16 LINSIZ EQU 64 VDMLC EQU 0CC00H RDRST: CALL TTYST ;NOTE: READER IS TTY RET RDRIN: CALL TTYIN ;NOTE: READER IS TTY NULST: MVI A,0FFH ;IF NULL DEVICE IS CONSOLE, CHAR ;IS ALWAYS READY ORA A RET NULIN: MVI A,1OFF LXI H,VDMLC SHLD DSPLOC LXI H,0000 SHLD CURHOR CALL CSON RET CSON: LHLD DSPLOC MOV A,M ORI 80H MOV M,A RET CSOFF: LHLD DSPLOC MOV A,M ANI 7FH MOV M,A RET DSPLOC EQU 0047H CURHOR EQU 0049H CURVRT EQU 004AH CHR EQU:10010000AFD3C8217D020100083620230BAFA8C25F :10011000090121F003110000060FCD5001112B0041 :10012000060DCD50011130000609CD5001113400EB :100130000604CD5001113B000602CD5001113C00D8 :100140000601CD5001113E000601CD5001C35901F9 :1001500019366F2305C25101C9219Fееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее02100000CC7E23FE06C21202237EFE11C23102F2 :10022000117E1406077205CA520223732305C225E4 :1002300002FE14C23C02112D13C32302FE13C24757 :1002400002115F12C32302FE12C21A02112D11C342 :10025000230201B80B0BAFA8C25502C9C3000001AD :1002600010105D7E20280A0A190A0A0A5ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее05361621A208 :1001600005360721A405366E2A5F0222A7052A61FB :100170000222A9052A630222AB052A650222DE05B6 :100180002A670222E0052A690222E20522E4052A02 :100190006B0222E6052A6D0222E8052A6F0222EA96 :1001A000052A7102221D062A7302221F0622210639 :1001B0002223062AееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееB39395DD6 :0E027000200620112D11206F2D6F201919006E :0000000000 57 :1002400002115F12C32302FE12C21A02112D11C342 :10025000230201B80B0BAFA8C25502C9C3000001AD :1002600010105D7E20280A0A190A0A0A5ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее75022225062A77022227062AEA :1001C000790222290601DFFF215B0636190323AFDE :1001D000A8C2CB012100CCEB217D027E23EB77234B :1001E0007CEBFED0C2DB01CDED01C3D401014003A5 :1001F000C5CDFF01CD0F02C10BAFA8C2F001C921CF :1002000001CC0ED07E2B7723237CB9C20402C921F6 :10ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее