author | peter_k
<peter_k> 2005-06-23 08:43:56 UTC |
committer | peter_k
<peter_k> 2005-06-23 08:43:56 UTC |
parent | 2adaad73ecebffccefaca969459c4d1fb10ebd5a |
poprecog/record/Compile.txt | +6 | -0 |
poprecog/record/GRAPH13H.PAS | +1394 | -0 |
poprecog/record/M_XMS.PAS | +215 | -0 |
poprecog/record/READ.TXT | +36 | -0 |
poprecog/record/record.pas | +420 | -0 |
diff --git a/poprecog/record/Compile.txt b/poprecog/record/Compile.txt new file mode 100644 index 0000000..67b71d2 --- /dev/null +++ b/poprecog/record/Compile.txt @@ -0,0 +1,6 @@ +Before compiling set this : + +Target : Real mode +Options / Compiler : enable 286 instructions + +Mean file : record.pas \ No newline at end of file diff --git a/poprecog/record/GRAPH13H.PAS b/poprecog/record/GRAPH13H.PAS new file mode 100644 index 0000000..48721c2 --- /dev/null +++ b/poprecog/record/GRAPH13H.PAS @@ -0,0 +1,1394 @@ +UNIT GRAPH13H; + +{ +############################################ +Biblioteka do trybu 13h +(rozdzielczosc : 320 x 200 ; max. 256 r\xf3\xbfnych kolor\xf3w) + +Autor : Piotr Kochanek +WWW : www.pop2.princed.com.ar + +Obsluguje : +* Bufor Wirtualny +* Obrazki (mozliwosc ladowania z BMP) +* Palete kolorow +* Czcionke wbudowana w program +* Czcionke wczytywana z pliku +* Efekty graficzne (wygaszanie ekranu, rozjasnianie ekranu ird.) + +Wiekszosc procedur jest napisana obiektowo +############################################ +} + +INTERFACE + USES + CRT; + TYPE + { // Bufor } + TBufor + = ARRAY [0..63999] OF byte; + { // Obrazek } + TImage + = OBJECT + Use : Boolean; { Czy obrazek jest uzywany } + Width : Word; { Szerokosc obrazka } + Height : Word; { Wysokosc obrazka } + Size : Word; { Rozmiar obrazka } + Handler : ^TBufor; { Wskaznik do obrazka w pamieci } + { // Tworzy nowy obrazek } + PROCEDURE NewImage (x,y : word); + { // Kladzie piksel na obrazek } + PROCEDURE PutPix (x,y : integer ; c : byte); + { // Pobiera pixel z obrazka } + FUNCTION GetPix (x,y : integer ; c : byte) : byte; + { // Kopiuje inny obrazek } + PROCEDURE CopyImage (Image : TImage); + { // Rysuje obrazek na buforze } + PROCEDURE XY ( x,y : integer ); + { // Rysunek przezroczysty } + PROCEDURE XYV (X,Y : integer); + { // Rysuje obrazek na buforze ( kolor przezroczysty ) } + PROCEDURE XYT ( x,y : integer; TransparentColor : byte); + { // NIEUZYWANE } + FUNCTION LoadAFG (sciezka,nazwa : string) : Boolean; + { // Laduje plik BMP (mozna takze automatycznie ustawic palete tego pliku) } +{!!!}{ FUNCTION OldLoadBMP (sciezka : string) : Boolean;} + FUNCTION LoadBMP (FileName : string ; LoadPalette : Boolean) : Boolean; + { // Usuwa obrazek z pamieci } + PROCEDURE Unload; + END; + { // Czcionka } + TFontData + = ARRAY [0..255,0..15] OF byte; + TFont + = OBJECT + Use : Boolean; + Font : ^TFontData; + { // Laduje czcionke z pliku } + FUNCTION Load (NazwaPliku : string) : boolean; + { // Usuwa czionke z pamieci } + PROCEDURE Unload; + { // Kladzie pojedynczy znak } + PROCEDURE Ch (X,Y : Word ; Znak : Char ; Color, Shadow : Byte); + + PROCEDURE ChA (X,Y : Word ; Znak : Char ; Color, Shadow : Byte); + { // ??? } + PROCEDURE ColorChar (X,Y : Word ; Znak : Char ; Color,Shadow : Byte); + { // Podaje dlugosc danego znaku } + FUNCTION Weidth (Znak : Char) : Byte; + { // Podaje dlugosc danego tekstu } + FUNCTION StrLength (Tekst : String) : Word; + { // Wyswietla napis na buforze } + PROCEDURE XY (X,Y : Word ; Tekst : String ; C,S : Byte); + { // Wczytuje tekst od u\xbfytkownika } + FUNCTION Read (PolX,PolY : Integer ; Var Tekst : String ; Max,C,B : Byte) : String; + END; + { // Naglowek BMP } + THandleBMP + = RECORD + FType : Word; + FSize : Longint; + FReserved1 : Word; + FReserved2 : Word; + FFirstPixel : Longint; + FInfoSize : Longint; + FWidth : Longint; + FHeight : Longint; + FPlanes : Word; + FBitPerPixel : Word; + FCompression : Longint; + FImageSize : Longint; + FDPIWidth : Longint; + FDPIHeight : Longint; + FColorUsed : Longint; + FImportantColor : Longint; + END; + { // Palety } + TPalette + = ARRAY [0..255] OF + RECORD + R : Byte; + G : Byte; + B : Byte; + END; + TPaletteBMP + = ARRAY [0..255] OF + RECORD + B : Byte; + G : Byte; + R : Byte; + N : Byte; + END; +CONST + GetMaxX = 319; + GetMaxY = 199; +VAR + Screen : Pointer; + Bufor : ^TBufor; + DefaultPalette : TPalette; + Plik : File; + X : Word; + Y : Word; + I : Integer; + + { ### Glowne funkcje do wlanczania / wylanczania trybu 13h ### } + + { // Wlacz tryb 13h } + PROCEDURE Load13h; + { // Wylacz tryb 13h } + PROCEDURE Unload13h; + { // Aktualny tryb } + FUNCTION GetVideoMode : Byte; + { // Ustawia wybrany tryb } + PROCEDURE SetVideoMode( Mode : Byte ); + { // Ustawia Bufor } + PROCEDURE SetBufor (Adres : Pointer); + { // Funkcja wyprowadza adres aktualnie uzywanego buforu } + FUNCTION GetBufor : Pointer; + + { ### Obsluga palety w 13h ### } + + { // Zapisz aktualna palete } + PROCEDURE SavePalette (var Palette : TPalette); + { // Zaladuj palete } + PROCEDURE LoadPalette (Palette : TPalette); + { // ??? } + FUNCTION GetAverageColor(nr : byte) : byte; + { // Ustal kolor palety} + PROCEDURE SetColor(numer, r, g, b : byte); + { // Pobierz kolor palety } + PROCEDURE GetColors(numer : byte; var r, g, b : byte); + { // ??? } + FUNCTION GetColor(numer : byte ; color : char) : byte; + { // Znajduje kolor w aktualnej palecie najbardziej pasujacy do szukanego } + FUNCTION Color (r,g,b : byte) : byte; + + { ### Funkcje do obslugi pixeli ### } + + { // Rysuje pixel na buforze } + PROCEDURE PutPixel(x,y : integer ; c : byte); + { // Rysuje pixel na ekranie } + PROCEDURE FPutPixel(x,y : integer ; c : byte); + { // Pobiera pixel z buforu } + FUNCTION GetPixel(x,y : integer) : byte; + { // Pobiera pixel z ekranu } + FUNCTION FGetPixel(x,y : integer) : byte; + + { ### Figury geometryczne ### } + + { // Rysuje linie } + PROCEDURE Line (x1,y1,x2,y2 : word; c : byte); + { // Rysuje linie pozioma } + PROCEDURE LineAcross(x,y,leng : integer ; color : byte); + { // Rysuje linie pionowa } + PROCEDURE LineDown(x,y,leng : integer ; color : byte); + { // Rysuje prostokat } + PROCEDURE Rectangle(x1,y1,x2,y2 : integer ; color : byte); + { // Rysuje wypelniony prostokat } + PROCEDURE RectangleFilled(x1,y1,x2,y2 : integer ; color : byte); + { // Rysuje kolo } + PROCEDURE Circle(X,Y,R : Longint; color: Byte); + + { ### Obsluga czcionki systemowej ### } + + { ### Dodatkowe procedury do obrazkow ### } + + { // Laduje palete z pliku BMP } + PROCEDURE LoadBMPPalette (sciezka : string); + + { ### Przenoszenie bufora na ekran ### } + + { // Czeka na powrot pionowy } + PROCEDURE WaitForStopWriting; + { // Kopiuje bufor } + PROCEDURE CopyBufor (BuforIn,BuforOut : Pointer); + { // Kopiuje bufor na ekran usuwajac 'mruganie ekranu' } + PROCEDURE ShowBufor (BuforIn : Pointer); + { // Jezeli trwa powrot pionowy to wyswietla ekran } + PROCEDURE TryShowBufor (BuforIn : Pointer); + + { ### Efekty ### } + + { // Czysci bufor na wybrany kolor } + PROCEDURE Clr13h (color : byte); + { // Ustawia kolor czarnobialy } + PROCEDURE BlackWhite; + { // Odwraca kolory } + PROCEDURE RetreatColors; + { // Wygasza ekran } + PROCEDURE WygasEkran (przerwa : byte); + { // Rozjasnia ekran } + PROCEDURE RozjasnijEkran (paleta_k : TPalette ; przerwa : Byte); + { // Rozmazuje ekran } + PROCEDURE Blur; + + { ### Procedury pomocnicze ### } + + { // Zmienia palete bmp na rgb } + PROCEDURE PaletteBMPToRGB (PaletteBMP : TPaletteBMP ; Var Palette : TPalette); + { // Zmienia palete rgb na bmp } + PROCEDURE PaletteRGBtoBMP (Palette : TPalette ; Var PaletteBMP : TPaletteBMP); + +IMPLEMENTATION + +PROCEDURE SetBufor (Adres : Pointer); +BEGIN + Bufor := Adres; +END; + +FUNCTION GetBufor : Pointer; +BEGIN + GetBufor := Bufor; +END; + +FUNCTION GetVideoMode : Byte; +VAR + tempVMode : Byte; +BEGIN + ASM + mov ah,$0f + int $10 + mov tempvmode,al + END; + GetVideoMode := tempVMode; +END; + +PROCEDURE SetVideoMode( Mode : Byte ); +BEGIN + ASM + mov ah, Mode; + int $10 + END; +END; + +PROCEDURE Load13h; +BEGIN + ASM + mov ax, 13h; + int 10h; + END; + Clr13h (0); + SavePalette (DefaultPalette); +END; + +PROCEDURE Unload13h; +BEGIN + ASM + mov ax, 3h; + int 10h; + END; +END; + +PROCEDURE SavePalette (var Palette : TPalette); +VAR r,g,b : byte; +BEGIN + FOR x := 0 TO 255 DO + BEGIN + GetColors(x,r,g,b); + palette [x].r := r; + palette [x].g := g; + palette [x].b := b; + END; +END; + +PROCEDURE LoadPalette (Palette : TPalette); +BEGIN + FOR x := 0 TO 255 DO + BEGIN + SetColor(x,palette [x].r,palette [x].g,palette [x].b); + END; +END; + +FUNCTION GetAverageColor(nr : byte) : byte; +Var + r,g,b : byte; +BEGIN + GetColors(nr,r,g,b); + GetAverageColor := (r + g + b) div 3; +END; + +PROCEDURE SetColor(numer, r, g, b : byte); +BEGIN + port[$3c8] := numer; + port[$3c9] := r; + port[$3c9] := g; + port[$3c9] := b; +END; + +PROCEDURE GetColors(numer : byte; var r, g, b : byte); +BEGIN + port[$3c7] := numer; + r := port[$3c9]; + g := port[$3c9]; + b := port[$3c9]; +END; + +FUNCTION GetColor(numer : byte ; color : char) : byte; +var r,g,b : byte; +BEGIN + GetColors(numer,r,g,b); + IF color = 'r' THEN GetColor := r; + IF color = 'g' THEN GetColor := g; + IF color = 'b' THEN GetColor := b; +END; + +PROCEDURE PutPixel(x,y : integer ; c : byte); Assembler; +ASM + cmp x, 0 + jl @end + cmp y, 0 + jl @end + cmp x, 319 + jg @end + cmp y, 199 + jg @end + mov ax, y + mov di, ax + shl ax, 8 + shl di, 6 + add di, ax + add di, x + les ax, bufor {???} + mov al, c + mov byte ptr es:[di], al + @end: +END; +{ exit; + + IF (X <= GetMaxX) and (Y <= GetMaxY) and (X >= 0) and (Y >= 0) THEN + BUFOR^ [320 * y + x] := c; +END;} + +PROCEDURE FPutPixel(x,y : integer ; c : byte); assembler; +ASM + mov ax, $a000 + mov es, ax + + mov dx, y + mov di, x + xchg dh, dl + add di, dx + shr dx, 2 + add di, dx + + mov al, c + mov es:[di], al +END; + +FUNCTION GetPixel(x,y : integer) : byte; +BEGIN + GetPixel := BUFOR^[320 * y + x]; +END; + +FUNCTION FGetPixel(x,y : integer) : byte; assembler; +ASM + mov ax, $a000 + mov es, ax + + mov dx, y + mov di, x + xchg dh, dl + add di, dx + shr dx, 2 + add di, dx + + mov al, es:[di] +END; + +PROCEDURE Line (x1,y1,x2,y2 : word; c : byte); + +FUNCTION sgn(a:real):integer; +BEGIN + if a > 0 then sgn := +1; + if a < 0 then sgn := -1; + if a = 0 then sgn := 0; +END; + +VAR + s : real; + u,i,v,d1x,d1y,d2x,d2y,m,n : integer; +BEGIN + u := x2 - x1; + v := y2 - y1; + d1x := SGN (u); + d1y := SGN (v); + d2x := SGN (u); + d2y := 0; + m := ABS (u); + n := ABS (v); + IF M <= N then + BEGIN + d2x := 0 ; + d2y := SGN (v); + m := ABS (v); + n := ABS (u); + END; + s := INT (m / 2); + FOR i := 0 TO m DO + BEGIN + PutPixel (x1,y1,c); + s := s + n; + IF s >= m THEN + BEGIN + s := s - m; + x1 := x1 + d1x; + y1 := y1 + d1y; + END + ELSE + BEGIN + x1 := x1 + d2x; + y1 := y1 + d2y; + END; + END; +END; + +PROCEDURE lineacross(x,y,leng : integer ; color : byte); + BEGIN + FOR x := x to x + leng - 1 do PutPixel(x,y,color); + END; + +PROCEDURE linedown(x,y,leng : integer ; color : byte); + BEGIN + FOR y := y to y + leng - 1 do PutPixel(x,y,color); + END; + +PROCEDURE Rectangle(x1,y1,x2,y2 : integer ; color : byte); + BEGIN + FOR x := x1 to x2 do + BEGIN + PutPixel(x,y1,color); + PutPixel(x,y2,color); + END; + FOR y := y1 to y2 do + BEGIN + PutPixel(x1,y,color); + PutPixel(x2,y,color); + END; + END; + +PROCEDURE RectangleFilled(x1,y1,x2,y2 : integer ; color : byte); +BEGIN + FOR x := x1 to x2 do + FOR y := y1 to y2 do + PutPixel(x,y,color); +END; + +PROCEDURE Circle(X,Y,R : longint; color: byte); +Var Xl,Yl : LongInt; +BEGIN + IF R=0 THEN + BEGIN + PutPixel(X,Y,color); + Exit; + END; + Xl := 0; + Yl := R; + R := R*R+1; + Repeat + PutPixel(X+Xl,Y+Yl,color); + PutPixel(X-Xl,Y+Yl,color); + PutPixel(X+Xl,Y-Yl,color); + PutPixel(X-Xl,Y-Yl,color); + IF Xl*Xl+Yl*Yl >= R THEN Dec(Yl) + Else Inc(Xl); + Until Yl = 0; + PutPixel(X+Xl,Y+Yl,color); + PutPixel(X-Xl,Y+Yl,color); + PutPixel(X+Xl,Y-Yl,color); + PutPixel(X-Xl,Y-Yl,color); +END; + +{PROCEDURE kopiuj(BUFOR1,BUFOR2:pointer);assembler; +asm +push ds +mov cx, 16000 +lds si, BUFOR1 +les di, BUFOR2 +cld +db $F3, $66, $A5 +pop ds +end;} + +PROCEDURE WaitForStopWriting; Assembler; +ASM + mov dx, 3dah + @wait: + in al, dx + test al, 00001000b + jnz @wait + @end: + in al, dx + test al, 00001000b + jz @end +END; + + +PROCEDURE CopyBufor (BuforIn,BuforOut : Pointer);Assembler; +{var + p : pointer; +{ p := mem[$a000:0];} +{ IF (not UseBUFOR) THEN exit;} + +{ kopiuj (BUFOR,mem [$a000:0]); + Move(BUFOR^,mem[$a000:0],64000);} +ASM + push ds + lds si,buforin + les di,buforout + cld + mov cx,32000 + rep movsw + pop ds +END; + +PROCEDURE ShowBufor (BuforIn : Pointer); ASSEMBLER; +ASM + mov dx, 3dah + @wait: + in al, dx + test al, 00001000b + jnz @wait + @end: + in al, dx + test al, 00001000b + jz @end + + push ds + lds si,buforin + mov ax, $A000 + mov es, ax + mov di, 0 + cld + mov cx,32000 + rep movsw + pop ds +END; + +PROCEDURE TryShowBufor (BuforIn : Pointer); ASSEMBLER; +ASM + mov dx, 3dah +{ @wait:} + in al, dx + test al, 00001000b + {jnz}jz @exit +{ @end: + in al, dx + test al, 00001000b + jz @exit} + + push ds + lds si,buforin + mov ax, $A000 + mov es, ax + mov di, 0 + cld + mov cx,32000 + rep movsw + pop ds + + @exit: +END; + +FUNCTION TFont.Load (NazwaPliku : string) : boolean; +Begin + Load := False; + If (Use) then Unload; + + Assign (Plik,NazwaPliku); + {$I-} + Reset (Plik,1); + {$I+} + If (IOResult <> 0) then Exit; + New (Font); + BlockRead (Plik,Font^,SizeOf (Font^)); + Close (Plik); + + Use := True; + Load := True; +End; + +PROCEDURE TFont.Unload; +Begin + If (not Use) then Exit; + Dispose (Font); + Use := False; +End; + +PROCEDURE TFont.Ch (X,Y : Word ; Znak : Char ; Color, Shadow : Byte); +var + MaskaBitowa : Byte; + LicznikY : Byte; + LicznikBitow : Byte; +Begin + If (not Use) then exit; + For LicznikY := 0 to 15 do + Begin + MaskaBitowa := $80; { 80h = 10000000b } + For LicznikBitow := 7 downto 0 do + Begin + If ((Font^ [Ord (Znak),LicznikY] and MaskaBitowa) = MaskaBitowa) + then + Begin + If (Color <> Shadow) then + PutPixel (X + LicznikBitow + 1,Y + LicznikY + 1,Shadow); + PutPixel (X + LicznikBitow,Y + LicznikY,Color); + End; + MaskaBitowa := MaskaBitowa shr 1; + End; + End; +End; + +PROCEDURE TFont.ChA (X,Y : Word ; Znak : Char ; Color, Shadow : Byte); Assembler; +ASM + {czy czcionka jest zaladowana} + mov ax, use + cmp ax, 0 + jz @end + {glowna petla - od 15 do 0} + mov cx, 16 + @petla: + push cx + mov ax, 10000000b + mov cx, 8 + @petla2: + loop @petla2 + pop cx + loop @petla + {koniec procedury} + @end: +END; + +PROCEDURE TFont.ColorChar (X,Y : Word ; Znak : Char ; Color,Shadow : Byte); +var + MaskaBitowa : Byte; + LicznikY : Byte; + LicznikBitow : Byte; + ActualColor : Byte; +Begin + If (not Use) then exit; + ActualColor := Color; + For LicznikY := 0 to 15 do + Begin + MaskaBitowa := $80; { 80h = 10000000b } + For LicznikBitow := 7 downto 0 do + Begin + If ((Font^ [Ord (Znak),LicznikY] and MaskaBitowa) = MaskaBitowa) + then + Begin + If (Color <> Shadow) then + PutPixel (X + LicznikBitow + 1,Y + LicznikY + 1,Shadow); + PutPixel (X + LicznikBitow,Y + LicznikY,ActualColor); + End; + MaskaBitowa := MaskaBitowa shr 1; + End; + Dec (ActualColor); + End; +End; + +FUNCTION TFont.Weidth (Znak : Char) : Byte; +var + X,Y,Leng,MaskaBitowa : Byte; +Begin + Leng := 0; + For Y := 0 to 15 do + Begin + MaskaBitowa := $01; + For X := 0 to 7 do + Begin + If ((Font^ [Ord (Znak),Y] and MaskaBitowa) = MaskaBitowa) then + Begin + If (X > Leng) then Leng := X; + End; + MaskaBitowa := MaskaBitowa shl 1; + End; + End; + Weidth := Leng + 1; +End; + +FUNCTION TFont.StrLength (Tekst : String) : Word; +var + Licznik : Byte; + Dlugosc : Word; +Begin + Dlugosc := 0; + For licznik := 1 to length (Tekst) do + Begin + Inc (Dlugosc,Weidth (Tekst [licznik]) + 1); + If (Tekst [Licznik] = #32) then Inc (Dlugosc,2); + End; + StrLength := Dlugosc; +End; + +PROCEDURE TFont.XY (X,Y : Word ; Tekst : String ; C,S : Byte); +var + Licznik : Byte; +Begin + For Licznik := 1 to Length (Tekst) do + Begin + Ch (X,Y,Tekst [Licznik],C,S); + If (Tekst [Licznik] = #32) then Inc (X,2); + Inc (X,Weidth (Tekst [Licznik]) + 1); + End; +End; + +{!!! - procedura zostaje ze wzgledu na algorytm dzialania} +FUNCTION TFont.Read (PolX,PolY : Integer ; Var Tekst : String ; Max,C,B : Byte) : String; +VAR + Kl : Char; + Ilosc : Byte; + OldBufor : Pointer; +BEGIN + Ilosc := Length (Tekst); + OldBufor := GetBufor; + SetBufor (Screen); + RectangleFilled (PolX,PolY + 1,PolX + 2 + (Max * 8),PolY + 17,B); + REPEAT + RectangleFilled (PolX + 2 + StrLength (Tekst),PolY + 1,PolX + 2 + (Max * 8),PolY + 17,B); + XY (PolX + 2,PolY,Tekst,C,C); + If (Keypressed) then Kl := Readkey else Kl := #1; + If (Kl = #0) THEN Readkey + Else If (Kl = #8) THEN + BEGIN + IF (Ilosc > 0) THEN + BEGIN + delete(tekst,length(tekst),1); + dec(ilosc); + END; + END + ELSE + BEGIN + IF (ord(kl) < 32) or (ord(kl) > 255) THEN continue; + IF ilosc >= max THEN continue; + inc(ilosc); + tekst := tekst + kl; + END; + UNTIL (Kl = #13); + SetBufor (OldBufor); +END; + + { EFFECTS } + +PROCEDURE Clr13h (color : byte); Assembler; +ASM + les di, Bufor; + mov ah, color + mov al, ah + mov cx, 32000 + cld + rep stosw +END; + +PROCEDURE BlackWhite; +BEGIN + FOR x := 0 to 255 do + BEGIN + y := (GetColor(x,'r') + GetColor(x,'g') + GetColor(x,'b') div 3); + SetColor(x,y,y,y); + END; +END; + +PROCEDURE RetreatColors; +Var + r,g,b : byte; +BEGIN + FOR x := 0 to 255 do + BEGIN + GetColors(x,r,g,b); + r := not r; + g := not g; + b := not b; + SetColor(x,r,g,b); + END; +END; + + { ADDITIONAL PROCEDURES } + +{FUNCTION _Color (R,G,B : Byte) : Byte; +Var + licznik : byte; + roznica : word; + r2,g2,b2 : byte; + najlepsza_roznica : word; + najlepszy_kolor : byte; +BEGIN + ASM + mov najlepsza_roznica, 1000 + mov cx, 256 + @petla: + push cx + dec cx + + mov roznica, 0 + + mov dx, 3c7h + mov ax, cx + out dx, ax + mov dx, 3c9h + in al, dx + mov r2, al + in al, dx + mov g2, al + in al, dx + mov b2, al + + mov al, r + cmp al, r2 + jb @nextr + mov ax, roznica + xor bx, bx + mov bh, r + add ax, bx + xor bx, bx + mov bh, r2 + sub ax, bx + add roznica, ax + jmp @nextr2 + @nextr: + mov ax, roznica + xor bx, bx + mov bh, r2 + add ax, bx + xor bx, bx + mov bh, r + sub ax, bx + add roznica, ax + @nextr2: + + mov al, g + cmp al, g2 + jb @nextg + mov ax, roznica + xor bx, bx + mov bh, g + add ax, bx + xor bx, bx + mov bh, g2 + sub ax, bx + add roznica, ax + jmp @nextg2 + @nextg: + mov ax, roznica + xor bx, bx + mov bh, g2 + add ax, bx + xor bx, bx + mov bh, g + sub ax, bx + add roznica, ax + @nextg2: + + mov al, b + cmp al, b2 + jb @nextb + mov ax, roznica + xor bx, bx + mov bh, b + add ax, bx + xor bx, bx + mov bh, b2 + sub ax, bx + add roznica, ax + jmp @nextb2 + @nextb: + mov ax, roznica + xor bx, bx + mov bh, b2 + add ax, bx + xor bx, bx + mov bh, b + sub ax, bx + add roznica, ax + @nextb2: + + mov ax, roznica + cmp ax, najlepsza_roznica + jae @next + mov ax, roznica + mov najlepsza_roznica, ax + mov ax, cx + mov najlepszy_kolor, ah + @next: + + pop cx + dec cx + cmp cx, 0 + jne @petla + END; + _Color := najlepszy_kolor; +END;} + +FUNCTION Color (r,g,b : byte) : byte; +Var + licznik : byte; + roznica : word; + r2,g2,b2 : byte; + najlepsza_roznica : word; + najlepszy_kolor : byte; +BEGIN + najlepsza_roznica := 1000; + FOR licznik := 0 to 255 do + BEGIN + roznica := 0; + GetColors (licznik,r2,g2,b2); + IF (r >= r2) + THEN roznica := roznica + r - r2 + else roznica := roznica + r2 - r; + IF (g >= g2) + THEN roznica := roznica + g - g2 + else roznica := roznica + g2 - g; + IF (b >= b2) + THEN roznica := roznica + b - b2 + else roznica := roznica + b2 - b; + IF roznica < najlepsza_roznica THEN + BEGIN + najlepsza_roznica := roznica; + najlepszy_kolor := licznik; + END; + END; + Color := najlepszy_kolor; +END; + +(* EFEKTY GRAFICZNE *) + +PROCEDURE WygasEkran (przerwa : byte); +var licznik1,licznik2 : byte; + wzorzec : record + R,G,B :Byte; + END; +BEGIN + FOR licznik2 := 0 to 63 do + BEGIN + FOR licznik1 := 0 to 255 do + BEGIN + GetColors (licznik1,wzorzec.r,wzorzec.g,wzorzec.b); + IF (wzorzec.r > 0) THEN dec (wzorzec.r); + IF (wzorzec.g > 0) THEN dec (wzorzec.g); + IF (wzorzec.b > 0) THEN dec (wzorzec.b); + SetColor (licznik1,wzorzec.r,wzorzec.g,wzorzec.b); + END; + IF (przerwa <> 0) THEN Delay (przerwa); + END; +END; + +PROCEDURE RozjasnijEkran (paleta_k : TPalette ; przerwa : Byte); +VAR + licznik1, licznik2 : Byte; + wzorzec : record + R,G,B : Byte; + END; +BEGIN + FOR licznik2 := 0 to 63 do + BEGIN + FOR licznik1 := 0 to 255 do + BEGIN + GetColors (licznik1,wzorzec.r,wzorzec.g,wzorzec.b); + IF (wzorzec.r < paleta_k [licznik1].r) THEN Inc (wzorzec.r); + IF (wzorzec.g < paleta_k [licznik1].g) THEN Inc (wzorzec.g); + IF (wzorzec.b < paleta_k [licznik1].b) THEN Inc (wzorzec.b); + SetColor (licznik1,wzorzec.r,wzorzec.g,wzorzec.b); + END; + IF (przerwa <> 0) THEN delay (przerwa); + END; +END; + +{PROCEDURE Blur; +Begin + For x := 0 to 319 do + For y := 0 to 199 do + PutPixel (x,y,GetPixel (x - 1 + random (3),y - 1 + random (3))); +End;} + +PROCEDURE Blur; +VAR + c : integer; +BEGIN + for x:= 0 to 319 do + for y:= 0 to 198 do + begin + c:=(BUFOR^[320*y+x]+BUFOR^[320*(y+1)+x+1]+BUFOR^[320*y+1+x]+BUFOR^[320*(y+1)+x]) div 4; + BUFOR^[320*y+x]:=c; + end; +END; + +(* OBRAZY *) + +PROCEDURE TImage.NewImage (x,y : word); +Begin + If (Use) then Unload; + Size := x * y; + Width := x; + Height := y; + GetMem (Handler,Size); + For I := 0 to Size - 1 do Handler^ [I] := 0; +End; + +PROCEDURE TImage.PutPix (x,y : integer ; c : byte); +Begin + If (Use) and (x > 0) and (y > 0) and + (x < Width) and (y < Height) + then Handler^ [((y - 1) * Width) + (x - 1)] := C; +End; + +FUNCTION TImage.GetPix (x,y : integer ; c : byte) : byte; +Begin + If (Use) and (x > 0) and (y > 0) and + (x < Width) and (y < Height) + then GetPix := Handler^ [((y - 1) * Width) + (x - 1)] + else GetPix := 0; +End; + +PROCEDURE TImage.CopyImage (Image : TImage); +Var + W : Word; +Begin + If (not Image.Use) then Exit; + If (Use) then Unload; + GetMem (Handler,Image.Size); + Size := Image.Size; + Width := Image.Width; + Height := Image.Height; + For w := 0 to Size - 1 do Handler^ [w] := Image.Handler^ [w]; + Use := True; +End; + +FUNCTION TImage.LoadAFG (sciezka,nazwa : string) : Boolean; +VAR + plik : file; + nagl : record + typ : string [3]; + ver : string [3]; + images : word; + END; + fnagl : record + adres : longint; + nazwa : string [10]; + rozmiar : word; + szerokosc : word; + wysokosc : word; + END; +BEGIN + LoadAFG := false; + If (Use) then Unload; + assign (plik,sciezka); + {$I-} + reset (plik, 1); + {$I+} + IF (IOResult <> 0) THEN exit; + + BlockRead (plik, nagl, 10); + IF (nagl.typ <> 'AFG') or (nagl.ver <> '1.0') THEN + BEGIN + close (plik); + exit; + END; + + Repeat + BlockRead (plik,fnagl,sizeof (fnagl)); + Until (fnagl.nazwa = nazwa) or (FilePos (plik) - 1 >= (nagl.images * 21) + 10); + + IF (FilePos (plik) - 1 >= (nagl.images * 21) + 10) THEN + BEGIN + close (plik); + exit; + END; + + Getmem (Handler, fnagl.rozmiar); + Seek (plik,fnagl.adres); + + writeln (fnagl.rozmiar); + writeln (FilePos (plik)); + writeln (FileSize (plik)); + + Size := Fnagl.Rozmiar; + Width := Fnagl.Szerokosc; + Height := Fnagl.Wysokosc; + + BlockRead (plik,Handler^ [0],fnagl.rozmiar); + + close (plik); + Use := True; + LoadAFG := true; +END; + +{FUNCTION TImage.OldLoadBMP (sciezka : string) : Boolean; +VAR + plik : file; + naglowek : naglowek_BMP; + licznik, wynik : word; + licznik_odczytu : word; +BEGIN + OldLoadBMP := False; + If (Use) then Unload; + assign (plik, sciezka); + {$I-} +{ reset (plik, 1); + {$I+} +{ If (IOResult <> 0) then exit; + licznik := sizeof (naglowek_BMP); + blockread (plik, naglowek, licznik, wynik); + seek (plik, 1078); + Width := naglowek.szerokosc_obrazu; + Height := naglowek.wysokosc_obrazu; + Size := naglowek.szerokosc_obrazu * naglowek.wysokosc_obrazu; + IF (maxavail < Size) THEN + BEGIN + close (plik); + exit; + END; + getmem (Handler, Size); + licznik := naglowek.szerokosc_obrazu; + + FOR licznik_odczytu := naglowek.wysokosc_obrazu - 1 downto 0 do + BEGIN + blockread (plik, Handler^ [(licznik_odczytu) * (Width)], licznik, wynik); + IF Width MOD 4 <> 0 THEN Seek(plik,FilePos (plik) + (4 - Width MOD 4)); + END; + + close (plik); + Use := True; + OldLoadBMP := True; +END;} + +PROCEDURE PaletteBMPToRGB (PaletteBMP : TPaletteBMP ; Var Palette : TPalette); +BEGIN + FOR I := 0 to 255 do + BEGIN + Palette [I]. R := PaletteBMP [I]. R shr 2; + Palette [I]. G := PaletteBMP [I]. G shr 2; + Palette [I]. B := PaletteBMP [I]. B shr 2; + END; +END; + +PROCEDURE PaletteRGBtoBMP (Palette : TPalette ; Var PaletteBMP : TPaletteBMP); +BEGIN + FOR I := 0 to 255 do + BEGIN + PaletteBMP [I]. R := Palette [I]. R shl 2; + PaletteBMP [I]. G := Palette [I]. G shl 2; + PaletteBMP [I]. B := Palette [I]. B shl 2; + END; +END; + +FUNCTION LoadHandleBMP (FileName : String; Var HandleBMP : THandleBMP) : Boolean; +BEGIN + LoadHandleBMP := FALSE; + Assign (Plik, FileName); + {$I-} + Reset (Plik, 1); + {$I+} + If (IOResult <> 0) then EXIT; + BlockRead (Plik, HandleBMP, SizeOf (HandleBMP)); + Close (Plik); + +{ UNLOAD13H; + Writeln ('HandleBMP. FWidth = ',HandleBMP. FWidth); + Writeln ('HandleBMP. FHeight = ',HandleBMP. FHeight); + Writeln ('HandleBMP. FBitPerPixel = ',HandleBMP. FBitPerPixel); + Writeln ('HandleBMP. FCompression = ',HandleBMP. FCompression); + ReadLn; + LOAD13H;} + + If (HandleBMP. FWidth > 320) then EXIT; + If (HandleBMP. FHeight > 200) then EXIT; + If (HandleBMP. FBitPerPixel <> 8) and + (HandleBMP. FBitPerPixel <> 24) then EXIT; + If (HandleBMP. FCompression <> 0) then EXIT; + LoadHandleBMP := TRUE; +END; + +FUNCTION TImage.LoadBMP (FileName : string ; LoadPalette : Boolean) : Boolean; +VAR + HandleBMP : THandleBMP; + Palette : TPalette; + PaletteBMP : TPaletteBMP; + Temp : Array [0 .. (320 * 3) - 1] of Byte; + I2 : Integer; +BEGIN + LoadBMP := FALSE; + If (NOT LoadHandleBMP (FileName,HandleBMP)) then EXIT; + If (Use) then Unload; + Assign (Plik, FileName); + {$I-} + Reset (Plik, 1); + {$I+} + If (IOResult <> 0) then EXIT; + Width := HandleBMP. FWidth; + Height := HandleBMP. FHeight; + Size := Width * Height; + IF (MaxAvail < Size) THEN + BEGIN + Close (Plik); + EXIT; + END; + CASE HandleBMP. FBitPerPixel OF + 8 : BEGIN + GetMem (Handler,Size); + IF (LoadPalette) THEN + BEGIN + Seek (Plik, 54); + BlockRead (Plik,PaletteBMP,1024); + PaletteBMPToRGB (PaletteBMP,Palette); + END; + Seek (Plik, 1078); + FOR I := Height - 1 downto 0 do + BEGIN + BlockRead (Plik, Handler^ [I * Width], Width); + IF (Width MOD 4) <> 0 THEN Seek (Plik,FilePos (Plik) + (4 - Width MOD 4)); + END; + END; + ELSE + BEGIN + Close (plik); + EXIT; + END; + END; + Close (plik); + Use := True; + LoadBMP := True; +END; + +PROCEDURE LoadBMPPalette (sciezka : string); +VAR + plik : file; + paleta_BMP : array [0..255] of record + b : byte; + g : byte; + r : byte; + z : byte; + END; + licznik,wynik : word; +BEGIN + assign (plik, sciezka); + reset (plik, 1); + seek (plik, sizeof (THandleBMP)); + licznik := sizeof (paleta_BMP); + blockread (plik, paleta_BMP, licznik, wynik); + port [$3c8] := 0; + FOR licznik := 0 to 255 do + BEGIN + port[$3c9] := paleta_BMP [licznik].r shr 2; + port[$3c9] := paleta_BMP [licznik].g shr 2; + port[$3c9] := paleta_BMP [licznik].b shr 2; + END; + close (plik); +END; + +PROCEDURE TImage.XY (X,Y : integer); +VAR + LicznikX,LicznikY : word; + { dodatkowe zmienne do asma } + PrzesBuforu,PrzesEkranu : word; +BEGIN +{ ASM + + mov ax, use + cmp ax, 0 + jne @end + + mov ax, y + mov przesekranu, 320 + mul przesekranu + mov przesekranu, ax + mov ax, x + add przesekranu, ax + + mov przesbuforu, 0 + + mov cx, height + @petla: + push cx + push ds + + mov ax, height + sub ax, cx + + les di, bufor + add di, przesbuforu + + mov ax, seg handler + mov ds, ax + mov si, offset handler + add si, przesekranu + + mov cx, width + + cld + rep movsb + + add przesekranu, 320 + sub przesekranu, width + + pop cx + pop ds + loop @petla + + @end: + END; + EXIT;} + + If (not Use) then Exit; + FOR LicznikY := 0 to Height - 1 do + FOR LicznikX := 0 to Width - 1 do + BEGIN + PutPixel (X + LicznikX,Y + LicznikY,Handler^ [(LicznikY * (Width)) + LicznikX]); + END; +END; + +PROCEDURE TImage.XYV (X,Y : integer); +VAR + LicznikX,LicznikY : word; + { dodatkowe zmienne do asma } + PrzesBuforu,PrzesEkranu : word; + Visible : Boolean; +BEGIN + If (not Use) then Exit; + FOR LicznikY := 0 to Height - 1 do + FOR LicznikX := 0 to Width - 1 do + BEGIN + If (Visible) then + Begin + PutPixel (X + LicznikX,Y + LicznikY,Handler^ [(LicznikY * (Width)) + LicznikX]); + Visible := False + End + Else + Visible := True; + If (Width mod 2 = 0) and (LicznikX = Width - 1) then + If (Visible) then Visible := False else Visible := True; + END; +END; + +PROCEDURE TImage.XYT (x,y : integer ; TransparentColor : byte); + VAR + LicznikX,LicznikY : longint; +BEGIN + If (not Use) then Exit; + FOR LicznikY := 0 to Height - 1 do + FOR LicznikX := 0 to Width - 1 do + BEGIN + If (Handler^ [(LicznikY * (Width)) + LicznikX] <> TransparentColor) then + PutPixel (X + LicznikX,Y + LicznikY,Handler^ [(LicznikY * (Width)) + LicznikX]); + END; +END; + +PROCEDURE TImage.Unload; +BEGIN + If (not Use) then Exit; + FreeMem (Handler,Size); + Width := 0; + Height := 0; + Size := 0; + Use := False; +END; + +{ +############################### +Koniec modulu M_13H. +Masz jakies uwagi lub pytania ? +Pisz : pt_k@wp.pl +############################### +} + +BEGIN + Screen := Ptr ($A000,0); + SetBufor (Screen); +END. \ No newline at end of file diff --git a/poprecog/record/M_XMS.PAS b/poprecog/record/M_XMS.PAS new file mode 100644 index 0000000..0947516 --- /dev/null +++ b/poprecog/record/M_XMS.PAS @@ -0,0 +1,215 @@ +(* + XMS library + + Author : Piotr Kochanek + WWW site : www.pop2.princed.com.ar +*) + +UNIT M_XMS; + +INTERFACE +Var + XMSError : Byte; + +{ // Czy pamiec XMS istnieje ? } +FUNCTION XMSFind : Boolean; +{ // Funkcja zwraca adres programu XMM } +FUNCTION XMSGetAddress : Pointer; +{ // Zwraca wersje sterownika XMM } +FUNCTION XMSVersion : Word; +{ // Funkcja inicjujaca modul i spraqdzajaca czy wszystko OK } +FUNCTION XMSSetup : Boolean; +{ // Funkcja zwraca ilosc wolnej pamieci XMS w KB } +FUNCTION XMSMemAvail : Word; +{ // Funkcja zwraca wielkosc najwiekszego bloku pamieci XMS w KB } +FUNCTION XMSMaxAvail : Word; +{ // Funkcja alokuje pamiec XMS } +FUNCTION XMSGetMem (Var Handler : Word ; Size : Word) : Boolean; +{ // Zmienia rozmiar pamieci XMS pod wybranym uchwytem } +FUNCTION XMSReGetMem (Handler : Word ; Size : Word) : Boolean; +{ // Funkcja usuwa pamiec XMS } +FUNCTION XMSFreeMem (Handler : Word) : Boolean; +{ // Funkcja kopiuje bajty do/z pamieci XMS } +FUNCTION XMSMoveMem (SrcHandler : Word ; SrcOffset : Pointer ; + DstHandler : Word ; DstOffset : Pointer ; Size : Longint) : Boolean; + +IMPLEMENTATION +VAR + { // Adres sterownika pamieci XMS } + XMSAddress : Pointer; + { // Rekord potrzebny przy przesylaniu pamieci } + XMSBlockInfo : + RECORD + Length : Longint; + SourceHandler : Word; + SourceOffset : Pointer; + DestinationHandler : Word; + DestinationOffset : Pointer; + END; + +(* + Funkcja sprawdza czy istnieje pamiec XMS +*) +FUNCTION XMSFind : Boolean; +BEGIN + ASM + mov ax, $4300 + int $2f + mov @result, FALSE + cmp al, $80 + jne @end + mov @result, TRUE + @end: + END; +END; + +(* + Zwraca adres sterownika pamieci XMS +*) +FUNCTION XMSGetAddress : Pointer; +VAR + XMSSeg : Word; + XMSOfs : Word; +BEGIN + ASM + mov ax, $4310 + int $2f + mov XMSSeg, es + mov XMSOfs, bx + END; + XMSGetAddress := Ptr (XMSSeg,XMSOfs); +END; + +(* + Zwraca wersje sterownika pamieci XMS +*) +FUNCTION XMSVersion : Word; +BEGIN + ASM + mov ax, $0000 + call [XMSAddress] + mov @result, ax + END; +END; + +(* + Sprawdza czy mozna uzywac pamiec XMS +*) +FUNCTION XMSSetup : Boolean; +BEGIN + XMSSetup := TRUE; + IF (XMSFind) + THEN XMSAddress := XMSGetAddress + ELSE XMSSetup := FALSE; +END; + +(* + Zwraca ilosc wolnej pamieci XMS w KB +*) +FUNCTION XMSMemAvail : Word; +BEGIN + ASM + mov ax, $0800 + call [XMSAddress] + mov @result, dx + END; +END; + +(* + Zwraca wielkosc najwiekszego wolnego bloku w KB +*) +FUNCTION XMSMaxAvail : Word; +BEGIN + ASM + mov ax, $0800 + call [XMSAddress] + mov @result, ax + END; +END; + +FUNCTION XMSGetMem (Var Handler : Word ; Size : Word) : Boolean; +BEGIN + ASM + mov @result, TRUE + mov ax, $0900 + mov dx, Size + call [XMSAddress] + les di, Handler + mov [es:di], dx + cmp ax, 1 + je @end + mov XMSError, bl + mov @result, FALSE + @end: + END; +END; + +FUNCTION XMSReGetMem (Handler : Word ; Size : Word) : Boolean; +BEGIN + ASM + mov @result, TRUE + mov ax, $0f00 + mov bx, Size + mov dx, Handler + call [XMSAddress] + cmp al, 1 + je @end + mov XMSError, bl + mov @result, FALSE + @end: + END; +END; + +FUNCTION XMSFreeMem (Handler : Word) : Boolean; +BEGIN + ASM + mov @result, TRUE + mov ax, $0a00 + mov dx, Handler + call [XMSAddress] + cmp ax, 1 + je @end + mov XMSError, bl + mov @result, FALSE + @end: + END; +END; + +FUNCTION XMSMoveMem (SrcHandler : Word ; SrcOffset : Pointer ; + DstHandler : Word ; DstOffset : Pointer ; Size : Longint) : Boolean; +BEGIN + WITH XMSBlockInfo DO + BEGIN + Length := Size; + SourceHandler := SrcHandler; + SourceOffset := SrcOffset; + DestinationHandler := DstHandler; + DestinationOffset := DstOffset; + END; + ASM + mov @result, TRUE + mov ax, seg XMSBlockInfo + mov ds, ax + mov si, offset XMSBlockInfo + mov ax, $0b00 + call [XMSAddress] + cmp ax, 1 + je @end + mov XMSError, bl + mov @result, FALSE + @end: + END; +END; + +FUNCTION XMSGetError (Error : Byte) : String; +VAR + ErrorInfo : String; +BEGIN + CASE Error OF + $80 : ErrorInfo := ''; + END; +END; + +BEGIN + +END. diff --git a/poprecog/record/READ.TXT b/poprecog/record/READ.TXT new file mode 100644 index 0000000..5f74fa2 --- /dev/null +++ b/poprecog/record/READ.TXT @@ -0,0 +1,36 @@ +RECORD README FILE + +Q : What can I do with this program ? +A : This program can capture tha animation from a game. After finish the game, it create as many bmp files as there was recorded frames. + + +Q : What should i have, to create own animation (for example in gif file) ? +A : You should have : + - game (which You want to record) :) + - record program (that You have downloaded) :) + - any program that can link *.bmp files into one file (gif, avi etc.). For example Animation Shop in Paint Shop Pro. + - that's all :). + Next question please ... + + +Q : What kinds of game (or programs) can i record ? +A : This program can record only games (or programs) that are running in 13h mode. + What's 13h mode ? This is very old graphic mode that have 320 * 200 resolution and displays 256 colors max. + Some of games that are running in that mode are : Prince of Persia 1 & 2, Liero, Dangerous Dave and much, much more :) + + +Q : How to record game ? +A : It's very easy. Create in notepad file start.bat which has : "record game.exe parameters". Game.exe is the name of file to execute. Parameters are optional. For example, if you want to record Prince of Persia 1 with cheats, write in this file : "record prince.exe magahit". After that, run this file. The game should start. +The function keys are : +F11 - Start recording +F12 - Stop recording +F10 - Single screenshot +F9 - View Bufor Status +After finish playing, confirm to save bmp files. This can take few minutes. + +Q : After few minutes (or seconds) i hear recurrent, noisy voices from PC Speaker. +A : Your recording bufor is overcrowded or You have running program that it isn't in 13h mode. + + +Q : When i run record program, it's display an error, that i haven't mouse ! +A : Don't run the program in the DOS mode :) \ No newline at end of file diff --git a/poprecog/record/record.pas b/poprecog/record/record.pas new file mode 100644 index 0000000..366f20a --- /dev/null +++ b/poprecog/record/record.pas @@ -0,0 +1,420 @@ +(* + RECORDer source file + + Author : Piotr Kochanek + WWW site : www.pop2.princed.com.ar + + This software can capture an animation from 13h games (320 * 200 and 256 colors). + After finish playing the game, it create as many bmp files as there was recorded frames. + Then, with for example Animation Shop (Paint Shop Pro), You can link this files into one file (gif, avi, etc). +*) + +PROGRAM SCREEN_RECORDER; + +USES + CRT, {!!!} + DOS, + HEAPMAN, + GRAPH13H, + M_XMS; +VAR + OPT : + RECORD + ProgramPath : String; + ProgramParameters : String; + StartAtBegin : Boolean; + {SkipSecFrame : Boolean;} + + UseMouse : Boolean; + UseF9F12 : Boolean; + UseCtrl : Boolean; + + UsePCSpeaker : Boolean; + DelDuplicateFrames : Boolean; + FilePrefix : String; + END; + +{ MButton : Byte; + MLButton : Byte; + MTime : Word;} + + KPress : Byte; + LKPress : Byte; + AltPressed : Boolean; + MButton : Byte; + MouseButtonPressed : Boolean; + + B : Byte; + REC : Byte; + W : Word; + I, + J : Integer; + Bool : Boolean; + AnimationHandle : array [0..19] of Word; + ActualBufor : Byte; + FramePalette : TPalette; + FramePaletteBMP : TPaletteBMP; + Old1Ch : Pointer; + ActualFrame : Longint; + ActualSaveFrame : Longint; + ActualXMSFrame : Longint; + MaxFrames : Longint; + TotalFrames : Longint; + OutputFile : File; + BMPHandle : THandleBMP; + FileName : String; + Line : Array [0..319] of Byte; + Line2 : Array [0..319] of Byte; + STOP : BOOLEAN; + Tmp : Longint; + Nr : Longint; + +PROCEDURE ERROR (Description : String ; HaltProgram : Boolean); +BEGIN + If (HaltProgram) then + Begin + Writeln ('ERROR : ' + Description); + Halt; + End + Else + Begin + Writeln ('WARNING : ' + Description); + Writeln; + End; +END; + +PROCEDURE S (Snd, Del : Word); +BEGIN + If (OPT. UsePCSpeaker) then + Begin + Sound (Snd); + Delay (Del); + NoSound; + End; +END; + +FUNCTION IntToStr (liczba : longint) : string; +VAR + tekst : string; +BEGIN + str (liczba,tekst); + IntToStr := tekst; +END; + +FUNCTION YN (Text : string) : BOOLEAN; +VAR Kl : Char; +BEGIN + While (Keypressed) do Readkey; + YN := FALSE; + Write (Text,' (Y/N)? '); + REPEAT + Kl := Readkey; + UNTIL (Kl = #121) OR (Kl = #89) OR (Kl = #13) OR (Kl = #110) OR (Kl = #78) OR (Kl = #27); + IF (Kl = #121) OR (Kl = #89) OR (Kl = #13) THEN + BEGIN + Writeln ('Y'); + YN := TRUE; + END + ELSE + Writeln ('N'); +END; + +PROCEDURE ProgramEnd; +BEGIN + For I := 0 to 19 do + Begin + If (I * 1035 >= MaxFrames) then Exit; + If (not XMSFreeMem (AnimationHandle [I])) then Error ('Error while freeing XMS memory',False); + End; + + Halt; +END; + +PROCEDURE PrerareToRecord; +BEGIN + Writeln ('13h Screen Recorder version 2.0 beta [2003/12/23]'); + Writeln ('Copyright by Peter_K { asm3@o2.pl }'); + Writeln ('Check for the latest version at www.princed.com.ar'); + Writeln; + Writeln ('! Before do anything please read READ.txt file !'); + Writeln; + +(* checking for XMS Memory *) + If (NOT XMSSetup) then Error ('XMS not found',True); + If (XMSMemAvail < 1000) then Error ('To little XMS memory',True); + If (XMSMemAvail < 6000) then Error ('You haven"t too much XMS memory',False); + + For I := 0 to 19 do + Begin + Tmp := XMSMemAvail; + If (NOT XMSGetMem (AnimationHandle [I],Tmp)) then Break; + MaxFrames := MaxFrames + ((1024 * Tmp) div 64768) - 1; { = 1 GB } + End; + +(* info about memory *) + Writeln ('Size of XMS bufor : ',MaxFrames,' [frames]'); + Writeln ('Max recording time : ',MaxFrames div 1110,' min. ( ',MaxFrames div 18,' sec. ).'); + Writeln; + +(* setting additional options *) + {OPT. SkipSecFrame := True;} + OPT. StartAtBegin := False; + OPT. UsePCSpeaker := True; + OPT. DelDuplicateFrames := False; + +{ If (YN ('Advenced settings ?')) then + Begin} + Write('Type program name to exec (with .exe !) : '); + Readln(OPT. ProgramPath); + Write('Type program parameters: '); + Readln(OPT. ProgramParameters); + Write('Type prefix for BMP files (maximum 3 signs): '); + Readln(OPT. FilePrefix); + OPT. UseMouse := YN ('Use mouse?'); + OPT. UseF9F12 := YN ('Use keys F9 - F12?'); + OPT. UseCtrl := YN ('Use ctrl key?'); + {OPT. SkipSecFrame := FALSE;{YN ('Skip seconds frames - 2x more time and increase speed');} + OPT. StartAtBegin := YN ('Start recording at beginning'); + OPT. UsePCSpeaker := YN ('Use PC Speaker'); + OPT. DelDuplicateFrames := YN ('Delete duplicate frames'); +{ End;} + If (OPT. StartAtBegin) Then + REC := 2 + Else + REC := 0; +END; + +PROCEDURE SaveScreen; INTERRUPT; +BEGIN + If (STOP) or (GetVideoMode <> $13) or (TotalFrames >= MaxFrames) then Begin S (200,100); Exit; End; + + STOP := TRUE; + + If (REC = 1) Then Rec := 0; + + If ((OPT. UseF9F12) OR (OPT. UseCtrl)) Then + Begin + {LKPress := KPress;} + KPress := port[$60]; + If (KPress = $57) then Rec := 2; + If (KPress = $58) then Rec := 0; + {If (LKPress = 56) then Rec := False;} + If (KPress = 56) then + BEGIN + if (NOT AltPressed) then Rec := 1; + AltPressed := TRUE; + END + ELSE + AltPressed := FALSE; + If (KPress = $43) then + Begin + Graph13h.RectangleFilled (200,0,300,5,Graph13h.Color (63,63,63)); + Case REC Of + 0 : Graph13h.RectangleFilled (200,0,200 + ((TotalFrames * 100) div MaxFrames),5,Graph13h.Color (63,0,0)); + 1 : Graph13h.RectangleFilled (200,0,200 + ((TotalFrames * 100) div MaxFrames),5,Graph13h.Color (0,63,0)); + 2 : Graph13h.RectangleFilled (200,0,200 + ((TotalFrames * 100) div MaxFrames),5,Graph13h.Color (0,63,0)); + End; + End; + End; + +{ If (OPT. UseMouse) then + Begin + MLButton := MButton; + MButton := MouseButton; + If (MButton = 1) Then + Begin + If (NOT MouseButtonPressed) Rec := 1; + MouseButtonPressed := TRUE; + End + Else + MouseButtonPressed := FALSE: + If (MButton = 2) Then Rec := 1; + If (MButton = 4) AND (MLButton <> 4) Then Rec := True; + If (MLButton = 4) AND (MButton <> 1) Then Rec := False; + End;} + + ActualBufor := TotalFrames div 1035; + ActualXMSFrame := TotalFrames mod 1035; + + IF (REC > 0) THEN + BEGIN + {If (TotalFrames mod 20 = 0) Then Begin S (600,2); End;} + SavePalette (FramePalette); + XMSMoveMem (0,@FramePalette,AnimationHandle [ActualBufor],Pointer (ActualXMSFrame * 64768),768); + XMSMoveMem (0,Screen,AnimationHandle [ActualBufor],Pointer ((ActualXMSFrame * 64768) + 768),64000); + Inc (TotalFrames); + Inc (ActualXMSFrame); + END; + +{ If (NOT REC) OR (MouseButton = 2) then + Begin + Graph13h.RectangleFilled (200,0,300,5,Graph13h.Color (63,63,63)); + Graph13h.RectangleFilled (200,0,200 + ((TotalFrames * 100) div MaxFrames),5,Graph13h.Color (0,63,0)); + Graph13h.RectangleFilled (200 + TotalFrames mod 100,0,201 + (TotalFrames mod 100),5,Graph13h.Color (63,0,0)); + End;} + + Inc (Nr); + + STOP := FALSE; +END; + +PROCEDURE ExecuteProgram; +BEGIN + Writeln ('Hit any key to execute program ...'); + While (Keypressed) do Readkey; + Readkey; + + GetIntVec ($1C,Old1Ch); + SetIntVec ($1C,@SaveScreen); + + If (Execute (OPT.ProgramPath,OPT.ProgramParameters) <> 0) then + Begin + SetIntVec ($1C,Old1Ch); + Error ('Cannot execute file ' + OPT. ProgramPath,False); + ProgramEnd; + End; + + SetIntVec ($1C,Old1Ch); + + Writeln ('Recording finished succesfull'); + Writeln ('Total frames : ',TotalFrames); + Writeln ('BMPs size after save : ',(TotalFrames * 65078) div 1048576,' MB'); + Writeln; +END; + +{PROCEDURE ViewAnimation; +BEGIN + If (TotalFrames = 0) then Exit; + Load13h; + SetBufor (Bufor); + ActualFrame := 0; + REPEAT + If (OPT.SavePalette) then + Begin + XMSMoveMem (AnimationHandle,Pointer (ActualFrame * 64768),0,@FramePalette,SizeOf (FramePalette)); + LoadPalette (FramePalette); + End; + XMSMoveMem (AnimationHandle,Pointer ((ActualFrame * 64768) + SizeOf (FramePalette)),0,Bufor,64000); + ShowBufor (Bufor); + Inc (ActualFrame); + Delay (100); + If (OPT.LoopAnimation) and (ActualFrame = TotalFrames) then ActualFrame := 0; + UNTIL (ActualFrame = TotalFrames) OR (Keypressed); + Unload13h; +END;} + +PROCEDURE SaveAnimation; +VAR + LastBufor : Byte; + LastXMSFrame : Longint; +BEGIN + {If (NOT YN ('Save bitmaps files')) Then If (YN ('Are You SURE')) Then Exit; + OPT. DelDuplicateFrames := YN ('Delete duplicate frames');} + + {$I-} + MkDir ('frames'); + {$I+} + If (IOResult <> 0) then begin end; + + New (Bufor); + + BMPHandle.FType := $4D42; + BMPHandle.FSize := 65078; + BMPHandle.FReserved1 := 0; + BMPHandle.FReserved2 := 0; + BMPHandle.FFirstPixel := 1078; + BMPHandle.FInfoSize := 40; + BMPHandle.FWidth := 320; + BMPHandle.FHeight := 200; + BMPHandle.FPlanes := 1; + BMPHandle.FBitPerPixel := 8; + BMPHandle.FCompression := 0; + BMPHandle.FImageSize := 64000; + BMPHandle.FDPIWidth := 3937; + BMPHandle.FDPIHeight := 3937; + BMPHandle.FColorUsed := 0; + BMPHandle.FImportantColor := 0; + + ActualSaveFrame := 0; + For ActualFrame := 0 to (TotalFrames - 1) do + Begin + { for skipping the same frames } + LastBufor := ActualBufor; + LastXMSFrame := ActualXMSFrame; + { ... } + ActualBufor := ActualFrame div 1035; + ActualXMSFrame := ActualFrame mod 1035; + + { for skipping the same frames } + If (OPT. DelDuplicateFrames) and (ActualFrame > 0) then + Begin + Bool := False; + For I := 0 to 199 do + Begin + XMSMoveMem (AnimationHandle [LastBufor],Pointer ((LastXMSFrame * 64768) + (I * 320) + SizeOf (FramePalette)), + 0,Addr (Line),320); + XMSMoveMem (AnimationHandle [ActualBufor],Pointer ((ActualXMSFrame * 64768) + (I * 320) + SizeOf (FramePalette)), + 0,Addr (Line2),320); + For J := 0 to 319 do + If (Line [J] <> Line2 [J]) then + Begin + Bool := True; + Break; + End; + If (Bool) then Break; + End; + If (NOT Bool) then + Continue; + End; + { ... } + + Inc(ActualSaveFrame); + FileName := IntToStr (ActualSaveFrame); + While (Length (FileName) < 5) do FileName := '0' + FileName; + FileName := OPT.FilePrefix + FileName + '.bmp'; + Assign (OutputFile,{OPT.SaveDir} + 'frames\' + FileName); + {$I-} + Rewrite (OutputFile, 1); + {$I+} + If (IOResult <> 0) then + Begin + Error ('Cannot save file ' + {OPT.SaveDir}'frames' + '\' + FileName,False); + Continue; + End; + +{ BlockRead (InputFile, FramePalette, 768);} + XMSMoveMem (AnimationHandle [ActualBufor],Pointer (ActualXMSFrame * 64768),0,@FramePalette,SizeOf (FramePalette)); + PaletteRGBToBMP (FramePalette,FramePaletteBMP); + +{ BlockRead (InputFile, Bufor^, 64000);} + XMSMoveMem (AnimationHandle [ActualBufor],Pointer ((ActualXMSFrame * 64768) + SizeOf (FramePalette)),0,Bufor,64000); + + BlockWrite (OutputFile,BMPHandle,SizeOf (BMPHandle)); + BlockWrite (OutputFile,FramePaletteBMP,SizeOf (FramePaletteBMP)); + FOR W:= 199 DOWNTO 0 DO + BEGIN + Move(Bufor^ [W * 320],Line,320); + BlockWrite(OutputFile,Line,320); + END; + + Close (OutputFile); + + GoToXY (1,WhereY); + Write (((ActualFrame + 1) * 100) div TotalFrames,'%, ( ',ActualFrame + 1,' frames ) '); + End; + Dispose (Bufor); + + Writeln; + Writeln; + Writeln ('Frames now are stored in "frames" dir.'); +END; + +BEGIN + PrerareToRecord; + + ExecuteProgram; + + If (TotalFrames > 0) then SaveAnimation; + + ProgramEnd; +END. \ No newline at end of file