home *** CD-ROM | disk | FTP | other *** search
- { FD> Hey Greg, do you think you could tell me how to access
- FD> Mode-X, preferably the source, if it's no trouble.... :)
-
- not a problem.... Mostly I do Graphics and stuff With C, but when it all comes
- down to it, whether you use Pascal or C For the outer shell the main Graphics
- routines are in Assembler (For speed) or use direct hardware port access
- (again, For speed).
- The following is a demo of using palette scrolling techniques in Mode 13h (X)
- to produce a flashy "bouncing bars" effect often seen in demos:
- }
-
- Program PaletteTricks;
- { Speccy demo in mode 13h (320x200x256) }
-
- Uses Crt;
-
- Const CGA_CharSet_Seg = $0F000; { Location of BIOS CGA Character set }
- CGA_CharSet_ofs = $0FA6E;
- CharLength = 8; { Each Char is 8x8 bits, }
- NumChars = 256; { and there are 256 Chars }
- VGA_Segment = $0A000; { Start of VGA memory }
- NumCycles = 200; { Cycles/lines per screen }
- Radius = 80;
-
- DispStr : String = ' ...THIS IS A LITTLE '+
- 'SCROLLY, DESIGNED to TEST SOME GROOVY PASCAL ROUTinES...'+
- ' ';
-
- { Colours For moving bars... Each bar is 15 pixels thick }
- { Three colours are palette entries For RGB values... }
- Colours : Array [1..15*3] of Byte =
- ( 7, 7, 63,
- 15, 15, 63,
- 23, 23, 63,
- 31, 31, 63,
- 39, 39, 63,
- 47, 47, 63,
- 55, 55, 63,
- 63, 63, 63,
- 55, 55, 63,
- 47, 47, 63,
- 39, 39, 63,
- 31, 31, 63,
- 23, 23, 63,
- 15, 15, 63,
- 7, 7, 63 );
-
-
- Type OneChar = Array [1..CharLength] of Byte;
-
- Var CharSet: Array [1..NumChars] of OneChar;
- Locs: Array [1..NumCycles] of Integer;
- BarLocs: Array [1..4] of Integer; { Location of each bar }
- CurrVert,
- Count: Integer;
- Key: Char;
- MemPos: Word;
-
- Procedure GetChars;
- { Read/copy BIOS Character set into Array }
- Var NumCounter,
- ByteCounter,
- MemCounter: Integer;
- begin
- MemCounter:=0;
- For NumCounter:=1 to NumChars do
- For ByteCounter:=1 to CharLength do
- begin
-
- CharSet[NumCounter][ByteCounter]:=Mem[CGA_CharSet_Seg:CGA_CharSet_ofs+MemCounter];
- inC(MemCounter);
- end;
- end;
-
-
- Procedure VideoMode ( Mode : Byte );
- { Set the video display mode }
- begin
- Asm
- MOV AH,00
- MOV AL,Mode
- inT 10h
- end;
- end;
-
-
- Procedure SetColor ( Color, Red, Green, Blue : Byte );
- { Update the colour palette, to define a new colour }
- begin
- Port[$3C8] := Color; { Colour number to redefine }
- Port[$3C9] := Red; { Red value of new colour }
- Port[$3C9] := Green; { Green " " " " }
- Port[$3C9] := Blue; { Blue " " " " }
- end;
-
-
- Procedure DispVert ( Var CurrLine : Integer );
- { Display next vertical 'chunk' of the Character onscreen }
- Var Letter: OneChar;
- VertLine,
- Count: Integer;
- begin
- { Calculate pixel position of start of letter: }
- Letter := CharSet[ord(DispStr[(CurrLine div 8)+1])+1];
- VertLine := (CurrLine-1) Mod 8;
-
- { Push the Character, pixel-by-pixel, to the screen: }
- For Count := 1 to 8 do
- if Letter[Count] and ($80 Shr VertLine) = 0
- then Mem[VGA_Segment:185*320+(Count-1)*320+319] := 0
- else Mem[VGa_Segment:185*320+(Count-1)*320+319] := 181;
- end;
-
- Procedure CalcLocs;
- { Calculate the location of the top of bars, based on sine curve }
- Var Count: Integer;
- begin
- For Count := 1 to NumCycles do
- Locs[Count] := Round(Radius*Sin((2*Pi/NumCycles)*Count))+Radius+1;
- end;
-
-
- Procedure DoCycle;
- { Display the bars on screen, by updating the palette entries to
- reflect the values from the COLOUR Array, or black For blank lines }
-
- Label Wait,Retr,BarLoop,PrevIsLast,Continue1,Continue2,Rep1,Rep2;
-
- begin
- Asm
- { First, wait For start of vertical retrace: }
- MOV DX,3DAh
- Wait: in AL,DX
- TEST AL,08h
- JZ Wait
- Retr: in AL,DX
- TEST AL,08h
- JNZ Retr
-
- { then do bars: }
- MOV BX,0
- BarLoop:
- PUSH BX
- MOV AX,Word PTR BarLocs[BX]
- MOV BX,AX
- DEC BX
- SHL BX,1
- MOV AX,Word PTR Locs[BX]
- PUSH AX
- CMP BX,0
- JE PrevIsLast
- DEC BX
- DEC BX
- MOV AX,Word PTR Locs[BX]
- JMP Continue1
-
- PrevIsLast:
- MOV AX,Word PTR Locs[(NumCycles-1)*2]
-
- Continue1:
- MOV DX,03C8h
- OUT DX,AL
- inC DX
- MOV CX,15*3
- MOV AL,0
- Rep1:
- OUT DX,AL
- LOOP Rep1
-
- DEC DX
- POP AX
- OUT DX,AL
- inC DX
- MOV CX,15*3
- xor BX,BX
- Rep2:
- MOV AL,Byte Ptr Colours[BX]
- OUT DX,AL
- inC BX
- LOOP Rep2
-
- POP BX
- inC Word PTR BarLocs[BX]
- CMP Word PTR BarLocs[BX],NumCycles
- JNG Continue2
-
- MOV Word PTR BarLocs[BX],1
- Continue2:
- inC BX
- inC BX
- CMP BX,8
- JNE BarLoop
-
- end;
- end;
-
-
- begin
-
- VideoMode($13); { Set video mode 320x200x256 }
- Port[$3C8] := 1; { Write palette table entry }
- For Count := 1 to 180 do { Black out the first 180 colours, }
- SetColor(Count,0,0,0); { one colour will be used per line }
-
- { Now colour each scan line using the given palette colour: }
- MemPos := 0;
- For Count := 1 to 180 do
- begin
- FillChar(Mem[VGA_Segment:MemPos],320,Chr(Count));
- MemPos := MemPos + 320;
- end;
-
- SetColor(181,63,63,0);
- CalcLocs;
- For Count := 1 to 4 do
- BarLocs[Count] := Count*10;
-
- GetChars;
- CurrVert := 1;
- Repeat
- DoCycle;
- For Count := 1 to 8 do
- Move(Mem[VGA_Segment:185*320+(Count-1)*320+1],
- Mem[VGA_Segment:185*320+(Count-1)*320],319);
- DispVert(CurrVert);
- inC(CurrVert);
- if CurrVert > Length(DispStr) * 8
- then CurrVert := 1;
-
- Until KeyPressed; { Repeat Until a key is pressed... }
-
- Key := ReadKey; { Absorb the key pressed }
- VideoMode(3); { Reset video mode back to Textmode } end.
- end.