observervram.pas

来自「一个不出名的GBA模拟器」· PAS 代码 · 共 892 行 · 第 1/2 页

PAS
892
字号
procedure TjdevVRAMViewer.reloadLayersFromDispCR(Sender: TObject);
var
  da: byte;
  index: integer;
begin
  da := vmReadByte($04000000 + DISPLAY_ACTIVE);
  for index := 0 to 7 do
    activeLayers.Checked[index] := da and (1 shl index) <> 0;
  UpdateObserver;
end;

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

procedure TjdevVRAMViewer.SaveLayersToDispCR(Sender: TObject);
var
  da: byte;
  index: integer;
begin
  da := 0;
  for index := 0 to 7 do
    if activeLayers.Checked[index] then da := da or (1 shl index);
  vmWriteByte($04000000 + DISPLAY_ACTIVE, da);
end;

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

procedure TjdevVRAMViewer.imageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  layerWatchX := X;
  layerWatchY := Y;

  lLayerPos.Caption := Format('Position: (%d, %d)', [layerWatchX, layerWatchY]);
  lLayerLayer.Caption := 'Top layer: <n/a>';
  lLayerColor.Caption := 'Color: <n/a>';

  lLayerPos.Visible := true;
  lLayerLayer.Visible := true;
  lLayerColor.Visible := true;

  UpdateObserver;
end;

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

procedure TjdevVRAMViewer.SaveToFile(Sender: TObject);
begin
  saveDialog.Filter := 'Bitmap Images|*.bmp|All files|*.*';
  saveDialog.DefaultExt := 'bmp';
  if saveDialog.Execute then myScreen.SaveToFile(saveDialog.FileName);
end;

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

procedure TjdevVRAMViewer.CopyToClipboard(Sender: TObject);
var
  myFormat: word;
  data: THandle;
  pal: HPalette;
begin
  myScreen.SaveToClipBoardFormat(myFormat, data, pal);
  clipboard.SetAsHandle(myFormat, data);
end;

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

procedure TjdevVRAMViewer.DispScreen;
var
  x, y: integer;
begin
  if pages.activePageIndex = 0 then begin
    image.Canvas.StretchDraw(Rect(0, 0, mult*256, mult*256), myScreen);

    x := lastFx;
    y := lastFy;

    // Draw the main piece
    image.Canvas.DrawFocusRect(Rect(x*mult, y*mult, (x+240)*mult-1, (y+160)*mult-1));

    // Display the (bottom) left wraparound portion if any
    if x+240 >= tileWidth then begin
      x := x - tileWidth;
      image.Canvas.DrawFocusRect(Rect(x*mult, y*mult, (x+240)*mult-1, (y+160)*mult-1));
    end;

    // Draw the top wraparound portions, if any
    if y+160 >= tileHeight then begin
      // Draw the top (left) wraparound portion
      y := y - tileHeight;
      image.Canvas.DrawFocusRect(Rect(x*mult, y*mult, (x+240)*mult-1, (y+160)*mult-1));

      // Draw the top right wraparound portion (if any)
      if x <> lastFx then begin
        x := lastFx;
        image.Canvas.DrawFocusRect(Rect(x*mult, y*mult, (x+240)*mult-1, (y+160)*mult-1));
      end;
    end;
  end else begin
    image.Canvas.StretchDraw(Rect(-mult*horizScroll.Position, -mult*vertScroll.Position,
                                  256*mult-mult*horizScroll.Position, 256*mult-mult*vertScroll.Position), myScreen);
  end;
end;

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

procedure TjdevVRAMViewer.imagePaint(Sender: TObject);
begin
  DispScreen;
end;

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

procedure TjdevVRAMViewer.DoScrollbar;
var
  i: integer;
begin
  mult := magnifier.position;
  case pages.ActivePageIndex of
    0: begin
      i := cbScreenSize.ItemIndex;
      if i = -1 then i := 0;

      if rRotScale.Checked then begin
        horizScroll.Max := Max(rotScaleSizes[i].x - 1 - image.width div mult, 0);
        vertScroll.Max := Max(rotScaleSizes[i].y - 1 - image.height div mult, 0);
        r256Colors.Checked := true;
        tileWidth := rotScaleSizes[i].x;
        tileHeight := rotScaleSizes[i].y;
      end else begin
        horizScroll.Max := Max(normalSizes[i].x - 1 - image.width div mult, 0);
        vertScroll.Max := Max(normalSizes[i].y - 1 - image.height div mult, 0);
        tileWidth := normalSizes[i].x;
        tileHeight := normalSizes[i].y;
      end;
    end;
    1: begin
      horizScroll.Max := Max(127 - image.width div mult, 0);
      vertScroll.Max := Max(127 - image.height div mult, 0);
    end;
    2: begin
      horizScroll.Max := Max(255 - image.width div mult, 0);
      vertScroll.Max := Max(127 - image.height div mult, 0);
    end;
    3, 4: begin
      horizScroll.Max := Max(239 - image.width div mult, 0);
      vertScroll.Max := Max(159 - image.height div mult, 0);
    end;
  end;
  horizScroll.Enabled := horizScroll.Max <> 0;
  vertScroll.Enabled := vertScroll.Max <> 0;
end;

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

procedure TjdevVRAMViewer.RenderTileMap;
var
  x, y: integer;
  line: Puint16;
begin
  // Render a tile map
  Puint16(@(banks.iospace^[BG2_CR]))^ := PackBgSettings;
  banks.iospace^[DISPLAY_ACTIVE] := 4;

  if rRotScale.Checked then begin
    banks.iospace^[DISPLAY_CR] := 1;
    Puint16(@(banks.iospace^[BG2_A]))^ := 256;
    Puint16(@(banks.iospace^[BG2_C]))^ := 0;
    Puint32(@(banks.iospace^[BG2_X]))^ := horizScroll.Position shl 8;
    Puint32(@(banks.iospace^[BG2_Y]))^ := vertScroll.Position shl 8;
  end else begin
    banks.iospace^[DISPLAY_CR] := 0;
    Puint16(@(banks.iospace^[BG2_X0]))^ := horizScroll.Position;
    Puint16(@(banks.iospace^[BG2_Y0]))^ := vertScroll.Position;
  end;

  // Draw the screen
  for y := 0 to 255 do begin
    line := vmDrawScanline(y, 256);
    Move(line^, myScreen.ScanLine[y]^, 256*2);
    Inc(Puint32(@(banks.iospace^[BG2_Y]))^, 256);
  end;

  // Draw some selection windows
  if rRotScale.Checked then begin
    x := Puint32(@(backups[BG2_X + cbBackgrounds.ItemIndex*$10]))^ shr 8;
    y := Puint32(@(backups[BG2_Y + cbBackgrounds.ItemIndex*$10]))^ shr 8;
  end else begin
    x := Puint16(@(backups[BG0_X0 + cbBackgrounds.ItemIndex*4]))^;
    y := Puint16(@(backups[BG0_Y0 + cbBackgrounds.ItemIndex*4]))^;
  end;
  x := x - horizScroll.Position;
  y := y - vertScroll.Position;

  lastFx := x;
  lastFy := y;

  lTileMapCR.Caption := 'Current CR: $' + IntToHex(PackBgSettings, 4);
end;

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

procedure TjdevVRAMViewer.RenderTiles;
var
  x, y, rbase, base, palBase: integer;
  pix: uint16;
  line: Puint16;
begin
  // BG tile rendering
  // Render tiles
  if cbTileSetTiles.ItemIndex < 0 then cbTileSetTiles.ItemIndex := 0;
  rbase := cbTileSetTiles.ItemIndex * $4000;

  if r256ColorTiles.Checked then begin
    // Draw the tiles as 256 color ones
    for y := 0 to 127 do begin
      base := rbase + (y and 7) shl 3 + (y shr 3) shl 10;
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 127 do begin
        pix := banks.VRAM[base + x and 7 + (x shr 3) shl 6];
        pix := Puint16(@(banks.palette[pix shl 1]))^;
        line^ := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
        Inc(line);
      end;

      // Fill the rest of the line with backdrop
      pix := Puint16(@(banks.palette[0]))^;
      pix := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
      for x := 128 to 255 do begin
        line^ := pix;
        Inc(line);
      end;
    end;

    // Fill the rest of the lines with backdrop
    pix := Puint16(@(banks.palette[0]))^;
    pix := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
    for y := 128 to 255 do begin
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 255 do begin
        line^ := pix;
        Inc(line);
      end;
    end;
  end else begin
    // Draw the tiles as 16 color ones
    palBase := paletteBase.Position*32;
    for y := 0 to 127 do begin
      base := rbase + (y and 7) shl 2 + (y shr 3) shl 10;
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 255 do begin
        pix := banks.VRAM[base + (x and 7) shr 1 + (x shr 3) shl 5];
        if Odd(x) then pix := pix shr 4 else pix := pix and $F;
        pix := Puint16(@(banks.palette[pix shl 1 + palBase]))^;
        line^ := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
        Inc(line);
      end;
    end;

    // Fill the rest of the lines with backdrop
    pix := Puint16(@(banks.palette[0]))^;
    pix := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
    for y := 128 to 255 do begin
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 255 do begin
        line^ := pix;
        Inc(line);
      end;
    end;
  end;
end;

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

procedure TjdevVRAMViewer.RenderSprites;
var
  x, y, rbase, base, palBase: integer;
  pix: uint16;
  line: Puint16;
begin
  // Sprite tile rendering
  // Render sprites
  if r256ColorSprites.Checked then begin
    rbase := $10000;
    palBase := 512;
    // Draw the tiles as 256 color ones
    for y := 0 to 127 do begin
      base := rbase + (y and 7) shl 3 + (y shr 3) shl 11;
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 255 do begin
        pix := banks.VRAM[base + x and 7 + (x shr 3) shl 6];
        pix := Puint16(@(banks.palette[pix shl 1 + palBase]))^;
        line^ := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
        Inc(line);
      end;
    end;

    // Fill the rest of the lines with backdrop
    pix := Puint16(@(banks.palette[0]))^;
    pix := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
    for y := 128 to 255 do begin
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 255 do begin
        line^ := pix;
        Inc(line);
      end;
    end;
  end else begin
    // Draw the tiles as 16 color ones
    palBase := paletteBase2.Position*32+512;
    for y := 0 to 255 do begin
      base := $10000 + (y and 7) shl 2 + (y shr 3) shl 10;
      line := @(myScreen.ScanLine[y]^);
      for x := 0 to 255 do begin
        pix := banks.VRAM[base + (x and 7) shr 1 + (x shr 3) shl 5];
        if Odd(x) then pix := pix shr 4 else pix := pix and $F;
        pix := Puint16(@(banks.palette[pix shl 1 + palBase]))^;
        line^ := (pix shr 10) and $1f + (pix and $1f) shl 10 + ((pix shr 5) and $1f) shl 5;
        Inc(line);
      end;
    end;
  end;
end;

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

procedure TjdevVRAMViewer.RenderFramebuffer;
var
  x, y: integer;
  pix: uint16;
  line: Puint16;
begin
  // Framebuffer rendering
  // Render the frame buffer
  banks.iospace^[DISPLAY_ACTIVE] := 4;
  if rMode4fb0.Checked then
    banks.iospace^[DISPLAY_CR] := 4
  else if rMode4fb1.Checked then
    banks.iospace^[DISPLAY_CR] := 4 or DISPLAY_CR_FB
  else if rMode5fb0.Checked then
    banks.iospace^[DISPLAY_CR] := 5
  else if rMode5fb1.Checked then
    banks.iospace^[DISPLAY_CR] := 5 or DISPLAY_CR_FB
  else
    banks.iospace^[DISPLAY_CR] := 3;

  Puint32(@(banks.iospace^[BG2_X]))^ := 0;
  Puint32(@(banks.iospace^[BG2_Y]))^ := 0;

  for y := 0 to 159 do begin
    // Render a bitmapped scanline
    line := vmDrawScanline(y, 256);
    Move(line^, myScreen.ScanLine[y]^, 256*2);
    Inc(Puint32(@(banks.iospace^[BG2_Y]))^, 256);

    // Fill the rest of the line with backdrop
    line := @(PWordArray(line)^[240]);
    pix := Puint16(@(banks.palette[0]))^;
    for x := 240 to 255 do begin
      line^ := pix;
      Inc(line);
    end;
  end;

  // Fill the rest of the lines with backdrop
  pix := Puint16(@(banks.palette[0]))^;
  for y := 160 to 255 do begin
    line := @(myScreen.ScanLine[y]^);
    for x := 0 to 255 do begin
      line^ := pix;
      Inc(line);
    end;
  end;
end;

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

procedure TjdevVRAMViewer.RenderLayers;
var
  x, y: integer;
  pix: uint16;
  line: Puint16;
begin
  // Layer rendering
  pix := 0;
  for y := 0 to 7 do
    if activeLayers.Checked[y] then pix := pix or (1 shl y);
      banks.iospace^[DISPLAY_ACTIVE] := pix;

  for y := 0 to 159 do begin
    // Draw
    line := vmDrawScanline(y, 256);
    Move(line^, myScreen.ScanLine[y]^, 256*2);
    Inc(Puint32(@(banks.iospace^[BG2_Y]))^, 256);

    // Layer watch
    if (y = layerWatchY) and (layerWatchX > -1) and (layerWatchX < 240) then begin
      pix := PWordArray(line)^[layerWatchX];
      lLayerLayer.Caption := Format('Top layer: %s', [layerStrings[vmGetLayerID(layerWatchX)] ]);
      lLayerColor.Caption := Format('Color: (%d, %d, %d)', [(pix shr 10) and $1F, (pix shr 5) and $1F, pix and $1F]);
    end;

    // Fill the rest of the line with backdrop
    line := @(PWordArray(line)^[240]);
    pix := Puint16(@(banks.palette[0]))^;
    for x := 240 to 255 do begin
      line^ := pix;
      Inc(line);
    end;
  end;

  // Fill the rest of the lines with backdrop
  pix := Puint16(@(banks.palette[0]))^;
  for y := 160 to 255 do begin
    line := @(myScreen.ScanLine[y]^);
    for x := 0 to 255 do begin
      line^ := pix;
      Inc(line);
    end;
  end;
end;

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

procedure TjdevVRAMViewer.LoadSettings(ini: TIniFile);
begin
  inherited;
  zoom := ini.ReadInteger(OCaption, 'Zoom', 1);
  pageIndex := ini.ReadInteger(OCaption, 'LastPage', 0);
end;

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

procedure TjdevVRAMViewer.SaveSettings(ini: TIniFile);
begin
  inherited;
  ini.WriteInteger(OCaption, 'Zoom', zoom);
  ini.WriteInteger(OCaption, 'LastPage', pageIndex);
end;

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

initialization
  RegisterViewer(TjdevVRAMViewer);
end.

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

⌨️ 快捷键说明

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