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); windowRefresh(characterEditorWindowHandle);
} else if ((gCharacterEditorIsCreationMode && (keyCode == 501 || keyCode == KEY_UPPERCASE_O || keyCode == KEY_LOWERCASE_O)) } else if ((gCharacterEditorIsCreationMode && (keyCode == 501 || keyCode == KEY_UPPERCASE_O || keyCode == KEY_LOWERCASE_O))
|| (!gCharacterEditorIsCreationMode && (keyCode == 501 || keyCode == KEY_UPPERCASE_P || keyCode == KEY_LOWERCASE_P))) { || (!gCharacterEditorIsCreationMode && (keyCode == 501 || keyCode == KEY_UPPERCASE_P || keyCode == KEY_LOWERCASE_P))) {
// _OptionWindow(); _OptionWindow();
windowRefresh(characterEditorWindowHandle); windowRefresh(characterEditorWindowHandle);
} else if (keyCode >= 525 && keyCode < 535) { } else if (keyCode >= 525 && keyCode < 535) {
_InfoButton(keyCode); _InfoButton(keyCode);
@ -3536,8 +3536,31 @@ int _OptionWindow()
int width = _GInfo[43].width; int width = _GInfo[43].width;
int height = _GInfo[43].height; 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) { 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) { if (win == -1) {
return -1; return -1;
} }
@ -3575,15 +3598,11 @@ int _OptionWindow()
memcpy(down[index], _grphbmp[43], size); memcpy(down[index], _grphbmp[43], size);
memcpy(up[index], _grphbmp[42], 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]; int offset = width * 7 + width / 2 - fontGetStringWidth(string4) / 2;
strcpy(dest, msg); fontDrawText(up[index] + offset, string4, width, width, _colorTable[18979]);
fontDrawText(down[index] + offset, string4, width, width, _colorTable[14723]);
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 btn = buttonCreate(win, 13, y, width, height, -1, -1, -1, 500 + index, up[index], down[index], NULL, BUTTON_FLAG_TRANSPARENT); int btn = buttonCreate(win, 13, y, width, height, -1, -1, -1, 500 + index, up[index], down[index], NULL, BUTTON_FLAG_TRANSPARENT);
if (btn != -1) { if (btn != -1) {
@ -3610,7 +3629,7 @@ int _OptionWindow()
fontSetCurrent(101); fontSetCurrent(101);
int rc = 0; int rc = 0;
while (rc != 0) { while (rc == 0) {
int keyCode = _get_input(); int keyCode = _get_input();
if (_game_user_wants_to_quit != 0) { if (_game_user_wants_to_quit != 0) {
@ -3625,84 +3644,74 @@ int _OptionWindow()
rc = 2; rc = 2;
} else if (keyCode == 503 || keyCode == KEY_UPPERCASE_E || keyCode == KEY_LOWERCASE_E) { } else if (keyCode == 503 || keyCode == KEY_UPPERCASE_E || keyCode == KEY_LOWERCASE_E) {
// ERASE // ERASE
char line1[512]; strcpy(string5, getmsg(&editorMessageList, &editorMessageListItem, 605));
strcpy(line1, getmsg(&editorMessageList, &editorMessageListItem, 605)); strcpy(string2, getmsg(&editorMessageList, &editorMessageListItem, 606));
char line2[512]; if (showDialogBox(NULL, dialogBody, 2, 169, 126, _colorTable[992], NULL, _colorTable[992], DIALOG_BOX_YES_NO) != 0) {
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) {
_ResetPlayer(); _ResetPlayer();
skillsGetTagged(_temp_tag_skill, NUM_TAGGED_SKILLS); skillsGetTagged(_temp_tag_skill, NUM_TAGGED_SKILLS);
int v224 = 3; int taggedSkillCount = 0;
int v225 = 0; for (int index = 3; index >= 0; index--) {
do { if (_temp_tag_skill[index] != -1) {
if (_temp_tag_skill[v224] != -1) {
break; break;
} }
--v224; taggedSkillCount++;
++v225;
} while (v224 > -1);
if (gCharacterEditorIsCreationMode) {
v225--;
} }
_tagskill_count = v225; if (gCharacterEditorIsCreationMode) {
taggedSkillCount--;
}
_tagskill_count = taggedSkillCount;
traitsGetSelected(&_temp_trait[0], &_temp_trait[1]); traitsGetSelected(&_temp_trait[0], &_temp_trait[1]);
int v226 = 1; int traitCount = 0;
int v227 = 0; for (int index = 1; index >= 0; index--) {
do { if (_temp_trait[index] != -1) {
if (_temp_trait[v226] != -1) {
break; break;
} }
--v226; traitCount++;
++v227; }
} while (v226 > -1);
_trait_count = v227; _trait_count = traitCount;
critterUpdateDerivedStats(gDude); critterUpdateDerivedStats(gDude);
_ResetScreen(); _ResetScreen();
} }
} else if (keyCode == 502 || keyCode == KEY_UPPERCASE_P || keyCode == KEY_LOWERCASE_P) { } else if (keyCode == 502 || keyCode == KEY_UPPERCASE_P || keyCode == KEY_LOWERCASE_P) {
// PRINT TO FILE // PRINT TO FILE
char dest[512]; string4[0] = '\0';
dest[0] = '\0';
strcat(dest, "*.TXT"); strcat(string4, "*.");
strcat(string4, "TXT");
char** fileList; char** fileList;
int fileListLength = fileNameListInit(dest, &fileList, 0, 0); int fileListLength = fileNameListInit(string4, &fileList, 0, 0);
if (fileListLength != -1) { if (fileListLength != -1) {
char v236[512];
// PRINT // PRINT
strcpy(v236, getmsg(&editorMessageList, &editorMessageListItem, 616)); strcpy(string1, getmsg(&editorMessageList, &editorMessageListItem, 616));
// PRINT TO FILE // 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) { if (showSaveFileDialog(string4, fileList, string1, fileListLength, 168, 80, 0) == 0) {
strcat(v236, ".TXT"); strcat(string1, ".");
strcat(string1, "TXT");
dest[0] = '\0'; string4[0] = '\0';
strcat(string4, string1);
if (!characterFileExists(dest)) { if (!characterFileExists(string4)) {
// already exists // already exists
sprintf(dest, sprintf(string4,
"%s %s", "%s %s",
compat_strupr(v236), strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 609)); getmsg(&editorMessageList, &editorMessageListItem, 609));
char v240[512]; strcpy(string5, getmsg(&editorMessageList, &editorMessageListItem, 610));
strcpy(v240, getmsg(&editorMessageList, &editorMessageListItem, 610));
const char* lines[] = { v240 }; if (showDialogBox(string4, dialogBody, 1, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0x10) != 0) {
if (showDialogBox(dest, lines, 1, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0x10) != 0) {
rc = 1; rc = 1;
} else { } else {
rc = 0; rc = 0;
@ -3712,24 +3721,24 @@ int _OptionWindow()
} }
if (rc != 0) { if (rc != 0) {
dest[0] = '\0'; string4[0] = '\0';
strcat(dest, v236); strcat(string4, string1);
if (characterPrintToFile(dest) == 0) { if (characterPrintToFile(string4) == 0) {
sprintf(dest, sprintf(string4,
"%s%s", "%s%s",
compat_strupr(v236), strupr(string1),
getmsg(&editorMessageList, &editorMessageListItem, 607)); 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 { } else {
soundPlayFile("iisxxxx1"); soundPlayFile("iisxxxx1");
sprintf(dest, sprintf(string4,
"%s%s%s", "%s%s%s",
getmsg(&editorMessageList, &editorMessageListItem, 611), 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 { } else {
soundPlayFile("iisxxxx1"); soundPlayFile("iisxxxx1");
strcpy(dest, getmsg(&editorMessageList, &editorMessageListItem, 615)); strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 615));
showDialogBox(dest, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0); showDialogBox(string4, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 0);
rc = 0; rc = 0;
} }
} else if (keyCode == 501 || keyCode == KEY_UPPERCASE_L || keyCode == KEY_LOWERCASE_L) { } else if (keyCode == 501 || keyCode == KEY_UPPERCASE_L || keyCode == KEY_LOWERCASE_L) {
// LOAD // LOAD
char path[COMPAT_MAX_PATH]; string4[0] = '\0';
path[0] = '\0'; strcat(string4, "*.");
strcat(path, "*."); strcat(string4, "GCD");
strcat(path, "GCD");
char** fileNames; char** fileNameList;
int filesCount = fileNameListInit(path, &fileNames, 0, 0); int fileNameListLength = fileNameListInit(string4, &fileNameList, 0, 0);
if (filesCount != -1) { 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 { } else {
soundPlayFile("iisxxxx1"); soundPlayFile("iisxxxx1");
// Error reading file list! // Error reading file list!
strcpy(path, getmsg(&editorMessageList, &editorMessageListItem, 615)); strcpy(string4, getmsg(&editorMessageList, &editorMessageListItem, 615));
rc = 0; 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) { } 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); windowRefresh(win);
@ -3804,7 +3953,7 @@ int _OptionWindow()
char title[512]; char title[512];
strcpy(title, getmsg(&editorMessageList, &editorMessageListItem, 602)); 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"); strcat(fileName, ".TXT");
title[0] = '\0'; title[0] = '\0';
@ -3814,7 +3963,7 @@ int _OptionWindow()
if (characterFileExists(title)) { if (characterFileExists(title)) {
sprintf(title, sprintf(title,
"%s %s", "%s %s",
compat_strupr(fileName), strupr(fileName),
getmsg(&editorMessageList, &editorMessageListItem, 609)); getmsg(&editorMessageList, &editorMessageListItem, 609));
char line2[512]; char line2[512];
@ -3839,7 +3988,7 @@ int _OptionWindow()
sprintf(title, sprintf(title,
"%s%s%s", "%s%s%s",
getmsg(&editorMessageList, &editorMessageListItem, 611), getmsg(&editorMessageList, &editorMessageListItem, 611),
compat_strupr(fileName), strupr(fileName),
"!"); "!");
showDialogBox(title, NULL, 0, 169, 126, _colorTable[32328], NULL, _colorTable[32328], 1); 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) { 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++; length++;
} }
} }

View File

@ -1,6 +1,7 @@
#include "dbox.h" #include "dbox.h"
#include "art.h" #include "art.h"
#include "character_editor.h"
#include "color.h" #include "color.h"
#include "core.h" #include "core.h"
#include "debug.h" #include "debug.h"
@ -18,6 +19,45 @@
#include <algorithm> #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 // 0x5108C8
const int gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT] = { const int gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT] = {
218, // MEDIALOG.FRM - Medium generic dialog box 218, // MEDIALOG.FRM - Medium generic dialog box
@ -55,7 +95,7 @@ const int _dblines[DIALOG_TYPE_COUNT] = {
}; };
// 0x510900 // 0x510900
int _flgids[7] = { int gLoadFileDialogFrmIds[FILE_DIALOG_FRM_COUNT] = {
224, // loadbox.frm - character editor 224, // loadbox.frm - character editor
8, // lilredup.frm - little red button up 8, // lilredup.frm - little red button up
9, // lilreddn.frm - little red button down 9, // lilreddn.frm - little red button down
@ -66,7 +106,7 @@ int _flgids[7] = {
}; };
// 0x51091C // 0x51091C
int _flgids2[7] = { int gSaveFileDialogFrmIds[FILE_DIALOG_FRM_COUNT] = {
225, // savebox.frm - character editor 225, // savebox.frm - character editor
8, // lilredup.frm - little red button up 8, // lilredup.frm - little red button up
9, // lilreddn.frm - little red button down 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; return rc;
} }
// 0x41EA78 // 0x41DE90
int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLength, int x, int y, int flags) int showLoadFileDialog(char *title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
{ {
int oldFont = fontGetCurrent(); int oldFont = fontGetCurrent();
unsigned char* frmBuffers[7]; bool isScrollable = false;
CacheEntry* frmHandles[7]; if (fileListLength > FILE_DIALOG_LINE_COUNT) {
Size frmSizes[7]; isScrollable = true;
}
for (int index = 0; index < 7; index++) { int selectedFileIndex = 0;
int fid = buildFid(6, _flgids2[index], 0, 0, 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)); frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
if (frmBuffers[index] == NULL) { if (frmBuffers[index] == NULL) {
while (--index >= 0) { 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) { if (win == -1) {
for (int index = 0; index < 7; index++) { for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]); artUnlock(frmHandles[index]);
} }
return -1; return -1;
} }
unsigned char* windowBuffer = windowGetBuffer(win); 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; MessageList messageList;
MessageListItem messageListItem; MessageListItem messageListItem;
@ -488,7 +550,7 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
if (!messageListInit(&messageList)) { if (!messageListInit(&messageList)) {
windowDestroy(win); windowDestroy(win);
for (int index = 0; index < 7; index++) { for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]); artUnlock(frmHandles[index]);
} }
@ -501,7 +563,7 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
if (!messageListLoad(&messageList, path)) { if (!messageListLoad(&messageList, path)) {
windowDestroy(win); windowDestroy(win);
for (int index = 0; index < 7; index++) { for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
artUnlock(frmHandles[index]); artUnlock(frmHandles[index]);
} }
@ -512,23 +574,23 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
// DONE // DONE
const char* done = getmsg(&messageList, &messageListItem, 100); 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 // CANCEL
const char* cancel = getmsg(&messageList, &messageListItem, 103); 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, int doneBtn = buttonCreate(win,
58, LOAD_FILE_DIALOG_DONE_BUTTON_X,
214, LOAD_FILE_DIALOG_DONE_BUTTON_Y,
frmSizes[2].width, frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
frmSizes[2].height, frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
-1, -1,
-1, -1,
-1, -1,
500, 500,
frmBuffers[1], frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
frmBuffers[2], frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
NULL, NULL,
BUTTON_FLAG_TRANSPARENT); BUTTON_FLAG_TRANSPARENT);
if (doneBtn != -1) { if (doneBtn != -1) {
@ -536,16 +598,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
} }
int cancelBtn = buttonCreate(win, int cancelBtn = buttonCreate(win,
163, LOAD_FILE_DIALOG_CANCEL_BUTTON_X,
214, LOAD_FILE_DIALOG_CANCEL_BUTTON_Y,
frmSizes[2].width, frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
frmSizes[2].height, frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
-1, -1,
-1, -1,
-1, -1,
501, 501,
frmBuffers[1], frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
frmBuffers[2], frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
NULL, NULL,
BUTTON_FLAG_TRANSPARENT); BUTTON_FLAG_TRANSPARENT);
if (cancelBtn != -1) { if (cancelBtn != -1) {
@ -553,16 +615,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
} }
int scrollUpBtn = buttonCreate(win, int scrollUpBtn = buttonCreate(win,
36, FILE_DIALOG_SCROLL_BUTTON_X,
44, FILE_DIALOG_SCROLL_BUTTON_Y,
frmSizes[6].width, frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].width,
frmSizes[6].height, frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
-1, -1,
505, 505,
506, 506,
505, 505,
frmBuffers[5], frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL],
frmBuffers[6], frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED],
NULL, NULL,
BUTTON_FLAG_TRANSPARENT); BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) { if (scrollUpBtn != -1) {
@ -570,16 +632,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
} }
int scrollDownButton = buttonCreate(win, int scrollDownButton = buttonCreate(win,
36, FILE_DIALOG_SCROLL_BUTTON_X,
44 + frmSizes[6].height, FILE_DIALOG_SCROLL_BUTTON_Y + frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
frmSizes[4].width, frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].width,
frmSizes[4].height, frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].height,
-1, -1,
503, 503,
504, 504,
503, 503,
frmBuffers[3], frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL],
frmBuffers[4], frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED],
NULL, NULL,
BUTTON_FLAG_TRANSPARENT); BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) { if (scrollUpBtn != -1) {
@ -588,10 +650,10 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
buttonCreate( buttonCreate(
win, win,
55, FILE_DIALOG_FILE_LIST_X,
49, FILE_DIALOG_FILE_LIST_Y,
190, FILE_DIALOG_FILE_LIST_WIDTH,
124, FILE_DIALOG_FILE_LIST_HEIGHT,
-1, -1,
-1, -1,
-1, -1,
@ -601,25 +663,714 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
NULL, NULL,
0); 0);
if (a1 != NULL) { if (title != NULL) {
fontDrawText(windowBuffer + frmSizes[0].width * 16 + 49, a1, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]); 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 // 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 lineHeight = fontGetLineHeight();
int y = 49; int y = FILE_DIALOG_FILE_LIST_Y;
bufferFill(buffer + y * pitch + 55, 190, 124, pitch, 100); 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 != 0) {
if (fileListLength - pageOffset > 12) { if (fileListLength - pageOffset > FILE_DIALOG_LINE_COUNT) {
fileListLength = 12; fileListLength = FILE_DIALOG_LINE_COUNT;
} }
for (int index = 0; index < fileListLength; index++) { for (int index = 0; index < fileListLength; index++) {
int color = index == selectedIndex ? _colorTable[32747] : _colorTable[992]; 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; y += lineHeight;
} }
} }

View File

@ -16,17 +16,35 @@ typedef enum DialogType {
DIALOG_TYPE_COUNT, DIALOG_TYPE_COUNT,
} DialogType; } 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 gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT];
extern const int _ytable[DIALOG_TYPE_COUNT]; extern const int _ytable[DIALOG_TYPE_COUNT];
extern const int _xtable[DIALOG_TYPE_COUNT]; extern const int _xtable[DIALOG_TYPE_COUNT];
extern const int _doneY[DIALOG_TYPE_COUNT]; extern const int _doneY[DIALOG_TYPE_COUNT];
extern const int _doneX[DIALOG_TYPE_COUNT]; extern const int _doneX[DIALOG_TYPE_COUNT];
extern const int _dblines[DIALOG_TYPE_COUNT]; extern const int _dblines[DIALOG_TYPE_COUNT];
extern int _flgids[7]; extern int gLoadFileDialogFrmIds[FILE_DIALOG_FRM_COUNT];
extern int _flgids2[7]; 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 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); int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags);
void _PrntFlist(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch); 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 */ #endif /* DBOX_H */

View File

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