fpc/rtl/morphos/video.pp
Károly Balogh 7f0f0d4287 + added required units to compile IDE
they're a total mess ATM, under fixing/cleanup, but IDE start up at least

git-svn-id: trunk@6086 -
2007-01-20 00:27:08 +00:00

429 lines
11 KiB
ObjectPascal

{
This file is part of the Free Pascal run time library.
Copyright (c) 2006 by Karoly Balogh
member of the Free Pascal development team
Video unit for Amiga and MorphOS
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit Video;
interface
uses
intuition;
{$i videoh.inc}
var
videoWindow : pWindow;
implementation
uses
// dos
exec,graphics;
{$i video.inc}
{$i videodata.inc}
const
LastCursorType: word = crUnderline;
OrigScreen: PVideoBuf = nil;
OrigScreenSize: cardinal = 0;
var
videoColorMap : pColorMap;
videoPens : array[0..15] of longint;
oldCursorX, oldCursorY: longint;
visibleCursor: boolean;
oldvisibleCursor: boolean;
procedure SysInitVideo;
var counter: longint;
begin
writeln('sysinitvideo');
InitGraphicsLibrary;
InitIntuitionLibrary;
{
ScreenColor:=true;
GetConsoleScreenBufferInfo(TextRec(Output).Handle, OrigConsoleInfo);
GetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
OrigCP := GetConsoleCP;
ConsoleInfo:=OrigConsoleInfo;
ConsoleCursorInfo:=OrigConsoleCursorInfo;
{
About the ConsoleCursorInfo record: There are 3 possible
structures in it that can be regarded as the 'screen':
- dwsize : contains the cols & row in current screen buffer.
- srwindow : Coordinates (relative to buffer) of upper left
& lower right corners of visible console.
- dmMaximumWindowSize : Maximal size of Screen buffer.
The first implementation of video used srWindow. After some
bug-reports, this was switched to dwMaximumWindowSize.
}
with ConsoleInfo.dwMaximumWindowSize do
begin
ScreenWidth:=X;
ScreenHeight:=Y;
end;
{ TDrawBuffer only has FVMaxWidth elements
larger values lead to crashes }
if ScreenWidth> FVMaxWidth then
ScreenWidth:=FVMaxWidth;
CursorX:=ConsoleInfo.dwCursorPosition.x;
CursorY:=ConsoleInfo.dwCursorPosition.y;
if not ConsoleCursorInfo.bvisible then
CursorLines:=0
else
CursorLines:=ConsoleCursorInfo.dwSize;
}
videoWindow:=OpenWindowTags(Nil, [
WA_Left,50,
WA_Top,50,
WA_InnerWidth,80*8,
WA_InnerHeight,25*16,
// WA_IDCMP,IDCMP_MOUSEBUTTONS Or IDCMP_RAWKEYS,
WA_IDCMP,IDCMP_VANILLAKEY Or IDCMP_RAWKEY,
WA_Title,DWord(PChar('Free Pascal Video Output')),
WA_Flags,(WFLG_GIMMEZEROZERO Or WFLG_SMART_REFRESH Or WFLG_NOCAREREFRESH Or WFLG_ACTIVATE Or WFLG_DRAGBAR Or WFLG_DEPTHGADGET)
]);
ScreenWidth := 80;
ScreenHeight := 25;
videoColorMap := pScreen(videoWindow^.WScreen)^.ViewPort.ColorMap;
for counter:=0 to 15 do begin
videoPens[counter]:=ObtainPen(videoColorMap,-1,
vgacolors[counter,0] shl 24,vgacolors[counter,1] shl 24,vgacolors[counter,2] shl 24,
PEN_EXCLUSIVE);
// writeln(videoPens[counter]);
// XXX: do checks for -1 colors (KB)
end;
CursorX:=0;
CursorY:=0;
oldCursorX:=0;
oldCursorY:=0;
visibleCursor:=true;
oldvisibleCursor:=true;
end;
procedure SysDoneVideo;
var counter: longint;
begin
if videoWindow<>nil then CloseWindow(videoWindow);
for counter:=0 to 15 do ReleasePen(videoColorMap,videoPens[counter]);
{
SetConsoleScreenBufferSize (TextRec (Output).Handle, OrigConsoleInfo.dwSize);
SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, OrigConsoleInfo.srWindow);
SetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
SetConsoleCP(OrigCP);
}
end;
function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
{
var MI: Console_Screen_Buffer_Info;
C: Coord;
SR: Small_Rect;
}
begin
{
if not (GetConsoleScreenBufferInfo (TextRec (Output).Handle, MI)) then
SysVideoModeSelector := false
else
begin
with MI do
begin
C.X := VideoMode.Col;
C.Y := VideoMode.Row;
end;
with SR do
begin
Top := 0;
Left := 0;
{ First, we need to make sure we reach the minimum window size
to always fit in the new buffer after changing buffer size. }
Right := MI.srWindow.Right - MI.srWindow.Left;
if VideoMode.Col <= Right then
Right := Pred (VideoMode.Col);
Bottom := MI.srWindow.Bottom - MI.srWindow.Top;
if VideoMode.Row <= Bottom then
Bottom := Pred (VideoMode.Row);
end;
if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
if SetConsoleScreenBufferSize (TextRec (Output).Handle, C) then
begin
with SR do
begin
{ Now, we can resize the window to the final size. }
Right := Pred (VideoMode.Col);
Bottom := Pred (VideoMode.Row);
end;
if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
begin
SysVideoModeSelector := true;
SetCursorType (LastCursorType);
ClearScreen;
end
else
begin
SysVideoModeSelector := false;
SetConsoleScreenBufferSize (TextRec (Output).Handle, MI.dwSize);
SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
SetCursorType (LastCursorType);
end
end
else
begin
SysVideoModeSelector := false;
SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
SetCursorType (LastCursorType);
end
else
SysVideoModeSelector := false;
end;
}
end;
Const
SysVideoModeCount = 6;
SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
(Col: 40; Row: 25; Color: True),
(Col: 80; Row: 25; Color: True),
(Col: 80; Row: 30; Color: True),
(Col: 80; Row: 43; Color: True),
(Col: 80; Row: 50; Color: True),
(Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
);
Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
Var
I : Integer;
begin
{
I:=SysVideoModeCount-1;
SysSetVideoMode:=False;
While (I>=0) and Not SysSetVideoMode do
If (Mode.col=SysVMD[i].col) and
(Mode.Row=SysVMD[i].Row) and
(Mode.Color=SysVMD[i].Color) then
SysSetVideoMode:=True
else
Dec(I);
If SysSetVideoMode then
begin
if SysVideoModeSelector(Mode) then
begin
ScreenWidth:=SysVMD[I].Col;
ScreenHeight:=SysVMD[I].Row;
ScreenColor:=SysVMD[I].Color;
end else SysSetVideoMode := false;
end;
}
end;
Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
begin
SysGetVideoModeData:=(Index<=high(SysVMD));
If SysGetVideoModeData then
Data:=SysVMD[Index];
end;
Function SysGetVideoModeCount : Word;
begin
SysGetVideoModeCount:=SysVideoModeCount;
end;
procedure SysClearScreen;
begin
UpdateScreen(true);
end;
procedure DrawChar(x,y: longint; bitmap: pBitmap; drawCursor: boolean);
var tmpCharData: word;
tmpChar : byte;
tmpRow : byte;
tmpFGColor : byte;
tmpBGColor : byte;
var
counterX, counterY:longint;
sX,sY: longint;
begin
tmpCharData:=VideoBuf^[y*ScreenWidth+x];
tmpChar :=tmpCharData and $0ff;
tmpFGColor :=(tmpCharData shr 8) and %00001111;
tmpBGColor :=(tmpCharData shr 12) and %00000111;
// write('"',char(tmpChar),'" ',tmpChar);
sX:=x*8;
sY:=y*16;
SetAPen(videoWindow^.RPort,videoPens[tmpBGColor]);
RectFill(videoWindow^.RPort, sX, sY, sX + 7, sY + 15);
SetAPen(videoWindow^.Rport,videoPens[tmpFGColor]);
for counterY:=0 to 15 do begin
tmpRow:=vgafont[tmpChar,counterY];
if (tmpRow>0) then begin
for counterX:=0 to 7 do begin
if ((tmpRow and (1 shl counterX)) > 0) then
WritePixel(videoWindow^.RPort,sX+counterX,sY+counterY);
end;
end;
end;
if drawCursor then begin
gfxMove(videoWindow^.RPort,sX,sY+14); Draw(videoWindow^.RPort,sX+7,sY+14);
gfxMove(videoWindow^.RPort,sX,sY+15); Draw(videoWindow^.RPort,sX+7,sY+15);
end;
end;
procedure SysUpdateScreen(force: boolean);
var
BufCounter : Longint;
smallforce : boolean;
counter, counterX, counterY: longint;
var
tmpBitmap : tBitmap;
begin
if force then
smallforce:=true
else begin
counter:=0;
while not smallforce and (counter<(VideoBufSize div 4)-1) do begin
if PDWord(VideoBuf)[counter]<>PDWord(OldVideoBuf)[counter] then smallforce:=true;
counter+=1;
end;
end;
BufCounter:=0;
if smallforce then begin
for counterY:=0 to ScreenHeight-1 do begin
for counterX:=0 to ScreenWidth-1 do begin
if VideoBuf^[BufCounter]<>OldVideoBuf^[BufCounter] then
DrawChar(counterX,counterY,@tmpBitmap,false);
Inc(BufCounter);
end;
end;
move(VideoBuf^,OldVideoBuf^,VideoBufSize);
end;
if (oldvisibleCursor<>visibleCursor) or (CursorX<>oldCursorX) or (CursorY<>oldCursorY) then begin
writeln('kurzor:',cursorx,' ',cursory);
DrawChar(oldCursorY,oldCursorX,@tmpBitmap,false);
DrawChar(CursorY,CursorX,@tmpBitmap,visibleCursor);
oldCursorX:=CursorX;
oldCursorY:=CursorY;
oldVisibleCursor:=visibleCursor;
end;
end;
procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
begin
CursorX:=NewCursorY;
CursorY:=NewCursorX;
SysUpdateScreen(false);
end;
function SysGetCapabilities: Word;
begin
SysGetCapabilities:=cpColor or cpChangeCursor;
end;
function SysGetCursorType: Word;
begin
if not visibleCursor then SysGetCursorType:=crHidden
else SysGetCursorType:=crUnderline;
{
GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
if not ConsoleCursorInfo.bvisible then
SysGetCursorType:=crHidden
else
case ConsoleCursorInfo.dwSize of
1..30:
SysGetCursorType:=crUnderline;
31..70:
SysGetCursorType:=crHalfBlock;
71..100:
SysGetCursorType:=crBlock;
end;
}
end;
procedure SysSetCursorType(NewType: Word);
begin
if newType=crHidden then visibleCursor:=false
else visibleCursor:=true;
SysUpdateScreen(false);
{
GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
if newType=crHidden then
ConsoleCursorInfo.bvisible:=false
else
begin
ConsoleCursorInfo.bvisible:=true;
case NewType of
crUnderline:
ConsoleCursorInfo.dwSize:=10;
crHalfBlock:
ConsoleCursorInfo.dwSize:=50;
crBlock:
ConsoleCursorInfo.dwSize:=99;
end
end;
SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
}
end;
const
SysVideoDriver : TVideoDriver = (
InitDriver : @SysInitVideo;
DoneDriver : @SysDoneVideo;
UpdateScreen : @SysUpdateScreen;
ClearScreen : @SysClearScreen;
SetVideoMode : @SysSetVideoMode;
GetVideoModeCount : @SysGetVideoModeCount;
GetVideoModeData : @SysGetVideoModeData;
SetCursorPos : @SysSetCursorPos;
GetCursorType : @SysGetCursorType;
SetCursorType : @SysSetCursorType;
GetCapabilities : @SysGetCapabilities
);
initialization
SetVideoDriver(SysVideoDriver);
end.