{
SettingsWindow используется для создания окна, в котором пользователь
производит настройку Малик Эмулятора на свой вкус и предпочтения.
Этот исходный текст является частью Малик Эмулятора.
Следующие файлы используются этим исходным текстом:
settingswindow.lfm
На них так же распространяются те же права, как и на этот исходный текст.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Малик Эмулятор – свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Малик Эмулятор распространяется в надежде, что он может быть полезен,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit SettingsWindow;
{$MODE DELPHI}
interface
uses
Classes,
SysUtils,
Forms,
Graphics,
Dialogs,
StdCtrls,
ComCtrls,
ExtCtrls,
Lang,
Images,
EmulThemes,
StaticRecompilers,
EmulatorInterfaces;
{%region public }
type
TRadioButton_Array1d = array of TRadioButton;
AdjustableRecompiler_Array1d = array of AdjustableRecompiler;
TSettingsForm = class(TForm, _Interface, GraphicListener)
settingsTabs: TPageControl;
emulatorTab: TTabSheet;
behavior: TGroupBox;
fullscreenOnLaunch: TCheckBox;
closeOnTerminate: TCheckBox;
graphicScalingAlgorithm: TGroupBox;
graphicScalingWhyAlgorithm: TLabel;
graphicScalingSystem: TRadioButton;
graphicScalingNearest: TRadioButton;
graphicScalingScaleNx: TRadioButton;
graphicScalingHqNx: TRadioButton;
graphicScalingStandard: TRadioButton;
maximumFrames: TGroupBox;
maximumFramesValue: TTrackBar;
maximumFramesLabel: TLabel;
themeTab: TTabSheet;
themeSelectorLabel: TLabel;
themeSelector: TComboBox;
themePreviewLabel: TLabel;
themePreview: TPaintBox;
themeComment: TLabel;
disasmTab: TTabSheet;
disasmSelectorLabel: TLabel;
disasmSelector: TComboBox;
disasmColorLabel: TLabel;
disasmColor: TColorButton;
disasmPreviewLabel: TLabel;
disasmPreview: TPaintBox;
recompilerTab: TTabSheet;
recompilerSelectorLabel: TLabel;
recompilerSelector: TComboBox;
recompilerBevel: TBevel;
recompilerAlignment: TCheckBox;
recompilerCompression: TGroupBox;
recompilerCompressionSelector: TTrackBar;
recompilerCompressionLabel1: TLabel;
recompilerCompressionLabel2: TLabel;
recompilerStack: TGroupBox;
recompilerStackSelector: TTrackBar;
recompilerStackLabel1: TLabel;
recompilerStackLabel2: TLabel;
recompilerStackLabel3: TLabel;
recompilerHeap: TGroupBox;
recompilerHeapSelector: TTrackBar;
recompilerHeapLabel1: TLabel;
recompilerHeapLabel2: TLabel;
recompilerHeapLabel3: TLabel;
recompilerExecFileNameLabel: TLabel;
recompilerExecFileName: TEdit;
recompilerExecFileExt: TLabel;
closeButton: TButton;
procedure formShow(sender: TObject);
procedure radioButtonEnter(sender: TObject);
procedure maximumFramesValueChange(sender: TObject);
procedure themeSelectorChange(sender: TObject);
procedure themePreviewPaint(sender: TObject);
procedure disasmSelectorChange(sender: TObject);
procedure disasmColorChange(sender: TObject);
procedure disasmPreviewPaint(sender: TObject);
procedure recompilerSelectorChange(sender: TObject);
procedure recompilerAlignmentChange(sender: TObject);
procedure recompilerCompressionSelectorChange(sender: TObject);
procedure recompilerStackSelectorChange(sender: TObject);
procedure recompilerHeapSelectorChange(sender: TObject);
procedure recompilerExecFileNameChange(sender: TObject);
private
owner: MainWindowInterface;
algorithms: TRadioButton_Array1d;
themeImage: TBitmap;
themeImagePixels: PIntArray;
disasmColors: int_Array1d;
disasmImage: TBitmap;
recompilers: AdjustableRecompiler_Array1d;
function getScalingAlgorithm(): AnsiString;
procedure drawWindow(t: Theme; state, left, top, width, height: int);
procedure drawTheme(t: Theme);
procedure drawDisasm();
public
constructor create(theOwner: TComponent); override;
destructor destroy; override;
procedure afterConstruction(); override;
procedure beforeDestruction(); override;
{ _Interface }
function getClass(): _Class;
function asObject(): TObject;
{ GraphicListener }
procedure putPixel(x, y, argb: int);
end;
{%endregion}
implementation
{$R *.LFM}
{%region private }
var
SCALING_ALGORITHMS: AnsiString_Array1d;
{%endregion}
{%region routine }
function toSettingString(value: boolean): AnsiString; overload;
begin
if value then begin
result := '1';
end else begin
result := '0';
end;
end;
function toSettingString(value: long): AnsiString; overload;
begin
result := toDecString(value);
end;
function TRadioButton_Array1d_create(length: int): TRadioButton_Array1d;
begin
setLength(result, length);
end;
function toTRadioButtonArray1d(const arr: array of TRadioButton): TRadioButton_Array1d;
begin
setLength(result, length(arr));
move(arr[0], result[0], length(result) * sizeof(_Object));
end;
procedure arraycopy(const src: TRadioButton_Array1d; srcOffset: int; const dst: TRadioButton_Array1d; dstOffset: int; length: int); overload;
var
lim: int;
len: int;
begin
lim := srcOffset + length;
len := System.length(src);
if (lim > len) or (lim < srcOffset) or (srcOffset < 0) or (srcOffset > len) then begin
raise ArrayIndexOutOfBoundsException.create('arraycopy: индекс элемента массива выходит из диапазона.');
end;
lim := dstOffset + length;
len := System.length(dst);
if (lim > len) or (lim < dstOffset) or (dstOffset < 0) or (dstOffset > len) then begin
raise ArrayIndexOutOfBoundsException.create('arraycopy: индекс элемента массива выходит из диапазона.');
end;
move(src[srcOffset], dst[dstOffset], length * sizeof(_Object));
end;
function AdjustableRecompiler_Array1d_create(length: int): AdjustableRecompiler_Array1d;
begin
setLength(result, length);
end;
function toAdjustableRecompilerArray1d(const arr: array of AdjustableRecompiler): AdjustableRecompiler_Array1d;
var
i: int;
begin
setLength(result, length(arr));
for i := length(result) - 1 downto 0 do begin
result[i] := arr[i];
end;
end;
procedure arraycopy(const src: AdjustableRecompiler_Array1d; srcOffset: int; const dst: AdjustableRecompiler_Array1d; dstOffset: int; length: int); overload;
var
lim: int;
len: int;
i: int;
begin
lim := srcOffset + length;
len := System.length(src);
if (lim > len) or (lim < srcOffset) or (srcOffset < 0) or (srcOffset > len) then begin
raise ArrayIndexOutOfBoundsException.create('arraycopy: индекс элемента массива выходит из диапазона.');
end;
lim := dstOffset + length;
len := System.length(dst);
if (lim > len) or (lim < dstOffset) or (dstOffset < 0) or (dstOffset > len) then begin
raise ArrayIndexOutOfBoundsException.create('arraycopy: индекс элемента массива выходит из диапазона.');
end;
if (src = dst) and (srcOffset < dstOffset) then begin
for i := length - 1 downto 0 do begin
dst[dstOffset + i] := src[srcOffset + i];
end;
end else begin
for i := 0 to length - 1 do begin
dst[dstOffset + i] := src[srcOffset + i];
end;
end;
end;
{%endregion}
{%region TSettingsForm }
constructor TSettingsForm.create(theOwner: TComponent);
begin
inherited create(nil);
theOwner.getInterface(stringToGUID(MAIN_WINDOW_INTERFACE_GUID), owner);
themeImage := TBitmap.create();
themeImagePixels := createPixelImage(themeImage, themePreview.width, themePreview.height);
disasmImage := TBitmap.create();
end;
destructor TSettingsForm.destroy;
begin
disasmImage.free();
themeImage.free();
inherited destroy;
end;
procedure TSettingsForm.formShow(sender: TObject);
begin
disasmColor.height := disasmSelector.height;
end;
procedure TSettingsForm.radioButtonEnter(sender: TObject);
begin
(sender as TRadioButton).checked := true;
end;
procedure TSettingsForm.maximumFramesValueChange(sender: TObject);
begin
maximumFramesLabel.caption := toDecString(long(maximumFramesValue.position));
end;
procedure TSettingsForm.themeSelectorChange(sender: TObject);
begin
drawTheme(getTheme(themeSelector.itemIndex));
themePreviewPaint(themePreview);
end;
procedure TSettingsForm.themePreviewPaint(sender: TObject);
begin
themePreview.canvas.draw(0, 0, themeImage);
end;
procedure TSettingsForm.disasmSelectorChange(sender: TObject);
begin
disasmColor.buttonColor := byteSwap(disasmColors[disasmSelector.itemIndex]) shr 8;
end;
procedure TSettingsForm.disasmColorChange(sender: TObject);
begin
disasmColors[disasmSelector.itemIndex] := byteSwap(disasmColor.buttonColor) shr 8;
drawDisasm();
disasmPreviewPaint(disasmPreview);
end;
procedure TSettingsForm.disasmPreviewPaint(sender: TObject);
begin
disasmPreview.canvas.draw(0, 0, disasmImage);
end;
procedure TSettingsForm.recompilerSelectorChange(sender: TObject);
var
recompiler: AdjustableRecompiler;
begin
recompiler := self.recompilers[recompilerSelector.itemIndex];
recompilerAlignment.checked := recompiler.getAlignment();
recompilerCompressionSelector.position := recompiler.getCompressionLevel();
recompilerStackSelector.position := recompiler.getStackSize();
recompilerHeapSelector.position := recompiler.getHeapSize() shr 10;
recompilerExecFileName.text := recompiler.getOutputExecutableFileName();
end;
procedure TSettingsForm.recompilerAlignmentChange(sender: TObject);
begin
recompilers[recompilerSelector.itemIndex].setAlignment(recompilerAlignment.checked);
end;
procedure TSettingsForm.recompilerCompressionSelectorChange(sender: TObject);
var
value: int;
begin
value := recompilerCompressionSelector.position;
recompilers[recompilerSelector.itemIndex].setCompressionLevel(value);
end;
procedure TSettingsForm.recompilerStackSelectorChange(sender: TObject);
var
value: int;
begin
value := recompilerStackSelector.position;
recompilers[recompilerSelector.itemIndex].setStackSize(value);
recompilerStackLabel2.caption := toDecString(value);
end;
procedure TSettingsForm.recompilerHeapSelectorChange(sender: TObject);
var
value: int;
r: AdjustableRecompiler;
begin
value := recompilerHeapSelector.position;
r := recompilers[recompilerSelector.itemIndex];
r.setHeapSize(value shl 10);
r.setDescriptorsSize(value shl 5);
recompilerHeapLabel2.caption := toDecString(value);
end;
procedure TSettingsForm.recompilerExecFileNameChange(sender: TObject);
var
value: AnsiString;
i: int;
begin
value := recompilerExecFileName.text;
for i := length(value) downto 1 do begin
if value[i] in ['\', '|', '*', ':', '?', '"', '<', '>'] then begin
delete(value, i, 1);
end;
end;
recompilers[recompilerSelector.itemIndex].setOutputExecutableFileName(value);
recompilerExecFileName.text := value;
end;
function TSettingsForm.getScalingAlgorithm(): AnsiString;
var
i: int;
j: int;
begin
j := 0;
for i := 1 to length(algorithms) - 1 do begin
if algorithms[i].checked then begin
j := i;
break;
end;
end;
result := SCALING_ALGORITHMS[j];
end;
procedure TSettingsForm.drawWindow(t: Theme; state, left, top, width, height: int);
var
tbh: int;
bbh: int;
lbw: int;
rbw: int;
bis: int;
b1s: int;
b2s: int;
b3s: int;
b4s: int;
b5s: int;
w: int;
h: int;
i: int;
j: int;
k: int;
begin
case state of
1: bis := 3;
2: bis := 5;
else
bis := 0;
end;
state := (state shl 16) + $06;
tbh := short(t.getSizes(state) shr 16);
bbh := short(t.getSizes(state + $0400) shr 16);
lbw := short(t.getSizes(state + $0200));
rbw := short(t.getSizes(state + $0300));
bis := (bis shl 16) + $06;
b1s := t.getSizes(bis + $1600);
b2s := t.getSizes(bis + $1500);
b3s := t.getSizes(bis + $1200);
b4s := t.getSizes(bis + $1100);
b5s := t.getSizes(bis + $1000);
tbh := max(tbh, max(short(b1s shr 16), max(short(b2s shr 16), max(short(b3s shr 16), max(short(b4s shr 16), short(b5s shr 16))))));
t.drawElement(self, state, left, top, width, tbh);
t.drawElement(self, state + $0200, left, top + tbh, lbw, height - tbh - bbh);
t.drawElement(self, state + $0300, left + width - rbw, top + tbh, rbw, height - tbh - bbh);
t.drawElement(self, state + $0400, left, top + height - bbh, width, bbh);
t.drawElement(self, state + $0500, left + lbw, top + tbh, width - lbw - rbw, height - tbh - bbh);
t.drawElement(self, bis + $1600, left + width - rbw - short(b1s) - short(b2s) - short(b3s) - short(b4s) - short(b5s), top, short(b1s), short(b1s shr 16));
t.drawElement(self, bis + $1500, left + width - rbw - short(b2s) - short(b3s) - short(b4s) - short(b5s), top, short(b2s), short(b2s shr 16));
t.drawElement(self, bis + $1200, left + width - rbw - short(b3s) - short(b4s) - short(b5s), top, short(b3s), short(b3s shr 16));
t.drawElement(self, bis + $1100, left + width - rbw - short(b4s) - short(b5s), top, short(b4s), short(b4s shr 16));
t.drawElement(self, bis + $1000, left + width - rbw - short(b5s), top, short(b5s), short(b5s shr 16));
if (state shr 16) <> 0 then begin
exit;
end;
inc(left, lbw);
inc(top, tbh);
dec(width, lbw + rbw);
dec(height, tbh + bbh);
bbh := max(16, short(t.getSizes($020d) shr 16));
w := max(100, short(t.getSizes($0004)));
h := max(16, short(t.getSizes($0004) shr 16));
t.drawElement(self, $0004, left, top, w, h);
t.drawElement(self, $0304, left, top + h + 4, w, h);
t.drawElement(self, $0104, left, top + 2 * h + 8, w, h);
t.drawElement(self, $0204, left, top + 3 * h + 12, w, h);
i := (633 * width) shr 10;
t.drawElement(self, $010d, left, top + height - bbh, i, bbh);
t.drawElement(self, $020d, left + i, top + height - bbh, width - i, bbh);
inc(left, w + 4);
inc(top, 0);
dec(width, w + 4);
dec(height, bbh);
t.drawElement(self, $0108, left, top, width, height);
w := max(8, short(t.getSizes($050a)));
h := max(8, short(t.getSizes($040a) shr 16));
k := height - 3 * h - 4;
i := k div 3;
j := (k div 3) + 1;
k := k - i - j;
t.drawElement(self, $000a, left + width - w - 2, top + 2, w, h);
t.drawElement(self, $080a, left + width - w - 2, top + h + 2, w, i);
t.drawElement(self, $050a, left + width - w - 2, top + h + i + 2, w, j);
t.drawElement(self, $090a, left + width - w - 2, top + h + i + j + 2, w, k);
t.drawElement(self, $010a, left + width - w - 2, top + height - 2 * h - 2, w, h);
k := width - 3 * w - 4;
i := k div 3;
j := (k div 3) + 1;
k := k - i - j;
t.drawElement(self, $020a, left + 2, top + height - h - 2, w, h);
t.drawElement(self, $060a, left + w + 2, top + height - h - 2, i, h);
t.drawElement(self, $040a, left + w + i + 2, top + height - h - 2, j, h);
t.drawElement(self, $070a, left + w + i + j + 2, top + height - h - 2, k, h);
t.drawElement(self, $030a, left + width - 2 * w - 2, top + height - h - 2, w, h);
t.drawElement(self, $0c0a, left + width - w - 2, top + height - h - 2, w, h);
end;
procedure TSettingsForm.drawTheme(t: Theme);
var
w: int;
h: int;
c: int;
i: int;
begin
w := themeImage.width;
h := themeImage.height;
c := t.getSystemColor(1) and $00ffffff;
for i := w * h - 1 downto 0 do begin
themeImagePixels[i] := c;
end;
drawWindow(t, 1, 10, 10, 400, 140);
drawWindow(t, 0, 20, 30, 400, 140);
end;
procedure TSettingsForm.drawDisasm();
var
f: int;
i: int;
j: int;
k: int;
l: int;
t: int;
w: int;
h: int;
c1: int;
c2: int;
r: AnsiString;
s: AnsiString_Array1d;
strings: AnsiString_Array2d;
rect: TRect;
begin
disasmImage.setSize(disasmPreview.width, disasmPreview.height);
with disasmImage.canvas do begin
font := disasmPreview.font;
f := abs(font.height);
textWidth(#32); { без этой строки не будет корректно работать brush.color := clBtnFace }
brush.style := bsSolid;
brush.color := clBtnFace;
fillRect(0, 0, width, height);
brush.style := bsClear;
pen.style := psSolid;
pen.color := clWindowText;
pen.width := 1;
{ стак }
strings := toStringArray2d([
toStringArray1d(['null', 'overflow']),
toStringArray1d(['<пусто>']),
toStringArray1d(['<пусто>']),
toStringArray1d(['<пусто>']),
toStringArray1d(['$8219ed IF=0', 'ireturn']),
toStringArray1d(['1 ($1)', 'int']),
toStringArray1d(['$0094c578', 'object']),
toStringArray1d(['EIP=$8219f4 EBP=$240…', 'except']),
toStringArray1d(['<пусто>']),
toStringArray1d(['$24017d0', 'oldebp']),
toStringArray1d(['$817e07', 'return']),
toStringArray1d(['null', 'object'])
]);
w := textWidth('<пусто>');
h := height;
for i := 0 to length(strings) - 1 do begin
k := 0;
s := strings[i];
for j := 0 to length(s) - 1 do begin
inc(k, textWidth(s[j]));
if j > 0 then begin
inc(k, textWidth(#32));
end;
end;
if k > w then begin
w := k;
end;
end;
inc(w, 2);
l := width - w;
t := 0;
rectangle(bounds(l, t, w, h));
rect := bounds(l + 1, t + 1, w - 2, h - 2);
font.color := clWindowText;
textRect(rect, l + 1, t, 'Стак');
k := t + f + 1;
moveTo(l, k);
lineTo(l + w, k);
if f = 0 then begin
exit;
end;
j := (h - k - 1) div f;
font.color := byteSwap(disasmColors[0]) shr 8;
for i := -length(strings) + j - 1 downto 0 do begin
textRect(rect, l + 1, k, '<пусто>');
inc(k, f);
end;
for i := 0 to length(strings) - 1 do begin
s := strings[i];
if length(s) > 1 then begin
r := s[1];
if r = 'overflow' then begin
c1 := byteSwap(disasmColors[2]) shr 8;
c2 := byteSwap(disasmColors[13]) shr 8;
end else
if r = 'object' then begin
c1 := byteSwap(disasmColors[2]) shr 8;
c2 := byteSwap(disasmColors[8]) shr 8;
end else
if r = 'except' then begin
c1 := byteSwap(disasmColors[3]) shr 8;
c2 := byteSwap(disasmColors[9]) shr 8;
end else
if r = 'oldebp' then begin
c1 := byteSwap(disasmColors[4]) shr 8;
c2 := byteSwap(disasmColors[10]) shr 8;
end else
if r = 'return' then begin
c1 := byteSwap(disasmColors[5]) shr 8;
c2 := byteSwap(disasmColors[11]) shr 8;
end else
if r = 'ireturn' then begin
c1 := byteSwap(disasmColors[6]) shr 8;
c2 := byteSwap(disasmColors[12]) shr 8;
end else begin
c1 := byteSwap(disasmColors[1]) shr 8;
c2 := byteSwap(disasmColors[7]) shr 8;
end;
end else begin
c1 := byteSwap(disasmColors[0]) shr 8;
c2 := 0;
end;
font.color := c1;
textRect(rect, l + 1, k, s[0]);
if length(s) > 1 then begin
font.color := c2;
r := s[1];
textRect(rect, l + w - textWidth(r) - 1, k, r);
end;
inc(k, f);
end;
{ дизассемблер }
strings := toStringArray2d([
toStringArray1d(['java.lang.MalikInterrupt . enable(boolean)']),
toStringArray1d([' 00836a7c', 'fb0000', 'enter $0']),
toStringArray1d([' 00836a7f', '0815000000', 'load except java.lang.MalikInte']),
toStringArray1d([' MalikInterrupt.java[378]']),
toStringArray1d([' 00836a84', 'e20200', 'load int [ebp+$20]']),
toStringArray1d([' 00836a87', 'ff2404', 'je int 0 java.lang.MalikInte'])
]);
w := l - 1;
h := f * (length(strings) + 1) + 3;
l := 0;
t := 0;
rectangle(bounds(l, t, w, h));
rect := bounds(l + 1, t + 1, w - 2, h - 2);
font.color := clWindowText;
textRect(rect, l + 1, t, 'Дизассемблер');
k := t + f + 1;
moveTo(l, k);
lineTo(l + w, k);
c1 := l + textWidth(' 00000000 ');
c2 := c1 + textWidth('000000000000 ');
for i := 0 to length(strings) - 1 do begin
s := strings[i];
r := s[0];
if startsWith(' ', r) then begin
font.color := clWindowText;
font.style := [];
end else
if startsWith(' ', r) then begin
font.color := byteSwap(disasmColors[15]) shr 8;
font.style := [fsBold];
end else begin
font.color := byteSwap(disasmColors[14]) shr 8;
font.style := [fsBold];
end;
textRect(rect, l + 1, k, r);
if length(s) > 1 then begin
textRect(rect, c1, k, s[1]);
end;
if length(s) > 2 then begin
textRect(rect, c2, k, s[2]);
end;
inc(k, f);
end;
{ инспектор отладки }
s := toStringArray1d([
' length: int',
' chars: char[]',
'Унаследовано от java.lang.Object',
' monitor: java.lang.Thread$Monitor',
' refcount: int',
' objclass: java.lang.Class'
]);
l := 0;
t := h + 1;
h := height - t;
rectangle(bounds(l, t, w, h));
rect := bounds(l + 1, t + 1, w - 2, h - 2);
font.color := clWindowText;
textRect(rect, l + 1, t, 'Инспектор отладки');
k := t + f + 1;
moveTo(l, k);
lineTo(l + w, k);
for i := 0 to 5 do begin
case i of
0, 4: begin
font.color := byteSwap(disasmColors[1]) shr 8;
font.style := [];
end;
1, 3, 5: begin
font.color := byteSwap(disasmColors[2]) shr 8;
font.style := [];
end;
else
font.color := byteSwap(disasmColors[16]) shr 8;
font.style := [fsBold];
end;
textRect(rect, l + 1, k, s[i]);
inc(k, f);
end;
font.style := [];
end;
end;
procedure TSettingsForm.afterConstruction();
var
owner: MainWindowInterface;
recompilers: AdjustableRecompiler_Array1d;
recompiler: StaticRecompiler;
adjustable: AdjustableRecompiler;
index: int;
i: int;
c: int;
s: AnsiString;
begin
inherited afterConstruction();
owner := self.owner;
{ Вкладка «Эмулятор» }
algorithms := toTRadioButtonArray1d([
graphicScalingSystem, graphicScalingNearest, graphicScalingScaleNx,
graphicScalingHqNx, graphicScalingStandard
]);
fullscreenOnLaunch.checked := owner.getSetting(SECTION_EMULATOR, KEY_AUTO_FULLSCREEN, '0') = '1';
closeOnTerminate.checked := owner.getSetting(SECTION_EMULATOR, KEY_AUTO_CLOSEWND, '0') = '1';
s := toLowerCase(owner.getSetting(SECTION_EMULATOR, KEY_GRAPHIC_SCALING, ''));
c := 0;
for i := 0 to length(SCALING_ALGORITHMS) - 1 do begin
if s = toLowerCase(SCALING_ALGORITHMS[i]) then begin
c := i;
break;
end;
end;
algorithms[c].checked := true;
maximumFramesValue.position := parseDecInt(owner.getSetting(SECTION_EMULATOR, KEY_MAXIMUM_FPS, ''), 25);
maximumFramesValueChange(maximumFramesValue);
{ Вкладка «Тема» }
c := getThemesCount();
with themeSelector.items do begin
for i := 0 to c - 1 do begin
add(getTheme(i).getName());
end;
end;
index := 0;
s := owner.getSetting(SECTION_EMULATOR, KEY_THEME, '');
for i := 0 to c - 1 do begin
if getTheme(i).getName() = s then begin
index := i;
break;
end;
end;
themeSelector.itemIndex := index;
drawTheme(getTheme(index));
{ Вкладка «Дизассемблер» }
disasmColors := toIntArray1d([
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_EMPTY_DATA, ''), DEFAULT_DEBUGGER_COLOR_EMPTY_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_NORMAL_DATA, ''), DEFAULT_DEBUGGER_COLOR_NORMAL_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_OBJECT_DATA, ''), DEFAULT_DEBUGGER_COLOR_OBJECT_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_EXCEPT_DATA, ''), DEFAULT_DEBUGGER_COLOR_EXCEPT_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_OLDEBP_DATA, ''), DEFAULT_DEBUGGER_COLOR_OLDEBP_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_RETURN_DATA, ''), DEFAULT_DEBUGGER_COLOR_RETURN_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_IRETURN_DATA, ''), DEFAULT_DEBUGGER_COLOR_IRETURN_DATA),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_NORMAL_TYPE, ''), DEFAULT_DEBUGGER_COLOR_NORMAL_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_OBJECT_TYPE, ''), DEFAULT_DEBUGGER_COLOR_OBJECT_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_EXCEPT_TYPE, ''), DEFAULT_DEBUGGER_COLOR_EXCEPT_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_OLDEBP_TYPE, ''), DEFAULT_DEBUGGER_COLOR_OLDEBP_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_RETURN_TYPE, ''), DEFAULT_DEBUGGER_COLOR_RETURN_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_IRETURN_TYPE, ''), DEFAULT_DEBUGGER_COLOR_IRETURN_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_OVERFLOW_TYPE, ''), DEFAULT_DEBUGGER_COLOR_OVERFLOW_TYPE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_FUNCTION_NAME, ''), DEFAULT_DEBUGGER_COLOR_FUNCTION_NAME),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_SOURCE_LINE, ''), DEFAULT_DEBUGGER_COLOR_SOURCE_LINE),
parseHexInt(owner.getSetting(SECTION_DEBUGGER_COLORS, KEY_INHERITED, ''), DEFAULT_DEBUGGER_COLOR_INHERITED)
]);
disasmColor.buttonColor := disasmColors[0];
drawDisasm();
{ Вкладка «Статический рекомпилятор» }
recompilers := AdjustableRecompiler_Array1d_create(getRecompilersCount());
c := 0;
for i := 0 to length(recompilers) - 1 do begin
recompiler := getRecompiler(i);
recompiler.getInterface(stringToGUID(ADJUSTABLE_RECOMPILER_GUID), adjustable);
if adjustable <> nil then begin
recompilers[c] := adjustable;
inc(c);
end;
end;
self.recompilers := AdjustableRecompiler_Array1d_create(c);
arraycopy(recompilers, 0, self.recompilers, 0, c);
with recompilerSelector.items do begin
for i := 0 to c - 1 do begin
add(recompilers[i].getPlatformName());
end;
end;
recompilerSelector.itemIndex := 0;
recompilerSelectorChange(recompilerSelector);
end;
procedure TSettingsForm.beforeDestruction();
var
owner: MainWindowInterface;
i: int;
r: AdjustableRecompiler;
s: AnsiString;
begin
owner := self.owner;
owner.setSetting(SECTION_EMULATOR, KEY_AUTO_FULLSCREEN, toSettingString(fullscreenOnLaunch.checked));
owner.setSetting(SECTION_EMULATOR, KEY_AUTO_CLOSEWND, toSettingString(closeOnTerminate.checked));
owner.setSetting(SECTION_EMULATOR, KEY_GRAPHIC_SCALING, getScalingAlgorithm());
owner.setSetting(SECTION_EMULATOR, KEY_MAXIMUM_FPS, toDecString(maximumFramesValue.position));
owner.setSetting(SECTION_EMULATOR, KEY_THEME, themeSelector.text);
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_EMPTY_DATA, toHexString(disasmColors[0], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_NORMAL_DATA, toHexString(disasmColors[1], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_OBJECT_DATA, toHexString(disasmColors[2], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_EXCEPT_DATA, toHexString(disasmColors[3], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_OLDEBP_DATA, toHexString(disasmColors[4], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_RETURN_DATA, toHexString(disasmColors[5], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_IRETURN_DATA, toHexString(disasmColors[6], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_NORMAL_TYPE, toHexString(disasmColors[7], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_OBJECT_TYPE, toHexString(disasmColors[8], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_EXCEPT_TYPE, toHexString(disasmColors[9], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_OLDEBP_TYPE, toHexString(disasmColors[10], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_RETURN_TYPE, toHexString(disasmColors[11], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_IRETURN_TYPE, toHexString(disasmColors[12], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_OVERFLOW_TYPE, toHexString(disasmColors[13], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_FUNCTION_NAME, toHexString(disasmColors[14], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_SOURCE_LINE, toHexString(disasmColors[15], 6));
owner.setSetting(SECTION_DEBUGGER_COLORS, KEY_INHERITED, toHexString(disasmColors[16], 6));
for i := 0 to length(recompilers) - 1 do begin
r := recompilers[i];
s := 'platform: ' + r.getPlatformName();
owner.setSetting(s, KEY_ALIGNMENT, toSettingString(r.getAlignment()));
owner.setSetting(s, KEY_COMPRESSION, toSettingString(r.getCompressionLevel()));
owner.setSetting(s, KEY_STACK, toSettingString(r.getStackSize()));
owner.setSetting(s, KEY_HEAP, toSettingString(r.getHeapSize() shr 10));
owner.setSetting(s, KEY_EXECUTABLE, r.getOutputExecutableFileName());
end;
owner.saveSettings();
inherited beforeDestruction();
end;
function TSettingsForm.getClass(): _Class;
begin
result := ClassData.create(classType());
end;
function TSettingsForm.asObject(): TObject;
begin
result := self;
end;
procedure TSettingsForm.putPixel(x, y, argb: int);
var
width: int;
height: int;
pindex: int;
begin
width := themeImage.width;
height := themeImage.height;
if (x < 0) or (y < 0) or (x >= width) or (y >= height) then begin
exit;
end;
pindex := x + (height - y - 1) * width;
themeImagePixels[pindex] := computePixel(themeImagePixels[pindex], argb, false, true);
end;
{%endregion}
initialization {%region}
SCALING_ALGORITHMS := toStringArray1d([
'', 'near', 'scaleNx', 'hqNx', 'standard'
]);
{%endregion}
end.