📄 cpugraphics.pas
字号:
{$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 + -