TONY: Beginnings of converting dialog processes to coroutines

This commit is contained in:
Paul Gilbert 2012-05-06 23:51:11 +10:00
parent 156d8cdb73
commit 0b8974ec4a
5 changed files with 333 additions and 331 deletions

View file

@ -1875,70 +1875,80 @@ DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg
// @@@@ This cannot be skipped!!!!!!!!!!!!!!!!!!! // @@@@ This cannot be skipped!!!!!!!!!!!!!!!!!!!
DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) { DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) {
int nChoice; CORO_BEGIN_CONTEXT;
uint32 nChoice;
uint32 *sl; uint32 *sl;
int i, num; int i, num;
char *string; char *string;
RMDialogChoice dc; RMDialogChoice dc;
int sel; int sel;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
curDialog = nDialog; curDialog = nDialog;
// Chiama l'MPAL per iniziare il dialogo // Call MPAL to start the dialog
mpalQueryDoDialogU32(nDialog, nStartGroup); mpalQueryDoDialogU32(nDialog, nStartGroup);
// Aspetta che una scelta si presenti // Wait until a choice is selected
while ((nChoice = mpalQueryDialogWaitForChoice()) != -1) { mpalQueryDialogWaitForChoice(&_ctx->nChoice);
while (_ctx->nChoice != -1) {
// Si fa dare la lista di opzioni e le conta // Si fa dare la lista di opzioni e le conta
sl = mpalQueryDialogSelectList(nChoice); _ctx->sl = mpalQueryDialogSelectList(_ctx->nChoice);
for (num = 0; sl[num] != 0; num++) for (_ctx->num = 0; _ctx->sl[_ctx->num] != 0; _ctx->num++)
; ;
// Se c'e' una sola opzione, la fa automaticamente, e aspetta la prossima scelta // Se c'e' una sola opzione, la fa automaticamente, e aspetta la prossima scelta
if (num == 1) { if (_ctx->num == 1) {
mpalQueryDialogSelectionU32(nChoice, sl[0]); mpalQueryDialogSelectionU32(_ctx->nChoice, _ctx->sl[0]);
GlobalFree(sl); GlobalFree(_ctx->sl);
continue; continue;
} }
// Crea una scelta per il dialogo // Crea una scelta per il dialogo
dc.Init(); _ctx->dc.Init();
dc.SetNumChoices(num); _ctx->dc.SetNumChoices(_ctx->num);
// Scrive tutte le possibili opzioni // Scrive tutte le possibili opzioni
for (i = 0; i < num; i++) { for (_ctx->i = 0; _ctx->i < _ctx->num; _ctx->i++) {
string = mpalQueryDialogPeriod(sl[i]); _ctx->string = mpalQueryDialogPeriod(_ctx->sl[_ctx->i]);
assert(string != NULL); assert(_ctx->string != NULL);
dc.AddChoice(string); _ctx->dc.AddChoice(_ctx->string);
GlobalFree(string); GlobalFree(_ctx->string);
} }
// Attiva l'oggetto // Attiva l'oggetto
LinkGraphicTask(&dc); LinkGraphicTask(&_ctx->dc);
dc.Show(); _ctx->dc.Show();
// Disegna il puntatore // Disegna il puntatore
Pointer->SetSpecialPointer(Pointer->PTR_NONE); Pointer->SetSpecialPointer(Pointer->PTR_NONE);
MainShowMouse(); MainShowMouse();
while (!(Input->MouseLeftClicked() && ((sel = dc.GetSelection()) != -1))) { while (!(Input->MouseLeftClicked() && ((_ctx->sel = _ctx->dc.GetSelection()) != -1))) {
WaitFrame(); WaitFrame();
Freeze(); Freeze();
dc.DoFrame(Input->MousePos()); _ctx->dc.DoFrame(Input->MousePos());
Unfreeze(); Unfreeze();
} }
// Nascondi il puntatore // Nascondi il puntatore
MainHideMouse(); MainHideMouse();
dc.Hide(); _ctx->dc.Hide();
mpalQueryDialogSelectionU32(nChoice, sl[sel]); mpalQueryDialogSelectionU32(_ctx->nChoice, _ctx->sl[_ctx->sel]);
// Chiude la scelta // Chiude la scelta
dc.Close(); _ctx->dc.Close();
GlobalFree(sl); GlobalFree(_ctx->sl);
// Wait for the next choice to be made
mpalQueryDialogWaitForChoice(&_ctx->nChoice);
} }
CORO_END_CODE;
} }

View file

@ -1335,93 +1335,101 @@ void LocationPollThread(CORO_PARAM, const void *param) {
* *
\****************************************************************************/ \****************************************************************************/
void PASCAL ShutUpDialogThread(HANDLE hThread) { void ShutUpDialogThread(CORO_PARAM, const void *param) {
WaitForSingleObject(hThread, INFINITE); CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
uint32 pid = *(const uint32 *)param;
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_2(_vm->_scheduler.waitForSingleObject, pid, INFINITE);
bExecutingDialog = false; bExecutingDialog = false;
nExecutingDialog = 0; nExecutingDialog = 0;
nExecutingChoice = 0; nExecutingChoice = 0;
SetEvent(hAskChoice); SetEvent(hAskChoice);
ExitThread(1);
// _endthread(); CORO_KILL_SELF();
CORO_END_CODE;
} }
void DoChoice(CORO_PARAM, uint32 nChoice);
/****************************************************************************\ /**
* * Executes a group of the current dialog. Can 'be the Starting point of a process.
* Function: void GroupThread(uint32 nGroup); * @parm nGroup Number of the group to perform
* */
* Description: Esegue un gruppo del dialogo corrente. Puo' essere lo void GroupThread(CORO_PARAM, const void *param) {
* starting point di un thread. CORO_BEGIN_CONTEXT;
*
* Input: uint32 nGroup Numero del gruppo da eseguire
*
\****************************************************************************/
void DoChoice(uint32 nChoice);
void PASCAL GroupThread(uint32 nGroup) {
LPMPALDIALOG dialog; LPMPALDIALOG dialog;
int i, j, k; int i, j, k;
int type;
CORO_END_CONTEXT(_ctx);
/* Locka i dialoghi */ uint32 nGroup = *(const uint32 *)param;
CORO_BEGIN_CODE(_ctx);
// Lock the _ctx->dialog
LockDialogs(); LockDialogs();
/* Trova il puntatore al dialogo corrente */ // Find the pointer to the current _ctx->dialog
dialog = lpmdDialogs+nExecutingDialog; _ctx->dialog = lpmdDialogs + nExecutingDialog;
/* Cerca il gruppo richiesto all'interno del dialogo */ // Search inside the group requesting the _ctx->dialog
for (i = 0; dialog->Group[i].num != 0; i++) for (_ctx->i = 0; _ctx->dialog->Group[_ctx->i].num != 0; _ctx->i++) {
if (dialog->Group[i].num==nGroup) { if (_ctx->dialog->Group[_ctx->i].num == nGroup) {
/* Cicla eseguendo i comandi del gruppo */ // Cycle through executing the commands of the group
for (j = 0; j < dialog->Group[i].nCmds; j++) { for (_ctx->j = 0; _ctx->j < _ctx->dialog->Group[_ctx->i].nCmds; _ctx->j++) {
k=dialog->Group[i].CmdNum[j]; _ctx->k = _ctx->dialog->Group[_ctx->i].CmdNum[_ctx->j];
switch (dialog->Command[k].type) { _ctx->type = _ctx->dialog->Command[_ctx->k].type;
/* Funzione custom: la richiama */ if (_ctx->type == 1) {
case 1: // Call custom function
// FIXME: Convert to co-routine CORO_INVOKE_4(lplpFunctions[_ctx->dialog->Command[_ctx->k].nCf],
lplpFunctions[dialog->Command[k].nCf]( _ctx->dialog->Command[_ctx->k].arg1,
nullContext, _ctx->dialog->Command[_ctx->k].arg2,
dialog->Command[k].arg1, _ctx->dialog->Command[_ctx->k].arg3,
dialog->Command[k].arg2, _ctx->dialog->Command[_ctx->k].arg4
dialog->Command[k].arg3,
dialog->Command[k].arg4
); );
break;
/* Variabile: la setta */ } else if (_ctx->type == 2) {
case 2: // Set a variable
LockVar(); LockVar();
varSetValue(dialog->Command[k].lpszVarName,EvaluateExpression(dialog->Command[k].expr)); varSetValue(_ctx->dialog->Command[_ctx->k].lpszVarName, EvaluateExpression(_ctx->dialog->Command[_ctx->k].expr));
UnlockVar(); UnlockVar();
break;
/* DoChoice: richiama la funzione di scelta */ } else if (_ctx->type == 3) {
case 3: // DoChoice: call the chosen function
DoChoice((uint32)dialog->Command[k].nChoice); CORO_INVOKE_1(DoChoice, (uint32)_ctx->dialog->Command[_ctx->k].nChoice);
break;
default: } else {
mpalError = 1; mpalError = 1;
UnlockDialogs(); UnlockDialogs();
ExitThread(0);
// _endthread(); CORO_KILL_SELF();
return;
} }
} }
/* Abbiamo eseguito il gruppo. Possiamo uscire alla funzione chiamante. /* The gruop is finished, so we can return to the calling function.
Se il gruppo era il primo chiamato, allora automaticamente il * If the group was the first called, then the process will automatically
thread viene chiuso, altrimenti si ritorno al gruppo chiamante. */ * end. Otherwise it returns to the caller method
UnlockDialogs(); */
return; return;
} }
}
/* Se siamo qui, vuol dire che non abbiamo trovato il gruppo richiesto */ /* Se siamo qui, vuol dire che non abbiamo trovato il gruppo richiesto */
mpalError = 1; mpalError = 1;
UnlockDialogs(); UnlockDialogs();
ExitThread(0);
// _endthread(); CORO_KILL_SELF();
CORO_END_CODE;
} }
@ -1435,52 +1443,58 @@ void PASCAL GroupThread(uint32 nGroup) {
* *
\****************************************************************************/ \****************************************************************************/
void DoChoice(uint32 nChoice) { void DoChoice(CORO_PARAM, uint32 nChoice) {
CORO_BEGIN_CONTEXT;
LPMPALDIALOG dialog; LPMPALDIALOG dialog;
int i, j, k; int i, j, k;
uint32 nGroup;
CORO_END_CONTEXT(_ctx);
/* Locka i dialoghi */ CORO_BEGIN_CODE(_ctx);
/* Locka _ctx->i dialoghi */
LockDialogs(); LockDialogs();
/* Trova il puntatore al dialogo corrente */ /* Trova il puntatore al dialogo corrente */
dialog=lpmdDialogs+nExecutingDialog; _ctx->dialog=lpmdDialogs+nExecutingDialog;
/* Cerca la scelta richiesta tra quelle nel dialogo */ /* Cerca la scelta richiesta tra quelle nel dialogo */
for (i = 0; dialog->Choice[i].nChoice != 0; i++) for (_ctx->i = 0; _ctx->dialog->Choice[_ctx->i].nChoice != 0; _ctx->i++)
if (dialog->Choice[i].nChoice == nChoice) if (_ctx->dialog->Choice[_ctx->i].nChoice == nChoice)
break; break;
/* Se non l'ha trovata, esce con errore */ /* Se non l'ha trovata, esce con errore */
if (dialog->Choice[i].nChoice == 0) { if (_ctx->dialog->Choice[_ctx->i].nChoice == 0) {
/* Se siamo qui, non abbiamo trovato la choice richiesta */ /* Se siamo qui, non abbiamo trovato la choice richiesta */
mpalError = 1; mpalError = 1;
UnlockDialogs(); UnlockDialogs();
ExitThread(0);
// _endthread(); CORO_KILL_SELF();
return;
} }
/* Abbiamo trova la choice richiesta. Ricordiamoci qual e' nella /* Abbiamo trova la choice richiesta. Ricordiamoci qual e' nella
variabile globale */ variabile globale */
nExecutingChoice = i; nExecutingChoice = _ctx->i;
while (1) { while (1) {
nExecutingChoice = i; nExecutingChoice = _ctx->i;
k = 0; _ctx->k = 0;
/* Calcoliamo le when expression di ciascun select, per vedere se sono /* Calcoliamo le when expression di ciascun select, per vedere se sono
attivi o disattivi */ attivi o disattivi */
for (j = 0; dialog->Choice[i].Select[j].dwData != 0; j++) for (_ctx->j = 0; _ctx->dialog->Choice[_ctx->i].Select[_ctx->j].dwData != 0; _ctx->j++)
if (dialog->Choice[i].Select[j].when == NULL) { if (_ctx->dialog->Choice[_ctx->i].Select[_ctx->j].when == NULL) {
dialog->Choice[i].Select[j].curActive = 1; _ctx->dialog->Choice[_ctx->i].Select[_ctx->j].curActive = 1;
k++; _ctx->k++;
} else if (EvaluateExpression(dialog->Choice[i].Select[j].when)) { } else if (EvaluateExpression(_ctx->dialog->Choice[_ctx->i].Select[_ctx->j].when)) {
dialog->Choice[i].Select[j].curActive = 1; _ctx->dialog->Choice[_ctx->i].Select[_ctx->j].curActive = 1;
k++; _ctx->k++;
} else } else
dialog->Choice[i].Select[j].curActive = 0; _ctx->dialog->Choice[_ctx->i].Select[_ctx->j].curActive = 0;
/* Se non ci sono scelte attivate, la scelta e' finita */ /* Se non ci sono scelte attivate, la scelta e' finita */
if (k == 0) { if (_ctx->k == 0) {
UnlockDialogs(); UnlockDialogs();
break; break;
} }
@ -1491,31 +1505,36 @@ void DoChoice(uint32 nChoice) {
SetEvent(hAskChoice); SetEvent(hAskChoice);
WaitForSingleObject(hDoneChoice, INFINITE); WaitForSingleObject(hDoneChoice, INFINITE);
/* Ora che la scelta e' stata effettuata, possiamo eseguire i gruppi /* Ora che la scelta e' stata effettuata, possiamo eseguire _ctx->i gruppi
associati con la scelta */ associati con la scelta */
j=nSelectedChoice; _ctx->j = nSelectedChoice;
for (k = 0; dialog->Choice[i].Select[j].wPlayGroup[k] != 0; k++) for (_ctx->k = 0; _ctx->dialog->Choice[_ctx->i].Select[_ctx->j].wPlayGroup[_ctx->k] != 0; _ctx->k++) {
GroupThread(dialog->Choice[i].Select[j].wPlayGroup[k]); _ctx->nGroup = _ctx->dialog->Choice[_ctx->i].Select[_ctx->j].wPlayGroup[_ctx->k];
CORO_INVOKE_1(GroupThread, &_ctx->nGroup);
}
/* Controllo sugli attributi */ /* Controllo sugli attributi */
if (dialog->Choice[i].Select[j].attr & (1 << 0)) { if (_ctx->dialog->Choice[_ctx->i].Select[_ctx->j].attr & (1 << 0)) {
/* Bit 0 settato: fine della scelta */ /* Bit 0 settato: fine della scelta */
UnlockDialogs(); UnlockDialogs();
break; break;
} }
if (dialog->Choice[i].Select[j].attr & (1 << 1)) { if (_ctx->dialog->Choice[_ctx->i].Select[_ctx->j].attr & (1 << 1)) {
/* Bit 1 settato: fine del dialogo */ /* Bit 1 settato: fine del dialogo */
UnlockDialogs(); UnlockDialogs();
ExitThread(1);
// _endthread(); CORO_KILL_SELF();
return;
} }
/* Fine della scelta senza attributi: bisogna rifarla */ /* Fine della scelta senza attributi: bisogna rifarla */
} }
/* Se siamo qui, abbiamo trovato un end choice. Ritorna al gruppo chiamante */ // If we're here, we found an end choice. Return to the caller group
return; return;
CORO_END_CODE;
} }
@ -1605,57 +1624,40 @@ static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) {
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
/**
* Shows a dialog in a separate process.
*
* @param nDlgOrd The index of the dialog in the dialog list
* @param nGroup Number of the group to perform
* @returns The process Id of the process running the dialog
* or INVALID_HANDLE_VALUE on error
* @remarks The dialogue runs in a thread created on purpose,
* so that must inform through an event and when 'necessary to you make a choice.
* The data on the choices may be obtained through various queries.
*/
static uint32 DoDialog(uint32 nDlgOrd, uint32 nGroup) {
uint32 h;
/****************************************************************************\ // Store the running dialog in a global variable
*
* Function: HANDLE DoDialog(uint32 nDlgOrd, uint32 nGroup);
*
* Description: Esegue un dialogo in un thread
*
* Input: uint32 nDlgOrd Indice del dialogo da eseguire
* all'interno dell'array di strutture
* dei dialoghi
* uint32 nGroup Numero del gruppo da eseguire
*
* Return: Handle del thread che sta eseguendo il dialogo, o
* INVALID_HANDLE_VALUE in caso di errore
*
* Note: Il dialogo viene eseguito in un thread creato apposta, che
* deve informa tramite un evento quando e' necessario far
* fare una scelta all'utente. I dati sulle scelte possono
* essere richiesti tramite le varie query.
*
\****************************************************************************/
static HANDLE DoDialog(uint32 nDlgOrd, uint32 nGroup) {
// LPMPALDIALOG dialog=lpmdDialogs+nDlgOrd;
uint32 dwId;
HANDLE h;
/* Si ricorda nella variabile globale qual e' il dialogo in esecuzione */
nExecutingDialog = nDlgOrd; nExecutingDialog = nDlgOrd;
/* Attiva la flag per indicare che c'e' un dialogo in esecuzione */ // Enables the flag to indicate that there is' a running dialogue
bExecutingDialog = true; bExecutingDialog = true;
ResetEvent(hAskChoice); ResetEvent(hAskChoice);
ResetEvent(hDoneChoice); ResetEvent(hDoneChoice);
/* Crea un thread in cui esegue un gruppo del dialogo */ // Create a thread that performs the dialogue group
// !!! Nuova gestione dei thread // Create the process
if ((h = CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)GroupThread, (void *)nGroup, 0, &dwId)) == NULL) if ((h = _vm->_scheduler.createProcess(GroupThread, &nGroup, sizeof(uint32))) == 0)
// if ((h=(void*)_beginthread(GroupThread, 10240,(void *)nGroup))==(void*)-1) return 0;
return INVALID_HANDLE_VALUE;
/* Crea un thread che attende la fine del dialogo e rimette a posto le // Create a thread that waits until the end of the dialog process, and will restore the global variables
variabili globali */ if (_vm->_scheduler.createProcess(ShutUpDialogThread, &h, sizeof(uint32)) == 0) {
// !!! Nuova gestione dei thread // Something went wrong, so kill the previously started dialog process
if (CreateThread(NULL, 10240,(LPTHREAD_START_ROUTINE)ShutUpDialogThread,(void *)h, 0, &dwId) == NULL) { _vm->_scheduler.killMatchingProcess(h);
//if ((h=(void*)_beginthread(ShutUpDialogThread, 10240,(void *)h))==(void*)-1) return 0;
TerminateThread(h, 0);
CloseHandle(h);
return INVALID_HANDLE_VALUE;
} }
return h; return h;
@ -1893,243 +1895,230 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName,
#define GETARG(type) va_arg(v,type) #define GETARG(type) va_arg(v,type)
uint32 mpalQuery(uint16 wQueryType, ...) { void mpalQueryInner(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, va_list v) {
uint32 dwRet = 0; CORO_BEGIN_CONTEXT;
int x, y, z; int x, y, z;
char *n; char *n;
va_list v;
Common::String buf; Common::String buf;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
mpalError = OK; mpalError = OK;
va_start(v, wQueryType);
switch (wQueryType) { if (wQueryType == MPQ_VERSION) {
/* /*
* uint32 mpalQuery(MPQ_VERSION); * uint32 mpalQuery(MPQ_VERSION);
*/ */
case MPQ_VERSION: *dwRet = HEX_VERSION;
dwRet = HEX_VERSION;
break;
} else if (wQueryType == MPQ_GLOBAL_VAR) {
/* /*
* uint32 mpalQuery(MPQ_GLOBAL_VAR, char * lpszVarName); * uint32 mpalQuery(MPQ_GLOBAL_VAR, char * lpszVarName);
*/ */
case MPQ_GLOBAL_VAR:
LockVar(); LockVar();
dwRet = (uint32)varGetValue(GETARG(char *)); *dwRet = (uint32)varGetValue(GETARG(char *));
UnlockVar(); UnlockVar();
break;
} else if (wQueryType == MPQ_MESSAGE) {
/* /*
* char * mpalQuery(MPQ_MESSAGE, uint32 nMsg); * char * mpalQuery(MPQ_MESSAGE, uint32 nMsg);
*/ */
case MPQ_MESSAGE:
LockMsg(); LockMsg();
dwRet = (uint32)DuplicateMessage(msgGetOrderFromNum(GETARG(uint32))); *dwRet = (uint32)DuplicateMessage(msgGetOrderFromNum(GETARG(uint32)));
UnlockMsg(); UnlockMsg();
break;
} else if (wQueryType == MPQ_ITEM_PATTERN) {
/* /*
* uint32 mpalQuery(MPQ_ITEM_PATTERN, uint32 nItem); * uint32 mpalQuery(MPQ_ITEM_PATTERN, uint32 nItem);
*/ */
case MPQ_ITEM_PATTERN:
LockVar(); LockVar();
buf = Common::String::format("Pattern.%u", GETARG(uint32)); _ctx->buf = Common::String::format("Pattern.%u", GETARG(uint32));
dwRet = (uint32)varGetValue(buf.c_str()); *dwRet = (uint32)varGetValue(_ctx->buf.c_str());
UnlockVar(); UnlockVar();
break;
} else if (wQueryType == MPQ_LOCATION_SIZE) {
/* /*
* uint32 mpalQuery(MPQ_LOCATION_SIZE, uint32 nLoc, uint32 dwCoord); * uint32 mpalQuery(MPQ_LOCATION_SIZE, uint32 nLoc, uint32 dwCoord);
*/ */
case MPQ_LOCATION_SIZE:
LockLocations(); LockLocations();
x = locGetOrderFromNum(GETARG(uint32)); _ctx->x = locGetOrderFromNum(GETARG(uint32));
y = GETARG(uint32); _ctx->y = GETARG(uint32);
if (x != -1) { if (_ctx->x != -1) {
if (y == MPQ_X) if (_ctx->y == MPQ_X)
dwRet = lpmlLocations[x].dwXlen; *dwRet = lpmlLocations[_ctx->x].dwXlen;
else if (y == MPQ_Y) else if (_ctx->y == MPQ_Y)
dwRet = lpmlLocations[x].dwYlen; *dwRet = lpmlLocations[_ctx->x].dwYlen;
else else
mpalError = 1; mpalError = 1;
} else } else
mpalError = 1; mpalError = 1;
UnlockLocations(); UnlockLocations();
break;
} else if (wQueryType == MPQ_LOCATION_IMAGE) {
/* /*
* HGLOBAL mpalQuery(MPQ_LOCATION_IMAGE, uint32 nLoc); * HGLOBAL mpalQuery(MPQ_LOCATION_IMAGE, uint32 nLoc);
*/ */
case MPQ_LOCATION_IMAGE:
LockLocations(); LockLocations();
x = locGetOrderFromNum(GETARG(uint32)); _ctx->x = locGetOrderFromNum(GETARG(uint32));
dwRet = (uint32)resLoad(lpmlLocations[x].dwPicRes); *dwRet = (uint32)resLoad(lpmlLocations[_ctx->x].dwPicRes);
UnlockLocations(); UnlockLocations();
break;
} else if (wQueryType == MPQ_RESOURCE) {
/* /*
* HGLOBAL mpalQuery(MPQ_RESOURCE, uint32 dwRes); * HGLOBAL mpalQuery(MPQ_RESOURCE, uint32 dwRes);
*/ */
case MPQ_RESOURCE: *dwRet = (uint32)resLoad(GETARG(uint32));
dwRet = (uint32)resLoad(GETARG(uint32));
break;
} else if (wQueryType == MPQ_ITEM_LIST) {
/* /*
* uint32 mpalQuery(MPQ_ITEM_LIST, uint32 nLoc); * uint32 mpalQuery(MPQ_ITEM_LIST, uint32 nLoc);
*/ */
case MPQ_ITEM_LIST:
LockVar(); LockVar();
dwRet = (uint32)GetItemList(GETARG(uint32)); *dwRet = (uint32)GetItemList(GETARG(uint32));
LockVar(); LockVar();
break;
} else if (wQueryType == MPQ_ITEM_DATA) {
/* /*
* LPITEM mpalQuery(MPQ_ITEM_DATA, uint32 nItem); * LPITEM mpalQuery(MPQ_ITEM_DATA, uint32 nItem);
*/ */
case MPQ_ITEM_DATA:
LockItems(); LockItems();
dwRet = (uint32)GetItemData(itemGetOrderFromNum(GETARG(uint32))); *dwRet = (uint32)GetItemData(itemGetOrderFromNum(GETARG(uint32)));
UnlockItems(); UnlockItems();
break;
} else if (wQueryType == MPQ_ITEM_IS_ACTIVE) {
/* /*
* bool mpalQuery(MPQ_ITEM_IS_ACTIVE, uint32 nItem); * bool mpalQuery(MPQ_ITEM_IS_ACTIVE, uint32 nItem);
*/ */
case MPQ_ITEM_IS_ACTIVE:
LockVar(); LockVar();
x = GETARG(uint32); _ctx->x = GETARG(uint32);
buf = Common::String::format("Status.%u", x); _ctx->buf = Common::String::format("Status.%u", _ctx->x);
if (varGetValue(buf.c_str()) <= 0) if (varGetValue(_ctx->buf.c_str()) <= 0)
dwRet = (uint32)false; *dwRet = (uint32)false;
else else
dwRet = (uint32)true; *dwRet = (uint32)true;
UnlockVar(); UnlockVar();
break;
} else if (wQueryType == MPQ_ITEM_NAME) {
/* /*
* uint32 mpalQuery(MPQ_ITEM_NAME, uint32 nItem, char * lpszName); * uint32 mpalQuery(MPQ_ITEM_NAME, uint32 nItem, char * lpszName);
*/ */
case MPQ_ITEM_NAME:
LockVar(); LockVar();
x = GETARG(uint32); _ctx->x = GETARG(uint32);
n=GETARG(char *); _ctx->n = GETARG(char *);
buf = Common::String::format("Status.%u", x); _ctx->buf = Common::String::format("Status.%u", _ctx->x);
if (varGetValue(buf.c_str()) <= 0) if (varGetValue(_ctx->buf.c_str()) <= 0)
n[0]='\0'; _ctx->n[0]='\0';
else { else {
LockItems(); LockItems();
y = itemGetOrderFromNum(x); _ctx->y = itemGetOrderFromNum(_ctx->x);
CopyMemory(n, (char *)(lpmiItems+y)->lpszDescribe, MAX_DESCRIBE_SIZE); CopyMemory(_ctx->n, (char *)(lpmiItems+_ctx->y)->lpszDescribe, MAX_DESCRIBE_SIZE);
UnlockItems(); UnlockItems();
} }
UnlockVar(); UnlockVar();
break;
} else if (wQueryType == MPQ_DIALOG_PERIOD) {
/* /*
* char * mpalQuery(MPQ_DIALOG_PERIOD, uint32 nDialog, uint32 nPeriod); * char * mpalQuery(MPQ_DIALOG_PERIOD, uint32 nDialog, uint32 nPeriod);
*/ */
case MPQ_DIALOG_PERIOD:
LockDialogs(); LockDialogs();
y = GETARG(uint32); _ctx->y = GETARG(uint32);
dwRet = (uint32)DuplicateDialogPeriod(y); *dwRet = (uint32)DuplicateDialogPeriod(_ctx->y);
UnlockDialogs(); UnlockDialogs();
break;
} else if (wQueryType == MPQ_DIALOG_WAITFORCHOICE) {
/* /*
* void mpalQuery(MPQ_DIALOG_WAITFORCHOICE); * void mpalQuery(MPQ_DIALOG_WAITFORCHOICE);
*/ */
case MPQ_DIALOG_WAITFORCHOICE:
WaitForSingleObject(hAskChoice, INFINITE); WaitForSingleObject(hAskChoice, INFINITE);
ResetEvent(hAskChoice); ResetEvent(hAskChoice);
if (bExecutingDialog) if (bExecutingDialog)
dwRet = (uint32)nExecutingChoice; *dwRet = (uint32)nExecutingChoice;
else else
dwRet = (uint32)((int)-1); *dwRet = (uint32)((int)-1);
break;
} else if (wQueryType == MPQ_DIALOG_SELECTLIST) {
/* /*
* uint32 *mpalQuery(MPQ_DIALOG_SELECTLIST, uint32 nChoice); * uint32 *mpalQuery(MPQ_DIALOG_SELECTLIST, uint32 nChoice);
*/ */
case MPQ_DIALOG_SELECTLIST:
LockDialogs(); LockDialogs();
dwRet = (uint32)GetSelectList(GETARG(uint32)); *dwRet = (uint32)GetSelectList(GETARG(uint32));
UnlockDialogs(); UnlockDialogs();
break; break;
} else if (wQueryType == MPQ_DIALOG_SELECTION) {
/* /*
* bool mpalQuery(MPQ_DIALOG_SELECTION, uint32 nChoice, uint32 dwData); * bool mpalQuery(MPQ_DIALOG_SELECTION, uint32 nChoice, uint32 dwData);
*/ */
case MPQ_DIALOG_SELECTION:
LockDialogs(); LockDialogs();
x = GETARG(uint32); _ctx->x = GETARG(uint32);
y = GETARG(uint32); _ctx->y = GETARG(uint32);
dwRet = (uint32)DoSelection(x,y); *dwRet = (uint32)DoSelection(_ctx->x,_ctx->y);
UnlockDialogs(); UnlockDialogs();
break;
} else if (wQueryType == MPQ_DO_ACTION) {
/* /*
* int mpalQuery(MPQ_DO_ACTION, uint32 nAction, uint32 nItem, uint32 dwParam); * int mpalQuery(MPQ_DO_ACTION, uint32 nAction, uint32 nItem, uint32 dwParam);
*/ */
case MPQ_DO_ACTION:
/*
if (bExecutingAction)
{
dwRet = (uint32)INVALID_HANDLE_VALUE;
break;
}
*/
LockItems(); LockItems();
LockVar(); LockVar();
x = GETARG(uint32); _ctx->x = GETARG(uint32);
z = GETARG(uint32); _ctx->z = GETARG(uint32);
y = itemGetOrderFromNum(z); _ctx->y = itemGetOrderFromNum(_ctx->z);
if (y!=-1) { if (_ctx->y!=-1) {
dwRet = (uint32)DoAction(x, y, GETARG(uint32)); *dwRet = (uint32)DoAction(_ctx->x, _ctx->y, GETARG(uint32));
} else { } else {
dwRet = (uint32)INVALID_HANDLE_VALUE; *dwRet = (uint32)INVALID_HANDLE_VALUE;
mpalError = 1; mpalError = 1;
} }
UnlockVar(); UnlockVar();
UnlockItems(); UnlockItems();
break;
} else if (wQueryType == MPQ_DO_DIALOG) {
/* /*
* int mpalQuery(MPQ_DO_DIALOG, uint32 nDialog, uint32 nGroup); * int mpalQuery(MPQ_DO_DIALOG, uint32 nDialog, uint32 nGroup);
*/ */
case MPQ_DO_DIALOG: if (!bExecutingDialog) {
if (bExecutingDialog)
break;
LockDialogs(); LockDialogs();
x = dialogGetOrderFromNum(GETARG(uint32)); _ctx->x = dialogGetOrderFromNum(GETARG(uint32));
y = GETARG(uint32); _ctx->y = GETARG(uint32);
dwRet = (uint32)DoDialog(x, y); *dwRet = DoDialog(_ctx->x, _ctx->y);
UnlockDialogs(); UnlockDialogs();
break; }
} else {
/* /*
* DEFAULT -> ERROR * DEFAULT -> ERROR
*/ */
default:
mpalError = 1; mpalError = 1;
break;
} }
CORO_END_CODE;
}
uint32 mpalQuery(uint16 wQueryType, ...) {
uint32 dwRet;
va_list v;
va_start(v, wQueryType);
mpalQueryInner(nullContext, wQueryType, &dwRet, v);
va_end(v); va_end(v);
return dwRet; return dwRet;
} }
void mpalQueryCoro(CORO_PARAM, uint32 *dwRet, uint16 wQueryType, ...) {
va_list v;
va_start(v, wQueryType);
mpalQueryInner(coroParam, wQueryType, dwRet, v);
va_end(v);
}
/****************************************************************************\ /****************************************************************************\
* *

View file

@ -474,10 +474,8 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION;
* *
\****************************************************************************/ \****************************************************************************/
#define mpalQueryDialogWaitForChoice() \ #define mpalQueryDialogWaitForChoice(dwRet) \
(int)mpalQuery(MPQ_DIALOG_WAITFORCHOICE) CORO_INVOKE_2(mpalQueryCoro, dwRet, MPQ_DIALOG_WAITFORCHOICE)
/****************************************************************************\ /****************************************************************************\
* *
@ -627,7 +625,7 @@ bool EXPORT mpalInit(const char *lpszFileName, const char *lpszMprFileName,
uint32 EXPORT mpalQuery(uint16 wQueryType, ...); uint32 EXPORT mpalQuery(uint16 wQueryType, ...);
void mpalQueryCoro(CORO_PARAM, uint32 *dwRet, uint16 wQueryType, ...);
/****************************************************************************\ /****************************************************************************\
* *

View file

@ -80,10 +80,12 @@ void Sleep(uint32 time) {
} }
int WaitForSingleObject(HANDLE ThreadId, uint32 dwSleepTime) { int WaitForSingleObject(HANDLE ThreadId, uint32 dwSleepTime) {
warning("TODO: Old style WaitForSingleObject");
return 0; return 0;
} }
uint32 WaitForMultipleObjects(uint32 nCount, const HANDLE *lpHandles, bool bWaitAll, uint32 dwMilliseconds) { uint32 WaitForMultipleObjects(uint32 nCount, const HANDLE *lpHandles, bool bWaitAll, uint32 dwMilliseconds) {
warning("TODO: Old style WaitForMultipleObjects");
return 0; return 0;
} }

View file

@ -299,6 +299,9 @@ void Scheduler::giveWay(PPROCESS pReSchedProc) {
* @param expired Set to true if delay period expired * @param expired Set to true if delay period expired
*/ */
void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration, bool *expired) { void Scheduler::waitForSingleObject(CORO_PARAM, int pid, int duration, bool *expired) {
if (!pCurrent)
error("Called Scheduler::waitForSingleObject from the main process");
CORO_BEGIN_CONTEXT; CORO_BEGIN_CONTEXT;
uint32 endTime; uint32 endTime;
PROCESS *pProc; PROCESS *pProc;