⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 platformvideo.pas

📁 一个不出名的GBA模拟器
💻 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 + -