.module VDU .include "Text.asm" ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Vdu.Reset === ; ; Resets the VDU to its initial state. ; ;@doc:end ;------------------------------------------------------------------------------- Reset push af push hl ld hl,Lcd.WriteData ld (Text.PutMapWriteLcdIndirection+1),hl ld hl,$9D95-kb(2) ld de,(Memory.TotalAllocated) add hl,de ld (Vdu.Text.UserDefinableFont),hl ld d,h ld e,l inc de ld bc,kb(2)-1 ld (hl),0 ldir ld hl,(Vdu.Text.UserDefinableFont) ld de,8*' ' add hl,de ex de,hl ld hl,Resources.LargeFont ld bc,(128-' ')*8 ldir xor a ld (Text.GraphicalText),a ld (Text.BackgroundColour),a ld (Text.SpriteFontCharacter+6),a ld (Text.SpriteFontCharacter+7),a ld (Text.PageMode),a inc a ld (WriteToLcdEnabled),a ld a,127 ld (Text.ForegroundColour),a ld a,$C3 ld (Text.Clear),a ld (Text.GetBufferCharAddress),a ld (Text.PutMapNoWriteBuffer),a ld (Text.PutMap),a ld (Text.GetBufferPixelAddress),a ld (Text.Scroll.Up),a ld (Text.Scroll.Down),a ld (Text.Cursor.Up),a ld (Text.Cursor.Down),a ld (Text.Cursor.Left),a ld (Text.Cursor.Right),a ld (Text.Cursor.PutBlinking),a ld (Vdu.Text.Cursor.MoveToLeft),a call Vdu4 xor a call Text.Modes.Set pop hl pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Vdu.WriteSequence === ; ; Writes a sequence of bytes from memory to the VDU emulator. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to memory containing VDU sequence. ; * B - Number of bytes in sequence. ; ; DESTROYED: ; * HL, B, AF. ; ;@doc:end ;------------------------------------------------------------------------------- WriteSequence ld a,(hl) inc hl call WriteByte djnz WriteSequence ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Vdu.WriteByte === ; ; Puts a character onto the display and cursor buffer at the current cursor ; position, then increments the cursor position one place. ; Certain escape sequences are processed by this routine. ; ; INPUTS: ; REGISTERS ; * A - The character value to display. ; ; DESTROYED: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- WriteByte ld (CurrentByte),a ld a,(CommandQueue.Length) or a jp z,NoNeedTopUpVduQueue ; The VDU queue needs topping up! push hl push de ld l,a ld h,$FF ld de,CommandQueue+CommandQueue.MaxSize add hl,de ld a,(CurrentByte) ld (hl),a pop de pop hl ld a,(CommandQueue.Length) inc a ld (CommandQueue.Length),a ret nz ; Queue has been topped up, but it's still not complete. HandleVduCode ld a,(CommandQueue) cp 32 jr nc,DoneExecCommand push iy push ix push hl push de push bc add a,a ld l,a ld h,0 ld de,VduCodesJumpTable add hl,de ld e,(hl) inc hl ld d,(hl) ld hl,ExitVduCommand push hl push de \ ret ExitVduCommand pop bc pop de pop hl pop ix pop iy DoneExecCommand ret VduCodesJumpTable .dw Dud ; 0 NUL .dw Dud ; 1 Data -> Printer .dw Dud ; 2 Enable printer. .dw Dud ; 3 Disable printer. .dw Vdu4 ; 4 Write text at text cursor position. .dw Vdu5 ; 5 Write text at graphics cursor position. .dw Dud ; 6 Enable output to the screen. .dw Dud ; 7 BEL .dw Text.Cursor.Left ; 8 Move text cursor backwards one character. .dw Text.Cursor.Right ; 9 Move text cursor forwards one character. .dw Text.Cursor.Down ; 10 Move text cursor down a line. .dw Text.Cursor.Up ; 11 Move text cursor up a line. .dw Text.Clear ; 12 Clear the text area (CLS). .dw CharCR ; 13 Move text cursor to start of current line. .dw PageMode.On ; 14 Enable the auto-paging mode. .dw PageMode.Off ; 15 Disable the auto-paging mode. .dw ClearGraphics ; 16 Clear the graphics area (CLG). .dw Colour ; 17 Define a text colour (COLOUR). .dw GColour ; 18 Define a graphics colour (CGOL). .dw Dud ; 19 Select a colour palette. .dw ResetColours ; 20 Restore default logical colours. .dw Dud ; 21 Disable output to the screen. .dw SetMode ; 22 Set the screen mode (MODE). .dw UserDefinition ; 23 User-defined characters and screen modes. .dw SetGViewport ; 24 Define a graphics viewport. .dw Plot ; 25 PLOT .dw ResetViewports ; 26 Restore default viewports. .dw DirectOut ; 27 Send the next character to the screen. .dw SetTViewport ; 28 Define a text viewport. .dw SetGOrigin ; 29 Set the graphics origin. .dw HomeUp ; 30 Home the cursor to the top-left of the screen. .dw Tab ; 31 Move the text cursor (TAB(x,y)). Dud ret .function VDUQ(offset, commandLength) VDUQ = CommandQueue + offset + CommandQueue.MaxSize - commandLength .endfunction ; ======================================================================================== ; VDU 4 DRAW TEXT AT TEXT CURSOR ; ======================================================================================== Vdu4 ld hl,(Text.4.PutMapNoWriteBuffer) ld (Text.PutMapNoWritebuffer+1),hl ld hl,(Text.4.PutMap) ld (Text.PutMap+1),hl ld hl,Text.Cursor.Up.Routine \ ld (Text.Cursor.Up+1),hl ld hl,Text.Cursor.Down.Routine \ ld (Text.Cursor.Down+1),hl ld hl,Text.Cursor.Left.Routine \ ld (Text.Cursor.Left+1),hl ld hl,Text.Cursor.Right.Routine \ ld (Text.Cursor.Right+1),hl ld hl,Text.Cursor.PutBlinking.Routine \ ld (Text.Cursor.PutBlinking+1),hl ld hl,Text.Cursor.MoveToLeft.Routine \ ld (Vdu.Text.Cursor.MoveToLeft+1),hl xor a - ld (Text.GraphicalText),a ret ; ======================================================================================== ; VDU 5 DRAW TEXT AT GRAPHICS CURSOR ; ======================================================================================== Vdu5 ld hl,Text.Graphical.PutMap.Routine ld (Text.PutMapNoWritebuffer+1),hl ld (Text.PutMap+1),hl ld hl,Text.Graphical.Cursor.Up.Routine \ ld (Text.Cursor.Up+1),hl ld hl,Text.Graphical.Cursor.Down.Routine \ ld (Text.Cursor.Down+1),hl ld hl,Text.Graphical.Cursor.Left.Routine \ ld (Text.Cursor.Left+1),hl ld hl,Text.Graphical.Cursor.Right.Routine \ ld (Text.Cursor.Right+1),hl ld hl,Text.Graphical.Cursor.PutBlinking.Routine \ ld (Text.Cursor.PutBlinking+1),hl ld hl,Text.Graphical.Cursor.MoveToLeft.Routine \ ld (Vdu.Text.Cursor.MoveToLeft+1),hl ld a,$FF jr - ; ======================================================================================== ; VDU 13 CARRIAGE RETURN ; ======================================================================================== CharCR = Text.Cursor.MoveToLeft ; ======================================================================================== ; VDU 14 ENABLE AUTO-PAGING MODE ; ======================================================================================== PageMode.On ld a,-1 ld (Text.PageMode),a xor a ld (Text.Page.LinesOutput),a ret ; ======================================================================================== ; VDU 15 DISABLE AUTO-PAGING MODE ; ======================================================================================== PageMode.Off xor a ld (Text.PageMode),a ret ; ======================================================================================== ; VDU 16 CLEAR GRAPHICS VIEWPORT ; ======================================================================================== ClearGraphics .fcall "Graphics.Clear" ret ; ======================================================================================== ; VDU 17, SET TEXT COLOUR ; ======================================================================================== Colour ld a,(VDUQ(0,1)) bit 7,a jr nz,+ add a,a add a,a add a,a cpl and $7F ld (Text.ForegroundColour),a ret + add a,a add a,a add a,a cpl and $7F ld (Text.BackgroundColour),a ret ; ======================================================================================== ; VDU 18,, SET GRAPHICS COLOUR ; ======================================================================================== GColour ld a,(VDUQ(0,2)) ld (Graphics.PlotMode),a ld a,(VDUQ(1,2)) bit 7,a jr nz,+ add a,a add a,a add a,a cpl and $7F ld (Graphics.ForegroundColour),a jr ++ + add a,a add a,a add a,a cpl and $7F ld (Graphics.BackgroundColour),a ++ ld hl,0 ld (Graphics.CustomFill),hl ret ; ======================================================================================== ; VDU 20 RESET COLOURS ; ======================================================================================== ResetColours xor a ld (Graphics.PlotMode),a ld (Graphics.BackgroundColour),a ld (Text.BackgroundColour),a ld a,127 ld (Graphics.ForegroundColour),a ld (Text.ForegroundColour),a ld hl,0 ld (Graphics.CustomFill),hl ret ; ======================================================================================== ; VDU 22 SET MODE ; ======================================================================================== SetMode ld a,(VDUQ(0,1)) .fcall "Vdu.Text.Modes.Set" call ResetColours ; VDU 20 call ResetViewports ; VDU 26 call ClearGraphics ; VDU 16 call Vdu4 ; VDU 4 call Text.Clear ; VDU 12 ret ; ======================================================================================== ; VDU 23,,,..., USER DEFINITIONS ; ======================================================================================== UserDefinition ld a,(VDUQ(0,9)) cp 1 jr nz,NotCursorEnable ld a,(VDUQ(1,9)) or a jr nz,+ ld a,(VDUQ(2,9)) or a + ld a,(Text.StateFlags) jr z,+ or 1<;;;; SET GRAPHICS VIEWPORT ; ======================================================================================== SetGViewport ld hl,(VDUQ(0,8)) ld de,(Graphics.Origin.X) add hl,de .fcall "Graphics.ScaleX.HL" ld b,95 call ClampGViewport ld (Graphics.Bounds.MinX),a ld hl,(VDUQ(4,8)) ld de,(Graphics.Origin.X) add hl,de .fcall "Graphics.ScaleX.HL" ld b,95 call ClampGViewport ld (Graphics.Bounds.MaxX),a ld hl,(VDUQ(2,8)) ld de,(Graphics.Origin.Y) add hl,de .fcall "Graphics.ScaleY.HL" .fcall "Graphics.FlipY16" ld b,63 call ClampGViewport ld (Graphics.Bounds.MinY),a ld hl,(VDUQ(6,8)) ld de,(Graphics.Origin.Y) add hl,de .fcall "Graphics.ScaleY.HL" .fcall "Graphics.FlipY16" ld b,63 call ClampGViewport ld (Graphics.Bounds.MaxY),a ld a,(Graphics.Bounds.MinX) ; MinX ld b,a ld a,(Graphics.Bounds.MaxX) ; MaxX cp b jr nc,+ ld (Graphics.Bounds.MinX),a ld a,b ld (Graphics.Bounds.MaxX),a + ld a,(Graphics.Bounds.MinY) ld b,a ld a,(Graphics.Bounds.MaxY) cp b jr nc,+ ld (Graphics.Bounds.MinY),a ld a,b ld (Graphics.Bounds.MaxY),a + ret ClampGViewport ld a,h or a jr z,+ xor a bit 7,h ret nz ld a,95 ret + ld a,l cp b ; b = upper bound (inclusive). ret c ld a,b ret ; ======================================================================================== ; VDU 25,,;; PLOT ; ======================================================================================== Plot ld a,(VDUQ(0,5)) ld (Graphics.PlotShape),a ld de,0 ld b,d \ ld c,e bit 2,a jr nz,+ ld hl,(Graphics.VisitedPoints+0) ld de,(Graphics.Origin.X) or a sbc hl,de ld d,h ld e,l ld hl,(Graphics.VisitedPoints+2) ld bc,(Graphics.Origin.Y) or a sbc hl,bc ld b,h ld c,l + ld hl,(VDUQ(3,5)) add hl,bc push hl ld hl,(VDUQ(1,5)) add hl,de pop de ld (TempSP),sp ld sp,(TIOS.SP) .fcall "Graphics.VisitPoint" .fcall "Graphics.Plot" ld sp,(TempSP) ret ; ======================================================================================== ; VDU 26 RESET VIEWPORTS ; ======================================================================================== ResetViewports xor a ld (Graphics.Bounds+0),a ; XMin ld (Graphics.Bounds+2),a ; YMin ld (Text.Cursor.X),a ld (Text.Cursor.Y),a ld (Text.Bounds.MinX),a ld (Text.Bounds.MinY),a ld (Text.Page.LinesOutput),a ld a,95 ld (Graphics.Bounds+1),a ; XMax ld a,63 ld (Graphics.Bounds+3),a ; YMax ld a,(Text.Bounds.Abs.MaxX) ld (Text.Bounds.MaxX),a ld a,(Text.Bounds.Abs.MaxY) ld (Text.Bounds.MaxY),a ld hl,0 ld (Graphics.Origin.X),hl ld (Graphics.Origin.Y),hl ld hl,Graphics.VisitedPoints+0 ld de,Graphics.VisitedPoints+1 ld (hl),0 ld bc,Graphics.VisitedPoints.Size-1 ldir call Text.Scroll.ClearPending ret ; ======================================================================================== ; VDU 27, PRINT ESCAPE CHARACTER ; ======================================================================================== DirectOut ld a,(VDUQ(0,1)) jp AbsolutelyNotEscapeCode ; ======================================================================================== ; VDU 28,,,, SET TEXT VIEWPORT ; ======================================================================================== SetTViewport call Text.Scroll.ClearPending xor a ld (Text.Page.LinesOutput),a ld a,(Text.Bounds.Abs.MaxX) ld b,a ld a,(VDUQ(0,4)) call ClampTViewport ld c,a ld (Text.Bounds.MinX),a ld d,a ld a,(Text.Bounds.Abs.MaxX) ld b,a ld a,(VDUQ(2,4)) call ClampTViewport cp c jr nc,+ ld a,c + ld (Text.Bounds.MaxX),a ld e,a ld a,(Text.Bounds.Abs.MaxY) ld b,a ld a,(VDUQ(3,4)) call ClampTViewport ld c,a ld (Text.Bounds.MinY),a ld h,a ld a,(Text.Bounds.Abs.MaxY) ld b,a ld a,(VDUQ(1,4)) call ClampTViewport cp c jr nc,+ ld a,c + ld (Text.Bounds.MaxY),a ld l,a ; Make sure the cursor is inside the text viewport. ld a,(Text.Cursor.X) cp d jr c,HomeUp cp e jr nc,HomeUp ld a,(Text.Cursor.Y) cp h jr c,HomeUp cp l jr nc,HomeUp ret ClampTViewport bit 7,a jr z,+ xor a ret + cp b ; b = upper bound (inclusive). ret c ld a,b ret ; ======================================================================================== ; VDU 29,;; SET GRAPHICS ORIGIN ; ======================================================================================== SetGOrigin ld hl,(VDUQ(0,4)) ld (Graphics.Origin.X),hl ld hl,(VDUQ(2,4)) ld (Graphics.Origin.Y),hl ret ; ======================================================================================== ; VDU 30 MOVE CURSOR TO TOP-LEFT ; ======================================================================================== HomeUp call Text.Scroll.ClearPending xor a ld (Text.Page.LinesOutput),a ld a,(Text.GraphicalText) or a jr z,HomeUp.Text push hl push de ld a,(Graphics.Bounds.MinY) .fcall "Graphics.FlipY8" ld e,a ld a,(Graphics.Scale.Y) .fcall "Maths.Mul.U8U8" push hl ld a,(Graphics.Bounds.MinX) ld e,a ld a,(Graphics.Scale.X) .fcall "Maths.Mul.U8U8" pop de .fcall "Graphics.VisitPointAbsolute" pop de pop hl ret HomeUp.Text ld a,(Text.Bounds.MinX) ld (Text.Cursor.X),a ld a,(Text.Bounds.MinY) ld (Text.Cursor.Y),a ret ; ======================================================================================== ; VDU 31,, MOVE CURSOR ; ======================================================================================== Tab call Text.Scroll.ClearPending ld a,(VDUQ(0,2)) ld e,a ld a,(Text.Bounds.MinX) dec a cp e jp pe,+ ld a,(Text.Bounds.MaxX) cp e jr c,+ ld a,e ld (Text.Cursor.X),a + ld a,(VDUQ(1,2)) ld l,a ld a,(Text.Bounds.MinY) dec a cp l jp pe,+ ld a,(Text.Bounds.MaxY) cp l jr c,+ ld a,l ld (Text.Cursor.Y),a + ret ; ======================================================================================== ; VDU 127 DELETE ; ======================================================================================== Delete call Text.Scroll.DisplayPending ld a,(Text.CopyKey.Enabled) or a call nz,Text.SwapCopyKeyCursorPosition call Text.Cursor.Left ld a,(Text.GraphicalText) or a jr z,Delete.Text Delete.Graphical call Text.Graphical.PutMap.Delete jr DeletedOld Delete.Text ld a,' ' call Text.PutMap DeletedOld ld a,(Text.CopyKey.Enabled) or a call nz,Text.SwapCopyKeyCursorPosition or a ret NoNeedTopUpVduQueue ld a,(CurrentByte) ld (CommandQueue),a ; Check for escape/control codes: cp 32 jp nc,NotEscapeCode cp 17 ; COLOUR jr z,OneByteEscape cp 22 ; MODE jr z,OneByteEscape cp 27 jr nz,NotOneByteEscape OneByteEscape ld a,-1 ld (CommandQueue.Length),a ret NotOneByteEscape cp 18 ; GCOL jr z,TwoByteEscape cp 31 ; TAB(x,y) jr nz,NotTwoByteEscape TwoByteEscape ld a,-2 ld (CommandQueue.Length),a ret NotTwoByteEscape cp 28 ; Text viewport jr z,FourByteEscape cp 29 ; Graphics origin jr nz,NotFourByteEscape FourByteEscape ld a,-4 ld (CommandQueue.Length),a ret NotFourByteEscape cp 19 ; Palette jr z,FiveByteEscape cp 25 ; PLOT jr nz,NotFiveByteEscape FiveByteEscape ld a,-5 ld (CommandQueue.Length),a ret NotFiveByteEscape cp 24 ; Viewport jr nz,NotEightByteEscape EightByteEscape ld a,-8 ld (CommandQueue.Length),a ret NotEightByteEscape cp 23 ; User definitions. jr nz,NotNineByteEscape NineByteEscape ld a,-9 ld (CommandQueue.Length),a ret NotNineByteEscape ; ! jp HandleVduCode NotEscapeCode ; Well, that was fairly uneventful. cp 127 jp z,Delete AbsolutelyNotEscapeCode call Text.Scroll.DisplayPending call Text.PutMap jp Text.Cursor.Right .endmodule