-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwrapper_util.pas
163 lines (139 loc) · 4.26 KB
/
wrapper_util.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
unit wrapper_util;
{$mode objfpc}{$H+}
interface
uses
SysUtils, Windows, Glide2x, tracefile;
var
g_ctx: record
data_16bit, data_24bit: PByte;
width, height, wxh: integer;
buffer_swaps, lfb_locks: integer;
lfb_write_trace: boolean;
lfb_write_buffer: pointer;
lfb_write_buffer_size: integer;
lfb_info: record
size: integer;
ptr: Pointer;
stride: TFxU32;
locked: boolean;
end;
end;
procedure InitGCtx();
procedure SaveFrontBuffer();
procedure SaveLfbPtr();
//should be available from Windows 98 on
function GetWriteWatch(dwFlags: DWORD; lpBaseAddress: PVOID; dwRegionSize: SIZE_T;
lpAddresses: PVOID; lpdwCount: PLongWord; lpdwGranularity: PLongWord): UINT;
stdcall; external 'kernel32.dll' Name 'GetWriteWatch';
const
WRITE_WATCH_FLAG_RESET = $01;
implementation
procedure Rgb565ToRgb24(const src, dst: pbyte; const w, h: integer);
var
i: integer;
r, g, b, c: integer;
begin
for i := 0 to w * h - 1 do
begin
c := (src[i * 2 + 1] shl 8) or src[i * 2 + 0];
b := (c and %00011111) shl 3;
g := ((c shr 5) and %00111111) shl 2;
r := ((c shr 11) and %00011111) shl 3;
//fill lowest bits - not strictly needed but nicer?
b := b or (b shr 5);
g := g or (g shr 6);
r := r or (r shr 5);
dst[i * 3 + 0] := byte(r);
dst[i * 3 + 1] := byte(g);
dst[i * 3 + 2] := byte(b);
end;
end;
procedure PnmSave(const fname: string; const p: pbyte; const w, h: word);
var
f: file;
c: PChar;
begin
c := PChar(format('P6'#10'%d %d'#10'255'#10, [w, h]));
AssignFile(f, fname);
Rewrite(f, 1);
BlockWrite(f, c^, strlen(c));
BlockWrite(f, p^, w * h * 3);
CloseFile(f);
end;
procedure InitGCtx;
var
w, h, wxh: integer;
lfb_valloc_flags: integer;
begin
with g_ctx do
begin
buffer_swaps := 0;
lfb_locks := 0;
wxh := 0;
lfb_write_trace := False;
lfb_write_buffer := nil;
lfb_info.locked := False;
end;
g_ctx.lfb_write_trace := false; //experimental
w := grSstScreenWidth();
h := grSstScreenHeight();
wxh := w * h;
Trace(format('InitGBuffer %dx%d', [w, h]));
if g_ctx.wxh < wxh then
begin
if g_ctx.wxh > 0 then
begin
freemem(g_ctx.data_16bit);
if g_ctx.lfb_write_buffer <> nil then
VirtualFree(g_ctx.lfb_write_buffer, 0, MEM_RELEASE);
//todo free valloc;
end;
g_ctx.width := w;
g_ctx.height := h;
g_ctx.wxh := wxh;
g_ctx.data_16bit := GetMem(wxh * 5);
g_ctx.data_24bit := g_ctx.data_16bit + wxh * 2;
if g_ctx.lfb_write_trace then
begin
g_ctx.lfb_write_buffer_size := wxh * 8; //todo height * max.stride
lfb_valloc_flags := MEM_COMMIT or MEM_RESERVE or MEM_WRITE_WATCH;
g_ctx.lfb_write_buffer := VirtualAlloc(nil, g_ctx.lfb_write_buffer_size, lfb_valloc_flags, PAGE_READWRITE);
if g_ctx.lfb_write_buffer = nil then
Trace('VirtualAlloc failed with errno ' + IntToStr(GetLastError));
end;
end;
end;
procedure SaveFrontBuffer();
var
ok: TFxBOOL;
begin
if g_ctx.wxh <= 0 then
exit;
ok := grLfbReadRegion(GR_BUFFER_FRONTBUFFER, 0, 0, g_ctx.width, g_ctx.height, g_ctx.width * 2, g_ctx.data_16bit);
if ok then
begin
Rgb565ToRgb24(g_ctx.data_16bit, g_ctx.data_24bit, g_ctx.width, g_ctx.height);
PnmSave(format('screenshots\screen_%0.6d.pnm', [g_ctx.buffer_swaps]), g_ctx.data_24bit, g_ctx.width, g_ctx.height);
end;
end;
procedure SaveLfbPtr();
const
MAX_ADR = 1200; //max glide window height
var
used_adresses: array[0..MAX_ADR] of pointer;
used_adresses_count, page_size: longword;
gww_ok: longword;
begin
used_adresses_count := MAX_ADR;
gww_ok := GetWriteWatch(WRITE_WATCH_FLAG_RESET,
g_ctx.lfb_write_buffer, g_ctx.lfb_write_buffer_size,
@used_adresses[0], @used_adresses_count, @page_size);
if gww_ok <> 0 then begin
Trace('something went wrong with LFB tracing...');
exit;
end;
Trace(format('adr: %d pagesize: %d', [used_adresses_count, page_size]));
Rgb565ToRgb24(g_ctx.lfb_write_buffer, g_ctx.data_24bit, g_ctx.width, g_ctx.height);
PnmSave(format('lfbptr_%0.6d.pnm', [g_ctx.lfb_locks]), g_ctx.data_24bit, g_ctx.width, g_ctx.height);
end;
end.