Decompile editor options window

This commit is contained in:
Alexander Batalov 2022-06-07 23:18:59 +03:00
parent e6dfce21c9
commit a49970ac3f
5 changed files with 1060 additions and 137 deletions

View File

@ -722,7 +722,7 @@ int _editor_design(bool isCreationMode)
windowRefresh(characterEditorWindowHandle);
} else if ((gCharacterEditorIsCreationMode && (keyCode == 501 || keyCode == KEY_UPPERCASE_O || keyCode == KEY_LOWERCASE_O))
|| (!gCharacterEditorIsCreationMode && (keyCode == 501 || keyCode == KEY_UPPERCASE_P || keyCode == KEY_LOWERCASE_P))) {
// _OptionWindow();
_OptionWindow();
windowRefresh(characterEditorWindowHandle);
} else if (keyCode >= 525 && keyCode < 535) {
_InfoButton(keyCode);
@ -3536,8 +3536,31 @@ int _OptionWindow()
int width = _GInfo[43].width;
int height = _GInfo[43].height;
// NOTE: The following is a block of general purpose string buffers used in
// this function. They are either store path, or strings from .msg files. I
// don't know if such usage was intentional in the original code or it's a
// result of some kind of compiler optimization.
char string1[512];
char string2[512];
char string3[512];
char string4[512];
char string5[512];
// Only two of the these blocks are used as a dialog body. Depending on the
// dialog either 1 or 2 strings used from this array.
const char* dialogBody[2] = {
string5,
string2,
};
if (gCharacterEditorIsCreationMode) {
int win = windowCreate(238, 90, _GInfo[41].width, _GInfo[41].height, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x02);
int optionsWindowX = (screenGetWidth() != 640)
? (screenGetWidth() - _GInfo[41].width) / 2
: 238;
int optionsWindowY = (screenGetHeight() != 480)
? (screenGetHeight() - _GInfo[41].height) / 2
: 90;
int win = windowCreate(optionsWindowX, optionsWindowY, _GInfo[41].width, _GInfo[41].height, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x02);
if (win == -1) {
return -1;
}
@ -3575,15 +3598,11 @@ int _OptionWindow()
memcpy(down[index], _grphbmp[43], size);
memcpy(up[index], _grphbmp[42], size);
const char* msg = getmsg(&editorMessageList, &editorMessageListItem, 600 + index);
strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 600 + index));
char dest[512];
strcpy(dest, msg);
int length = fontGetStringWidth(dest);
int v60 = width / 2 - length / 2;
fontDrawText(up[index] + v60, dest, width, width, _colorTable[18979]);
fontDrawText(down[index] + v60, dest, width, width, _colorTable[14723]);
int offset = width * 7 + width / 2 - fontGetStringWidth(string4) / 2;
fontDrawText(up[index] + offset, string4, width, width, _colorTable[18979]);
fontDrawText(down[index] + offset, string4, width, width, _colorTable[14723]);
int btn = buttonCreate(win, 13, y, width, height, -1, -1, -1, 500 + index, up[index], down[index], NULL, BUTTON_FLAG_TRANSPARENT);
if (btn != -1) {
@ -3610,7 +3629,7 @@ int _OptionWindow()
fontSetCurrent(101);
int rc = 0;
while (rc != 0) {
while (rc == 0) {
int keyCode = _get_input();
if (_game_user_wants_to_quit != 0) {
@ -3625,84 +3644,74 @@ int _OptionWindow()
rc = 2;
} else if (keyCode == 503 || keyCode == KEY_UPPERCASE_E || keyCode == KEY_LOWERCASE_E) {
// ERASE
char line1[512];
strcpy(line1, getmsg(&editorMessageList, &editorMessageListItem, 605));
strcpy(string5, getmsg(&editorMessageList, &editorMessageListItem, 605));
strcpy(string2, getmsg(&editorMessageList, &editorMessageListItem, 606));
char line2[512];
strcpy(line2, getmsg(&editorMessageList, &editorMessageListItem, 606));
const char* lines[] = { line1, line2 };
if (showDialogBox(NULL, lines, 2, 169, 126, _colorTable[992], NULL, _colorTable[992], 0x10) != 0) {
if (showDialogBox(NULL, dialogBody, 2, 169, 126, _colorTable[992], NULL, _colorTable[992], DIALOG_BOX_YES_NO) != 0) {
_ResetPlayer();
skillsGetTagged(_temp_tag_skill, NUM_TAGGED_SKILLS);
int v224 = 3;
int v225 = 0;
do {
if (_temp_tag_skill[v224] != -1) {
int taggedSkillCount = 0;
for (int index = 3; index >= 0; index--) {
if (_temp_tag_skill[index] != -1) {
break;
}
--v224;
++v225;
} while (v224 > -1);
if (gCharacterEditorIsCreationMode) {
v225--;
taggedSkillCount++;
}
_tagskill_count = v225;
if (gCharacterEditorIsCreationMode) {
taggedSkillCount--;
}
_tagskill_count = taggedSkillCount;
traitsGetSelected(&_temp_trait[0], &_temp_trait[1]);
int v226 = 1;
int v227 = 0;
do {
if (_temp_trait[v226] != -1) {
int traitCount = 0;
for (int index = 1; index >= 0; index--) {
if (_temp_trait[index] != -1) {
break;
}
--v226;
++v227;
} while (v226 > -1);
traitCount++;
}
_trait_count = v227;
_trait_count = traitCount;
critterUpdateDerivedStats(gDude);
_ResetScreen();
}
} else if (keyCode == 502 || keyCode == KEY_UPPERCASE_P || keyCode == KEY_LOWERCASE_P) {
// PRINT TO FILE
char dest[512];
dest[0] = '\0';
string4[0] = '\0';
strcat(dest, "*.TXT");
strcat(string4, "*.");
strcat(string4, "TXT");
char** fileList;
int fileListLength = fileNameListInit(dest, &fileList, 0, 0);
int fileListLength = fileNameListInit(string4, &fileList, 0, 0);
if (fileListLength != -1) {
char v236[512];
// PRINT
strcpy(v236, getmsg(&editorMessageList, &editorMessageListItem, 616));
strcpy(string1, getmsg(&editorMessageList, &editorMessageListItem, 616));
// PRINT TO FILE
strcpy(dest, getmsg(&editorMessageList, &editorMessageListItem, 602));
strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 602));
if (_save_file_dialog(dest, fileList, v236, fileListLength, 168, 80, 0) == 0) {
strcat(v236, ".TXT");
if (showSaveFileDialog(string4, fileList, string1, fileListLength, 168, 80, 0) == 0) {
strcat(string1, ".");
strcat(string1, "TXT");
dest[0] = '\0';
string4[0] = '\0';
strcat(string4, string1);
if (!characterFileExists(dest)) {
if (!characterFileExists(string4)) {
// already exists
sprintf(dest,
sprintf(string4,
"%s %s",
compat_strupr(v236),
strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 609));
char v240[512];
strcpy(v240, getmsg(&editorMessageList, &editorMessageListItem, 610));
strcpy(string5, getmsg(&editorMessageList, &editorMessageListItem, 610));
const char* lines[] = { v240 };
if (showDialogBox(dest, lines, 1, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0x10) != 0) {
if (showDialogBox(string4, dialogBody, 1, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0x10) != 0) {
rc = 1;
} else {
rc = 0;
@ -3712,24 +3721,24 @@ int _OptionWindow()
}
if (rc != 0) {
dest[0] = '\0';
strcat(dest, v236);
string4[0] = '\0';
strcat(string4, string1);
if (characterPrintToFile(dest) == 0) {
sprintf(dest,
if (characterPrintToFile(string4) == 0) {
sprintf(string4,
"%s%s",
compat_strupr(v236),
strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 607));
showDialogBox(dest, NULL, 0, 169, 126, _colorTable[992], NULL, _colorTable[992], 0);
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[992], NULL, _colorTable[992], 0);
} else {
soundPlayFile("iisxxxx1");
sprintf(dest,
sprintf(string4,
"%s%s%s",
getmsg(&editorMessageList, &editorMessageListItem, 611),
compat_strupr(v236),
strupr(string1),
"!");
showDialogBox(dest, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[992], 0x01);
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[992], 0x01);
}
}
}
@ -3738,33 +3747,173 @@ int _OptionWindow()
} else {
soundPlayFile("iisxxxx1");
strcpy(dest, getmsg(&editorMessageList, &editorMessageListItem, 615));
showDialogBox(dest, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 615));
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
rc = 0;
}
} else if (keyCode == 501 || keyCode == KEY_UPPERCASE_L || keyCode == KEY_LOWERCASE_L) {
// LOAD
char path[COMPAT_MAX_PATH];
path[0] = '\0';
strcat(path, "*.");
strcat(path, "GCD");
string4[0] = '\0';
strcat(string4, "*.");
strcat(string4, "GCD");
char** fileNames;
int filesCount = fileNameListInit(path, &fileNames, 0, 0);
if (filesCount != -1) {
char** fileNameList;
int fileNameListLength = fileNameListInit(string4, &fileNameList, 0, 0);
if (fileNameListLength != -1) {
// NOTE: This value is not copied as in save dialog.
char* title = getmsg(&editorMessageList, &editorMessageListItem, 601);
int loadFileDialogRc = showLoadFileDialog(title, fileNameList, string3, fileNameListLength, 168, 80, 0);
if (loadFileDialogRc == -1) {
fileNameListFree(&fileNameList, 0);
// FIXME: This branch ignores cleanup at the end of the loop.
return -1;
}
if (loadFileDialogRc == 0) {
string4[0] = '\0';
strcat(string4, string3);
int oldRemainingCharacterPoints = characterEditorRemainingCharacterPoints;
_ResetPlayer();
if (gcdLoad(string4) == 0) {
critterUpdateDerivedStats(gDude);
pcStatsReset();
for (int stat = 0; stat < SAVEABLE_STAT_COUNT; stat++) {
critterSetBonusStat(gDude, stat, 0);
}
perksReset();
critterUpdateDerivedStats(gDude);
skillsGetTagged(_temp_tag_skill, 4);
int taggedSkillCount = 0;
for (int index = 3; index >= 0; index--) {
if (_temp_tag_skill[index] != -1) {
break;
}
taggedSkillCount++;
}
if (gCharacterEditorIsCreationMode) {
taggedSkillCount--;
}
_tagskill_count = taggedSkillCount;
traitsGetSelected(&(_temp_trait[0]), &(_temp_trait[1]));
int traitCount = 0;
for (int index = 1; index >= 0; index--) {
if (_temp_trait[index] != -1) {
break;
}
traitCount++;
}
_trait_count = traitCount;
critterUpdateDerivedStats(gDude);
critterAdjustHitPoints(gDude, 1000);
rc = 1;
} else {
_RestorePlayer();
characterEditorRemainingCharacterPoints = oldRemainingCharacterPoints;
critterAdjustHitPoints(gDude, 1000);
soundPlayFile("iisxxxx1");
strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 612));
strcat(string4, string3);
strcat(string4, "!");
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
}
_ResetScreen();
}
fileNameListFree(&fileNameList, 0);
} else {
soundPlayFile("iisxxxx1");
// Error reading file list!
strcpy(path, getmsg(&editorMessageList, &editorMessageListItem, 615));
strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 615));
rc = 0;
showDialogBox(path, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
}
} else if (keyCode == 500 || keyCode == KEY_UPPERCASE_S || keyCode == KEY_LOWERCASE_S) {
// TODO: Incomplete.
// SAVE
string4[0] = '\0';
strcat(string4, "*.");
strcat(string4, "GCD");
char** fileNameList;
int fileNameListLength = fileNameListInit(string4, &fileNameList, 0, 0);
if (fileNameListLength != -1) {
strcpy(string1, getmsg(&editorMessageList, &editorMessageListItem, 617));
strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 600));
if (showSaveFileDialog(string4, fileNameList, string1, fileNameListLength, 168, 80, 0) == 0) {
strcat(string1, ".");
strcat(string1, "GCD");
string4[0] = '\0';
strcat(string4, string1);
bool shouldSave;
if (characterFileExists(string4)) {
sprintf(string4, "%s %s",
strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 609));
strcpy(string5, getmsg(&editorMessageList, &editorMessageListItem, 610));
if (showDialogBox(string4, dialogBody, 1, 169, 126, _colorTable[32328], NULL, _colorTable[32328], DIALOG_BOX_YES_NO) != 0) {
shouldSave = true;
} else {
shouldSave = false;
}
} else {
shouldSave = true;
}
if (shouldSave) {
skillsSetTagged(_temp_tag_skill, 4);
traitsSetSelected(_temp_trait[0], _temp_trait[1]);
string4[0] = '\0';
strcat(string4, string1);
if (gcdSave(string4) != 0) {
soundPlayFile("iisxxxx1");
sprintf(string4, "%s%s!",
strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 611));
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], DIALOG_BOX_LARGE);
rc = 0;
} else {
sprintf(string4, "%s%s",
strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 607));
showDialogBox(string4, NULL, 0, 169, 126, _colorTable[992], NULL, _colorTable[992], DIALOG_BOX_LARGE);
rc = 1;
}
}
}
fileNameListFree(&fileNameList, 0);
} else {
soundPlayFile("iisxxxx1");
// Error reading file list!
char* msg = getmsg(&editorMessageList, &editorMessageListItem, 615);
showDialogBox(msg, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
rc = 0;
}
}
windowRefresh(win);
@ -3804,7 +3953,7 @@ int _OptionWindow()
char title[512];
strcpy(title, getmsg(&editorMessageList, &editorMessageListItem, 602));
if (_save_file_dialog(title, fileNames, fileName, filesCount, 168, 80, 0) == 0) {
if (showSaveFileDialog(title, fileNames, fileName, filesCount, 168, 80, 0) == 0) {
strcat(fileName, ".TXT");
title[0] = '\0';
@ -3814,7 +3963,7 @@ int _OptionWindow()
if (characterFileExists(title)) {
sprintf(title,
"%s %s",
compat_strupr(fileName),
strupr(fileName),
getmsg(&editorMessageList, &editorMessageListItem, 609));
char line2[512];
@ -3839,7 +3988,7 @@ int _OptionWindow()
sprintf(title,
"%s%s%s",
getmsg(&editorMessageList, &editorMessageListItem, 611),
compat_strupr(fileName),
strupr(fileName),
"!");
showDialogBox(title, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 1);
}

View File

@ -650,7 +650,12 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a
}
if (!v2) {
sprintf(xlist->fileNames[index], "%s%s", fileName, extension);
// NOTE: Quick and dirty fix to buffer overflow. See RE to
// understand the problem.
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s", fileName, extension);
free(xlist->fileNames[length]);
xlist->fileNames[length] = strdup(path);
length++;
}
}

View File

@ -1,6 +1,7 @@
#include "dbox.h"
#include "art.h"
#include "character_editor.h"
#include "color.h"
#include "core.h"
#include "debug.h"
@ -18,6 +19,45 @@
#include <algorithm>
#define FILE_DIALOG_LINE_COUNT 12
#define FILE_DIALOG_DOUBLE_CLICK_DELAY 32
#define LOAD_FILE_DIALOG_DONE_BUTTON_X 58
#define LOAD_FILE_DIALOG_DONE_BUTTON_Y 187
#define LOAD_FILE_DIALOG_DONE_LABEL_X 79
#define LOAD_FILE_DIALOG_DONE_LABEL_Y 187
#define LOAD_FILE_DIALOG_CANCEL_BUTTON_X 163
#define LOAD_FILE_DIALOG_CANCEL_BUTTON_Y 187
#define LOAD_FILE_DIALOG_CANCEL_LABEL_X 182
#define LOAD_FILE_DIALOG_CANCEL_LABEL_Y 187
#define SAVE_FILE_DIALOG_DONE_BUTTON_X 58
#define SAVE_FILE_DIALOG_DONE_BUTTON_Y 214
#define SAVE_FILE_DIALOG_DONE_LABEL_X 79
#define SAVE_FILE_DIALOG_DONE_LABEL_Y 213
#define SAVE_FILE_DIALOG_CANCEL_BUTTON_X 163
#define SAVE_FILE_DIALOG_CANCEL_BUTTON_Y 214
#define SAVE_FILE_DIALOG_CANCEL_LABEL_X 182
#define SAVE_FILE_DIALOG_CANCEL_LABEL_Y 213
#define FILE_DIALOG_TITLE_X 49
#define FILE_DIALOG_TITLE_Y 16
#define FILE_DIALOG_SCROLL_BUTTON_X 36
#define FILE_DIALOG_SCROLL_BUTTON_Y 44
#define FILE_DIALOG_FILE_LIST_X 55
#define FILE_DIALOG_FILE_LIST_Y 49
#define FILE_DIALOG_FILE_LIST_WIDTH 190
#define FILE_DIALOG_FILE_LIST_HEIGHT 124
// 0x5108C8
const int gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT] = {
218, // MEDIALOG.FRM - Medium generic dialog box
@ -55,7 +95,7 @@ const int _dblines[DIALOG_TYPE_COUNT] = {
};
// 0x510900
int _flgids[7] = {
int gLoadFileDialogFrmIds[FILE_DIALOG_FRM_COUNT] = {
224, // loadbox.frm - character editor
8, // lilredup.frm - little red button up
9, // lilreddn.frm - little red button down
@ -66,7 +106,7 @@ int _flgids[7] = {
};
// 0x51091C
int _flgids2[7] = {
int gSaveFileDialogFrmIds[FILE_DIALOG_FRM_COUNT] = {
225, // savebox.frm - character editor
8, // lilredup.frm - little red button up
9, // lilreddn.frm - little red button down
@ -451,17 +491,32 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
return rc;
}
// 0x41EA78
int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLength, int x, int y, int flags)
// 0x41DE90
int showLoadFileDialog(char *title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
{
int oldFont = fontGetCurrent();
unsigned char* frmBuffers[7];
CacheEntry* frmHandles[7];
Size frmSizes[7];
bool isScrollable = false;
if (fileListLength > FILE_DIALOG_LINE_COUNT) {
isScrollable = true;
}
for (int index = 0; index < 7; index++) {
int fid = buildFid(6, _flgids2[index], 0, 0, 0);
int selectedFileIndex = 0;
int pageOffset = 0;
int maxPageOffset = fileListLength - (FILE_DIALOG_LINE_COUNT + 1);
if (maxPageOffset < 0) {
maxPageOffset = fileListLength - 1;
if (maxPageOffset < 0) {
maxPageOffset = 0;
}
}
unsigned char* frmBuffers[FILE_DIALOG_FRM_COUNT];
CacheEntry* frmHandles[FILE_DIALOG_FRM_COUNT];
Size frmSizes[FILE_DIALOG_FRM_COUNT];
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
int fid = buildFid(6, gLoadFileDialogFrmIds[index], 0, 0, 0);
frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
if (frmBuffers[index] == NULL) {
while (--index >= 0) {
@ -471,16 +526,23 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
}
}
int win = windowCreate(x, y, frmSizes[0].width, frmSizes[0].height, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
int backgroundWidth = frmSizes[FILE_DIALOG_FRM_BACKGROUND].width;
int backgroundHeight = frmSizes[FILE_DIALOG_FRM_BACKGROUND].height;
// Maintain original position in original resolution, otherwise center it.
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundWidth) / 2;
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundHeight) / 2;
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
if (win == -1) {
for (int index = 0; index < 7; index++) {
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
return -1;
}
unsigned char* windowBuffer = windowGetBuffer(win);
memcpy(windowBuffer, frmBuffers[0], frmSizes[0].width * frmSizes[0].height);
memcpy(windowBuffer, frmBuffers[FILE_DIALOG_FRM_BACKGROUND], backgroundWidth * backgroundHeight);
MessageList messageList;
MessageListItem messageListItem;
@ -488,7 +550,7 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
if (!messageListInit(&messageList)) {
windowDestroy(win);
for (int index = 0; index < 7; index++) {
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
@ -501,7 +563,7 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
if (!messageListLoad(&messageList, path)) {
windowDestroy(win);
for (int index = 0; index < 7; index++) {
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
@ -512,23 +574,23 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
// DONE
const char* done = getmsg(&messageList, &messageListItem, 100);
fontDrawText(windowBuffer + frmSizes[0].width * 213 + 79, done, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]);
fontDrawText(windowBuffer + LOAD_FILE_DIALOG_DONE_LABEL_Y * backgroundWidth + LOAD_FILE_DIALOG_DONE_LABEL_X, done, backgroundWidth, backgroundWidth, _colorTable[18979]);
// CANCEL
const char* cancel = getmsg(&messageList, &messageListItem, 103);
fontDrawText(windowBuffer + frmSizes[0].width * 213 + 182, cancel, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]);
fontDrawText(windowBuffer + LOAD_FILE_DIALOG_CANCEL_LABEL_Y * backgroundWidth + LOAD_FILE_DIALOG_CANCEL_LABEL_X, cancel, backgroundWidth, backgroundWidth, _colorTable[18979]);
int doneBtn = buttonCreate(win,
58,
214,
frmSizes[2].width,
frmSizes[2].height,
LOAD_FILE_DIALOG_DONE_BUTTON_X,
LOAD_FILE_DIALOG_DONE_BUTTON_Y,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
-1,
-1,
-1,
500,
frmBuffers[1],
frmBuffers[2],
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (doneBtn != -1) {
@ -536,16 +598,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
}
int cancelBtn = buttonCreate(win,
163,
214,
frmSizes[2].width,
frmSizes[2].height,
LOAD_FILE_DIALOG_CANCEL_BUTTON_X,
LOAD_FILE_DIALOG_CANCEL_BUTTON_Y,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
-1,
-1,
-1,
501,
frmBuffers[1],
frmBuffers[2],
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (cancelBtn != -1) {
@ -553,16 +615,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
}
int scrollUpBtn = buttonCreate(win,
36,
44,
frmSizes[6].width,
frmSizes[6].height,
FILE_DIALOG_SCROLL_BUTTON_X,
FILE_DIALOG_SCROLL_BUTTON_Y,
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
-1,
505,
506,
505,
frmBuffers[5],
frmBuffers[6],
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL],
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
@ -570,16 +632,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
}
int scrollDownButton = buttonCreate(win,
36,
44 + frmSizes[6].height,
frmSizes[4].width,
frmSizes[4].height,
FILE_DIALOG_SCROLL_BUTTON_X,
FILE_DIALOG_SCROLL_BUTTON_Y + frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].height,
-1,
503,
504,
503,
frmBuffers[3],
frmBuffers[4],
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL],
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
@ -588,10 +650,10 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
buttonCreate(
win,
55,
49,
190,
124,
FILE_DIALOG_FILE_LIST_X,
FILE_DIALOG_FILE_LIST_Y,
FILE_DIALOG_FILE_LIST_WIDTH,
FILE_DIALOG_FILE_LIST_HEIGHT,
-1,
-1,
-1,
@ -601,25 +663,714 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
NULL,
0);
if (a1 != NULL) {
fontDrawText(windowBuffer + frmSizes[0].width * 16 + 49, a1, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]);
if (title != NULL) {
fontDrawText(windowBuffer + backgroundWidth * FILE_DIALOG_TITLE_Y + FILE_DIALOG_TITLE_X, title, backgroundWidth, backgroundWidth, _colorTable[18979]);
}
fontSetCurrent(101);
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
windowRefresh(win);
int doubleClickSelectedFileIndex = -2;
int doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
int rc = -1;
while (rc == -1) {
unsigned int tick = _get_time();
int keyCode = _get_input();
int scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_NONE;
int scrollCounter = 0;
bool isScrolling = false;
if (keyCode == 500) {
if (fileListLength != 0) {
strncpy(dest, fileList[selectedFileIndex + pageOffset], 16);
rc = 0;
} else {
rc = 1;
}
} else if (keyCode == 501 || keyCode == KEY_ESCAPE) {
rc = 1;
} else if (keyCode == 502 && fileListLength != 0) {
int mouseX;
int mouseY;
mouseGetPosition(&mouseX, &mouseY);
int selectedLine = (mouseY - y - FILE_DIALOG_FILE_LIST_Y) / fontGetLineHeight();
if (selectedLine - 1 < 0) {
selectedLine = 0;
}
if (isScrollable || selectedLine < fileListLength) {
if (selectedLine >= FILE_DIALOG_LINE_COUNT) {
selectedLine = FILE_DIALOG_LINE_COUNT - 1;
}
} else {
selectedLine = fileListLength - 1;
}
selectedFileIndex = selectedLine;
if (selectedFileIndex == doubleClickSelectedFileIndex) {
soundPlayFile("ib1p1xx1");
strncpy(dest, fileList[selectedFileIndex + pageOffset], 16);
rc = 0;
}
doubleClickSelectedFileIndex = selectedFileIndex;
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
} else if (keyCode == 506) {
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_UP;
} else if (keyCode == 504) {
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_DOWN;
} else {
switch (keyCode) {
case KEY_ARROW_UP:
pageOffset--;
if (pageOffset < 0) {
selectedFileIndex--;
if (selectedFileIndex < 0) {
selectedFileIndex = 0;
}
pageOffset = 0;
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
case KEY_ARROW_DOWN:
if (isScrollable) {
pageOffset++;
// FIXME: Should be >= maxPageOffset (as in save dialog).
// Otherwise out of bounds index is considered selected.
if (pageOffset > maxPageOffset) {
selectedFileIndex++;
// FIXME: Should be >= FILE_DIALOG_LINE_COUNT (as in
// save dialog). Otherwise out of bounds index is
// considered selected.
if (selectedFileIndex > FILE_DIALOG_LINE_COUNT) {
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
}
pageOffset = maxPageOffset;
}
} else {
selectedFileIndex++;
if (selectedFileIndex > maxPageOffset) {
selectedFileIndex = maxPageOffset;
}
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
case KEY_HOME:
selectedFileIndex = 0;
pageOffset = 0;
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
case KEY_END:
if (isScrollable) {
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
pageOffset = maxPageOffset;
} else {
selectedFileIndex = maxPageOffset;
pageOffset = 0;
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
}
}
if (scrollDirection != FILE_DIALOG_SCROLL_DIRECTION_NONE) {
unsigned int scrollDelay = 4;
doubleClickSelectedFileIndex = -2;
while (1) {
unsigned int scrollTick = _get_time();
scrollCounter += 1;
if ((!isScrolling && scrollCounter == 1) || (isScrolling && scrollCounter > 14.4)) {
isScrolling = true;
if (scrollCounter > 14.4) {
scrollDelay += 1;
if (scrollDelay > 24) {
scrollDelay = 24;
}
}
if (scrollDirection == FILE_DIALOG_SCROLL_DIRECTION_UP) {
pageOffset--;
if (pageOffset < 0) {
selectedFileIndex--;
if (selectedFileIndex < 0) {
selectedFileIndex = 0;
}
pageOffset = 0;
}
} else {
if (isScrollable) {
pageOffset++;
if (pageOffset > maxPageOffset) {
selectedFileIndex++;
if (selectedFileIndex >= FILE_DIALOG_LINE_COUNT) {
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
}
pageOffset = maxPageOffset;
}
} else {
selectedFileIndex++;
if (selectedFileIndex > maxPageOffset) {
selectedFileIndex = maxPageOffset;
}
}
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
windowRefresh(win);
}
unsigned int delay = (scrollCounter > 14.4) ? 1000 / scrollDelay : 1000 / 24;
while (getTicksSince(scrollTick) < delay) {
}
if (_game_user_wants_to_quit != 0) {
rc = 1;
break;
}
int keyCode = _get_input();
if (keyCode == 505 || keyCode == 503) {
break;
}
}
} else {
windowRefresh(win);
doubleClickTimer--;
if (doubleClickTimer == 0) {
doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
doubleClickSelectedFileIndex = -2;
}
while (getTicksSince(tick) < (1000 / 24)) {
}
}
if (_game_user_wants_to_quit) {
rc = 1;
}
}
windowDestroy(win);
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
messageListFree(&messageList);
fontSetCurrent(oldFont);
return rc;
}
// 0x41EA78
int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
{
int oldFont = fontGetCurrent();
bool isScrollable = false;
if (fileListLength > FILE_DIALOG_LINE_COUNT) {
isScrollable = true;
}
int selectedFileIndex = 0;
int pageOffset = 0;
int maxPageOffset = fileListLength - (FILE_DIALOG_LINE_COUNT + 1);
if (maxPageOffset < 0) {
maxPageOffset = fileListLength - 1;
if (maxPageOffset < 0) {
maxPageOffset = 0;
}
}
unsigned char* frmBuffers[FILE_DIALOG_FRM_COUNT];
CacheEntry* frmHandles[FILE_DIALOG_FRM_COUNT];
Size frmSizes[FILE_DIALOG_FRM_COUNT];
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
int fid = buildFid(6, gSaveFileDialogFrmIds[index], 0, 0, 0);
frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
if (frmBuffers[index] == NULL) {
while (--index >= 0) {
artUnlock(frmHandles[index]);
}
return -1;
}
}
int backgroundWidth = frmSizes[FILE_DIALOG_FRM_BACKGROUND].width;
int backgroundHeight = frmSizes[FILE_DIALOG_FRM_BACKGROUND].height;
// Maintain original position in original resolution, otherwise center it.
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundWidth) / 2;
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundHeight) / 2;
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
if (win == -1) {
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
return -1;
}
unsigned char* windowBuffer = windowGetBuffer(win);
memcpy(windowBuffer, frmBuffers[FILE_DIALOG_FRM_BACKGROUND], backgroundWidth * backgroundHeight);
MessageList messageList;
MessageListItem messageListItem;
if (!messageListInit(&messageList)) {
windowDestroy(win);
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
return -1;
}
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s", asc_5186C8, "DBOX.MSG");
if (!messageListLoad(&messageList, path)) {
windowDestroy(win);
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
return -1;
}
fontSetCurrent(103);
// DONE
const char* done = getmsg(&messageList, &messageListItem, 100);
fontDrawText(windowBuffer + backgroundWidth * SAVE_FILE_DIALOG_DONE_LABEL_Y + SAVE_FILE_DIALOG_DONE_LABEL_X, done, backgroundWidth, backgroundWidth, _colorTable[18979]);
// CANCEL
const char* cancel = getmsg(&messageList, &messageListItem, 103);
fontDrawText(windowBuffer + backgroundWidth * SAVE_FILE_DIALOG_CANCEL_LABEL_Y + SAVE_FILE_DIALOG_CANCEL_LABEL_X, cancel, backgroundWidth, backgroundWidth, _colorTable[18979]);
int doneBtn = buttonCreate(win,
SAVE_FILE_DIALOG_DONE_BUTTON_X,
SAVE_FILE_DIALOG_DONE_BUTTON_Y,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
-1,
-1,
-1,
500,
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (doneBtn != -1) {
buttonSetCallbacks(doneBtn, _gsound_red_butt_press, _gsound_red_butt_release);
}
int cancelBtn = buttonCreate(win,
SAVE_FILE_DIALOG_CANCEL_BUTTON_X,
SAVE_FILE_DIALOG_CANCEL_BUTTON_Y,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
-1,
-1,
-1,
501,
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (cancelBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
}
int scrollUpBtn = buttonCreate(win,
FILE_DIALOG_SCROLL_BUTTON_X,
FILE_DIALOG_SCROLL_BUTTON_Y,
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
-1,
505,
506,
505,
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL],
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
}
int scrollDownButton = buttonCreate(win,
FILE_DIALOG_SCROLL_BUTTON_X,
FILE_DIALOG_SCROLL_BUTTON_Y + frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].width,
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].height,
-1,
503,
504,
503,
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL],
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
}
buttonCreate(
win,
FILE_DIALOG_FILE_LIST_X,
FILE_DIALOG_FILE_LIST_Y,
FILE_DIALOG_FILE_LIST_WIDTH,
FILE_DIALOG_FILE_LIST_HEIGHT,
-1,
-1,
-1,
502,
NULL,
NULL,
NULL,
0);
if (title != NULL) {
fontDrawText(windowBuffer + backgroundWidth * FILE_DIALOG_TITLE_Y + FILE_DIALOG_TITLE_X, title, backgroundWidth, backgroundWidth, _colorTable[18979]);
}
fontSetCurrent(101);
int cursorHeight = fontGetLineHeight();
int cursorWidth = fontGetStringWidth("_") - 4;
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
int fileNameLength = 0;
char* pch = dest;
while (*pch != '\0' && *pch != '.') {
fileNameLength++;
if (fileNameLength >= 12) {
break;
}
}
dest[fileNameLength] = '\0';
char fileNameCopy[32];
strncpy(fileNameCopy, dest, 32);
int fileNameCopyLength = strlen(fileNameCopy);
fileNameCopy[fileNameCopyLength + 1] = '\0';
fileNameCopy[fileNameCopyLength] = ' ';
unsigned char* fileNameBufferPtr = windowBuffer + backgroundWidth * 190 + 57;
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
windowRefresh(win);
int blinkingCounter = 3;
bool blink = false;
int doubleClickSelectedFileIndex = -2;
int doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
int rc = -1;
while (rc == -1) {
unsigned int tick = _get_time();
int keyCode = _get_input();
int scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_NONE;
int scrollCounter = 0;
bool isScrolling = false;
if (keyCode == 500) {
rc = 0;
} else if (keyCode == KEY_RETURN) {
soundPlayFile("ib1p1xx1");
rc = 0;
} else if (keyCode == 501 || keyCode == KEY_ESCAPE) {
rc = 1;
} else if ((keyCode == KEY_DELETE || keyCode == KEY_BACKSPACE) && fileNameCopyLength > 0) {
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
fileNameCopy[fileNameCopyLength - 1] = ' ';
fileNameCopy[fileNameCopyLength] = '\0';
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
fileNameCopyLength--;
windowRefresh(win);
} else if (keyCode < KEY_FIRST_INPUT_CHARACTER || keyCode > KEY_LAST_INPUT_CHARACTER || fileNameCopyLength >= 8) {
if (keyCode == 502 && fileListLength != 0) {
int mouseX;
int mouseY;
mouseGetPosition(&mouseX, &mouseY);
int selectedLine = (mouseY - y - FILE_DIALOG_FILE_LIST_Y) / fontGetLineHeight();
if (selectedLine - 1 < 0) {
selectedLine = 0;
}
if (isScrollable || selectedLine < fileListLength) {
if (selectedLine >= FILE_DIALOG_LINE_COUNT) {
selectedLine = FILE_DIALOG_LINE_COUNT - 1;
}
} else {
selectedLine = fileListLength - 1;
}
selectedFileIndex = selectedLine;
if (selectedFileIndex == doubleClickSelectedFileIndex) {
soundPlayFile("ib1p1xx1");
strncpy(dest, fileList[selectedFileIndex + pageOffset], 16);
int index;
for (index = 0; index < 12; index++) {
if (dest[index] == '.' || dest[index] == '\0') {
break;
}
}
dest[index] = '\0';
rc = 2;
} else {
doubleClickSelectedFileIndex = selectedFileIndex;
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
strncpy(fileNameCopy, fileList[selectedFileIndex + pageOffset], 16);
int index;
for (index = 0; index < 12; index++) {
if (fileNameCopy[index] == '.' || fileNameCopy[index] == '\0') {
break;
}
}
fileNameCopy[index] = '\0';
fileNameCopyLength = strlen(fileNameCopy);
fileNameCopy[fileNameCopyLength] = ' ';
fileNameCopy[fileNameCopyLength + 1] = '\0';
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
}
} else if (keyCode == 506) {
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_UP;
} else if (keyCode == 504) {
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_DOWN;
} else {
switch (keyCode) {
case KEY_ARROW_UP:
pageOffset--;
if (pageOffset < 0) {
selectedFileIndex--;
if (selectedFileIndex < 0) {
selectedFileIndex = 0;
}
pageOffset = 0;
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
case KEY_ARROW_DOWN:
if (isScrollable) {
pageOffset++;
if (pageOffset >= maxPageOffset) {
selectedFileIndex++;
if (selectedFileIndex >= FILE_DIALOG_LINE_COUNT) {
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
}
pageOffset = maxPageOffset;
}
} else {
selectedFileIndex++;
if (selectedFileIndex > maxPageOffset) {
selectedFileIndex = maxPageOffset;
}
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
case KEY_HOME:
selectedFileIndex = 0;
pageOffset = 0;
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
case KEY_END:
if (isScrollable) {
selectedFileIndex = 11;
pageOffset = maxPageOffset;
} else {
selectedFileIndex = maxPageOffset;
pageOffset = 0;
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
doubleClickSelectedFileIndex = -2;
break;
}
}
} else if (_isdoschar(keyCode)) {
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
fileNameCopy[fileNameCopyLength] = keyCode & 0xFF;
fileNameCopy[fileNameCopyLength + 1] = ' ';
fileNameCopy[fileNameCopyLength + 2] = '\0';
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
fileNameCopyLength++;
windowRefresh(win);
}
if (scrollDirection != FILE_DIALOG_SCROLL_DIRECTION_NONE) {
unsigned int scrollDelay = 4;
doubleClickSelectedFileIndex = -2;
while (1) {
unsigned int scrollTick = _get_time();
scrollCounter += 1;
if ((!isScrolling && scrollCounter == 1) || (isScrolling && scrollCounter > 14.4)) {
isScrolling = true;
if (scrollCounter > 14.4) {
scrollDelay += 1;
if (scrollDelay > 24) {
scrollDelay = 24;
}
}
if (scrollDirection == FILE_DIALOG_SCROLL_DIRECTION_UP) {
pageOffset--;
if (pageOffset < 0) {
selectedFileIndex--;
if (selectedFileIndex < 0) {
selectedFileIndex = 0;
}
pageOffset = 0;
}
} else {
if (isScrollable) {
pageOffset++;
if (pageOffset > maxPageOffset) {
selectedFileIndex++;
if (selectedFileIndex >= FILE_DIALOG_LINE_COUNT) {
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
}
pageOffset = maxPageOffset;
}
} else {
selectedFileIndex++;
if (selectedFileIndex > maxPageOffset) {
selectedFileIndex = maxPageOffset;
}
}
}
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
windowRefresh(win);
}
// NOTE: Original code is slightly different. For unknown reason
// entire blinking stuff is placed into two different branches,
// which only differs by amount of delay. Probably result of
// using large blinking macro as there are no traces of inlined
// function.
blinkingCounter -= 1;
if (blinkingCounter == 0) {
blinkingCounter = 3;
int color = blink ? 100 : _colorTable[992];
blink = !blink;
bufferFill(fileNameBufferPtr + fontGetStringWidth(fileNameCopy) - cursorWidth, cursorWidth, cursorHeight - 2, backgroundWidth, color);
}
// FIXME: Missing windowRefresh makes blinking useless.
unsigned int delay = (scrollCounter > 14.4) ? 1000 / scrollDelay : 1000 / 24;
while (getTicksSince(scrollTick) < delay) {
}
if (_game_user_wants_to_quit != 0) {
rc = 1;
break;
}
int key = _get_input();
if (key == 505 || key == 503) {
break;
}
}
} else {
blinkingCounter -= 1;
if (blinkingCounter == 0) {
blinkingCounter = 3;
int color = blink ? 100 : _colorTable[992];
blink = !blink;
bufferFill(fileNameBufferPtr + fontGetStringWidth(fileNameCopy) - cursorWidth, cursorWidth, cursorHeight - 2, backgroundWidth, color);
}
windowRefresh(win);
doubleClickTimer--;
if (doubleClickTimer == 0) {
doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
doubleClickSelectedFileIndex = -2;
}
while (getTicksSince(tick) < (1000 / 24)) {
}
}
if (_game_user_wants_to_quit != 0) {
rc = 1;
}
}
if (rc == 0) {
if (fileNameCopyLength != 0) {
fileNameCopy[fileNameCopyLength] = '\0';
strcpy(dest, fileNameCopy);
} else {
rc = 1;
}
} else {
if (rc == 2) {
rc = 0;
}
}
windowDestroy(win);
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]);
}
messageListFree(&messageList);
fontSetCurrent(oldFont);
return rc;
}
// 0x41FBDC
void _PrntFlist(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch)
void fileDialogRenderFileList(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch)
{
int lineHeight = fontGetLineHeight();
int y = 49;
bufferFill(buffer + y * pitch + 55, 190, 124, pitch, 100);
int y = FILE_DIALOG_FILE_LIST_Y;
bufferFill(buffer + y * pitch + FILE_DIALOG_FILE_LIST_X, FILE_DIALOG_FILE_LIST_WIDTH, FILE_DIALOG_FILE_LIST_HEIGHT, pitch, 100);
if (fileListLength != 0) {
if (fileListLength - pageOffset > 12) {
fileListLength = 12;
if (fileListLength - pageOffset > FILE_DIALOG_LINE_COUNT) {
fileListLength = FILE_DIALOG_LINE_COUNT;
}
for (int index = 0; index < fileListLength; index++) {
int color = index == selectedIndex ? _colorTable[32747] : _colorTable[992];
fontDrawText(buffer + y * index + 55, fileList[index], pitch, pitch, color);
fontDrawText(buffer + pitch * y + FILE_DIALOG_FILE_LIST_X, fileList[pageOffset + index], pitch, pitch, color);
y += lineHeight;
}
}

View File

@ -16,17 +16,35 @@ typedef enum DialogType {
DIALOG_TYPE_COUNT,
} DialogType;
typedef enum FileDialogFrm {
FILE_DIALOG_FRM_BACKGROUND,
FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL,
FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED,
FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL,
FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED,
FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL,
FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED,
FILE_DIALOG_FRM_COUNT,
} FileDialogFrm;
typedef enum FileDialogScrollDirection {
FILE_DIALOG_SCROLL_DIRECTION_NONE,
FILE_DIALOG_SCROLL_DIRECTION_UP,
FILE_DIALOG_SCROLL_DIRECTION_DOWN,
} FileDialogScrollDirection;
extern const int gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT];
extern const int _ytable[DIALOG_TYPE_COUNT];
extern const int _xtable[DIALOG_TYPE_COUNT];
extern const int _doneY[DIALOG_TYPE_COUNT];
extern const int _doneX[DIALOG_TYPE_COUNT];
extern const int _dblines[DIALOG_TYPE_COUNT];
extern int _flgids[7];
extern int _flgids2[7];
extern int gLoadFileDialogFrmIds[FILE_DIALOG_FRM_COUNT];
extern int gSaveFileDialogFrmIds[FILE_DIALOG_FRM_COUNT];
int showDialogBox(const char* title, const char** body, int bodyLength, int x, int y, int titleColor, const char* a8, int bodyColor, int flags);
int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLength, int x, int y, int flags);
void _PrntFlist(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch);
int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags);
int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags);
void fileDialogRenderFileList(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch);
#endif /* DBOX_H */

View File

@ -617,7 +617,7 @@ bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler, XList
}
} while (fileFindNext(&directoryFileFindData));
}
return findFindClose(&directoryFileFindData);
findFindClose(&directoryFileFindData);
}
xbase = xbase->next;
}