📄 platformvideo.pas
字号:
//////////////////////////////////////////////////////////////////////
// //
// platformVideo.pas: Platform dependant video code (sort of) //
// //
// The contents of this file are subject to the Bottled Light //
// Public License Version 1.0 (the "License"); you may not use this //
// file except in compliance with the License. You may obtain a //
// copy of the License at http://www.bottledlight.com/BLPL/ //
// //
// Software distributed under the License is distributed on an //
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or //
// implied. See the License for the specific language governing //
// rights and limitations under the License. //
// //
// The Original Code is the Mappy VM User Interface, released //
// April 1st, 2003. The Initial Developer of the Original Code is //
// Bottled Light, Inc. Portions created by Bottled Light, Inc. are //
// Copyright (C) 2001-2003 Bottled Light, Inc. All Rights Reserved. //
// //
// Author(s): //
// Michael Noland (joat), michael@bottledlight.com //
// //
// Changelog: //
// 1.0: First public release (April 1st, 2003) //
// //
// Notes: //
// The rotation code is all commented out right now. //
// //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
unit platformVideo; //////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
interface ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
uses
Windows, Classes, Graphics, MMSystem, Forms, nexus, console,
sysAviWriter, AddressSpace;
//////////////////////////////////////////////////////////////////////
type
TRotationMode = (rm0, rm90, rm180, rm270);
//////////////////////////////////////////////////////////////////////
var
msBetweenFrames: uint32;
renderSplitRGB, renderShowGrid: boolean;
screenWidth, screenHeight: integer;
// fxBMP, rotBMP: TBitmap;
// rotBMPallocated: boolean;
renderRotationMode: TRotationMode;
displayBMP: TBitmap;
//////////////////////////////////////////////////////////////////////
procedure InitVideo;
procedure FreeVideo;
procedure InitRenderModes;
procedure OnVideoReady(y: integer; sline: Puint16);
procedure platformRenderScreen;
procedure writeRampEntry(ramp, index, color: byte);
function readRampEntry(ramp, index: byte): byte;
procedure InvalidateRamp;
procedure videoResetRamp;
//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
uses
jdev_main;
//////////////////////////////////////////////////////////////////////
var
videoRampR, videoRampG, videoRampB: array[0..31] of longword;
backBMP: TBitmap;
//////////////////////////////////////////////////////////////////////
procedure videoResetRamp;
var
i: integer;
begin
for i := 0 to 31 do begin
writeRampEntry(0, i, (i+1)*8-1);
writeRampEntry(1, i, (i+1)*8-1);
writeRampEntry(2, i, (i+1)*8-1);
end;
end;
//////////////////////////////////////////////////////////////////////
procedure InitVideo;
begin
videoResetRamp;
renderRotationMode := rm0;
renderSplitRGB := false;
renderShowGrid := false;
displayBMP := TBitmap.Create;
displayBMP.Width := 240;
displayBMP.Height := 160;
displayBMP.PixelFormat := pf32bit;
backBMP := TBitmap.Create;
backBMP.Width := 240;
backBMP.Height := 160;
backBMP.PixelFormat := pf15bit;
end;
//////////////////////////////////////////////////////////////////////
procedure FreeVideo;
begin
displayBMP.Free;
backBMP.Free;
// fxBMP.Free;
// if rotBMPallocated then rotBMP.Free;
end;
//////////////////////////////////////////////////////////////////////
procedure backToFront(y: integer);
var
color: uint16;
i: integer;
sline: puint16;
c: uint32;
l2: array[0..3] of Puint32;
x: integer;
begin
sline := backBMP.ScanLine[y];
if renderSplitRGB and renderShowGrid then begin
// Set up 4 pixel pointers, one on top of each other
for i := 0 to 2 do l2[i] := displayBMP.ScanLine[y*4+i];
// Draw a 1x3 column for each of R,G,B, with a 4th 1x3 black column
for x := 0 to 239 do begin
color := sline^;
c := videoRampR[color and 31];
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
c := videoRampG[(color shr 5) and 31];
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
c := videoRampB[(color shr 10) and 31];
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
c := 0;
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
Inc(sline);
end;
// Draw a 240*4 black line on the 4th scanline of the quad
FillChar(displayBMP.ScanLine[y*4+3]^, 240*4*4, 0);
end else if renderSplitRGB then begin
// Set up 3 pixel pointers, one on top of each other
for i := 0 to 2 do l2[i] := displayBMP.ScanLine[y*3+i];
// Draw a 1x3 column for each of R,G,B
for x := 0 to 239 do begin
color := sline^;
c := videoRampR[color and 31];
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
c := videoRampG[(color shr 5) and 31];
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
c := videoRampB[(color shr 10) and 31];
l2[0]^ := c; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[2]^ := c; Inc(l2[2]);
Inc(sline);
end;
end else if renderShowGrid then begin
// Set up 3 pixel pointers, one on top of each other
for i := 0 to 2 do l2[i] := displayBMP.ScanLine[y*3+i];
// Draw the normal pixel in a 2x2 block
for x := 0 to 239 do begin
color := sline^;
Inc(sline);
c := videoRampR[color and 31] + videoRampG[(color shr 5) and 31] + videoRampB[(color shr 10) and 31];;
l2[0]^ := c; Inc(l2[0]);
l2[0]^ := c; Inc(l2[0]);
l2[0]^ := 0; Inc(l2[0]);
l2[1]^ := c; Inc(l2[1]);
l2[1]^ := c; Inc(l2[1]);
l2[1]^ := 0; Inc(l2[1]);
end;
// Draw a 240*3 black line on the 3th scanline of the triplet
FillChar(l2[2]^, 240*3*4, 0);
end else begin
l2[0] := displayBMP.ScanLine[y];
for i := 0 to 239 do begin
color := sline^;
l2[0]^ := (videoRampR[color and 31] + videoRampG[(color shr 5) and 31] + videoRampB[(color shr 10) and 31]);
Inc(sline);
Inc(l2[0]);
end;
end;
end;
//////////////////////////////////////////////////////////////////////
procedure InitRenderModes;
var
y: integer;
begin
// Calculate the new size of the display
if renderSplitRGB and renderShowGrid then begin
screenWidth := 240*4;
screenHeight := 160*4;
end else if renderSplitRGB or renderShowGrid then begin
screenWidth := 240*3;
screenHeight := 160*3;
end else begin
screenWidth := 240;
screenHeight := 160;
end;
// Resize the display bitmap
displayBMP.Free;
displayBMP := TBitmap.Create;
displayBMP.Width := screenWidth;
displayBMP.Height := screenHeight;
displayBMP.PixelFormat := pf32bit;
// Redraw the display
for y := 0 to 159 do backToFront(y);
// Resize the window
jdevMain.dontResize := true;
jdevMain.ClientWidth := screenWidth;
jdevMain.ClientHeight := screenHeight + jdevMain.status.Height;
jdevMain.dontResize := false;
jdevMain.FormResize(nil);
end;
//////////////////////////////////////////////////////////////////////
procedure OnVideoReady(y: integer; sline: Puint16);
begin
Move(sline^, backBMP.ScanLine[y]^, 240*2);
backToFront(y);
if y = 159 then begin
platformRenderScreen;
if capturing then begin
captureIndex := captureIndex + 1;
if captureIndex >= captureTarget then begin
captureIndex := captureIndex - captureTarget;
aviAddFrame(backBMP);
end;
end;
end;
end;
//////////////////////////////////////////////////////////////////////
// fixme!
//var
// scans: array[0..1024*4-1] of Puint32;
procedure platformRenderScreen;
begin
{var
x, y: integer;
i: byte;
c: uint32;
line: Puint32;
l2: array[0..3] of Puint32;
begin
case renderRotationMode of
rm0:}
jdevMain.canvas.StretchDraw(Rect(0,0,screenWidth,screenHeight), displayBMP);
{ rm90: begin
for y := 0 to rotBMP.height - 1 do scans[y] := rotBMP.ScanLine[y];
for y := fxBMP.height-1 downto 0 do begin
line := fxBMP.ScanLine[y];
for x := 0 to fxBMP.width-1 do begin
scans[x]^ := line^;
Inc(scans[x]);
Inc(line);
end;
end;
jdevMain.pscreen.canvas.StretchDraw(Rect(0,0,screenWidth,screenHeight), rotBMP);
end;
rm180: begin
for y := 0 to rotBMP.height - 1 do scans[y] := rotBMP.ScanLine[rotBMP.height-y-1];
for y := fxBMP.height-1 downto 0 do begin
line := pointer(integer(fxBMP.ScanLine[y]) + (fxBMP.width-1)*4);
for x := 0 to fxBMP.width-1 do begin
scans[y]^ := line^;
Inc(scans[y]);
Dec(line);
end;
end;
jdevMain.pscreen.canvas.StretchDraw(Rect(0,0,screenWidth,screenHeight), rotBMP);
end;
rm270: begin
for y := 0 to rotBMP.height - 1 do scans[y] := rotBMP.ScanLine[y];
for y := 0 to fxBMP.height-1 do begin
line := fxBMP.ScanLine[y];
for x := fxBMP.width - 1 downto 0 do begin
scans[x]^ := line^;
Inc(scans[x]);
Inc(line);
end;
end;
jdevMain.pscreen.canvas.StretchDraw(Rect(0,0,screenWidth,screenHeight), fxBMP);
end;
end;}
end;
//////////////////////////////////////////////////////////////////////
procedure writeRampEntry(ramp, index, color: byte);
begin
case ramp of
0: videoRampR[index] := color shl 16;
1: videoRampG[index] := color shl 8;
2: videoRampB[index] := color;
end;
end;
//////////////////////////////////////////////////////////////////////
function readRampEntry(ramp, index: byte): byte;
begin
case ramp of
0: Result := videoRampR[index] shr 16;
1: Result := videoRampG[index] shr 8;
2: Result := videoRampB[index];
else
Result := 0;
end;
end;
//////////////////////////////////////////////////////////////////////
procedure InvalidateRamp;
var
y: integer;
begin
// Redraw the display
for y := 0 to 159 do backToFront(y);
platformRenderScreen;
end;
//////////////////////////////////////////////////////////////////////
end.
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -