]> pd.if.org Git - mmurtl/commitdiff
autocommit for file dated 1994-10-27 08:28:42
authorRichard Burgess <>
Thu, 27 Oct 1994 08:28:42 +0000 (08:28 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Mon, 17 Oct 2016 14:03:47 +0000 (14:03 +0000)
ossource/video.asm [new file with mode: 0644]

diff --git a/ossource/video.asm b/ossource/video.asm
new file mode 100644 (file)
index 0000000..24ce1fa
--- /dev/null
@@ -0,0 +1,1023 @@
+;   MMURTL Operating System Source Code\r
+;   Copyright 1991,1992,1993,1994 Richard A. Burgess\r
+;   ALL RIGHTS RESERVED\r
+;   Version 1.0\r
+\r
+;This module contains ALL Video code & Data\r
+;    (along with EdLine for lack of a better place)\r
+;\r
+;This module supports MMURTL's Virtual Text Video.\r
+;All video calls are based on the video information in the job's\r
+;Job Control Block.\r
+;\r
+;Virtual video buffers allow a job to output data even when it is\r
+;not assigned to the real video display buffer.\r
+;\r
+;The call SetVidOwner is the key. It swaps virtual buffers for the real one\r
+;and changes the current pointer in that job's JCB.  It also updates\r
+;the cursor in the correct place on entry.\r
+;\r
+; The following calls are implemented here:\r
+;\r
+;------------------------------\r
+;GetVidOwner(pdJobNumRet)\r
+; Desc: This returns the Job Number that currently has active video\r
+; screen.\r
+;------------------------------\r
+;SetVidOwner(ddJobNum)\r
+; Desc: This selects the screen that you see.  This call is used\r
+; by the monitor in conjunction with the SetKbdOwner call to change\r
+; who gets the keystrokes and video (should be the same app).\r
+; The internal debugger is the only code that will use this call\r
+; and not move the keyboard also.  It has it's own keyboard code\r
+; (else how could it debug the real keyboard code??)\r
+; Params:\r
+;   ddJobNum is the new Job to get the active screen\r
+;   (the one to be displayed)\r
+;------------------------------\r
+;SetNormVid(dAttr)\r
+; Desc: This selects the normal background attribute and fill char\r
+; used by ClrScr and ScrollVid on the screen.\r
+; Params:\r
+;   dCharAttr is the Character and aAttr values used in\r
+;   standard video operation on the current screen\r
+;\r
+;------------------------------\r
+;GetNormVid(pVidRet)\r
+;\r
+; Desc: This returns the value the normal screen attribute\r
+; used by ClrScr and ScrollVid on the screen.\r
+;\r
+; Params:\r
+;   pVidRet points to the character where you want the NormVid\r
+;   attribute returned.\r
+;\r
+;------------------------------\r
+;ClrScr ();\r
+;\r
+; Desc:\r
+;   This clears the screen for the executing job. It may or may not\r
+;   be the one you are viewing...\r
+;\r
+;------------------------------\r
+;TTYOut (pTextOut, ddTextOut, ddAttrib)\r
+;\r
+;   Desc: This places characters on the screen in a TTY fashion at the\r
+;   X & Y coordinates that are in effect for that screen.\r
+;   The following characters in the stream are interpreted as follows:\r
+;   Hex   Action\r
+;   0A    Line Feed\r
+;     The cursor (next active character placement) will be on the\r
+;     following line at column 0.  If this line is below the bottom\r
+;     of the screen, the entire screen will be scrolled up on line,\r
+;     the bottom line will be blanked, and the cursor will be placed\r
+;     on the last line in the first column.\r
+;   0D    Carriage Return\r
+;     The Cursor will be moved to column zero on the current line.\r
+;   08    BackSpace - The cursor will be moved one column to the left.\r
+;     If already at column 0, Backspace will have no effect.\r
+;     The backspace is non-destructive (no chars are changed)\r
+;\r
+;   pTextOut is a NEAR Ptr to the text.\r
+;   ddTextOut is the number of chars of text.\r
+;   ddAttrib is the attribute/Color you want.\r
+;\r
+;------------------------------\r
+;PutVidChars(ddCol,ddLine,pChars,sChars,ddAttrib)\r
+;\r
+; Desc: This places characters on the screen without affecting\r
+;   the current TTY coordinates or the TTY data.  It is independent\r
+;   of the current video "Stream."\r
+;\r
+; Params:\r
+;   ddCol is the column to start on (0-79)\r
+;   ddLine is the line (0-24)\r
+;   pChars is a pointer the text to be displayed\r
+;   sChars is the number of chars\r
+;   ddAtrib is the color/attribute to use during display\r
+;    which applies to all of the characters on this\r
+;    call to PutVidChars.\r
+;------------------------------\r
+;GetVidChar(ddCol,ddLine,pCharRet,pAttrRet)\r
+;\r
+; Desc: This returns the current character and attribute\r
+;   from the screen coordinates you specify.\r
+;\r
+; Params:\r
+;   ddCol is the column to start on (0-79)\r
+;   ddLine is the line (0-24)\r
+;   pCharRet is a pointer where you want the character returned\r
+;   pAttrRet is a pointer where you want the attribute returned\r
+;------------------------------\r
+;PutVidAttrs(ddCol,ddLine,sChars,dAttr)\r
+;\r
+; Desc: This sets screen colors (attrs) for the without affecting\r
+;   the current TTY coordinates or the character data. It is independent\r
+;   of the current video "Stream."\r
+;\r
+; Params:\r
+;   ddCol is the column to start on (0-79)\r
+;   ddLine is the line (0-24)\r
+;   sChars is the number of char spaces to place dAttr\r
+;   dAttr is the color/attribute to fill the character spaces with\r
+;\r
+;------------------------------\r
+;ScrollVid(ddULCol,ddULline,nddCols,nddLines, ddfUp)\r
+;\r
+; Desc: This scrolls the described square area on the screen either\r
+;   UP or DOWN one line.  If ddfUp is NON-ZERO the scroll will be UP.\r
+;   The line left blank is filled with NormAttr from JCB.\r
+; Parms:\r
+;   ddULCol is the UPERR LEFT column to start on (0-79)\r
+;   ddULLine is the UPPER LEFT line (0-24)\r
+;   nddCols is the number of columns to be scrolled.\r
+;   nddLines is the count of lines to be scrolled.\r
+;   ddfUp is NON-ZERO to cause the scroll to be up (vise down).\r
+;\r
+;   If you want to scroll the entire screen UP one line, the\r
+;   params would be  ScrollVid(VidNum, 0,0,80,25,1).\r
+;   In this case the top line is lost (not really scrolled),\r
+;   and the bottom line would be blanked. Infact, if you specified\r
+;   (Vidnum, 0,1,80,24,1) you would get the same results.\r
+;\r
+;------------------------------\r
+;SetXY(NewX,NewY)\r
+; Desc: Position VGA cursor (Text mode) to the X & Y position.\r
+;\r
+; Params:\r
+;   NewX is the new horizontal cursor postion\r
+;   NewY is the new vertical cursor position\r
+;\r
+;------------------------------\r
+;GetXY(pXRet,pYRet)\r
+; Desc: Returns the current X & Y position for your job.\r
+;\r
+; Params:\r
+;   pXRet is a ptr where you want the current horizontal cursor postion\r
+;   pYRet is a ptr where you want the current vertical cursor position\r
+;\r
+.DATA\r
+.INCLUDE MOSEDF.INC\r
+.INCLUDE JOB.INC\r
+\r
+;This is the data for the virtual character video service.\r
+;The video code is fully reentrant because each job has it's own\r
+;video screen.  Only one of these screens will be the active video\r
+;display.\r
+;\r
+;Video Equates and Types\r
+;\r
+CRTCPort1   EQU 03D4h   ;Index port for CRTC\r
+CRTCPort2   EQU 03D5h   ;Data port for CRTC\r
+CRTCAddHi   EQU 0Ch     ;Register for lo byte of Video address\r
+CRTCAddLo   EQU 0Dh     ;Register for lo byte of Video address\r
+CRTCCurHi   EQU 0Eh     ;Register for lo byte of Cursor address\r
+CRTCCurLo   EQU 0Fh     ;Register for lo byte of Cursor address\r
+CRTC0C      DB 0        ;CRT Reg 0C HiByte address value\r
+CRTC0D      DB 0        ;CRT Reg 0D LoByte address value\r
+\r
+PUBLIC ddVidOwner   DD 1        ;JCB that currently owns video\r
+                                ;Default to monitor (Job 1)\r
+\r
+;End of Data & Equates\r
+;\r
+;============================================================================\r
+; BEGIN INTERNAL CODE FOR VIDEO\r
+;============================================================================\r
+;\r
+.CODE\r
+;\r
+EXTRN GetpJCB NEAR\r
+EXTRN GetpCrntJCB NEAR\r
+EXTRN ReadDbgKbd NEAR\r
+EXTRN GetCrntJobNum NEAR\r
+\r
+;InitVideo makes Video Screen 0 the default screen. That\r
+;makes the VGATextBase address 0B8000h\r
+;\r
+PUBLIC InitVideo:\r
+        MOV AL, CRTCAddHi       ;Index of hi byte\r
+        MOV DX, CRTCPort1       ;Index Port\r
+        OUT DX, AL\r
+        MOV AL, CRTC0C          ;hi byte value to send\r
+        MOV DX, CRTCPort2       ;Data Port\r
+        OUT DX, AL\r
+        ;\r
+        MOV AL, CRTCAddLo       ;Index of lo byte\r
+        MOV DX, CRTCPort1       ;Index Port\r
+        OUT DX, AL\r
+        MOV AL, CRTC0D          ;lo byte value to send\r
+        MOV DX, CRTCPort2       ;Data Port\r
+        OUT DX, AL\r
+        RETN\r
+;\r
+;============================================================================\r
+; BEGIN PUBLIC CODE FOR VIDEO\r
+;============================================================================\r
+;\r
+;============================================================================\r
+; SetVidOwner - Make a new a screen actively displayed.\r
+; EAX Returns NON-Zero if JOB number is invalid\r
+\r
+ddJobVidCV  EQU DWORD PTR [EBP+12]\r
+\r
+PUBLIC __SetVidOwner:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        MOV EAX, ddJobVidCV     ;\r
+        CMP EAX, ddVidOwner     ;Already own it?\r
+        JNE ChgVid01            ;No\r
+        XOR EAX, EAX            ;Yes\r
+        JMP ChgVidDone\r
+ChgVid01:\r
+        CALL GetpJCB                    ;Leaves ptr to new vid JCB in EAX\r
+        CMP DWORD PTR [EAX+pVidMem] ,0  ;Got valid video memory???\r
+        JNE ChgVid02                    ;Yes\r
+        MOV EAX, ErcVidNum      ;NO! Give em an error!\r
+        JMP ChgVidDone\r
+ChgVid02:\r
+        ;Save data on screen to CURRENT job's pVirtVid\r
+        MOV EAX, ddVidOwner\r
+        CALL GetpJCB\r
+        PUSH VGATextBase        ;Source\r
+        MOV EBX, [EAX+pVirtVid] ;Destination\r
+        PUSH EBX\r
+        PUSH 4000               ;Size of video\r
+        CALL FWORD PTR _CopyData    ;Do it!\r
+\r
+        ;Make pVidMem same as pVirtVid for CURRENT OWNER\r
+        MOV EAX, ddVidOwner\r
+        CALL GetpJCB            ;Leaves ptr to new vid JCB in EAX\r
+        MOV EBX, [EAX+pVirtVid]\r
+        MOV [EAX+pVidMem], EBX\r
+\r
+        ;Update current video owner to NEW owner\r
+\r
+        MOV EAX, ddJobVidCV     ;\r
+        MOV ddVidOwner, EAX\r
+\r
+        ;Copy in Data from new pVirtVid\r
+\r
+        MOV EAX, ddVidOwner\r
+        CALL GetpJCB\r
+        MOV EBX, [EAX+pVirtVid] ;Source\r
+        PUSH EBX\r
+        PUSH VGATextBase        ;Destination\r
+        PUSH 4000               ;Size of video\r
+        CALL FWORD PTR _CopyData    ;Do it!\r
+\r
+        ;Make new pVidMem real video screen for new owner\r
+\r
+        MOV EAX, ddVidOwner\r
+        CALL GetpJCB\r
+        MOV EBX, VGATextBase\r
+        MOV [EAX+pVidMem], EBX\r
+\r
+        ;Set Cursor position\r
+\r
+        MOV EAX, ddVidOwner\r
+        CALL GetpJCB\r
+        MOV ECX, EAX\r
+        MOV EBX, [ECX+CrntX]    ;Get current X for new screen\r
+        MOV EAX, [EBX+CrntY]    ;Current Y\r
+        CALL HardXY             ;Set it up\r
+        XOR EAX, EAX            ;No Error\r
+ChgVidDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 4\r
+\r
+;============================================================================\r
+; SetNormVid - Sets the normal video attribute (color) used in\r
+; ClrScr, EditLine, and ScrollVid.\r
+; EAX Returns Zero (No Error)\r
+\r
+ddNormVid   EQU DWORD PTR [EBP+12]\r
+\r
+PUBLIC __SetNormVid:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;pJCB -> EAX\r
+        MOV EBX, ddNormVid      ;\r
+        MOV [EAX+NormAttr], EBX ;\r
+        XOR EAX, EAX\r
+        POP EBP                 ;\r
+        RETF 4\r
+\r
+;============================================================================\r
+; GetNormVid - Returns the normal video attribute (color) used in\r
+; ClrScr, EditLine, and ScrollVid.\r
+; EAX Returns Zero (No Error)\r
+\r
+pdNormVidRet EQU DWORD PTR [EBP+12]\r
+\r
+PUBLIC __GetNormVid:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;pJCB -> EAX\r
+        MOV EBX, [EAX+NormAttr] ;\r
+        MOV ESI, pdNormVidRet   ;\r
+        MOV [ESI], BL           ;\r
+        XOR EAX, EAX\r
+        POP EBP                 ;\r
+        RETF 4\r
+\r
+;============================================================================\r
+; GetVidOwner - Returns the Job number of current active video\r
+;  number to the caller.\r
+;=============================================================================\r
+\r
+pVidNumRet  EQU DWORD PTR [EBP+12]\r
+\r
+PUBLIC __GetVidOwner:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        MOV ESI, pVidNumRet     ;\r
+        MOV EAX, ddVidOwner     ;\r
+        MOV [ESI], EAX          ;\r
+        XOR EAX, EAX            ; no error obviously\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 4\r
+\r
+;=============================================================================\r
+; Clear caller's video screen (Use Space and Attr from JCB NormAttr)\r
+;=============================================================================\r
+;\r
+PUBLIC __ClrScr:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+        MOV EDI,[EBX+pVidMem]   ;EDI points to his video memory\r
+        MOV EAX, [EBX+NormAttr] ;Attr\r
+        SHL EAX, 8              ;\r
+        MOV AL, 20h             ;\r
+        MOV DX, AX\r
+        SHL EAX, 16\r
+        MOV AX, DX              ;Fill Char & Attr\r
+        MOV ECX,0400h\r
+        CLD\r
+        REP STOSD\r
+        PUSH 0\r
+        PUSH 0\r
+        CALL FWORD PTR _SetXY   ;Erc in EAX on Return\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF\r
+\r
+;=============================================================================\r
+; TTYOut:\r
+;=============================================================================\r
+\r
+pTextOut    EQU DWORD PTR [EBP+20]\r
+sTextOut    EQU DWORD PTR [EBP+16]\r
+dAttrText   EQU DWORD PTR [EBP+12]\r
+\r
+DataByte    EQU BYTE PTR [ECX]\r
+\r
+PUBLIC __TTYOut:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+        MOV EAX, sTextOut       ;make sure count isn't null\r
+        OR EAX, EAX\r
+        JZ TTYDone\r
+\r
+TTY00:\r
+        MOV EAX,[EBX+CrntX]     ; EAX has CrntX (col)\r
+        MOV EDX,[EBX+CrntY]     ; EDX has CrntY (line)\r
+        MOV ECX,pTextOut\r
+\r
+        CMP DataByte,0Ah        ; LF?\r
+        JNE TTY02\r
+        INC EDX\r
+        CMP EDX,[EBX+nLines]    ; Equal to or past the bottom?\r
+        JB  TTY06               ; No\r
+        JMP TTYScr              ; Yes, goto scroll\r
+TTY02:\r
+        CMP DataByte,0Dh        ; CR?\r
+        JNE TTY03\r
+        MOV EAX,0\r
+        JMP TTY06\r
+TTY03:\r
+        CMP DataByte,08h        ; BackSpace?\r
+        JNE TTY04\r
+        CMP EAX,0\r
+        JE  TTY04\r
+        DEC EAX\r
+        JMP TTY06\r
+TTY04:\r
+        PUSH EBX                ;Save pointer to VCB\r
+\r
+        PUSH EAX                ;X (Param 1)\r
+        PUSH EDX                ;Y (Param 2)\r
+        PUSH ECX                ;pointer to text char (Param3)\r
+        PUSH 1                  ;Param 4 (nchars)\r
+        MOV ECX,dAttrText       ;\r
+        PUSH ECX                ;Param 5\r
+        CALL FWORD PTR _PutVidChars ;\r
+        POP EBX                 ;restore ptr to VCB\r
+        CMP EAX, 0\r
+        JNE TTYDone\r
+        MOV EAX, [EBX+CrntX]\r
+        MOV EDX, [EBX+CrntY]\r
+        INC EAX                 ;Next column\r
+        CMP EAX,[EBX+nCols]\r
+        JNE TTY06               ;Make cursor follow\r
+        MOV EAX,0\r
+        INC EDX\r
+        CMP EDX,[EBX+nLines]    ; past the bottom?\r
+        JNE TTY06               ; No - goto 06 else fall thru\r
+\r
+TTYScr:\r
+        DEC EDX                 ; back up one line\r
+        PUSH EAX                ;Save registers (scroll eats em)\r
+        PUSH EBX\r
+        PUSH ECX\r
+        PUSH EDX\r
+\r
+        PUSH 0\r
+        PUSH 0\r
+        PUSH 80\r
+        PUSH 25\r
+        PUSH 1                  ;fUP (non zero)\r
+        CALL FWORD PTR _ScrollVid   ;Ignore error\r
+        POP EDX                 ;restore registers\r
+        POP ECX\r
+        POP EBX\r
+        POP EAX                 ;Fall thru to\r
+\r
+TTY06:\r
+        PUSH EBX                ;save ptr to pJCB\r
+\r
+        PUSH EAX\r
+        PUSH EDX\r
+        CALL FWORD PTR _SetXY\r
+\r
+        POP EBX                 ;Restore ptr to VCB\r
+        CMP EAX, 0\r
+        JNE TTYDone\r
+        DEC sTextOut\r
+        JZ TTYDone\r
+        INC pTextOut\r
+        JMP TTY00               ; Go back for next char\r
+TTYDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 12\r
+\r
+\r
+\r
+;=============================================================================\r
+; PutVidAttrs:\r
+; Desc: This sets screen colors (attrs) for the without affecting\r
+;   the current TTY coordinates or the character data. It is independent\r
+;   of the current video "Stream."\r
+;\r
+; Params:\r
+;   ddCol is the column to start on (0-79)\r
+;   ddLine is the line (0-24)\r
+;   sChars is the number of char spaces to place dAttr\r
+;   dAttr is the color/attribute to fill the character spaces with\r
+;\r
+; Start Position in screen memory is (Line * 80 + (Column*2))\r
+; pass Char, then Color, pass char, then color etc... DO NOT EXCEED 2000!\r
+; Needs to be fixed to tell if ECX + sDDChars will go off screen...\r
+;\r
+;=============================================================================\r
+\r
+oADDX       EQU DWORD PTR [EBP+24] ;Param 1 COLUMN\r
+oADDY       EQU DWORD PTR [EBP+20] ;Param 2 LINE\r
+sADDChars   EQU DWORD PTR [EBP+16] ;Param 3 sChars\r
+sADDColor   EQU DWORD PTR [EBP+12] ;Param 4 Attr\r
+\r
+PUBLIC __PutVidAttrs:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+\r
+        MOV EDI, [EBX+pVidMem]  ;point to this VCBs video memory\r
+        MOV EBX,oADDx           ;x Position\r
+        SHL EBX,1               ;Times 2\r
+        MOV EAX,oADDy           ;y Position\r
+        MOV ECX,0A0h            ;Times 160 (char/attrs per line)\r
+        MUL ECX                 ;Times nColumns\r
+        ADD EAX,EBX\r
+        CMP EAX,0F9Eh           ;Last legal posn on screen\r
+        JBE PutAttrs00\r
+        MOV EAX, ErcVidParam\r
+        JMP PcADone\r
+PutAttrs00:\r
+        MOV ECX,sADDChars\r
+        OR ECX, ECX\r
+        JZ PcADone\r
+        ADD EDI,EAX\r
+        MOV EAX,sADDColor\r
+        CLD\r
+pcAMore:\r
+        INC EDI                 ;Pass the char value\r
+        STOSB                   ;Move Color in\r
+        LOOP pcAMore\r
+        XOR EAX, EAX            ;No Error!\r
+pcADone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 16\r
+\r
+;=============================================================================\r
+; PutVidChars:\r
+; This Places characters on the VGA Character Screen in the XY Coords\r
+;  Params\r
+;  1) DD X (Column 0-79)\r
+;  2) DD Y (Line 0-24)\r
+;  3) DD Near Ptr (relative to DS) of string\r
+;  4) DD Size of String\r
+;  5) DD (of which the low order byte is the Color)\r
+;\r
+; Start Position in screen memory is (Line * 80 + (Column*2))\r
+; Put Char, then Color, then char, then color etc... DO NOT EXCEED 2000!\r
+; Needs to be fixed to tell if ECX + sDDChars will go off screen...\r
+;\r
+;=============================================================================\r
+\r
+oDDX        EQU DWORD PTR [EBP+28] ;Param 1 COLUMN\r
+oDDY        EQU DWORD PTR [EBP+24] ;Param 2 LINE\r
+pDDChars    EQU DWORD PTR [EBP+20] ;Param 3 pChars\r
+sDDChars    EQU DWORD PTR [EBP+16] ;Param 4 sChars\r
+sDDColor    EQU DWORD PTR [EBP+12] ;Param 5 Attr\r
+\r
+PUBLIC __PutVidChars:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+               CLI\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+        MOV EDI, [EBX+pVidMem]  ;point to this VCBs video memory\r
+               STI\r
+        MOV EBX,oDDx\r
+        SHL EBX,1               ;Times 2\r
+        MOV EAX,oDDy\r
+        MOV ECX,0A0h            ;Times 160\r
+        MUL ECX                 ;Times nColumns\r
+        ADD EAX,EBX\r
+        CMP EAX,0F9Eh           ;Last legal posn on screen\r
+        JBE PutChars00\r
+        MOV EAX, ErcVidParam\r
+        JMP PcDone\r
+PutChars00:\r
+        MOV ECX,sDDChars\r
+        OR ECX, ECX\r
+        JZ PcDone\r
+        MOV ESI,pDDChars\r
+        ADD EDI,EAX\r
+        MOV EAX,sDDColor\r
+        CLD\r
+pcMore:\r
+        MOVSB                   ;Move Char in\r
+        STOSB                   ;Move Color in\r
+        LOOP pcMore\r
+        XOR EAX, EAX            ;No Error!\r
+pcDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 20\r
+\r
+;=============================================================================\r
+;GetVidChar(ddCol,ddLine,pCharRet,pAttrRet)\r
+;\r
+; Desc: This returns the current character and attribute\r
+;   from the screen coordinates you specify.\r
+;\r
+; Params:\r
+;   ddCol is the column to start on (0-79)\r
+;   ddLine is the line (0-24)\r
+;   pCharRet is a pointer where you want the character returned\r
+;   pAttrRet is a pointer where you want the attribute returned\r
+;\r
+\r
+oGDDX       EQU DWORD PTR [EBP+24] ;Param 1 COLUMN\r
+oGDDY       EQU DWORD PTR [EBP+20] ;Param 2 LINE\r
+pGDDCRet    EQU DWORD PTR [EBP+16] ;Param 3 pCharRet\r
+pGDDARet    EQU DWORD PTR [EBP+12] ;Param 4 pAttrRet\r
+\r
+PUBLIC __GetVidChar:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+\r
+        MOV EDI, [EBX+pVidMem]  ;point to this VCBs video memory\r
+        MOV EBX,oGDDx\r
+        SHL EBX,1               ;Times 2\r
+        MOV EAX,oGDDy\r
+        MOV ECX,0A0h            ;Times 160\r
+        MUL ECX                 ;Times nColumns\r
+        ADD EAX,EBX\r
+        CMP EAX,0F9Eh           ;Last legal posn on screen\r
+        JBE GetChar00\r
+        MOV EAX, ErcVidParam\r
+        JMP PcGDone\r
+GetChar00:\r
+        ADD EDI,EAX             ;EDI now points to char\r
+        MOV ESI,pGDDCRet\r
+        MOV AL, [EDI]\r
+        MOV [ESI], AL           ;Give them the char\r
+        INC EDI                 ;Move to Attr\r
+        MOV ESI,pGDDARet\r
+        MOV AL, [EDI]\r
+        MOV [ESI], AL           ;Give them the Attr\r
+        XOR EAX, EAX            ;No Error!\r
+pcGDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 20\r
+;=============================================================================\r
+; ScrollVid:\r
+; This scrolls the defined area up or down one line.\r
+;  Params\r
+;  1) Upper Left column X (Column 0-79)\r
+;  2) Upper Left line Y (Line 0-24)\r
+;  3) nCols to scroll\r
+;  4) nLines to scroll\r
+;  5) TRUE for up (any NON zero QUAD)\r
+;\r
+;  We check all params for validity. ErcVidParam is returned if one is\r
+;  invalid.\r
+;=============================================================================\r
+\r
+oULX        EQU DWORD PTR [EBP+28] ;Param 1 COLUMN\r
+oULY        EQU DWORD PTR [EBP+24] ;Param 2 LINE\r
+nddCols     EQU DWORD PTR [EBP+20] ;Param 3 Number of columns\r
+nddLines    EQU DWORD PTR [EBP+16] ;Param 4 Number of Lines\r
+ddfUP       EQU DWORD PTR [EBP+12] ;Param 5 Attr\r
+\r
+PUBLIC __ScrollVid:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX            ;Save pJCB & use in EBX\r
+        MOV EAX, oULX\r
+        CMP EAX, 79\r
+        JA svErcExit\r
+        ADD EAX, nddCols\r
+        CMP EAX, 80\r
+        JA svErcExit\r
+        MOV EAX, oULY\r
+        CMP EAX, 24\r
+        JA svErcExit\r
+        ADD EAX, nddLines\r
+        CMP EAX, 25\r
+        JA svErcExit\r
+\r
+        CMP ddfUP, 0        ;Scroll UP?\r
+        JNE svUP0           ;Yes... Scroll UP!\r
+\r
+;Scroll DOWN begins\r
+\r
+        MOV EAX, oULY       ;First line\r
+        ADD EAX, nddLines   ;Last line\r
+        MOV ECX, 160\r
+        MUL ECX                 ;times nBytes per line\r
+        MOV EDI, [EBX+pVidMem]  ;EDI points to video memory 0,0\r
+        MOV EDX, EBX            ;Save pJCB\r
+        ADD EDI, EAX            ;EDI is ptr to 1st dest line\r
+        ADD EDI, oULX       ;offset into line\r
+        ADD EDI, oULX       ;add again for attributes\r
+        MOV ESI, EDI        ;\r
+        SUB ESI, 160        ;ESI is 1st source line\r
+        MOV EBX, ESI        ;Save in EBX for reload\r
+        MOV EAX, nDDLines   ;How many lines to move\r
+        DEC EAX             ;one less than window height\r
+svDOWN1:\r
+        MOV ECX, nddCols    ;How many WORDS per line to move\r
+        REP MOVSW           ;Move a line (of WORDS!)\r
+        MOV EDI, EBX        ;Reload Dest to next line\r
+        MOV ESI, EDI\r
+        SUB ESI, 160\r
+        MOV EBX, ESI        ;Save again\r
+        DEC EAX\r
+        JNZ svDOWN1\r
+        MOV EAX, [EDX+NormAttr] ;Normal video attributes!!!\r
+        SHL EAX, 8\r
+        MOV AL, 20h             ;Space\r
+        MOV EDI, EBX            ;Put the last line into EDI\r
+        MOV ECX, nddCols\r
+        CLD\r
+        REP STOSW\r
+        XOR EAX, EAX        ;No error\r
+        JMP svDone\r
+                            ;No... scroll down begins\r
+svUP0:\r
+        MOV EAX, oULY       ;First line\r
+        MOV ECX, 160\r
+        MUL ECX                 ;times nBytes per line\r
+        MOV EDI, [EBX+pVidMem]  ;EDI points to video memory 0,0\r
+        MOV EDX, EBX            ;Save pJCB\r
+        ADD EDI, EAX            ;EDI is ptr to 1st dest line\r
+        ADD EDI, oULX       ;offset into line\r
+        ADD EDI, oULX       ;add again for attributes\r
+        MOV ESI, EDI        ;\r
+        ADD ESI, 160        ;ESI is 1st source line\r
+        MOV EBX, ESI        ;Save in EBX for reload\r
+        MOV EAX, nDDLines   ;How many lines to move\r
+        DEC EAX             ;two less than window height\r
+svUP1:\r
+        MOV ECX, nddCols    ;How many WORDS per line to move\r
+        REP MOVSW           ;Move a line (of WORDS!)\r
+        MOV EDI, EBX        ;Reload Dest to next line\r
+        MOV ESI, EDI\r
+        ADD ESI, 160\r
+        MOV EBX, ESI        ;Save again\r
+        DEC EAX\r
+        JNZ svUP1\r
+        MOV EAX, [EDX+NormAttr] ;Normal video attributes!!!\r
+        SHL EAX, 8\r
+        MOV AL, 20h             ;Space\r
+        MOV EDI, EBX        ;Put the last line into EDI\r
+        SUB EDI, 160\r
+        MOV ECX, nddCols\r
+        CLD\r
+        REP STOSW\r
+        XOR EAX, EAX        ;No error\r
+        JMP svDone\r
+svErcExit:                  ;Error exits will jump here\r
+        MOV EAX, ErcVidParam\r
+svDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 20\r
+;\r
+;=============================================================\r
+; HardXY - Intenal  Internal to support SetXY and SetVidOwner\r
+;           This sets the hardware cursor position\r
+; Input:\r
+;   EAX : New Y position\r
+;   EBX : New X position\r
+; Used:\r
+;   EAX, EBX, EDX, Flags\r
+; Output:\r
+;   None\r
+\r
+HardXY:\r
+        MOV ECX,80\r
+        MUL ECX                 ; Line * 80\r
+        ADD EAX,EBX             ; Line plus column\r
+        MOV DX,CRTCPort1        ; Index register\r
+        PUSH EAX\r
+        MOV AL,CRTCCurLo\r
+        OUT DX,AL               ; Index 0Fh for low byte\r
+        POP EAX\r
+        MOV DX,CRTCPort2        ; Data register\r
+        OUT DX,AL               ; Send Low byte out\r
+        SHR EAX,08              ; shift hi byte into AL\r
+        PUSH EAX\r
+        MOV DX,CRTCPort1\r
+        MOV AL,CRTCCurHi\r
+        OUT DX,AL               ; Index for High byte\r
+        POP EAX\r
+        MOV DX,CRTCPort2\r
+        OUT DX,AL               ; Send High byte out\r
+        RETN\r
+;\r
+;=============================================================================\r
+; SetXY:\r
+; Position VGA cursor (Text mode) to the X & Y position.\r
+; Also sets hardware CrntX and CrntY cursor position if\r
+; crnt job is assigned the real screen\r
+;=============================================================================\r
+\r
+NewX        EQU DWORD PTR [EBP+16]\r
+NewY        EQU DWORD PTR [EBP+12]\r
+\r
+PUBLIC __SetXY:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+\r
+        MOV ECX,NewX            ; Column\r
+        MOV EDX,NewY            ; Line\r
+        MOV [EBX+CrntX],ECX     ; This saves it in the VCB\r
+        MOV [EBX+CrntY],EDX     ;\r
+\r
+        CALL GetCrntJobNum      ;Leaves ptr to current JCB in EAX\r
+        CMP EAX, ddVidOwner\r
+        JNE GotoXYDone          ;If not on Active screen, skip it\r
+\r
+        MOV EAX,NewY            ;Setup to call HardXY\r
+        MOV EBX,NewX\r
+        CALL HardXY\r
+GotoXYDone:\r
+        XOR EAX,EAX             ;No Error\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 8\r
+\r
+;=============================================================================\r
+; GetXY:\r
+; Returns position of VGA cursor (Text mode X & Y position).\r
+; This appliies to the values for the caller's VCB\r
+;=============================================================================\r
+\r
+pXret       EQU DWORD PTR [EBP+16]\r
+pYret       EQU DWORD PTR [EBP+12]\r
+\r
+PUBLIC __GetXY:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, EAX\r
+\r
+        MOV EAX,[EBX+CrntX]     ; Column\r
+        MOV ESI,pXret\r
+        MOV [ESI], EAX\r
+        MOV EAX,[EBX+CrntY]     ; Line\r
+        MOV ESI,pYret\r
+        MOV [ESI], EAX\r
+        XOR EAX,EAX\r
+QXYDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 8\r
+\r
+\r
+;=============================================================================\r
+; EditLine\r
+; Reads a line of text from the keyboard and puts it into the\r
+; specified string with full line editing features.\r
+;\r
+; EditLine(pStr, dCrntLen, dMaxLen, pdLenRet, pbExitChar): dError\r
+;\r
+; Param 1 is a NEAR Ptr to string to be edited\r
+; Param 2 is current length of string to edit (80 Max)\r
+; Param 3 is the max length the string can be (80 Max)\r
+; Param 4 is a NEAR Ptr to a DD where the length of the string is returned\r
+; Param 5 is a pointer to a Byte where the exit key from the edit\r
+;        operation is returned.\r
+; Param 6 is the editing attribute to use.\r
+;\r
+; Display and keyboard are handled entirely inside EditLine.\r
+; The following keys are recognized and handled inside, any other key\r
+; causes Editline to exit returning the string in it's current condition\r
+; and returning the key that caused the exit to pKeyRet:\r
+;\r
+; 08 (Backspace) move cursor to left replacing char with 20h\r
+;     which is a destructive backspace\r
+; 20-7E Hex places character in current position and advances position\r
+\r
+; Any other keystroke causes the edit line routine to be exited\r
+; with that keystroke returned to pExitKeyRet\r
+;\r
+;\r
+;=============================================================================\r
+\r
+pEdString       EQU DWORD PTR [EBP+32]\r
+ddSzCrnt        EQU DWORD PTR [EBP+28]\r
+ddSzMax         EQU DWORD PTR [EBP+24]\r
+pddSzRet        EQU DWORD PTR [EBP+20]\r
+pExitKeyRet     EQU DWORD PTR [EBP+16]\r
+dEditAttr       EQU DWORD PTR [EBP+12]\r
+\r
+;Local vars EditX and EditY hold position of first char of text\r
+;CrntX is the cursor postion\r
+;\r
+PosnX           EQU DWORD PTR [EBP-04]\r
+EditX           EQU DWORD PTR [EBP-08]\r
+EditY           EQU DWORD PTR [EBP-12]\r
+KeyCode         EQU DWORD PTR [EBP-16]\r
+\r
+PUBLIC __EditLine:\r
+        PUSH EBP                ;\r
+        MOV EBP,ESP             ;\r
+        SUB ESP, 16\r
+\r
+        CMP ddSzCrnt, 80     ;Is it currently too long?\r
+        JA BadEdit\r
+        CMP ddSzMax, 80      ;Is Max len to long?\r
+        JA BadEdit\r
+        MOV EAX, ddSzCrnt\r
+        CMP EAX, ddSzMax     ;Is Crnt len > Max???\r
+        JA BadEdit\r
+\r
+        LEA EAX, EditX          ;Get current cursor posns in local vars\r
+        PUSH EAX\r
+        LEA EAX, EditY\r
+        PUSH EAX\r
+        CALL FWORD PTR _GetXY\r
+        CMP EAX, 0\r
+        JNE EditDone         ;Bad Erc from call\r
+\r
+        MOV EAX, EditX\r
+        ADD EAX, ddSzCrnt\r
+        MOV PosnX, EAX       ;make PosnX end of string\r
+\r
+        MOV ECX, ddSzMax\r
+        SUB ECX, ddSzCrnt    ;ECX  how many bytes to zero\r
+        JZ  EdLn01           ;None to zero out\r
+        MOV ESI, pEdString   ;Initialize currrent string\r
+        ADD ESI, ddSzCrnt    ;ESI ptr to 1st empty byte\r
+        MOV AL, 20h          ;fill with spaces\r
+Edln00:\r
+        MOV [ESI], AL\r
+        INC ESI\r
+        LOOP Edln00\r
+\r
+EdLn01:\r
+        PUSH PosnX\r
+        PUSH EditY\r
+        CALL FWORD PTR _SetXY\r
+        CMP EAX, 0\r
+        JNE EditDone\r
+\r
+EdLn02:\r
+        PUSH EditX              ;Display current string\r
+        PUSH EditY\r
+        PUSH pEdString\r
+        PUSH ddSzMax\r
+        PUSH dEditAttr          ;Attribute they selected\r
+        CALL FWORD PTR _PutVidChars\r
+        CMP EAX, 0\r
+        JNE EditDone\r
+EdLn03:\r
+        LEA EAX, KeyCode\r
+        PUSH EAX\r
+        CMP ddVidOwner, 2       ;Debugger???\r
+        JE EdLn035\r
+        PUSH 1                  ;Wait for a key\r
+        CALL FWORD PTR _ReadKbd ;Get a key\r
+        JMP SHORT EdLn036\r
+EdLn035:\r
+        CALL ReadDbgKbd\r
+EdLn036:\r
+        MOV EAX, KeyCode\r
+        AND EAX, 07Fh\r
+        OR  EAX, EAX\r
+        JZ  EdLn03\r
+        CMP EAX, 08h            ;BackSpace?\r
+        JNE EdLn04              ;No - Next test\r
+EdLn037:\r
+        CMP ddSzCrnt, 0\r
+        JE EdLn01\r
+        DEC PosnX\r
+        DEC ddSzCrnt\r
+        MOV ESI, pEdString\r
+        MOV ECX, ddSzCrnt\r
+        MOV BYTE PTR [ESI+ECX], 20h\r
+        JMP Edln01\r
+EdLn04: CMP EAX, 03h            ;Left?\r
+        JNE EdLn045             ;No - Next test\r
+        JMP EdLn037\r
+EdLn045:\r
+        CMP EAX, 83h            ;Num-Left?\r
+        JNE EdLn046             ;No - Next test\r
+        JMP EdLn037\r
+EdLn046:\r
+        CMP EAX, 0Dh            ;CR?\r
+        JNE EdLn05              ;No - Next test\r
+        JMP EdLn07\r
+EdLn05: CMP EAX, 1Bh            ;Escape?\r
+        JNE EdLn06              ;No - Next test\r
+        JMP EdLn07\r
+EdLn06:\r
+        CMP EAX, 7Eh            ;Is it above text?\r
+        JA  EdLn07              ;Yes, Exit!\r
+        CMP EAX, 20h            ;Is it below text??\r
+        JB  EdLn07              ;Yes, Exit\r
+        MOV ESI, pEdString      ;It's really a char!\r
+        MOV ECX, ddSzCrnt\r
+        MOV BYTE PTR [ESI+ECX], AL\r
+        MOV ECX, ddSzMax\r
+        CMP ddSzCrnt, ECX\r
+        JAE EdLn01\r
+        INC PosnX\r
+        INC ddSzCrnt\r
+        JMP EdLn01\r
+EdLn07:\r
+        MOV ESI,pExitKeyRet\r
+        MOV [ESI], AL\r
+        MOV ESI,pddSzRet\r
+        MOV EAX, ddSzCrnt\r
+        MOV [ESI], EAX\r
+\r
+        PUSH EditX              ;Display current string w/Norm Attrs\r
+        PUSH EditY\r
+        PUSH pEdString\r
+        PUSH ddSzMax\r
+        CALL GetpCrntJCB        ;Leaves ptr to current JCB in EAX\r
+        MOV EBX, [EAX+NormAttr]\r
+        PUSH EBX                ;Normal Attribute from JCB\r
+        CALL FWORD PTR _PutVidChars ;Ignore error (we are leaving anyway)\r
+        XOR EAX, EAX\r
+        JMP EditDone\r
+BadEdit:\r
+        MOV EAX, ErcEditParam\r
+EditDone:\r
+        MOV ESP,EBP             ;\r
+        POP EBP                 ;\r
+        RETF 24\r
+\r
+;===================== END OF MODULE ================\r