.module Text .include "Text/Scroll.asm" .include "Text/Cursor.asm" .include "Text/Modes.asm" .include "Text/Graphical.asm" ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.PutHexWord === ; ; Puts a 16-bit word value onto the display as a four-character hex string. ; ; INPUTS: ; REGISTERS ; * HL - The value to display. ; ; DESTROYED: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- PutHexWord ld a,h call PutHexByte ld a,l ; Deliberate run-on! ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.PutHexByte === ; ; Puts an 8-bit byte value onto the display as a two-character hex string. ; ; INPUTS: ; REGISTERS ; * A - The value to display. ; ; DESTROYED: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- PutHexByte push af srl a srl a srl a srl a call PutHexNybble pop af and $0F ; Deliberate run-on! ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.PutHexNybble === ; ; Puts a 4-bit nybble value onto the display as a single-character hex string. ; ; INPUTS: ; REGISTERS ; * A - The value to display. ; ; DESTROYED: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- PutHexNybble cp 10 jr nc,+ add a,'0' jp Vdu.WriteByte + add a,'A'-10 jp Vdu.WriteByte ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.WritePrintableChar === ; ; Writes a printable character. Non-printable characters are ignored. ; ; INPUTS: ; REGISTERS ; * A - The character value to display. ; ; DESTROYED: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- WritePrintableChar cp 32 jp nc,Vdu.WriteByte ld a,' ' jp Vdu.WriteByte ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.WriteCharAscii === ; ; Puts a character onto the display using "ASCII" newlines (ie, \n translates ; to \n\r automatically). ; ; INPUTS: ; REGISTERS ; * A - The character value to display. ; ; DESTROYED: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- WriteCharAscii cp '\n' jp z,NewLine jp Vdu.WriteByte ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.WriteString === ; ; Writes a NUL-terminated string to the display at the current cursor position. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to NUL-terminated string to write. ; ; OUTPUTS: ; REGISTERS ; * HL - Pointer to the byte after the written string's NUL terminator. ; ; DESTROYED: ; REGISTERS ; * HL, AF ; ;@doc:end ;------------------------------------------------------------------------------- WriteString ld a,(hl) inc hl or a ret z call Vdu.WriteByte jr WriteString ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.WriteString === ; ; Writes a NUL-terminated string to the display at the current cursor position ; and moves down a line. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to NUL-terminated string to write. ; ; OUTPUTS: ; REGISTERS ; * HL - Pointer to the byte after the written string's NUL terminator. ; ; DESTROYED: ; REGISTERS ; * HL, AF ; ;@doc:end ;------------------------------------------------------------------------------- WriteStringNewLine call WriteString jp NewLine ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.ReadCharIntercept === ; ; Reads a character from the console, but do not output the result. ; ; OUTPUTS: ; REGISTERS ; * A - Value of the pressed character. ; * F - S is set if the key is an extended (non-printable) one. ; ;@doc:end ;------------------------------------------------------------------------------- ReadCharIntercept push hl .fcall "Speed.SlowDown" .fcall "Sleep.ResetIdleTimer" call Cursor.ResetBlink call BeforeCursorDraw - call Cursor.PutBlinking .fcall "Sleep.SleepIfIdle" .fcall "Keypad.GetChar" halt jr nz,- push af .fcall "Speed.SpeedUp" call AfterCursorDraw pop af pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.ReadChar === ; ; Reads a character from the console and outputs the result. ; ; OUTPUTS: ; REGISTERS ; * A - Value of the pressed character. ; * F - S is set if the key is an extended (non-printable) one. ; ;@doc:end ;------------------------------------------------------------------------------- ReadChar call ReadCharIntercept ret m push af cp '\b' call nz,WritePrintableChar pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.ReadLine === ; ; Reads a line of input text from the console. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to location to store the string. ; * B - Maximum length of the string including its NUL terminator. ; ;@doc:end ;------------------------------------------------------------------------------- ReadLine push af push bc push de push hl .fcall "Speed.SlowDown" xor a ld (CopyKey.Enabled),a ld (Page.LinesOutput),a dec b ld (hl),'\r' ld c,0 ReadLineLoop call ReadCharIntercept jr nc,NotEsc call DisableCopyKey .fcall "Speed.SpeedUp" pop hl pop de pop bc pop af scf jp NewLine NotEsc jp p,NotExtended cp Keycode.Up \ jr nz,NotCopyUp push bc call EnableCopyKey jr c,NotCopyUp.Disabled ld a,(Cursor.Y) or a jr nz,+ ld a,(Bounds.Abs.MaxY) inc a + dec a ld (Cursor.Y),a NotCopyUp.Disabled pop bc jp ReadLineLoop NotCopyUp cp Keycode.Down \ jr nz,NotCopyDown push bc call EnableCopyKey jr c,NotCopyDown.Disabled ld a,(Bounds.Abs.MaxY) ld b,a ld a,(Cursor.Y) cp b jr nz,+ ld a,-1 + inc a ld (Cursor.Y),a NotCopyDown.Disabled pop bc jp ReadLineLoop NotCopyDown cp Keycode.Left \ jr nz,NotCopyLeft push bc call EnableCopyKey jr c,NotCopyLeft.Disabled ld a,(Cursor.X) or a jr nz,+ ld a,(Bounds.Abs.MaxX) inc a + dec a ld (Cursor.X),a NotCopyLeft.Disabled pop bc jp ReadLineLoop NotCopyLeft cp Keycode.Right \ jr nz,NotCopyRight push bc call EnableCopyKey jr c,NotCopyRight.Disabled ld a,(Bounds.Abs.MaxX) ld b,a ld a,(Cursor.X) cp b jr nz,+ ld a,-1 + inc a ld (Cursor.X),a NotCopyRight.Disabled pop bc jp ReadLineLoop NotCopyRight cp Keycode.Copy \ jr nz,NotCopy ld a,(CopyKey.Enabled) or a jp z,ReadLineLoop push bc push hl call GetBufferCharAddress xor a ld a,(hl) pop hl push af ld a,(Bounds.Abs.MaxX) inc a ld b,a ld a,(Bounds.Abs.MaxY) inc a ld c,a ld a,(Cursor.X) inc a ld (Cursor.X),a cp b jr nz,+ xor a ld (Cursor.X),a ld a,(Cursor.Y) inc a ld (Cursor.Y),a cp c jr nz,+ xor a ld (Cursor.Y),a + pop af pop bc jr NotExtended NotCopy jp ReadLineLoop NotExtended cp '\r' jr z,FinishedReadingLine cp 127 jr nz,NotBackspace ld a,c or a jp z,ReadLineLoop ; If copy-key editing is enabled, erase the 'write' cursor. ld a,(CopyKey.Enabled) or a jr z,+ call SwapCopyKeyCursorPosition ld a,' ' call PutMap call SwapCopyKeyCursorPosition + ld a,127 call Vdu.WriteByte ; If copy-key editing is enabled, redraw the 'write' cursor. ld a,(CopyKey.Enabled) or a jr z,+ call SwapCopyKeyCursorPosition ld a,127 call PutMapNoWriteBuffer call SwapCopyKeyCursorPosition + dec c inc b dec hl ld (hl),'\r' jp ReadLineLoop NotBackspace push af ld a,b or a jr nz,+ pop af jp ReadLineLoop + pop af push af ld a,(CopyKey.Enabled) or a call nz,SwapCopyKeyCursorPosition pop af push af call WritePrintableChar call Scroll.DisplayPending ld a,(CopyKey.Enabled) or a jr z,+ ld a,$7F call PutMapNoWriteBuffer call SwapCopyKeyCursorPosition + pop af ld (hl),a inc hl ld (hl),'\r' inc c dec b jp ReadLineLoop FinishedReadingLine call DisableCopyKey .fcall "Speed.SpeedUp" pop hl pop de pop bc pop af or a jp NewLine ; Internal function! EnableCopyKey ld a,(CopyKey.Enabled) or a ret nz ld a,(GraphicalText) or a jr z,+ scf ret + ld a,$7F call PutMap ld (CopyKey.Enabled),a ld a,(Cursor.X) ld (CopyKey.Cursor.X),a ld a,(Cursor.Y) ld (CopyKey.Cursor.Y),a or a ret DisableCopyKey ld a,(CopyKey.Enabled) or a ret z xor a ld (CopyKey.Enabled),a ld a,(CopyKey.Cursor.X) ld (Cursor.X),a ld a,(CopyKey.Cursor.Y) ld (Cursor.Y),a ld a,' ' call PutMap ret SwapCopyKeyCursorPosition push af ld a,(CopyKey.Cursor.X) push af ld a,(Cursor.X) \ ld (CopyKey.Cursor.X),a pop af ld (Cursor.X),a ld a,(CopyKey.Cursor.Y) push af ld a,(Cursor.Y) \ ld (CopyKey.Cursor.Y),a pop af ld (Cursor.Y),a pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.NewLine === ; ; Moves the cursor down a line and into the leftmost column. ; ;@doc:end ;------------------------------------------------------------------------------- NewLine push af ld a,'\n' call Vdu.WriteByte ld a,'\r' call Vdu.WriteByte pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Console.MakeColoursReadable === ; ; Ensures that text output by the console is readable (ie, no white-on-white ; or black-on-black text), enables WriteToLcd. ; ;@doc:end ;------------------------------------------------------------------------------- MakeColoursReadable push af ld a,-1 ld (WriteToLcdEnabled),a ld a,(ForegroundColour) or a ld a,(BackgroundColour) jr z,+ ; Foreground is black or a jr z,FixedColours xor a ld (ForegroundColour),a jr FixedColours + ; Background is black or a jr nz,FixedColours ld a,127 ld (ForegroundColour),a FixedColours pop af ret BeforeCursorDraw push af push hl push de push bc push ix call GetBufferPixelAddress ld de,12 ld ix,DataUnderCursor ld b,8 - ld a,(hl) ld (ix),a add hl,de inc ix djnz - pop ix pop bc pop de pop hl pop af ret AfterCursorDraw push af push hl push de push bc push ix push iy ld iy,WriteToLcdEnabled call GetBufferPixelAddress ld de,12 ld ix,DataUnderCursor ld b,8 - ld a,(ix) ld (hl),a bit 0,(iy+0) call nz,Lcd.WriteData add hl,de inc ix djnz - pop iy pop ix pop bc pop de pop hl pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Text.Scroll.DisplayPending === ; ; If a scroll is pending, scroll and clear the flag. ; ;@doc:end ;------------------------------------------------------------------------------- Scroll.DisplayPending push af ld a,(Text.StateFlags) bit Text.State.PendingScroll,a res Text.State.PendingScroll,a ld (Text.StateFlags),a call nz,Text.Scroll.Up pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Text.Scroll.ClearPending === ; ; Clear the scroll pending flag. ; ;@doc:end ;------------------------------------------------------------------------------- Scroll.ClearPending push af ld a,(Text.StateFlags) res Text.State.PendingScroll,a ld (Text.StateFlags),a pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === ATimes96 === ; ; Multiples A by 96. ; ; INPUTS: ; REGISTERS ; * A - Value to multiply by 96. ; ; OUPTUTS: ; REGISTERS ; * HL - A * 96 ; ; DESTROYED: ; REGISTERS ; * DE. ; ;@doc:end ;------------------------------------------------------------------------------- ATimes96 ld l,0 ld h,a srl h \ rr l ; * 128 srl h \ rr l ; * 64 ld d,h \ ld e,l srl h \ rr l ; * 32 add hl,de ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === ATimes72 === ; ; Multiples A by 72. ; ; INPUTS: ; REGISTERS ; * A - Value to multiply by 72. Must be smaller than 32. ; ; OUPTUTS: ; REGISTERS ; * HL - A * 72 ; ; DESTROYED: ; REGISTERS ; * DE. ; ;@doc:end ;------------------------------------------------------------------------------- ATimes72 ld l,0 ld h,a srl h \ rr l ; * 128 srl h \ rr l ; * 64 add a,a add a,a add a,a ld d,0 \ ld e,a add hl,de ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === ATimes12 === ; ; Multiples A by 24. ; ; INPUTS: ; REGISTERS ; * A - Value to multiply by 24. ; ; OUPTUTS: ; REGISTERS ; * HL - A * 24 ; ; DESTROYED: ; REGISTERS ; * DE. ; ;@doc:end ;------------------------------------------------------------------------------- ATimes24 ld h,0 ld l,a add hl,hl add hl,hl ld d,h \ ld e,l add hl,hl add hl,de add hl,hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === ATimes12 === ; ; Multiples A by 12. ; ; INPUTS: ; REGISTERS ; * A - Value to multiply by 12. ; ; OUPTUTS: ; REGISTERS ; * HL - A * 12 ; ; DESTROYED: ; REGISTERS ; * DE. ; ;@doc:end ;------------------------------------------------------------------------------- ATimes12 ld h,0 ld l,a add hl,hl add hl,hl ld d,h \ ld e,l add hl,hl add hl,de ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Vdu.Text.AlignToFieldWidth === ; ; Align the cursor to the current field width by printing spaces. ; ; INPUTS: ; MEMORY ; * STAVAR+0 - Field width. ; * COUNT - Number of characters output on the current line. ; ; DESTROYED: ; REGISTERS ; * AF, BC. ; ;@doc:end ;------------------------------------------------------------------------------- AlignToFieldWidth ld a,(Basic.BBCBASIC_STAVAR+0) ld b,a ; Deliberate run-on. ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Vdu.Text.AlignToFieldWidth.Custom === ; ; Align the cursor to a custom field width by printing spaces. ; ; INPUTS: ; REGISTERS ; * B - Field width. ; MEMORY ; * COUNT - Number of characters output on the current line. ; ; DESTROYED: ; REGISTERS ; * AF, BC. ; ;@doc:end ;------------------------------------------------------------------------------- AlignToFieldWidth.Custom ld a,(Basic.BBCBASIC_COUNT) or a ret z ld c,a xor a ; A = next column to align to. ; B = field width. ; C = current value of COUNT. - cp c jr nc,+ add a,b jr - + ; A = column to align to. ld (Basic.BBCBASIC_COUNT),a sub c ret z ; We're already in that column! ld b,a - ld a,' ' .oscall "Vdu.WriteByte" djnz - ret .endmodule