home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 8
/
CDASC08.ISO
/
VRAC
/
TVPROMPT.EXE
/
CRT.PKG
< prev
next >
Wrap
Text File
|
1992-04-09
|
5KB
|
128 lines
With Altslice,
Bit,
Doscall,
System;
package body CRT is
pragma all_checks(off);
-- Copyright 1992 Tom Moran
-- Note: we act as if the CRT had 100 lines at B800:0 .. B800:1FFF
-- The second 100 lines, interlaced with the first, come from
-- simply duplicating 0 .. 1FFF at 2000 .. 3FFF
-- N*80 mod 8192 = 0 => N=512
Number_Of_Different_Offsets:constant:=512;
subtype Line_Numbers is Integer range 0 .. Number_Of_Different_Offsets-1;
Line_At_Top : Line_Numbers := Line_Numbers'first;
Video_Ram_Segment: constant System.Word := 16#B800#;
Video_Ram_Length: constant := 16#4000#;
type Video_Ram_Addresses is range 0 .. Video_Ram_Length-1;
Odd_Bank_Offset : constant Video_Ram_Addresses := 16#2000#;
subtype Line_Addresses is Video_Ram_Addresses range 0 .. Odd_Bank_Offset-1;
Line_Address: array (Line_Numbers) of Line_Addresses;
procedure Scroll(New_Scan_Line: Full_Scan_Lines) is
Target:Line_Numbers;
begin
if Line_At_Top = Line_Numbers'last then
Line_At_Top:=Line_Numbers'first;
else
Line_At_Top:=Line_At_Top+1;
end if;
-- copy new line to bottom of screen
Target:=(Line_At_Top+Logical_Screen_Height-1) mod Line_Address'length;
-- a line may wrap in the middle from Line_Addresses'last to
-- to Line_Addresses'first.
-- If so, the odd bank copy of the tail will go at Odd_Bank_Offset,
-- which is exactly Line_Addresses'last+1, so it needn't wrap at all!
-- Unfortunately, the tail of the odd bank copy is supposed to wrap
-- from Video_Ram_Addresses'last to Video_Ram_Addresses'first, which
-- won't happen, so we'll have to copy it explicitly.
declare
Even,Odd:Full_Scan_Lines;
for Even
use at (Video_Ram_Segment,
System.Offset_type(Line_Address(Target)));
for Odd
use at (Video_Ram_Segment,
System.Offset_type(Line_Address(Target)+Odd_Bank_Offset));
begin
Even:=New_Scan_Line;
Odd:=New_Scan_Line;
end;
if Line_Address(Target) > Line_Addresses'last-Line_Width_In_Bytes+1 then
declare
Head_Length : constant Integer
:=Integer(Line_Addresses'last-Line_Address(Target)+1);
Tail_Length : constant Integer
:= Line_Width_In_Bytes-Head_Length;
Tail : constant X_Range:=New_Scan_Line'first+Head_Length;
begin
Altslice.Movmem(
Source => New_Scan_Line(Tail)'Address,
Destination => (Video_Ram_Segment,
System.Offset_Type(Video_Ram_Addresses'first)),
N_Bytes => System.Word(Tail_Length));
end;
end if;
-- line stored in video ram, now adjust 6845 Start Address register
declare
use System;
Status:System.Byte;
Word_Offset:constant Video_Ram_Addresses
:=Line_Address(Line_At_Top); -- /2;
begin
-- wait for out-of-vertical-retrace
loop
Bit.Inport(16#3DA#,Status);
exit when Status mod 16 < 8; -- exit when in vert retrace
end loop;
loop
Bit.Inport(16#3DA#,Status);
exit when Status mod 16 >= 8; -- exit when done vert retrace
end loop;
-- roll screen
Bit.Outport(16#3D4#,12);
Bit.Outport(16#3D5#,System.Byte(Word_Offset/256));
Bit.Outport(16#3D4#,13);
Bit.Outport(16#3D5#,System.Byte(Word_Offset mod 256));
end;
end Scroll;
procedure Open_White_Screen is -- put CGA in 640x200 monochrome mode
Regs : Doscall.Simple_Regs := (AX => 16#0006#, others => 0);
begin
Doscall.Simple_Int_Call(16#10#, Regs);
-- paint screen white
Altslice.Setmem(Destination => (Video_Ram_Segment,0),
Byte_Value => System.Byte(White),
N_Bytes => Video_Ram_Length);
end Open_White_Screen;
procedure Revert_To_Text is
Regs : Doscall.Simple_Regs := (AX => 16#0003#, others => 0);
begin
Doscall.Simple_Int_Call(16#10#, Regs);
end Revert_To_Text;
begin -- CRT
-- initialize Line_Address table
declare
type Big_Integers is
range 0 .. Line_Width_In_Bytes*Number_Of_Different_Offsets;
Offset:Big_Integers:=0;
begin
for I in Line_Address'range loop
Line_Address(I)
:=Line_Addresses(Offset mod Big_Integers(Line_Addresses'last+1));
Offset:=Offset+Line_Width_In_Bytes;
end loop;
end;
end CRT;