* first working version of CRT unit

This commit is contained in:
carl 1998-07-01 15:52:21 +00:00
parent 3474cf1a60
commit c2f855fbb7

View File

@ -1,8 +1,7 @@
{ {
$Id$ $Id$
This file is part of the Free Pascal run time library. This file is part of the Free Pascal run time library.
Copyright (c) 1997 by Nils Sjoholm Copyright (c) 1998 by Nils Sjoholm
member of the Amiga RTL development team.
See the file COPYING.FPC, included in this distribution, See the file COPYING.FPC, included in this distribution,
for details about the copyright. for details about the copyright.
@ -14,90 +13,118 @@
**********************************************************************} **********************************************************************}
unit Crt; unit Crt;
Interface
INTERFACE Const
{ Controlling consts }
Flushing=false; {if true then don't buffer output}
ScreenWidth = 80;
ScreenHeight = 25;
const { CRT modes }
{ screen modes } BW40 = 0; { 40x25 B/W on Color Adapter }
bw40 = 0; CO40 = 1; { 40x25 Color on Color Adapter }
co40 = 1; BW80 = 2; { 80x25 B/W on Color Adapter }
bw80 = 2; CO80 = 3; { 80x25 Color on Color Adapter }
co80 = 3; Mono = 7; { 80x25 on Monochrome Adapter }
mono = 7; Font8x8 = 256; { Add-in for ROM font }
font8x8 = 256;
{ screen color, fore- and background } { Mode constants for 3.0 compatibility }
black = 0; C40 = CO40;
blue = 1; C80 = CO80;
green = 2;
cyan = 3;
red = 4;
magenta = 5;
brown = 6;
lightgray = 7;
{ only foreground } {
darkgray = 8; When using this color constants on the Amiga
lightblue = 9; you can bet that they don't work as expected.
lightgreen = 10; You never know what color the user has on
lightcyan = 11; his Amiga. Perhaps we should do a check of
lightred = 12; the number of bitplanes (for number of colors)
lightmagenta = 13;
yellow = 14;
white = 15;
{ blink flag } The normal 4 first pens for an Amiga are
blink = $80;
var 0 LightGrey
{ for compatibility } 1 Black
checkbreak,checkeof,checksnow : boolean; 2 White
3 Blue
{ works in another way than in TP } }
{ true: cursor is set with direct port access }
{ false: cursor is set with a bios call }
directvideo : boolean;
lastmode : word; { screen mode} { Foreground and background color constants }
textattr : byte; { current text attribute } Black = 1; { normal pen for amiga }
windmin : word; { upper right corner of the CRT window } Blue = 3; { windowborder color }
windmax : word; { lower left corner of the CRT window } Green = 15;
Cyan = 7;
Red = 4;
Magenta = 5;
Brown = 6;
LightGray = 0; { canvas color }
function keypressed : boolean; { Foreground color constants }
function readkey : char; DarkGray = 8;
procedure gotoxy(x,y : integer); LightBlue = 9;
procedure window(left,top,right,bottom : byte); LightGreen = 10;
procedure clrscr; LightCyan = 11;
procedure textcolor(color : byte); LightRed = 12;
procedure textbackground(color : byte); LightMagenta = 13;
procedure assigncrt(var f : text); Yellow = 14;
function wherex : integer; White = 2; { third color on amiga }
function wherey : integer;
procedure delline;
procedure delline(line : byte);
procedure clreol;
procedure insline;
procedure cursoron;
procedure cursoroff;
procedure cursorbig;
procedure lowvideo;
procedure highvideo;
procedure nosound;
procedure sound(hz : word);
procedure delay(ms : longint);
procedure textmode(mode : integer);
procedure normvideo;
implementation { Add-in for blinking }
Blink = 128;
{Other Defaults}
TextAttr : Byte = $07;
LastMode : Word = 3;
WindMin : Word = $0;
WindMax : Word = $184f;
var
{ CheckBreak have to make this one to a function for Amiga }
CheckEOF,
CheckSnow,
DirectVideo: Boolean;
Procedure AssignCrt(Var F: Text);
Function KeyPressed: Boolean;
Function ReadKey: Char;
Procedure TextMode(Mode: Integer);
Procedure Window(X1, Y1, X2, Y2: Integer);
Procedure GoToXy(X: Integer; Y: Integer);
Function WhereX: Integer;
Function WhereY: Integer;
Procedure ClrScr;
Procedure ClrEol;
Procedure InsLine;
Procedure DelLine;
Procedure TextColor(Color: Byte);
Procedure TextBackground(Color: Byte);
Procedure LowVideo;
Procedure HighVideo;
Procedure NormVideo;
Procedure Delay(DTime: Word);
Procedure Sound(Hz: Word);
Procedure NoSound;
{ Extra functions }
Procedure CursorOn;
Procedure CursorOff;
Function CheckBreak: Boolean;
Implementation
{
The definitions of TextRec and FileRec are in separate files.
}
{$i textrec.inc}
{$i filerec.inc}
Type Type
{$PACKRECORDS 4}
{ returned by Info(), must be on a 4 byte boundary }
pInfoData = ^tInfoData; pInfoData = ^tInfoData;
tInfoData = record tInfoData = packed record
id_NumSoftErrors : Longint; { number of soft errors on disk } id_NumSoftErrors : Longint; { number of soft errors on disk }
id_UnitNumber : Longint; { Which unit disk is (was) mounted on } id_UnitNumber : Longint; { Which unit disk is (was) mounted on }
id_DiskState : Longint; { See defines below } id_DiskState : Longint; { See defines below }
@ -112,7 +139,7 @@ Type
{ * List Node Structure. Each member in a list starts with a Node * } { * List Node Structure. Each member in a list starts with a Node * }
pNode = ^tNode; pNode = ^tNode;
tNode = Record tNode = packed Record
ln_Succ, { * Pointer to next (successor) * } ln_Succ, { * Pointer to next (successor) * }
ln_Pred : pNode; { * Pointer to previous (predecessor) * } ln_Pred : pNode; { * Pointer to previous (predecessor) * }
ln_Type : Byte; ln_Type : Byte;
@ -120,12 +147,10 @@ Type
ln_Name : PChar; { * ID string, null terminated * } ln_Name : PChar; { * ID string, null terminated * }
End; { * Note: Integer aligned * } End; { * Note: Integer aligned * }
{$PACKRECORDS NORMAL}
{ normal, full featured list } { normal, full featured list }
pList = ^tList; pList = ^tList;
tList = record tList = packed record
lh_Head : pNode; lh_Head : pNode;
lh_Tail : pNode; lh_Tail : pNode;
lh_TailPred : pNode; lh_TailPred : pNode;
@ -134,7 +159,7 @@ Type
end; end;
pMsgPort = ^tMsgPort; pMsgPort = ^tMsgPort;
tMsgPort = record tMsgPort = packed record
mp_Node : tNode; mp_Node : tNode;
mp_Flags : Byte; mp_Flags : Byte;
mp_SigBit : Byte; { signal bit number } mp_SigBit : Byte; { signal bit number }
@ -143,14 +168,14 @@ Type
end; end;
pMessage = ^tMessage; pMessage = ^tMessage;
tMessage = record tMessage = packed record
mn_Node : tNode; mn_Node : tNode;
mn_ReplyPort : pMsgPort; { message reply port } mn_ReplyPort : pMsgPort; { message reply port }
mn_Length : Word; { message len in bytes } mn_Length : Word; { message len in bytes }
end; end;
pIOStdReq = ^tIOStdReq; pIOStdReq = ^tIOStdReq;
tIOStdReq = record tIOStdReq = packed record
io_Message : tMessage; io_Message : tMessage;
io_Device : Pointer; { device node pointer } io_Device : Pointer; { device node pointer }
io_Unit : Pointer; { unit (driver private)} io_Unit : Pointer; { unit (driver private)}
@ -164,7 +189,7 @@ Type
end; end;
pIntuiMessage = ^tIntuiMessage; pIntuiMessage = ^tIntuiMessage;
tIntuiMessage = record tIntuiMessage = packed record
ExecMessage : tMessage; ExecMessage : tMessage;
Class_ : Longint; Class_ : Longint;
Code : Word; Code : Word;
@ -179,7 +204,7 @@ Type
end; end;
pWindow = ^tWindow; pWindow = ^tWindow;
tWindow = record tWindow = packed record
NextWindow : pWindow; { for the linked list in a screen } NextWindow : pWindow; { for the linked list in a screen }
LeftEdge, LeftEdge,
TopEdge : Integer; { screen dimensions of window } TopEdge : Integer; { screen dimensions of window }
@ -233,7 +258,7 @@ Type
pConUnit = ^tConUnit; pConUnit = ^tConUnit;
tConUnit = record tConUnit = packed record
cu_MP : tMsgPort; cu_MP : tMsgPort;
cu_Window : Pointer; { (WindowPtr) intuition window bound to this unit } cu_Window : Pointer; { (WindowPtr) intuition window bound to this unit }
cu_XCP : Integer; { character position } cu_XCP : Integer; { character position }
@ -279,23 +304,30 @@ const
CD_MAXX = 3; CD_MAXX = 3;
CD_MAXY = 4; CD_MAXY = 4;
CSI = chr($9b);
function AllocVec( size, reqm : Longint ): Pointer; Assembler; SIGBREAKF_CTRL_C = 4096;
asm
function AllocVec( size, reqm : Longint ): Pointer;
begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _ExecBase,A6
MOVE.L size,d0 MOVE.L size,d0
MOVE.L reqm,d1 MOVE.L reqm,d1
MOVE.L _ExecBase, A6
JSR -684(A6) JSR -684(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
MOVE.L d0,@RESULT
end;
end; end;
function DoPkt(ID : pMsgPort; function DoPkt(ID : pMsgPort;
Action, Param1, Param2, Action, Param1, Param2,
Param3, Param4, Param5 : Longint) : Longint; Assembler; Param3, Param4, Param5 : Longint) : Longint;
asm begin
asm
MOVEM.L d2/d3/d4/d5/d6/d7/a6,-(A7) MOVEM.L d2/d3/d4/d5/d6/d7/a6,-(A7)
MOVE.L _DOSBase,A6
MOVE.L ID,d1 MOVE.L ID,d1
MOVE.L Action,d2 MOVE.L Action,d2
MOVE.L Param1,d3 MOVE.L Param1,d3
@ -303,79 +335,116 @@ asm
MOVE.L Param3,d5 MOVE.L Param3,d5
MOVE.L Param4,d6 MOVE.L Param4,d6
MOVE.L Param5,d7 MOVE.L Param5,d7
MOVE.L _DOSBase,A6
JSR -240(A6) JSR -240(A6)
MOVEM.L (A7)+,d2/d3/d4/d5/d6/d7/a6 MOVEM.L (A7)+,d2/d3/d4/d5/d6/d7/a6
MOVE.L d0,@RESULT
end;
end; end;
procedure FreeVec( memory : Pointer ); Assembler; procedure FreeVec( memory : Pointer );
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _ExecBase,A6
MOVE.L memory,a1 MOVE.L memory,a1
MOVE.L _ExecBase,A6
JSR -690(A6) JSR -690(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
end;
end; end;
function GetConsoleTask : pMsgPort; Assembler; function GetConsoleTask : pMsgPort;
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _DOSBase,A6 MOVE.L _DOSBase,A6
JSR -510(A6) JSR -510(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
MOVE.L d0,@RESULT
end;
end; end;
function GetMsg(port : pMsgPort): pMessage; Assembler; function GetMsg(port : pMsgPort): pMessage;
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _ExecBase,A6
MOVE.L port,a0 MOVE.L port,a0
MOVE.L _ExecBase,A6
JSR -372(A6) JSR -372(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
MOVE.L d0,@RESULT
end;
end; end;
function ModifyIDCMP(window : pWindow; function ModifyIDCMP(window : pWindow;
IDCMPFlags : Longint) : Boolean; Assembler; IDCMPFlags : Longint) : Boolean;
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _IntuitionBase,A6
MOVE.L window,a0 MOVE.L window,a0
MOVE.L IDCMPFlags,d0 MOVE.L IDCMPFlags,d0
MOVE.L _IntuitionBase,A6
JSR -150(A6) JSR -150(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
TST.L d0 TST.L d0
SNE d0 bne @success
bra @end
@success:
move.b #1,d0
@end:
move.b d0,@RESULT
end;
end; end;
procedure ReplyMsg(mess : pMessage); Assembler; procedure ReplyMsg(mess : pMessage);
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _ExecBase,A6
MOVE.L mess,a1 MOVE.L mess,a1
MOVE.L _ExecBase,A6
JSR -378(A6) JSR -378(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
end;
end; end;
function WaitPort(port : pMsgPort): pMessage; Assembler; function WaitPort(port : pMsgPort): pMessage;
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _ExecBase,A6
MOVE.L port,a0 MOVE.L port,a0
MOVE.L _ExecBase,A6
JSR -384(A6) JSR -384(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
MOVE.L d0,@RESULT
end;
end; end;
procedure Delay_(ticks : Integer); Assembler; procedure Delay_(ticks : Longint);
asm begin
asm
MOVE.L A6,-(A7) MOVE.L A6,-(A7)
MOVE.L _DOSBase,A6
MOVE.L ticks,d1 MOVE.L ticks,d1
MOVE.L _DOSBase,A6
JSR -198(A6) JSR -198(A6)
MOVE.L (A7)+,A6 MOVE.L (A7)+,A6
end;
end; end;
function SetSignal(newSignals, signalMask : Longint) : Longint;
begin
asm
MOVE.L A6,-(A7)
MOVE.L newSignals,d0
MOVE.L signalMask,d1
MOVE.L _ExecBase,A6
JSR -306(A6)
MOVE.L (A7)+,A6
MOVE.L d0,@RESULT
end;
end;
function OpenInfo : pInfoData; function OpenInfo : pInfoData;
var var
@ -436,14 +505,14 @@ begin
ConData := pos + 1; ConData := pos + 1;
end; end;
function wherex : integer; function WhereX : integer;
begin begin
wherex := ConData(CD_CURRX); WhereX := ConData(CD_CURRX);
end; end;
function wherey : integer; function WhereY : integer;
begin begin
wherey := ConData(CD_CURRY); WhereY := ConData(CD_CURRY);
end; end;
function maxx : integer; function maxx : integer;
@ -456,7 +525,7 @@ begin
maxy := ConData(CD_MAXY); maxy := ConData(CD_MAXY);
end; end;
procedure gotoxy(x, y : integer); procedure GotoXY(x, y : integer);
var var
mx, my : integer; mx, my : integer;
begin begin
@ -469,20 +538,20 @@ begin
if y < 1 then y := wherey if y < 1 then y := wherey
else if y > my then y := my; else if y > my then y := my;
Write($9b, y, ';', x, 'H'); Write(CSI, y, ';', x, 'H');
end; end;
procedure cursoroff; procedure CursorOff;
begin begin
Write($9b,'0 p'); Write(CSI,'0 p');
end; end;
procedure cursoron; procedure CursorOn;
begin begin
Write($9b,'1 p'); Write(CSI,'1 p');
end; end;
procedure clrscr; procedure ClrScr;
begin begin
Write(Chr($0c)); Write(Chr($0c));
end; end;
@ -497,7 +566,7 @@ var
imsg : pIntuiMessage; imsg : pIntuiMessage;
msg : pMessage; msg : pMessage;
key : char; key : char;
idcmp, vanil : longint; idcmp, vanil : Longint;
begin begin
key := #0; key := #0;
info := OpenInfo; info := OpenInfo;
@ -516,7 +585,7 @@ begin
if (imsg^.Class_ = IDCMP_VANILLAKEY) or (imsg^.Class_ = IDCMP_RAWKEY) then key := char(imsg^.Code); if (imsg^.Class_ = IDCMP_VANILLAKEY) or (imsg^.Class_ = IDCMP_RAWKEY) then key := char(imsg^.Code);
ReplyMsg(pMessage(imsg)); ReplyMsg(pMessage(imsg));
until key <> char(0); until key <> #0;
repeat repeat
msg := GetMsg(win^.UserPort); msg := GetMsg(win^.UserPort);
@ -532,22 +601,60 @@ begin
ReadKey := key; ReadKey := key;
end; end;
procedure textcolor(fgpen : byte); function KeyPressed : Boolean;
const
IDCMP_VANILLAKEY = $00200000;
IDCMP_RAWKEY = $00000400;
var
info : pInfoData;
win : pWindow;
imsg : pIntuiMessage;
msg : pMessage;
idcmp, vanil : Longint;
ispressed : Boolean;
begin begin
Write($9b, '3', fgpen, 'm'); ispressed := False;
info := OpenInfo;
if info <> nil then begin
win := pWindow(pConUnit((pIoStdReq(info^.id_InUse))^.io_Unit)^.cu_Window);
idcmp := win^.IDCMPFlags;
vanil := IDCMP_VANILLAKEY or IDCMP_RAWKEY;
ModifyIDCMP(win, (idcmp or vanil));
msg := WaitPort(win^.UserPort);
imsg := pIntuiMessage(GetMsg(win^.UserPort));
if (imsg^.Class_ = IDCMP_VANILLAKEY) or (imsg^.Class_ = IDCMP_RAWKEY) then ispressed := true;
ReplyMsg(pMessage(imsg));
repeat
msg := GetMsg(win^.UserPort);
if msg <> nil then ReplyMsg(msg);
until msg = nil;
ModifyIDCMP(win, idcmp);
CloseInfo(info);
end;
KeyPressed := ispressed;
end; end;
procedure textbackground(bgpen : byte); procedure TextColor(color : byte);
begin begin
Write($9b, '4', bgpen, 'm'); Write(CSI, '3', color, 'm');
end; end;
function keypressed : boolean; procedure TextBackground(color : byte);
begin begin
keypressed := true; Write(CSI, '4', color, 'm');
end; end;
procedure window(left,top,right,bottom : byte); procedure window(X1,Y1,X2,Y2 : Integer);
begin begin
end; end;
@ -555,24 +662,19 @@ procedure assigncrt(var f : text);
begin begin
end; end;
procedure delline; procedure DelLine;
begin begin
Write($9b,'X'); Write(CSI,'X');
end; end;
procedure delline(line : byte); procedure ClrEol;
begin begin
Write($9b,'X'); Write(CSI,'K');
end; end;
procedure clreol; procedure InsLine;
begin begin
Write($9b,'K'); Write(CSI,'1 L');
end;
procedure insline;
begin
Write($9b,'1 L');
end; end;
procedure cursorbig; procedure cursorbig;
@ -595,22 +697,22 @@ procedure sound(hz : word);
begin begin
end; end;
{ MsDos have 1000 ticks per second procedure delay(DTime : Word);
and Amiga only 50, so we have to
do some calcs here.
The min value this procedure will
handle is 20, (less you will get 0)
this will be 1 tick in Amiga. If
you want to use amigados delay just
use Delay_. }
procedure delay(ms : longint);
var var
dummy : integer; dummy : Longint;
begin begin
dummy := trunc((real(ms) / 1000.0) * 50.0); dummy := trunc((real(DTime) / 1000.0) * 50.0);
Delay_(dummy); Delay_(dummy);
end; end;
function CheckBreak : boolean;
begin
if (SetSignal(0, 0) and SIGBREAKF_CTRL_C) = SIGBREAKF_CTRL_C then
CheckBreak := true
else
CheckBreak := false;
end;
procedure textmode(mode : integer); procedure textmode(mode : integer);
begin begin
end; end;