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

📄 cpugraphics.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{$HINTS ON}

//////////////////////////////////////////////////////////////////////

  spriteRS16_1D: array[0..4] of TSpriteRenderFunc =
    (RenderRS16Color1DSprite0, RenderRS16Color1DSprite1, RenderRS16Color1DSprite2, RenderRS16Color1DSprite3, RenderRS16Color1DSprite4);
  spriteRS16_2D: array[0..4] of TSpriteRenderFunc =
    (RenderRS16Color2DSprite0, RenderRS16Color2DSprite1, RenderRS16Color2DSprite2, RenderRS16Color2DSprite3, RenderRS16Color2DSprite4);
  spriteRS256_1D: array[0..4] of TSpriteRenderFunc =
    (RenderRS256Color1DSprite0, RenderRS256Color1DSprite1, RenderRS256Color1DSprite2, RenderRS256Color1DSprite3, RenderRS256Color1DSprite4);
  spriteRS256_2D: array[0..4] of TSpriteRenderFunc =
    (RenderRS256Color2DSprite0, RenderRS256Color2DSprite1, RenderRS256Color2DSprite2, RenderRS256Color2DSprite3, RenderRS256Color2DSprite4);

//////////////////////////////////////////////////////////////////////

procedure RenderSprite(i: integer; y: integer; line: Puint16; wins, ids: Puint8);
var
  entry: PSpriteEntry;
  funcIndex: integer;
begin
  if i >= lastEntry then Exit;
  entry := @SpriteTable[i];

  funcIndex := registers[BLEND_S1] shr 6;

  // Overrides for forced a-blend sprites and sprite windows
  if entry^.typ = 1 then
    funcIndex := 1
  else if entry^.typ = 2 then
    funcIndex := 4;

  // Call the appropriate sprite renderer
  Dec(y, entry^.y);
  if entry^.rotscale then begin
    if entry^.a and SPRITE_A_256MODE = 0 then begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        spriteRS16_2D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ)
      else
        spriteRS16_1D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ);
    end else begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        spriteRS256_2D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ)
      else
        spriteRS256_1D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ);
    end;
  end else begin
    if entry^.a and SPRITE_A_256MODE = 0 then begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        sprite16_2D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ)
      else
        sprite16_1D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ);
    end else begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        sprite256_2D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ)
      else
        sprite256_1D[funcIndex](y, entry, line, wins, ids, DISPLAY_ACTIVE_OBJ);
    end;
  end;
end;

//////////////////////////////////////////////////////////////////////

function BuildSpriteEntry(y, i: integer; var cycs: integer; force: boolean): integer;
var
  a, b, c: uint16;
  t: byte;
  entry: PSpriteEntry;
  width, height: integer;
begin
  Result := -1;

  if force then lastEntry := 0;

  entry := @spriteTable[lastEntry];
  entry^.next := 255;

  // Read the sprite info entries
  a := Puint16(@(OAM[i shl 3]))^;
  b := Puint16(@(OAM[i shl 3 + 2]))^;
  c := Puint16(@(OAM[i shl 3 + 4]))^;
  entry^.a := a;
  entry^.b := b;
  entry^.c := c;
  entry^.index := i;

  // Work out the dimensions
  t := ((b shr 14) or ((a shr 12) and $C)) shl 1;
  entry^.width := SpriteSizes[t];
  entry^.height := SpriteSizes[t+1];
  entry^.run := entry^.width;

  // Work out the properties
  entry^.rotscale := a and SPRITE_A_ROTSCALE <> 0;
  entry^.doublesize := a and SPRITE_A_DOUBLESIZE <> 0;
  entry^.priority := (c shr 10) and $3;
  entry^.typ := (a shr 10) and $3;

  // Work out the height and width
  width := entry^.width;
  height := entry^.height;
  if entry^.doublesize then begin
    width := width shl 1;
    height := height shl 1;
  end;

  // Work out the positions
  entry^.x := b and $1FF;
  entry^.y := a and $FF;
  if entry^.x + width > 512 then Dec(entry^.x, 512);
  if entry^.y + height > 256 then Dec(entry^.y, 256);

  if force then begin
    entry^.x := 0;
    entry^.y := 0;
  end;

  if (y >= entry^.y) and (y < entry^.y + height) then begin
    // Decrement the sprite engine clock appropriately
    if entry^.rotscale then begin
      if entry^.doublesize then entry^.run := entry^.run*2;
      Dec(cycs, entry^.run*2 + 10);
      if cycs < 0 then Dec(entry^.run, cycs shr 1);
    end else begin
      Dec(cycs, entry^.width);
      if cycs < 0 then Dec(entry^.run, cycs);
      if entry^.doublesize then entry^.run := 0;
    end;

    // A touch of horizontal clipping
    if entry^.x <= -entry^.run then entry^.run := 0;
    if entry^.x+entry^.run > gfxScreenWidth then entry^.run := gfxScreenWidth - entry^.x;

    if entry^.run > 0 then begin
      if entry^.typ = 2 then entry^.priority := 4;

      // Add the sprite to a priority list
      entry^.next := spritePoints[entry^.priority];
      spritePoints[entry^.priority] := lastEntry;
      Result := lastEntry;
      Inc(lastEntry);
    end;
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure vmRenderSprite(i: integer; y: integer; line: Puint16);
var
  entry: PSpriteEntry;
  funcIndex: integer;
  wins, ids: array[0..255] of byte;
  junk: integer;
begin
  junk := 9999;
  FillChar(wins, 256, 1 shl 4);
  entry := @SpriteTable[BuildSpriteEntry(y, i, junk, true)];

  // Call the appropriate sprite renderer
  funcIndex := 0;
  Dec(y, entry^.y);

  if entry^.rotscale then begin
    if entry^.a and SPRITE_A_256MODE = 0 then begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        spriteRS16_2D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ)
      else
        spriteRS16_1D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ);
    end else begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        spriteRS256_2D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ)
      else
        spriteRS256_1D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ);
    end;
  end else begin
    if entry^.a and SPRITE_A_256MODE = 0 then begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        sprite16_2D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ)
      else
        sprite16_1D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ);
    end else begin
      if registers[DISPLAY_CR] and DISPLAY_CR_OBJ_1D = 0 then
        sprite256_2D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ)
      else
        sprite256_1D[funcIndex](y, entry, line, @wins, @ids, DISPLAY_ACTIVE_OBJ);
    end;
  end;
end;

//////////////////////////////////////////////////////////////////////

procedure BuildSpriteLists(y: integer);
var
  i, cycs: integer;
begin
  // Initialize the cycle counter to the number of cycles the sprite renderer has left
  if registers[DISPLAY_CR] or DISPLAY_CR_NOHBLOBJS <> 0 then cycs := 240*4 else cycs := 308*4;
  Dec(cycs, 6);

  // Clean up the list
  for i := 0 to 4 do spritePoints[i] := 255;

  // Build up to 4 display lists for visible sprites
  lastEntry := 0;
  for i := 0 to 127 do
    BuildSpriteEntry(y, i, cycs, false);
end;

//////////////////////////////////////////////////////////////////////

procedure RenderSprites(y: integer; priority: byte; line: Puint16; wins, ids: Puint8);
var
  i, j: integer;
begin
  if registers[DISPLAY_ACTIVE] and DISPLAY_ACTIVE_OBJ = 0 then Exit;

  i := spritePoints[priority];
  j := 0;
  while (i < 255) and (j < 128) do begin
    RenderSprite(i, y, line, wins, ids);
    i := spriteTable[i].next;
    Inc(j);
  end;
end;

//////////////////////////////////////////////////////////////////////

{$HINTS OFF}

//////////////////////////////////////////////////////////////////////

procedure RenderTextScreen0(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR, scrollX, scrollY: uint16);
{$INCLUDE gfxDrawText.pas}
{$DEFINE BLEND}{$DEFINE ABLEND}
procedure RenderTextScreen1(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR, scrollX, scrollY: uint16);
{$INCLUDE gfxDrawText.pas}
{$UNDEF ABLEND}{$DEFINE FADEUP}
procedure RenderTextScreen2(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR, scrollX, scrollY: uint16);
{$INCLUDE gfxDrawText.pas}
{$UNDEF FADEUP}{$DEFINE FADEDOWN}
procedure RenderTextScreen3(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR, scrollX, scrollY: uint16);
{$INCLUDE gfxDrawText.pas}
{$UNDEF FADEDOWN}{$UNDEF BLEND}

//////////////////////////////////////////////////////////////////////

procedure RenderRotScaleScreen0(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawRotScale.pas}
{$DEFINE BLEND}{$DEFINE ABLEND}
procedure RenderRotScaleScreen1(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawRotScale.pas}
{$UNDEF ABLEND}{$DEFINE FADEUP}
procedure RenderRotScaleScreen2(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawRotScale.pas}
{$UNDEF FADEUP}{$DEFINE FADEDOWN}
procedure RenderRotScaleScreen3(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawRotScale.pas}
{$UNDEF FADEDOWN}{$UNDEF BLEND}

//////////////////////////////////////////////////////////////////////

procedure RenderMode3Screen0(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP3.pas}
{$DEFINE BLEND}{$DEFINE ABLEND}
procedure RenderMode3Screen1(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP3.pas}
{$UNDEF ABLEND}{$DEFINE FADEUP}
procedure RenderMode3Screen2(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP3.pas}
{$UNDEF FADEUP}{$DEFINE FADEDOWN}
procedure RenderMode3Screen3(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP3.pas}
{$UNDEF FADEDOWN}{$UNDEF BLEND}

//////////////////////////////////////////////////////////////////////

procedure RenderMode4Screen0(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP4.pas}
{$DEFINE BLEND}{$DEFINE ABLEND}
procedure RenderMode4Screen1(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP4.pas}
{$UNDEF ABLEND}{$DEFINE FADEUP}
procedure RenderMode4Screen2(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP4.pas}
{$UNDEF FADEUP}{$DEFINE FADEDOWN}
procedure RenderMode4Screen3(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP4.pas}
{$UNDEF FADEDOWN}{$UNDEF BLEND}

//////////////////////////////////////////////////////////////////////

procedure RenderMode5Screen0(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP5.pas}
{$DEFINE BLEND}{$DEFINE ABLEND}
procedure RenderMode5Screen1(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP5.pas}
{$UNDEF ABLEND}{$DEFINE FADEUP}
procedure RenderMode5Screen2(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP5.pas}
{$UNDEF FADEUP}{$DEFINE FADEDOWN}
procedure RenderMode5Screen3(y: integer; line: Puint16; wins, ids: Puint8; mask: byte; CR: uint16; params: PRotScaleSet);
{$INCLUDE gfxDrawBMP5.pas}
{$UNDEF FADEDOWN}{$UNDEF BLEND}

//////////////////////////////////////////////////////////////////////

{$HINTS ON}

//////////////////////////////////////////////////////////////////////

const
  mode0funcs: array[0..3] of TTextRenderFunc =
    (RenderTextScreen0, RenderTextScreen1, RenderTextScreen2, RenderTextScreen3);
  mode1funcs: array[0..3] of TRSRenderFunc =
    (RenderRotScaleScreen0, RenderRotScaleScreen1, RenderRotScaleScreen2, RenderRotScaleScreen3);
  mode3funcs: array[0..3] of TRSRenderFunc =
    (RenderMode3Screen0, RenderMode3Screen1, RenderMode3Screen2, RenderMode3Screen3);
  mode4funcs: array[0..3] of TRSRenderFunc =
    (RenderMode4Screen0, RenderMode4Screen1, RenderMode4Screen2, RenderMode4Screen3);
  mode5funcs: array[0..3] of TRSRenderFunc =
    (RenderMode5Screen0, RenderMode5Screen1, RenderMode5Screen2, RenderMode5Screen3);

//////////////////////////////////////////////////////////////////////

function vmDrawScanline(y, width: integer): Puint16;
var
  i, bg, priority: uint32;
  color, CR: uint16;

  // Window stuff
  coeffa, x0, x1: integer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -