Skip to content

Instantly share code, notes, and snippets.

@JetsonDavis
Last active Dec 28, 2015
Embed
What would you like to do?
This is the operating system I wrote a long time ago for a homebrew Z-80 based computer. Something went wrong with the tabs on upload, sorry
***************************************************************************
* *
* PROGRAM MONITOR (TERMINAL) VERSION 1.0 *
* *
* *
* 1000-1100 EQU STACK ;SYSTEM STACK *
* 1101 DFW ADDR1 ;ADDRESS 1 *
* 1103 DFW ADDR2 ;ADDRESS 2 *
* 1105 DFB DATA ;DATA VARIABLE *
* 1106 DFB DOTFLAG ;FLAG INDICATING . IN LINE *
* 1107 DFB VP ;VERTICAL POINTER *
* 1108 DFB HP ;HORIZONTAL POINTER *
* 1109 DFB CURSOR ;CURSOR CHARACTER *
* 1F00-1FFF EQU KEYBUFFER ;KEYBOARD BUFFER *
* *
* SYSTEM STACK STARTS AT 1100H AND GOES BACKWARDS FROM THERE *
* *
***************************************************************************
0000:MONITOR ORG 0000H ;START OF PROGRAM SPACE
0000:31 00 11 LD SP, 1100H
0003:CD F9 00 CALL VDPRESET
0006:CD 7B 08 CALL LOGON
0009:CD F1 08 NEWLN CALL INITMON
000C:CD 6D 09 CALL GETLN
000F:7E LOOP LD A, (HL) ;GET NEXT CHARACTER
0010:FE 47 CP "G" ;GO COMMAND?
0012:C2 1C 00 JP NZ, N1 ;NO, TRY NEXT TEST
* "GO" MACRO
0015:DD 6E 00 GO LD L, (IX+0) ;GET ADDRn LOW
0018:DD 66 01 LD H, (IX+1) ;GET ADDRn HIGH
001B:E9 JP (HL) ;JUMP TO ADDRESS
001C:FE 3A N1 CP ":" ;INPUT COMMAND?
001E:CA 5C 00 JP Z, DATAIN ;IF SO, GOTO DATA IN MACRO
0021:FE 49 CP "I" ;PRINT ADDR1 COMMAND?
0023:C2 35 00 JP NZ, N2 ;NO, TRY NEXT TEST
* "PRINT ADDR1" MACRO
0026:DD 6E 00 LD L, (IX+0) ;GET ADDRn LOW
0029:DD 66 01 LD H, (IX+1) ;GET ADDRn HIGH
002C:CD 70 08 CALL HEXHL ;PRINT HL
002F:CD 30 08 CALL CR ;*CR*
0032:C3 09 00 JP NEWLN ;GET ANOTHER COMMAND LINE
0035:FE 2E N2 CP "." ;ENTER ADDR2 COMMAND?
0037:C2 47 00 JP NZ, N3 ;NO, TRY NEXT TEST
* "SWITCH ADDRn" MACRO
003A:3E FF LD A, 0FFH ;VALUE TO TOGGLE FLAG
003C:32 06 11 LD (1106), A ;STORE FLAG
003F:DD 21 03 11 LD IX, 1103H ;SET POINTER TO ADDR2
0043:23 N4 INC HL ;NEXT CHARACTER IN LINE
0044:C3 0F 00 JP LOOP
0047:FE 0D N3 CP 0DH ;*CR*?
0049:CA 94 00 JP Z, EOC ;OF SO, GOTO EOC MACRO
004C:CD 0C 09 CALL HEX? ;IS THIS A HEX DIGIT?
004F:DA 43 00 JP C, N4 ;NO, SO IGNORE THIS CHAR
0052:CD 25 09 CALL ASCHEX ;YES, CONVERT TO HEX
0055:CD 32 09 CALL SHIFT16 ;SHIFT INTO ADDRn
0058:23 INC HL ;NEXT CHAR
0059:C3 0F 00 JP LOOP
* "DATA INPUT" MACRO
005C:23 DATAIN INC HL ;LOOK AT NEXT CHAR
005D:7E IGNORE LD A, (HL) ;THIS IS HALF OF NEW DATA
005E:FE 0D CP ODH ;END OF DATA?
0060:CA 77 00 JP Z, ENTER ;YES, STORE LAST VALUE
0063:FE 20 CP " " ;DELIMITER?
0065:CA 77 00 JP Z, ENTER ;YES, STORE THIS VALUE
0068:CD 0C 09 CALL HEX? ;IS IT A HEX DIGIT?
006B:DA 5D 00 JP C, IGNORE ;ILLEGAL CHAR, IGNORE IT
006E:CD 25 09 CALL ASCHEX ;CONVERT TO HEX DIGIT
0071:CD 25 09 CALL SHIFT8 ;SHIFT INTO DATA BYTE
0074:C3 5C 00 JP DATAIN ;GET NEXT CHAR
0077:E5 ENTER PUSH HL ;SAVE HL
0078:F5 PUSH AF ;SAVE AF
0079:DD 6E 00 LD L, (IX+0) ;SET ADDRn LOW
007C:DD 66 01 LD H, (IX+1) ;SET ADDRn HIGH
007F:3A 05 11 LD A, (1105) ;GET DATA BYTE
0082:77 LD (HL), A ;STORE IN ADDRn
0083:23 INC HL ;ADVANCE ADDRn
0084:DD 75 00 LD (IX+0), L ;RESTORE ADDRn LOW
0087:DD 74 01 LD (IX+1), H ;RESTORE ADDRn HIGH
008A:F1 POP AF ;RESTORE AF
008B:E1 POP HL ;RESTORE HL
008C:FE 0D CP ODH ;LAST BYTE ON LINE?
008E:CA 09 00 JP Z, NEWLN ;YES, GET NEXT CHAR
0091:C3 5C 00 JP DATAIN ;NO, GET NEXT CHAR
* "END OF COMMAND LINE" MACRO
0094:3A 06 11 EOC LD A, (1106) ;GET DOTFLAG
0097:FE FF CP FFH ;IS IT SET?
0099:CA B1 00 JP Z, RANGE ;YES, PRINT RANGE
009C:DD 6E 00 LD L, (IX+0) ;NO, PRINT SINGLE VALUE
009F:DD 66 01 LD H, (IX+1) ;GET ADDRn LOW/HIGH
00A2:CD 70 08 CALL HEXHL ;PRINT ADDR
00A5:06 3A LD B, ":"
00A7:CD 17 08 CALL COUT ;PRINT ":"
00AA:7E LD A, (HL) ;GET VALUE OF (ADDR)
00AB:CD 49 08 CALL HEXBYTE ;PRINT IT
00AE:CD 30 08 CALL CR ;*CR*
00B1:C3 09 00 JP NEWLN ;BACK TO CURSOR
* "RANGE" MACRO - PRINT RANGE OF VALUES
00B4:DD 21 03 11 LD IX, 1103H ;IX=ADDR2
00B8:DD 56 01 LD D, (IX+1) ;LOAD D WITH ADDR2 LOW
00BB:DD 5E 00 LD E, (IX+0) ;LOAD E WITH ADDR2 HIGH
00BE:DD 21 05 11 LD IX, 1101h ;IX=ADDR1
00C2:DD 66 01 LD H, (IX+1) ;LOAD H WITH ADDR1 LOW
00C5:DD 6E 00 LD L, (IX+0) ;LOAD L WITH ADDR1 HIGH
00C8:13 INC DE
00C9:E5 PUSH HL ;PRINT HEADER-SAVE HL
00CA:21 FF 00 LD HL, MSG1 ;"HEADER" POINTER
00CD:CD A6 09 CALL MSGOUT ;PRINT HEADER
00D0:E1 POP HL ;RESTORE HL
00D1:0E 10NEXTLN LD C, 10H ;LINE LENGTH=16 BYTES
00D6:CD 70 08 CALL HEXHL ;PRINT ADDR FOR NEW LINE
00D9:06 3A LD B, ":"
00DB:CD 17 08 CALL COUT ;PRINT ":"
00DE:7E M1 LD A, (HL) ;GET VALUE TO BE PRINTED
00DF:CD 49 08 CALL HEXBYTE ;PRINT IT
00E2:06 20 LD B, " "
00E4:CD 17 08 CALL COUT ;PRINT A SPACE
00E7:23 INC HL ;NEXT VALUE
00E8:7A LD A, D ;
00E9:BC CP H ;CHECK FOR END OF LINE
00EA:C2 EF 00 JP NZ, OKAY ;NOT END OF LINE...
00ED:7B LD A, E
00EE:BD CP L ;CHECK FOR END OF BLOCK
00EF:CA 7C 01 JP Z, RETURN ;GOTO NEWLN WITH LF/*CR*
00F2:0D OKAY DEC C ;DROP COUNTER BY 1
00F3:C2 DB 00 JP NZ, M1 ;IF NOT EOL, KEEP GOING
00F6:C3 D1 00 JP NEXTLN ;IF EOL, START NEW LINE
00F9:DB 28 VDPRESET IN A, (28H) ;WAKE UP VIDEO CHIP
00FB:CD 00 08 CALL INIT_9600
00FE:C9 RET
* MESSAGE DATA BLOCK
00FF:41 44 44 52 DFB "ADDR:00 01 02 03 04 05 06 07 08 09
0103:3A 30 30 20 0A 0B 0C 0D 0E 0F"
0107:30 31 20 30
010B:32 20 30 33
010F:20 30 34 20
0113:30 35 20 30
0117:36 20 30 37
011B:20 30 38 20
011F:30 39 20 30
0123:41 20 30 42
0127:20 30 43 20
012B:30 44 20 30
012F:45 20 30 46
0133:0D DFB *CR*
***************************************************************************
* *
* VIDEO SUBROUNTINES *
* *
***************************************************************************
0134:E5 VDPINIT PUSH HL ;SAVE REGS
0135:C5 PUSH BC
0136:DB 19 IN A, (19H) ;READ VDP STATUS, WRITE MODE
0138:06 08 LD B, 08H ;LOOP COUNTER
013A:0E 80 LD C, 80H ;REGISTER COUNTER-
013C:21 6C 01 LD HL, VREGS ; (0-7+MASK=80H)
013F:7E Q1 LD A, (HL) ;GET VALUE FROM VREGS
0140:D3 19 OUT A, (19H) ;SEND TO VDP
0142:79 LD A, C ;GET REGISTER NUMBER
0143:D3 19 OUT A, (19H) ;SEND TO VDP
0145:0C INC C ;NEXT REGISTER
0146:23 INC HL ;NEXT VREG
0147:05 DEC B ;DEC LOOP COUNTER
0148:78 LD A, B ;CHECK FOR LOOP COUNT=0
0149:FE 00 CP A, 00H
014B:C2 3F 01 JP NZ, Q1 ;IF MORE, LOOP TO Q1
014E:21 00 02 LD HL, 0200H ;HL=CHAR GEN POINTER
0151:3E 00 LD A, 00H ;BASE ADDR LOW
0153:D3 19 OUT A, (19H) ;SEND TO VDP
0155:3E 49 LD A, 49H ;BASE ADDR HIGH
0157:D3 19 OUT A, (19H) ;SEND TO VDP
0159:7E Q2 LD A, (HL) ;GET VALUE FROM TABLE
015A:D3 18 OUT A, (18H) ;SEND TO VDP
015C:23 INC HL ;NEXT VALUE
015D:7D LD A, L ;CHECK FOR END OF DATA
015E:FE 00 CP 00H ;LAST DIGIT OF HL=0?
0160:C2 59 01 JP NZ, Q2 ;MORE, KEEP GOING AT Q2
0163:7C LD A, H ;FIRST DIGIT OF HL=05?
0164:FE 05 CP 05H
0166:C2 59 01 JP NZ, Q2 ;NO, KEEP GOING
0169:C1 POP BC ;YES, RESTORE REGS AND...
016A:E1 POP HL
016B:C9 RET
016C:00 VREG0 DISABLE VDP EXTERNAL INT, M3=0
016D:D0 VREG1 SELECT 16k,ACTIVE DISPLAY,
00 10
0170:01 20 02 F1
0174:00 00 00 00 UNUSED
0178:00 00 00 00 UNUSED
* "RETURN" MACRO - PRINTS *CR* AND GETS NEW INPUT LINE
017C:CD 30 08 RETURN CALL CR ;PRINT *CR*
017F:C3 09 00 JP NEWLN ;MONITOR REENTRY POINT
***************************************************************************
* *
* SUBROUTINE CLEAR *
* *
* CLEARS THE VIDEO SCREEN. NO REGS AFFECTED *
* *
***************************************************************************
0182:E5 CLEAR PUSH HL ;SAVE REGS
0183:21 C0 03 LD HL, 03C0H ;SET-UP COUNTER
0186:3E 00 LD A, 00H ;SEND BASE ADDR OF SCREEN
0188:D3 19 OUT (19H), A ; MEMORY TO VDP
018A:3E 40 LD A, 40H
018C:D3 19 OUT (19H), A
018E:3E 20 A2 LD A, " " ;A=SPACE CHAR (=20H)
0190:D3 18 OUT (18H), A ;OUTPUT A SPACE TO SCREEN MEM
0192:2B DEC HL ;DECREASE COUNTER
0193:7D LD A, L ;CHECK FOR END OF LOOP
0194:FE 00 CP 00H
0196:C2 8E 01 JP NZ, A2 ;NOT END, KEEP GOING
0199:7C LD A, H
019A:FE 00 CP 00H
019C:C2 8E 01 JP NZ, A2 ;STILL NOT OVER, KEEP GOING
019F:E1 POP HL ;OVER! RESTORE REGS
01A0:C9 RET ;RETURN
***************************************************************************
* *
* SUBROUTINE VDP_INIT *
* *
* SETS UP VP, HP, CURSOR. INITS VDP AND SERIAL PORTS *
* *
***************************************************************************
01A1:3E 00 VDP_INIT LD A, 00H
01A3:32 07 11 LD (1107H), A ;CLEAR VERTICAL POINTER
01A6:32 08 11 LD (1108H), A ;CLEAR HORIZONTAL POINTER
01A9:3E 5F LD A, 5FH ;CURSOR = ">"
01AB:32 09 11 LD (1109H), A ;PUT IN CURSOR REG
01AE:C3 34 01 CALL VDPINIT ;CALL MAIN VDP INIT ROUTINE
01B1:3E B0 INIT8255 LD A, B0H ;8255A MODE 1-PORT A SET
01B3:D3 13 OUT (13H), A ;SEND TO 8255a COMMAND PORT
01B5:3E 09 LD A, 09H ;SET INTERNAL INT ENABLE
01B7:D3 13 OUT (13H), A ;SEND TO COMMAND PORT
01B9:C9 RET ;RETURN
***************************************************************************
* *
* MONITOR SUBROUNTINES *
* *
***************************************************************************
0800: START ORG 0800 ;START OF SUBROUTINE SPACE
0000:31 00 11 INIT_9600 PUSH AF ACCESS BAUD RATE DIVIDER
HL ;RESTORE HL
00D1:0E 10 NEXTLN LD C, 10H ;LINE LENGTH=16 BYTES
00D6:CD 70 08 CALL HEXHL ;PRINT ADDR FOR
00DB:CD 17 08 CALL COUT ;PRINT ":"
00DE:7E M1 LD A, (HL) ;GET VALUE TO BE PRINTED
00DF: INT IT
00E2:06 20 LD B, " "
00E4:CD 17 08 CALL COUT ;PRINT A SPACE
00E7:23 INC HL ;NEXT VA * CHECK FOR END OF LINE
00EA:C2 EF 00 JP NZ, OKAY ;NOT END OF LINE...
00ED:7B LD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment