Browse Source

temp commit

louyihua 8 years ago
parent
commit
bbd5522ced
19 changed files with 1322 additions and 1440 deletions
  1. 7 10
      README.txt
  2. 119 116
      battle.c
  3. 0 8
      battle.h
  4. 5 3
      common.h
  5. 625 645
      fight.c
  6. 0 4
      fight.h
  7. 32 30
      global.c
  8. 6 11
      global.h
  9. 6 27
      itemmenu.c
  10. 6 27
      magicmenu.c
  11. 7 21
      script.c
  12. 14 0
      sdlpal.cfg.example
  13. 0 2
      sound.c
  14. 1 5
      sound.h
  15. 251 21
      text.c
  16. 16 0
      text.h
  17. 0 195
      ui.c
  18. 0 27
      ui.h
  19. 227 288
      uibattle.c

+ 7 - 10
README.txt

@@ -81,17 +81,14 @@ The compiled bundle should work as a "universal" binary which works on both
 Intel and PowerPC.
 
 
-CLASSIC BUILD
-=============
-
-By default, SDLPAL uses a revised battle system which is more exciting yet
-somewhat harder than the original game. If you prefer the traditional
-turn-based battle system, uncomment the following line:
-
-//#define PAL_CLASSIC           1
+REVISED BATTLE SYSTEM
+=====================
 
-in the file common.h and recompile. This will build a "classic" build which is
-100% the same as the original game.
+By default, SDLPAL uses the turn-based battle system which is 100% compatible
+to the original game. But SDLPAL also provides a revised battle system which
+is more exciting yet somewhat harder than the original game. If you prefer
+this version of battle system, please refer to the secion 'CONFIGURE THE GAME'
+for how to enable it.
 
 
 RUNNING THE GAME

+ 119 - 116
battle.c

@@ -367,9 +367,7 @@ PAL_BattleMain(
       g_Battle.BattleResult = kBattleResultOnGoing;
    }
 
-#ifndef PAL_CLASSIC
-   PAL_UpdateTimeChargingUnit();
-#endif
+   if (!gConfig.fIsClassic) PAL_UpdateTimeChargingUnit();
 
    dwTime = SDL_GetTicks();
 
@@ -922,32 +920,34 @@ PAL_BattleWon(
    {
       w = gpGlobals->rgParty[i].wPlayerRole;
 
-#if 1//def PAL_CLASSIC
-      gpGlobals->g.PlayerRoles.rgwHP[w] +=
-         (gpGlobals->g.PlayerRoles.rgwMaxHP[w] - gpGlobals->g.PlayerRoles.rgwHP[w]) / 2;
-      gpGlobals->g.PlayerRoles.rgwMP[w] +=
-         (gpGlobals->g.PlayerRoles.rgwMaxMP[w] - gpGlobals->g.PlayerRoles.rgwMP[w]) / 2;
-#else
-      if (gpGlobals->g.PlayerRoles.rgwHP[w] == 0)
+      if (gConfig.fIsClassic)
       {
-         gpGlobals->g.PlayerRoles.rgwHP[w] = 1;
+         gpGlobals->g.PlayerRoles.rgwHP[w] +=
+            (gpGlobals->g.PlayerRoles.rgwMaxHP[w] - gpGlobals->g.PlayerRoles.rgwHP[w]) / 2;
+         gpGlobals->g.PlayerRoles.rgwMP[w] +=
+            (gpGlobals->g.PlayerRoles.rgwMaxMP[w] - gpGlobals->g.PlayerRoles.rgwMP[w]) / 2;
       }
-      else if (g_Battle.iExpGained > 0)
+      else
       {
-         FLOAT f =
-            (gpGlobals->g.rgLevelUpExp[gpGlobals->g.PlayerRoles.rgwLevel[w]] / 5.0f) / g_Battle.iExpGained;
-
-         if (f < 2)
+         if (gpGlobals->g.PlayerRoles.rgwHP[w] == 0)
          {
-            f = 2;
+            gpGlobals->g.PlayerRoles.rgwHP[w] = 1;
          }
+         else if (g_Battle.iExpGained > 0)
+         {
+            FLOAT f = (gpGlobals->g.rgLevelUpExp[gpGlobals->g.PlayerRoles.rgwLevel[w]] / 5.0f) / g_Battle.iExpGained;
 
-         gpGlobals->g.PlayerRoles.rgwHP[w] +=
-            (gpGlobals->g.PlayerRoles.rgwMaxHP[w] - gpGlobals->g.PlayerRoles.rgwHP[w]) / f;
-         gpGlobals->g.PlayerRoles.rgwMP[w] +=
-            (gpGlobals->g.PlayerRoles.rgwMaxMP[w] - gpGlobals->g.PlayerRoles.rgwMP[w]) / f / 1.2;
+            if (f < 2.0f)
+            {
+               f = 2.0f;
+            }
+
+            gpGlobals->g.PlayerRoles.rgwHP[w] +=
+               (gpGlobals->g.PlayerRoles.rgwMaxHP[w] - gpGlobals->g.PlayerRoles.rgwHP[w]) / f;
+            gpGlobals->g.PlayerRoles.rgwMP[w] +=
+               (gpGlobals->g.PlayerRoles.rgwMaxMP[w] - gpGlobals->g.PlayerRoles.rgwMP[w]) / f / 1.2;
+         }
       }
-#endif
    }
 }
 
@@ -1195,102 +1195,103 @@ PAL_StartBattle(
          g_Battle.rgEnemy[i].wScriptOnReady = gpGlobals->g.rgObject[w].enemy.wScriptOnReady;
          g_Battle.rgEnemy[i].iColorShift = 0;
 
-#ifndef PAL_CLASSIC
-         g_Battle.rgEnemy[i].flTimeMeter = 50;
-
-         //
-         // HACK: Otherwise the black thief lady will be too hard to beat
-         //
-         if (g_Battle.rgEnemy[i].e.wDexterity == 164)
+         if (!gConfig.fIsClassic)
          {
-            g_Battle.rgEnemy[i].e.wDexterity /= ((gpGlobals->wMaxPartyMemberIndex == 0) ? 6 : 3);
-         }
+            g_Battle.rgEnemy[i].flTimeMeter = 50;
 
-         //
-         // HACK: Heal up automatically for final boss
-         //
-         if (g_Battle.rgEnemy[i].e.wHealth == 32760)
-         {
-            for (w = 0; w < MAX_PLAYER_ROLES; w++)
+            //
+            // HACK: Otherwise the black thief lady will be too hard to beat
+            //
+            if (g_Battle.rgEnemy[i].e.wDexterity == 164)
             {
-               gpGlobals->g.PlayerRoles.rgwHP[w] = gpGlobals->g.PlayerRoles.rgwMaxHP[w];
-               gpGlobals->g.PlayerRoles.rgwMP[w] = gpGlobals->g.PlayerRoles.rgwMaxMP[w];
+               g_Battle.rgEnemy[i].e.wDexterity /= ((gpGlobals->wMaxPartyMemberIndex == 0) ? 6 : 3);
             }
-         }
 
-         //
-         // Yet another HACKs
-         //
-         if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -32)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity = 0; // for Grandma Knife
-         }
-         else if (g_Battle.rgEnemy[i].e.wDexterity == 20)
-         {
             //
-            // for Fox Demon
+            // HACK: Heal up automatically for final boss
             //
-            if (gpGlobals->g.PlayerRoles.rgwLevel[0] < 15)
-            {
-               g_Battle.rgEnemy[i].e.wDexterity = 8;
-            }
-            else if (gpGlobals->g.PlayerRoles.rgwLevel[4] > 28 ||
-               gpGlobals->Exp.rgPrimaryExp[4].wExp > 0)
+            if (g_Battle.rgEnemy[i].e.wHealth == 32760)
             {
-               g_Battle.rgEnemy[i].e.wDexterity = 60;
+               for (w = 0; w < MAX_PLAYER_ROLES; w++)
+               {
+                  gpGlobals->g.PlayerRoles.rgwHP[w] = gpGlobals->g.PlayerRoles.rgwMaxHP[w];
+                  gpGlobals->g.PlayerRoles.rgwMP[w] = gpGlobals->g.PlayerRoles.rgwMaxMP[w];
+               }
             }
-         }
-         else if (g_Battle.rgEnemy[i].e.wExp == 250 &&
-            g_Battle.rgEnemy[i].e.wCash == 1100)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity += 12; // for Snake Demon
-         }
-         else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -60)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity = 15; // for Spider
-         }
-         else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -30)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity = (WORD)-10; // for Stone Head
-         }
-         else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -16)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity = 0; // for Zombie
-         }
-         else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -20)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity = -8; // for Flower Demon
-         }
-         else if (g_Battle.rgEnemy[i].e.wLevel < 20 &&
-            gpGlobals->wNumScene >= 0xD8 && gpGlobals->wNumScene <= 0xE2)
-         {
+
             //
-            // for low-level monsters in the Cave of Trial
+            // Yet another HACKs
             //
-            g_Battle.rgEnemy[i].e.wLevel += 15;
-            g_Battle.rgEnemy[i].e.wDexterity += 25;
-         }
-         else if (gpGlobals->wNumScene == 0x90)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity += 25; // for Tower Dragons
-         }
-         else if (g_Battle.rgEnemy[i].e.wLevel == 2 &&
-            g_Battle.rgEnemy[i].e.wCash == 48)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity += 8; // for Miao Fists
-         }
-         else if (g_Battle.rgEnemy[i].e.wLevel == 4 &&
-            g_Battle.rgEnemy[i].e.wCash == 240)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity += 18; // for Fat Miao
-         }
-         else if (g_Battle.rgEnemy[i].e.wLevel == 16 &&
-            g_Battle.rgEnemy[i].e.wMagicRate == 4 &&
-            g_Battle.rgEnemy[i].e.wAttackEquivItemRate == 4)
-         {
-            g_Battle.rgEnemy[i].e.wDexterity += 50; // for Black Spider
+            if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -32)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity = 0; // for Grandma Knife
+            }
+            else if (g_Battle.rgEnemy[i].e.wDexterity == 20)
+            {
+               //
+               // for Fox Demon
+               //
+               if (gpGlobals->g.PlayerRoles.rgwLevel[0] < 15)
+               {
+                  g_Battle.rgEnemy[i].e.wDexterity = 8;
+               }
+               else if (gpGlobals->g.PlayerRoles.rgwLevel[4] > 28 ||
+                  gpGlobals->Exp.rgPrimaryExp[4].wExp > 0)
+               {
+                  g_Battle.rgEnemy[i].e.wDexterity = 60;
+               }
+            }
+            else if (g_Battle.rgEnemy[i].e.wExp == 250 &&
+               g_Battle.rgEnemy[i].e.wCash == 1100)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity += 12; // for Snake Demon
+            }
+            else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -60)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity = 15; // for Spider
+            }
+            else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -30)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity = (WORD)-10; // for Stone Head
+            }
+            else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -16)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity = 0; // for Zombie
+            }
+            else if ((SHORT)g_Battle.rgEnemy[i].e.wDexterity == -20)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity = -8; // for Flower Demon
+            }
+            else if (g_Battle.rgEnemy[i].e.wLevel < 20 &&
+               gpGlobals->wNumScene >= 0xD8 && gpGlobals->wNumScene <= 0xE2)
+            {
+               //
+               // for low-level monsters in the Cave of Trial
+               //
+               g_Battle.rgEnemy[i].e.wLevel += 15;
+               g_Battle.rgEnemy[i].e.wDexterity += 25;
+            }
+            else if (gpGlobals->wNumScene == 0x90)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity += 25; // for Tower Dragons
+            }
+            else if (g_Battle.rgEnemy[i].e.wLevel == 2 &&
+               g_Battle.rgEnemy[i].e.wCash == 48)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity += 8; // for Miao Fists
+            }
+            else if (g_Battle.rgEnemy[i].e.wLevel == 4 &&
+               g_Battle.rgEnemy[i].e.wCash == 240)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity += 18; // for Fat Miao
+            }
+            else if (g_Battle.rgEnemy[i].e.wLevel == 16 &&
+               g_Battle.rgEnemy[i].e.wMagicRate == 4 &&
+               g_Battle.rgEnemy[i].e.wAttackEquivItemRate == 4)
+            {
+               g_Battle.rgEnemy[i].e.wDexterity += 50; // for Black Spider
+            }
          }
-#endif
       }
    }
 
@@ -1302,10 +1303,11 @@ PAL_StartBattle(
    for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
    {
       g_Battle.rgPlayer[i].flTimeMeter = 15.0f;
-#ifndef PAL_CLASSIC
-      g_Battle.rgPlayer[i].flTimeSpeedModifier = 2.0f;
-      g_Battle.rgPlayer[i].sTurnOrder = -1;
-#endif
+      if (!gConfig.fIsClassic)
+      {
+         g_Battle.rgPlayer[i].flTimeSpeedModifier = 2.0f;
+         g_Battle.rgPlayer[i].sTurnOrder = -1;
+      }
       g_Battle.rgPlayer[i].wHidingTime = 0;
       g_Battle.rgPlayer[i].state = kFighterWait;
       g_Battle.rgPlayer[i].action.sTarget = -1;
@@ -1376,12 +1378,13 @@ PAL_StartBattle(
 
    PAL_MKFReadChunk(g_Battle.lpEffectSprite, i, 10, gpGlobals->f.fpDATA);
 
-#ifdef PAL_CLASSIC
-   g_Battle.Phase = kBattlePhaseSelectAction;
-   g_Battle.fRepeat = FALSE;
-   g_Battle.fForce = FALSE;
-   g_Battle.fFlee = FALSE;
-#endif
+   if (gConfig.fIsClassic)
+   {
+      g_Battle.Phase = kBattlePhaseSelectAction;
+      g_Battle.fRepeat = FALSE;
+      g_Battle.fForce = FALSE;
+      g_Battle.fFlee = FALSE;
+   }
 
 #ifdef PAL_ALLOW_KEYREPEAT
    SDL_EnableKeyRepeat(120, 75);

+ 0 - 8
battle.h

@@ -114,9 +114,7 @@ typedef struct tagBATTLEPLAYER
    BOOL               fDefending;           // TRUE if player is defending
    WORD               wPrevHP;              // HP value prior to action
    WORD               wPrevMP;              // MP value prior to action
-#ifndef PAL_CLASSIC
    SHORT              sTurnOrder;           // turn order
-#endif
 } BATTLEPLAYER;
 
 typedef struct tagSUMMON
@@ -128,8 +126,6 @@ typedef struct tagSUMMON
 #define MAX_BATTLE_ACTIONS    256
 #define MAX_KILLED_ENEMIES    256
 
-#ifdef PAL_CLASSIC
-
 typedef enum tabBATTLEPHASE
 {
    kBattlePhaseSelectAction,
@@ -145,8 +141,6 @@ typedef struct tagACTIONQUEUE
 
 #define MAX_ACTIONQUEUE_ITEMS (MAX_PLAYERS_IN_PARTY + MAX_ENEMIES_IN_TEAM * 2)
 
-#endif
-
 typedef struct tagBATTLE
 {
    BATTLEPLAYER     rgPlayer[MAX_PLAYERS_IN_PARTY];
@@ -184,14 +178,12 @@ typedef struct tagBATTLE
 
    int              iBlow;
 
-#ifdef PAL_CLASSIC
    BATTLEPHASE      Phase;
    ACTIONQUEUE      ActionQueue[MAX_ACTIONQUEUE_ITEMS];
    int              iCurAction;
    BOOL             fRepeat;              // TRUE if player pressed Repeat
    BOOL             fForce;               // TRUE if player pressed Force
    BOOL             fFlee;                // TRUE if player pressed Flee
-#endif
 } BATTLE;
 
 extern BATTLE g_Battle;

+ 5 - 3
common.h

@@ -22,7 +22,7 @@
 #ifndef _COMMON_H
 #define _COMMON_H
 
-#define PAL_CLASSIC        1
+//#define gConfig.fIsClassic        1
 
 #ifdef __cplusplus
 extern "C"
@@ -321,8 +321,10 @@ extern "C"
 typedef const BYTE *LPCBYTE;
 #endif
 
-#ifndef __WINRT__
-#define PAL_HAS_NATIVEMIDI  1
+#ifdef __WINRT__
+# define feof WRT_feof
+#else
+# define PAL_HAS_NATIVEMIDI  1
 #endif
 
 #else

File diff suppressed because it is too large
+ 625 - 645
fight.c


+ 0 - 4
fight.h

@@ -32,8 +32,6 @@ PAL_BattleSelectAutoTarget(
    VOID
 );
 
-#ifndef PAL_CLASSIC
-
 VOID
 PAL_UpdateTimeChargingUnit(
    VOID
@@ -44,8 +42,6 @@ PAL_GetTimeChargingSpeed(
    WORD           wDexterity
 );
 
-#endif
-
 VOID
 PAL_BattleUpdateFighters(
    VOID

+ 32 - 30
global.c

@@ -70,6 +70,7 @@ PAL_InitGlobals(
 {
    FILE     *fp;
    CODEPAGE  iCodePage = CP_BIG5;		// Default for BIG5
+   DWORD     dwIsClassic = 1;
    DWORD     dwExtraMagicDescLines = 0;	// Default for PAL DOS/WIN95
    DWORD     dwExtraItemDescLines = 0;	// Default for PAL DOS/WIN95
    DWORD     dwScreenWidth = 0;
@@ -203,6 +204,10 @@ PAL_InitGlobals(
 				   {
 					   sscanf(ptr, "%u", &dwKeepAspectRatio);
 				   }
+				   else if (SDL_strcasecmp(p, "CLASSIC") == 0)
+				   {
+					   sscanf(ptr, "%u", &dwIsClassic);
+				   }
 				   else if (SDL_strcasecmp(p, "AUDIOBUFFERSIZE") == 0)
 				   {
 					   sscanf(ptr, "%d", &iAudioBufferSize);
@@ -233,6 +238,13 @@ PAL_InitGlobals(
 					   if (n > 0 && ptr[n - 1] == '\r') ptr[--n] = 0;
 					   if (n > 0) gConfig.pszMsgName = strdup(ptr);
 				   }
+				   else if (SDL_strcasecmp(p, "DESCRIPTIONFILENAME") == 0)
+				   {
+					   int n = strlen(ptr);
+					   if (n > 0 && ptr[n - 1] == '\n') ptr[--n] = 0;
+					   if (n > 0 && ptr[n - 1] == '\r') ptr[--n] = 0;
+					   if (n > 0) gConfig.pszDescFile = strdup(ptr);
+				   }
 #if USE_RIX_EXTRA_INIT
 				   else if (SDL_strcasecmp(p, "RIXEXTRAINIT") == 0)
 				   {
@@ -320,6 +332,7 @@ PAL_InitGlobals(
    //
    // Set configurable global options
    //
+   gConfig.fIsClassic = dwIsClassic ? TRUE : FALSE;
    gConfig.fIsWIN95 = dwIsDOS ? FALSE : TRUE;
    gConfig.fUseEmbeddedFonts = dwIsDOS && dwUseEmbeddedFonts ? TRUE : FALSE;
    gConfig.fUseSurroundOPL = dwUseStereo && dwUseSurroundOPL ? TRUE : FALSE;
@@ -379,7 +392,7 @@ PAL_InitGlobals(
    gpGlobals->f.fpRGM = UTIL_OpenRequiredFile("rgm.mkf");
    gpGlobals->f.fpSSS = UTIL_OpenRequiredFile("sss.mkf");
 
-   gpGlobals->lpObjectDesc = gConfig.fIsWIN95 ? NULL : PAL_LoadObjectDesc(va("%s%s", PAL_PREFIX, "desc.dat"));
+   if (!gConfig.fIsWIN95 && !gConfig.pszMsgName && gConfig.pszDescFile) PAL_LoadObjectDesc(gConfig.pszDescFile);
    gpGlobals->bCurrentSaveSlot = 1;
 
    return 0;
@@ -432,7 +445,18 @@ PAL_FreeGlobals(
    // Free the object description data
    //
    if (!gConfig.fIsWIN95)
-      PAL_FreeObjectDesc(gpGlobals->lpObjectDesc);
+   {
+      int i;
+      for (i = 1; i < MAX_OBJECTS; i++)
+	  {
+         if (gpGlobals->rgObjectDesc[i])
+         {
+            LPWSTR *p = gpGlobals->rgObjectDesc[i];
+            while (*p) free(*p++);
+            free(gpGlobals->rgObjectDesc[i]);
+         }
+      }
+   }
 
 #if USE_RIX_EXTRA_INIT
    free(gConfig.pExtraFMRegs);
@@ -632,9 +656,7 @@ PAL_LoadDefaultGame(
    gpGlobals->viewport = PAL_XY(0, 0);
    gpGlobals->wLayer = 0;
    gpGlobals->wChaseRange = 1;
-#ifndef PAL_CLASSIC
    gpGlobals->bBattleSpeed = 2;
-#endif
 
    memset(gpGlobals->rgInventory, 0, sizeof(gpGlobals->rgInventory));
    memset(gpGlobals->rgPoisonStatus, 0, sizeof(gpGlobals->rgPoisonStatus));
@@ -769,13 +791,7 @@ PAL_LoadGame_Common(
 	gpGlobals->wChasespeedChangeCycles = s->wChasespeedChangeCycles;
 	gpGlobals->nFollower = s->nFollower;
 	gpGlobals->dwCash = s->dwCash;
-#ifndef PAL_CLASSIC
-	gpGlobals->bBattleSpeed = s->wBattleSpeed;
-	if (gpGlobals->bBattleSpeed > 5 || gpGlobals->bBattleSpeed == 0)
-	{
-		gpGlobals->bBattleSpeed = 2;
-	}
-#endif
+	gpGlobals->bBattleSpeed = (!gConfig.fIsClassic && s->wBattleSpeed > 0 && s->wBattleSpeed <= 5) ? s->wBattleSpeed : 2;
 
 	memcpy(gpGlobals->rgParty, s->rgParty, sizeof(gpGlobals->rgParty));
 	memcpy(gpGlobals->rgTrail, s->rgTrail, sizeof(gpGlobals->rgTrail));
@@ -965,11 +981,7 @@ PAL_SaveGame_Common(
 	s->wChasespeedChangeCycles = gpGlobals->wChasespeedChangeCycles;
 	s->nFollower = gpGlobals->nFollower;
 	s->dwCash = gpGlobals->dwCash;
-#ifndef PAL_CLASSIC
-	s->wBattleSpeed = gpGlobals->bBattleSpeed;
-#else
-	s->wBattleSpeed = 2;
-#endif
+	s->wBattleSpeed = gConfig.fIsClassic ? 2 : gpGlobals->bBattleSpeed;
 
 	memcpy(s->rgParty, gpGlobals->rgParty, sizeof(gpGlobals->rgParty));
 	memcpy(s->rgTrail, gpGlobals->rgTrail, sizeof(gpGlobals->rgTrail));
@@ -1954,11 +1966,7 @@ PAL_GetPlayerDexterity(
 
    w = gpGlobals->g.PlayerRoles.rgwDexterity[wPlayerRole];
 
-#ifdef PAL_CLASSIC
-   for (i = 0; i <= MAX_PLAYER_EQUIPMENTS; i++)
-#else
-   for (i = 0; i <= MAX_PLAYER_EQUIPMENTS - 1; i++)
-#endif
+   for (i = 0; i <= MAX_PLAYER_EQUIPMENTS - (!gConfig.fIsClassic); i++)
    {
       w += gpGlobals->rgEquipmentEffect[i].rgwDexterity[wPlayerRole];
    }
@@ -2296,8 +2304,7 @@ PAL_SetPlayerStatus(
 
 --*/
 {
-#ifndef PAL_CLASSIC
-   if (wStatusID == kStatusSlow &&
+   if (!gConfig.fIsClassic && wStatusID == kStatusSlow &&
       gpGlobals->rgPlayerStatus[wPlayerRole][kStatusHaste] > 0)
    {
       //
@@ -2307,7 +2314,7 @@ PAL_SetPlayerStatus(
       return;
    }
 
-   if (wStatusID == kStatusHaste &&
+   if (!gConfig.fIsClassic && wStatusID == kStatusHaste &&
       gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSlow] > 0)
    {
       //
@@ -2316,18 +2323,13 @@ PAL_SetPlayerStatus(
       PAL_RemovePlayerStatus(wPlayerRole, kStatusSlow);
       return;
    }
-#endif
 
    switch (wStatusID)
    {
    case kStatusConfused:
    case kStatusSleep:
    case kStatusSilence:
-#ifdef PAL_CLASSIC
-   case kStatusParalyzed:
-#else
-   case kStatusSlow:
-#endif
+   case kStatusParalyzedOrSlow:
       //
       // for "bad" statuses, don't set the status when we already have it
       //

+ 6 - 11
global.h

@@ -97,11 +97,7 @@ extern "C"
 typedef enum tagSTATUS
 {
    kStatusConfused = 0,  // attack friends randomly
-#ifdef PAL_CLASSIC
-   kStatusParalyzed,     // paralyzed
-#else
-   kStatusSlow,          // slower
-#endif
+   kStatusParalyzedOrSlow,     // paralyzed or slower
    kStatusSleep,         // not allowed to move
    kStatusSilence,       // cannot use magic
    kStatusPuppet,        // for dead players only, continue attacking
@@ -112,9 +108,8 @@ typedef enum tagSTATUS
    kStatusAll
 } STATUS;
 
-#ifndef PAL_CLASSIC
-#define kStatusParalyzed kStatusSleep
-#endif
+#define kStatusSlow  kStatusParalyzedOrSlow
+#define kStatusParalyzed (gConfig.fIsClassic ? kStatusParalyzedOrSlow : kStatusSleep)
 
 // body parts of equipments
 typedef enum tagBODYPART
@@ -580,9 +575,7 @@ typedef struct tagGLOBALVARS
    BOOL             fNeedToFadeIn;       // TRUE if need to fade in when drawing scene
    BOOL             fInBattle;           // TRUE if in battle
    BOOL             fAutoBattle;         // TRUE if auto-battle
-#ifndef PAL_CLASSIC
    BYTE             bBattleSpeed;        // Battle Speed (1 = Fastest, 5 = Slowest)
-#endif
    WORD             wLastUnequippedItem; // last unequipped item
 
    PLAYERROLES      rgEquipmentEffect[MAX_PLAYER_EQUIPMENTS + 1]; // equipment effects
@@ -613,7 +606,7 @@ typedef struct tagGLOBALVARS
    ALLEXPERIENCE    Exp;                 // experience status
    POISONSTATUS     rgPoisonStatus[MAX_POISONS][MAX_PLAYABLE_PLAYER_ROLES]; // poison status
    INVENTORY        rgInventory[MAX_INVENTORY];  // inventory status
-   LPOBJECTDESC     lpObjectDesc;
+   LPWSTR          *rgObjectDesc[MAX_OBJECTS];
    DWORD            dwFrameNum;
 } GLOBALVARS, *LPGLOBALVARS;
 
@@ -666,6 +659,7 @@ typedef struct tagCONFIGURATION
 
 	/* Configurable options */
 	char            *pszMsgName;
+	char            *pszDescFile;
 #if USE_RIX_EXTRA_INIT
 	uint32_t        *pExtraFMRegs;
 	uint8_t         *pExtraFMVals;
@@ -697,6 +691,7 @@ typedef struct tagCONFIGURATION
 #endif
 	BOOL             fEnableJoyStick;
 	BOOL             fUseCustomScreenLayout;
+	BOOL             fIsClassic;
 } CONFIGURATION, *LPCONFIGURATION;
 
 extern CONFIGURATION gConfig;

+ 6 - 27
itemmenu.c

@@ -236,35 +236,14 @@ PAL_ItemSelectMenuUpdate(
    //
    if (!gConfig.fIsWIN95)
    {
-      if (!g_fNoDesc && gpGlobals->lpObjectDesc != NULL)
+      if (!g_fNoDesc && gpGlobals->rgObjectDesc[wObject] != NULL)
 	  {
-         WCHAR szDesc[512], *next;
-         const WCHAR *d = PAL_GetObjectDesc(gpGlobals->lpObjectDesc, wObject);
-
-         if (d != NULL)
+         int y = 150 - gConfig.dwExtraItemDescLines * 16;
+         LPWSTR *p = gpGlobals->rgObjectDesc[wObject];
+         while (*p)
          {
-            k = 150;
-            wcscpy(szDesc, d);
-            d = szDesc;
-
-            while (TRUE)
-            {
-               next = wcschr(d, '*');
-               if (next != NULL)
-               {
-                  *next++ = '\0';
-               }
-
-               PAL_DrawText(d, PAL_XY(75, k), DESCTEXT_COLOR, TRUE, FALSE, FALSE);
-               k += 16;
-
-               if (next == NULL)
-               {
-                  break;
-               }
-
-               d = next;
-            }
+            PAL_DrawText(*p++, PAL_XY(75, y), DESCTEXT_COLOR, TRUE, FALSE, FALSE);
+            y += 16;
          }
       }
    }

+ 6 - 27
magicmenu.c

@@ -121,7 +121,7 @@ PAL_MagicSelectionMenuUpdate(
 
    if (!gConfig.fIsWIN95)
    {
-      if (gpGlobals->lpObjectDesc == NULL)
+      if (gpGlobals->rgObjectDesc[0] == NULL)
       {
          //
          // Draw the cash amount.
@@ -142,36 +142,15 @@ PAL_MagicSelectionMenuUpdate(
       }
       else
       {
-         WCHAR szDesc[512], *next;
-         const WCHAR *d = PAL_GetObjectDesc(gpGlobals->lpObjectDesc, rgMagicItem[g_iCurrentItem].wMagic);
-
          //
          // Draw the magic description.
          //
-         if (d != NULL)
+         LPWSTR *p = gpGlobals->rgObjectDesc[rgMagicItem[g_iCurrentItem].wMagic];
+         int y = 3;
+         while (*p)
          {
-            k = 3;
-		    wcscpy(szDesc, d);
-            d = szDesc;
-
-            while (TRUE)
-            {
-               next = wcschr(d, '*');
-               if (next != NULL)
-               {
-                  *next++ = '\0';
-               }
-
-               PAL_DrawText(d, PAL_XY(100, k), DESCTEXT_COLOR, TRUE, FALSE, FALSE);
-               k += 16;
-
-               if (next == NULL)
-               {
-                  break;
-               }
-
-               d = next;
-            }
+            PAL_DrawText(*p++, PAL_XY(100, y), DESCTEXT_COLOR, TRUE, FALSE, FALSE);
+            y += 16;
          }
 
          //

+ 7 - 21
script.c

@@ -538,11 +538,9 @@ PAL_AdditionalCredits(
 
    LPCWSTR rgszStrings[] = {
       L"  SDLPAL (http://sdlpal.codeplex.com/)",
-#ifdef PAL_CLASSIC
-	  L"%ls(" WIDETEXT(__DATE__) L")",
-#else
+      gConfig.fIsClassic ?
+	  L"%ls(" WIDETEXT(__DATE__) L")" :
 	  L"                        (" WIDETEXT(__DATE__) L")",
-#endif
       L" ",
 	  L"    (c) 2009-2011, Wei Mingzhi",
 	  L"        <whistler_wmz@users.sf.net>.",
@@ -567,7 +565,7 @@ PAL_AdditionalCredits(
 	  if (wcsncmp(rgszStrings[i], L"%ls", 3) == 0)
 	  {
 		  // We've limited the length of g_rcCredits[i] in text.c, so no need to double check here.
-		  wcscpy(buffer, gConfig.pszMsgName ? g_rcCredits[i] : rgszcps[i][gpGlobals->iCodePage]);
+		  wcscpy(buffer, gConfig.pszMsgName ? g_rcCredits[i] : rgszcps[i][gConfig.iCodePage]);
 		  wcscat(buffer, rgszStrings[i] + 3);
 	  }
 	  else
@@ -1352,11 +1350,7 @@ PAL_InterpretInstruction(
       //
       w = g_Battle.rgEnemy[wEventObjectID].wObjectID;
 
-#ifdef PAL_CLASSIC
-      i = 9;
-#else
-      i = ((pScript->rgwOperand[0] == kStatusSlow) ? 14 : 9);
-#endif
+      i = (!gConfig.fIsClassic && (pScript->rgwOperand[0] == kStatusSlow) ? 14 : 9);
 
       if (RandomLong(0, i) >= gpGlobals->g.rgObject[w].enemy.wResistanceToSorcery &&
          g_Battle.rgEnemy[wEventObjectID].rgwStatus[pScript->rgwOperand[0]] == 0)
@@ -1430,19 +1424,11 @@ PAL_InterpretInstruction(
       {
          WCHAR s[256];
 
-#ifdef PAL_CLASSIC
-         i = RandomLong(1, gpGlobals->wCollectValue);
-         if (i > 9)
+         i = RandomLong(1, gConfig.fIsClassic ? gpGlobals->wCollectValue : 9);
+         if (i > (gConfig.fIsClassic ? 9 : gpGlobals->wCollectValue))
          {
-            i = 9;
+            i = (gConfig.fIsClassic ? 9 : gpGlobals->wCollectValue);
          }
-#else
-         i = RandomLong(1, 9);
-         if (i > gpGlobals->wCollectValue)
-         {
-            i = gpGlobals->wCollectValue;
-         }
-#endif
 
          gpGlobals->wCollectValue -= i;
          i--;

+ 14 - 0
sdlpal.cfg.example

@@ -20,12 +20,26 @@
 #      Non-zero for DOS-version (default), zero for WIN95-version.
 #DOS=1
 
+# Classic: Indicates whether to classic or revised version of battle system.
+#          Default to the classic version.
+#Classic=1
+
 # UseEmbeddedFonts: Indicates whether to use DOS-version's embedded fonts.
 #                   Non-zero for using DOS-version's embedded fonts (default),
 #                   zero for using SDLPAL's internal fonts.
 # Note that this value is ignored when the DOS option is zero.
 #UseEmbeddedFonts=1
 
+# DescriptionFileName: Indicates where to load external object descriptions
+#                      for DOS-version. For default, no external object
+#                      descriptions are provided. This file will have a format
+#                      like 'index=str' for each line, where 'index' is the ID
+#                      for an object, and 'str' is one line description text.
+#                      For descriptions more than one line, use same 'index' and
+#                      different 'str's in other lines.
+# Note that this value is ignored when the DOS option is zero.
+#DescriptionFileName=desc.dat
+
 # CD: Indicates which type of CD audio source to use. Valid types include 'RAW',
 #     'OGG' and 'MP3'. 'RAW' means use the SDL 1.2's CDAudio API (default when
 #     compiled with SDL 1.2), 'OGG' means use files named as '100xx.ogg' inside

+ 0 - 2
sound.c

@@ -37,9 +37,7 @@ static BOOL  gSndOpened = FALSE;
 BOOL         g_fNoSound = FALSE;
 BOOL         g_fNoMusic = FALSE;
 
-#ifdef PAL_CLASSIC
 int          g_iCurrChannel = 0;
-#endif
 
 #define PAL_CDTRACK_BASE    10000
 

+ 1 - 5
sound.h

@@ -78,12 +78,8 @@ SOUND_Reload(
 );
 #endif
 
-#ifdef PAL_CLASSIC
 extern int g_iCurrChannel;
-#define SOUND_Play(i) SOUND_PlayChannel((i), (g_iCurrChannel ^= 1))
-#else
-#define SOUND_Play(i) SOUND_PlayChannel((i), 0)
-#endif
+#define SOUND_Play(i) SOUND_PlayChannel((i), gConfig.fIsClassic ? (g_iCurrChannel ^= 1) : 0)
 
 extern BOOL       g_fNoSound;
 extern BOOL       g_fNoMusic;

+ 251 - 21
text.c

@@ -39,7 +39,6 @@ BOOL      g_fUpdatedInBattle      = FALSE;
 #define INCLUDE_CODEPAGE_H
 #include "codepage.h"
 
-#ifndef PAL_CLASSIC
 # define ATB_WORD_COUNT             6
 static LPWSTR gc_rgszAdditionalWords[CP_MAX][ATB_WORD_COUNT] = {
    { L"\x6230\x9B25\x901F\x5EA6", L"\x4E00", L"\x4E8C", L"\x4E09", L"\x56DB", L"\x4E94" },
@@ -47,7 +46,6 @@ static LPWSTR gc_rgszAdditionalWords[CP_MAX][ATB_WORD_COUNT] = {
    //{ L"\x6226\x95D8\x901F\x5EA6", L"\x4E00", L"\x4E8C", L"\x4E09", L"\x56DB", L"\x4E94" },
 };
 static LPWSTR gc_rgszDefaultAdditionalWords[ATB_WORD_COUNT] = { NULL, L"\xFF11", L"\xFF12", L"\xFF13", L"\xFF14", L"\xFF15" };
-#endif
 
 LPWSTR g_rcCredits[12];
 
@@ -105,7 +103,6 @@ PAL_ParseLine(
 			//
 			LPSTR end = line + strlen(line);
 			int index;
-			if (end > line && end[-1] == '\n') *(--end) = 0;
 			if (deltrail) while (end > line && iswspace(end[-1])) *(--end) = 0;
 
 			//
@@ -153,6 +150,7 @@ PAL_ReadOneLine(
 				}
 			}
 			if (tmp[n - 1] == '\n') tmp[n - 1] = 0;
+			if (tmp[n - 2] == '\r') tmp[n - 2] = 0;
 			return tmp;
 		}
 		else
@@ -166,6 +164,117 @@ PAL_ReadOneLine(
 		return NULL;
 }
 
+static void *
+PAL_ParseOneDescriptionLine(
+	char     *buffer,
+	void     *_head,
+	void     *_item
+	)
+{
+	struct _msg_entry
+	{
+		struct _msg_entry *next;
+		wchar_t *value;
+	};
+	struct _msg_list_entry
+	{
+		struct _msg_list_entry *next;
+		struct _msg_entry *value;
+		int index, count;
+	} *head = (struct _msg_list_entry *)_head, *item = (struct _msg_list_entry *)_item;
+	char *v;
+	int l, i = PAL_ParseLine(buffer, &v, &l, TRUE);
+	if (i > 0)
+	{
+		int len = PAL_MultiByteToWideCharCP(CP_UTF_8, v, -1, NULL, 0);
+		struct _msg_entry *e = (struct _msg_entry *)UTIL_malloc(sizeof(struct _msg_entry));
+		e->value = (wchar_t *)UTIL_malloc(len * sizeof(wchar_t)); e->next = NULL;
+		PAL_MultiByteToWideCharCP(CP_UTF_8, v, -1, e->value, len);
+
+		if (item && item->index != i)
+		{
+			if (head->next == NULL || head->next->index > i)
+			{
+				item = NULL;
+			}
+			else
+			{
+				if (item->index > i) item = head->next;
+				while (item->next && item->next->index < i) item = item->next;
+			}
+		}
+
+		if (item && item->index != i)
+		{
+			item->next = (struct _msg_list_entry *)UTIL_malloc(sizeof(struct _msg_list_entry));
+			item = item->next; item->next = NULL;
+			item->value = e; item->count = 1; item->index = i;
+		}
+		else if (!item)
+		{
+			item = (struct _msg_list_entry *)UTIL_malloc(sizeof(struct _msg_list_entry));
+			item->next = head->next; head->next = item; item->next = NULL;
+			item->value = e; item->count = 1; item->index = i;
+		}
+		else
+		{
+			struct _msg_entry *tmp = item->value;
+			while (tmp->next) tmp = tmp->next;
+			tmp->next = e; item->count++;
+		}
+
+		return item;
+	}
+	else
+		return _item;
+}
+
+static VOID
+PAL_ParseObjectDesc(
+	void     *_head
+	)
+{
+	struct _msg_entry
+	{
+		struct _msg_entry *next;
+		wchar_t *value;
+	};
+	struct _msg_list_entry
+	{
+		struct _msg_list_entry *next;
+		struct _msg_entry *value;
+		int index, count;
+	} *head = (struct _msg_list_entry *)_head, *item;
+	int count = 0;
+
+	for (item = head->next; item; count++)
+	{
+		struct _msg_list_entry *next = item->next;
+		struct _msg_entry *tmp = item->value;
+		if (item->index < MAX_OBJECTS)
+		{
+			int i = 0;
+			gpGlobals->rgObjectDesc[item->index] = (LPWSTR *)calloc(item->count + 1, sizeof(LPWSTR));
+			while (tmp)
+			{
+				struct _msg_entry *nxt = tmp->next;
+				gpGlobals->rgObjectDesc[item->index][i++] = tmp->value;
+				free(tmp); tmp = nxt;
+			}
+		}
+		else
+		{
+			while (tmp)
+			{
+				struct _msg_entry *nxt = tmp->next;
+				free(tmp->value); free(tmp); tmp = nxt;
+			}
+		}
+		free(item); item = next;
+	}
+	gpGlobals->rgObjectDesc[0] = (LPWSTR *)count;
+}
+
 static int
 PAL_ReadMessageFile(
 	FILE     *fp
@@ -183,20 +292,21 @@ PAL_ReadMessageFile(
 		struct _msg_entry *value;
 		int index;
 		int count;
-	} *head = NULL, *item = NULL;
+	} *head = NULL, *item = NULL, dhead = { NULL }, *ditem = NULL;
 	struct _word_list_entry
 	{
 		struct _word_list_entry *next;
 		wchar_t *value;
 		int index;
-	} whead = { NULL, NULL }, *witem = NULL;
+	} whead = { NULL }, *witem = NULL;
 	enum _message_state
 	{
 		ST_OUTSIDE,
 		ST_DIALOG,
 		ST_WORD,
 		ST_CREDIT,
-		ST_LAYOUT
+		ST_LAYOUT,
+		ST_DESCRIPTION
 	} state = ST_OUTSIDE;
 	int idx_cnt = 0, msg_cnt = 0, word_cnt = 0, sid, eid = -1;
 
@@ -242,15 +352,19 @@ PAL_ReadMessageFile(
 						//
 						witem = &whead;
 					}
-					else if (strncmp(buffer, "[BEGIN CREDITS]", 15) == 0 && !witem)
+					else if (strncmp(buffer, "[BEGIN CREDITS]", 15) == 0)
 					{
 						state = ST_CREDIT;
 					}
-					else if (strncmp(buffer, "[BEGIN LAYOUT]", 14) == 0 && !witem)
+					else if (strncmp(buffer, "[BEGIN LAYOUT]", 14) == 0)
 					{
 						state = ST_LAYOUT;
 						gConfig.fUseCustomScreenLayout = TRUE;
 					}
+					else if (strncmp(buffer, "[BEGIN DESCRIPTION]", 19) == 0 && !ditem)
+					{
+						state = ST_DESCRIPTION;
+					}
 					else
 					{
 						// Just ignore invalid lines
@@ -319,6 +433,20 @@ PAL_ReadMessageFile(
 					}
 				}
 				break;
+			case ST_DESCRIPTION:
+				//
+				// Check if to end description list
+				//
+				if (strncmp(buffer, "[END DESCRIPTION]", 17) == 0)
+				{
+					// End description list
+					state = ST_OUTSIDE;
+				}
+				else if (!gConfig.fIsWIN95)
+				{
+					item = PAL_ParseOneDescriptionLine(buffer, &dhead, item);
+				}
+				break;
 			case ST_CREDIT:
 				//
 				// Check if to end credit list
@@ -450,9 +578,7 @@ PAL_ReadMessageFile(
 		//
 		// Move values from linked list to array
 		//
-#ifndef PAL_CLASSIC
 		int i;
-#endif
 		if (word_cnt < MINIMAL_WORD_COUNT - 1) word_cnt = MINIMAL_WORD_COUNT - 1;
 		g_TextLib.nWords = (word_cnt += 1);
 		g_TextLib.lpWordBuf = (LPWSTR *)UTIL_calloc(word_cnt, sizeof(LPWSTR));
@@ -462,13 +588,16 @@ PAL_ReadMessageFile(
 			g_TextLib.lpWordBuf[witem->index] = witem->value;
 			free(witem); witem = temp;
 		}
-#ifndef PAL_CLASSIC
-		for (i = 1; i < ATB_WORD_COUNT; i++)
-			if (!g_TextLib.lpWordBuf[i + SYSMENU_LABEL_BATTLEMODE])
-				g_TextLib.lpWordBuf[i + SYSMENU_LABEL_BATTLEMODE] = gc_rgszDefaultAdditionalWords[i];
-#endif
+		if (!gConfig.fIsClassic)
+		{
+			for (i = 1; i < ATB_WORD_COUNT; i++)
+				if (!g_TextLib.lpWordBuf[i + SYSMENU_LABEL_BATTLEMODE])
+					g_TextLib.lpWordBuf[i + SYSMENU_LABEL_BATTLEMODE] = gc_rgszDefaultAdditionalWords[i];
+		}
 	}
 
+	if (dhead.next) PAL_ParseObjectDesc(&dhead);
+
 	fclose(fp);
 
 	return (msg_cnt > 0 && word_cnt > 0) ? 1 : 0;
@@ -681,9 +810,7 @@ PAL_InitText(
 
 	   g_TextLib.lpIndexBuf = NULL;
 
-#ifndef PAL_CLASSIC
-	   memcpy(g_TextLib.lpWordBuf + SYSMENU_LABEL_BATTLEMODE, gc_rgszAdditionalWords[gConfig.iCodePage], ATB_WORD_COUNT * sizeof(LPCWSTR));
-#endif
+	   if (!gConfig.fIsClassic) memcpy(g_TextLib.lpWordBuf + SYSMENU_LABEL_BATTLEMODE, gc_rgszAdditionalWords[gConfig.iCodePage], ATB_WORD_COUNT * sizeof(LPCWSTR));
    }
 
    g_TextLib.bCurrentFontColor = FONT_COLOR_DEFAULT;
@@ -1185,13 +1312,11 @@ PAL_ShowDialogText(
       //
       // The text should be shown in a small window at the center of the screen
       //
-#ifndef PAL_CLASSIC
-      if (gpGlobals->fInBattle && g_Battle.BattleResult == kBattleResultOnGoing)
+      if (!gConfig.fIsClassic && gpGlobals->fInBattle && g_Battle.BattleResult == kBattleResultOnGoing)
       {
          PAL_BattleUIShowText(lpszText, 1400);
       }
       else
-#endif
       {
          PAL_POS    pos;
          LPBOX      lpBox;
@@ -1787,3 +1912,108 @@ PAL_GetInvalidChar(
    default:          return 0;
    }
 }
+
+INT
+PAL_WordMaxWidth(
+   INT            nFirstWord,
+   INT            nWordNum
+)
+/*++
+  Purpose:
+
+    Calculate the maximal text width of a specific range of words in number of full width characters.
+
+  Parameters:
+
+    [IN]  nFirstWord - First index of word.
+	[IN]  nWordNum - Number of words.
+
+  Return value:
+
+    Maximal text width.
+
+--*/
+{
+	int i, r = 0;
+	for (i = 0; i < nWordNum; i++)
+	{
+		LPCWSTR itemText = PAL_GetWord(nFirstWord + i);
+		int j = 0, l = wcslen(itemText), w = 0;
+		for (j = 0; j < l; j++)
+		{
+			w += PAL_CharWidth(itemText[j]);
+		}
+		w = (w + 8) >> 4;
+		if (r < w)
+		{
+			r = w;
+		}
+	}
+	return r;
+}
+
+INT
+PAL_WordWidth(
+   INT            nWordIndex
+)
+/*++
+  Purpose:
+
+    Calculate the text width of a specific word.
+
+  Parameters:
+
+	[IN]  nWordNum - Index of the word.
+
+  Return value:
+
+    Text width.
+
+--*/
+{
+	LPCWSTR itemText = PAL_GetWord(nWordIndex);
+	int i, l = wcslen(itemText), w = 0;
+	for (i = 0; i < l; i++)
+	{
+		w += PAL_CharWidth(itemText[i]);
+	}
+	return (w + 8) >> 4;
+}
+
+VOID
+PAL_LoadObjectDesc(
+	LPCSTR    lpszFileName
+	)
+{
+	char temp[MESSAGE_MAX_BUFFER_SIZE];
+	struct _msg_entry
+	{
+		struct _msg_entry *next;
+		wchar_t *value;
+	};
+	struct _msg_list_entry
+	{
+		struct _msg_list_entry *next;
+		struct _msg_entry *value;
+		int index, count;
+	} head = { NULL }, *item = NULL;
+	int count = 0;
+
+	FILE *fp = UTIL_OpenFileForMode(lpszFileName, "r");
+	if (!fp) return;
+
+	while (!feof(fp))
+	{
+		char *buffer;
+		if (buffer = PAL_ReadOneLine(temp, MESSAGE_MAX_BUFFER_SIZE, fp))
+		{
+			item = PAL_ParseOneDescriptionLine(buffer, &head, item);
+
+			if (buffer != temp) free(buffer);
+		}
+	}
+
+	PAL_ParseObjectDesc(&head);
+
+	fclose(fp);
+}

+ 16 - 0
text.h

@@ -130,4 +130,20 @@ PAL_GetInvalidChar(
    CODEPAGE      iCodePage
 );
 
+INT
+PAL_WordMaxWidth(
+   INT            nFirstWord,
+   INT            nWordNum
+);
+
+INT
+PAL_WordWidth(
+   INT            nWordIndex
+);
+
+VOID
+PAL_LoadObjectDesc(
+   LPCSTR    lpszFileName
+);
+
 #endif

+ 0 - 195
ui.c

@@ -720,198 +720,3 @@ PAL_MenuTextMaxWidth(
 	}
 	return r;
 }
-
-INT
-PAL_WordMaxWidth(
-   INT            nFirstWord,
-   INT            nWordNum
-)
-/*++
-  Purpose:
-
-    Calculate the maximal text width of a specific range of words in number of full width characters.
-
-  Parameters:
-
-    [IN]  nFirstWord - First index of word.
-	[IN]  nWordNum - Number of words.
-
-  Return value:
-
-    Maximal text width.
-
---*/
-{
-	int i, r = 0;
-	for (i = 0; i < nWordNum; i++)
-	{
-		LPCWSTR itemText = PAL_GetWord(nFirstWord + i);
-		int j = 0, l = wcslen(itemText), w = 0;
-		for (j = 0; j < l; j++)
-		{
-			w += PAL_CharWidth(itemText[j]);
-		}
-		w = (w + 8) >> 4;
-		if (r < w)
-		{
-			r = w;
-		}
-	}
-	return r;
-}
-
-INT
-PAL_WordWidth(
-   INT            nWordIndex
-)
-/*++
-  Purpose:
-
-    Calculate the text width of a specific word.
-
-  Parameters:
-
-	[IN]  nWordNum - Index of the word.
-
-  Return value:
-
-    Text width.
-
---*/
-{
-	LPCWSTR itemText = PAL_GetWord(nWordIndex);
-	int i, l = wcslen(itemText), w = 0;
-	for (i = 0; i < l; i++)
-	{
-		w += PAL_CharWidth(itemText[i]);
-	}
-	return (w + 8) >> 4;
-}
-
-LPOBJECTDESC
-PAL_LoadObjectDesc(
-   LPCSTR         lpszFileName
-)
-/*++
-  Purpose:
-
-    Load the object description strings from file.
-
-  Parameters:
-
-    [IN]  lpszFileName - the filename to be loaded.
-
-  Return value:
-
-    Pointer to loaded data, in linked list form. NULL if unable to load.
-
---*/
-{
-   FILE                      *fp;
-   PAL_LARGE char             buf[512];
-   char                      *p;
-   LPOBJECTDESC               lpDesc = NULL, pNew = NULL;
-   unsigned int               i;
-
-   fp = fopen(lpszFileName, "r");
-
-   if (fp == NULL)
-   {
-      return NULL;
-   }
-
-   //
-   // Load the description data
-   //
-   while (fgets(buf, 512, fp) != NULL)
-   {
-      int wlen;
-      p = strchr(buf, '=');
-      if (p == NULL)
-      {
-         continue;
-      }
-
-      *p++ = '\0';
-	  wlen = PAL_MultiByteToWideChar(p, -1, NULL, 0);
-
-      pNew = UTIL_calloc(1, sizeof(OBJECTDESC));
-
-      sscanf(buf, "%x", &i);
-      pNew->wObjectID = i;
-	  pNew->lpDesc = (LPWSTR)UTIL_malloc(wlen * sizeof(WCHAR));
-	  PAL_MultiByteToWideChar(p, -1, pNew->lpDesc, wlen);
-
-      pNew->next = lpDesc;
-      lpDesc = pNew;
-   }
-
-   fclose(fp);
-   return lpDesc;
-}
-
-VOID
-PAL_FreeObjectDesc(
-   LPOBJECTDESC   lpObjectDesc
-)
-/*++
-  Purpose:
-
-    Free the object description data.
-
-  Parameters:
-
-    [IN]  lpObjectDesc - the description data to be freed.
-
-  Return value:
-
-    None.
-
---*/
-{
-   LPOBJECTDESC    p;
-
-   while (lpObjectDesc != NULL)
-   {
-      p = lpObjectDesc->next;
-      free(lpObjectDesc->lpDesc);
-      free(lpObjectDesc);
-      lpObjectDesc = p;
-   }
-}
-
-LPCWSTR
-PAL_GetObjectDesc(
-   LPOBJECTDESC   lpObjectDesc,
-   WORD           wObjectID
-)
-/*++
-  Purpose:
-
-    Get the object description string from the linked list.
-
-  Parameters:
-
-    [IN]  lpObjectDesc - the description data linked list.
-
-    [IN]  wObjectID - the object ID.
-
-  Return value:
-
-    The description string. NULL if the specified object ID
-    is not found.
-
---*/
-{
-   while (lpObjectDesc != NULL)
-   {
-      if (lpObjectDesc->wObjectID == wObjectID)
-      {
-         return lpObjectDesc->lpDesc;
-      }
-
-      lpObjectDesc = lpObjectDesc->next;
-   }
-
-   return NULL;
-}

+ 0 - 27
ui.h

@@ -225,33 +225,6 @@ PAL_MenuTextMaxWidth(
    INT            nMenuItem
 );
 
-INT
-PAL_WordMaxWidth(
-   INT            nFirstWord,
-   INT            nWordNum
-);
-
-INT
-PAL_WordWidth(
-   INT            nWordIndex
-);
-
-LPOBJECTDESC
-PAL_LoadObjectDesc(
-   LPCSTR          lpszFileName
-);
-
-VOID
-PAL_FreeObjectDesc(
-   LPOBJECTDESC    lpObjectDesc
-);
-
-LPCWSTR
-PAL_GetObjectDesc(
-   LPOBJECTDESC   lpObjectDesc,
-   WORD           wObjectID
-);
-
 extern LPSPRITE gpSpriteUI;
 
 #ifdef __cplusplus

+ 227 - 288
uibattle.c

@@ -162,81 +162,66 @@ PAL_PlayerInfoBox(
          gpScreen, PAL_XY(PAL_X(pos) - 2, PAL_Y(pos) - 4), bPoisonColor, 0);
    }
 
-#ifndef PAL_CLASSIC
-   //
-   // Draw a border for the Time Meter
-   //
-   rect.x = PAL_X(pos) + 31;
-   rect.y = PAL_Y(pos) + 4;
-   rect.w = 1;
-   rect.h = 6;
-   SDL_FillRect(gpScreen, &rect, 0xBD);
+   if (!gConfig.fIsClassic)
+   {
+      //
+      // Draw a border for the Time Meter
+      //
+      rect.x = PAL_X(pos) + 31;
+      rect.y = PAL_Y(pos) + 4;
+      rect.w = 1;
+      rect.h = 6;
+      SDL_FillRect(gpScreen, &rect, 0xBD);
 
-   rect.x += 39;
-   SDL_FillRect(gpScreen, &rect, 0xBD);
+      rect.x += 39;
+      SDL_FillRect(gpScreen, &rect, 0xBD);
 
-   rect.x = PAL_X(pos) + 32;
-   rect.y = PAL_Y(pos) + 3;
-   rect.w = 38;
-   rect.h = 1;
-   SDL_FillRect(gpScreen, &rect, 0xBD);
+      rect.x = PAL_X(pos) + 32;
+      rect.y = PAL_Y(pos) + 3;
+      rect.w = 38;
+      rect.h = 1;
+      SDL_FillRect(gpScreen, &rect, 0xBD);
 
-   rect.y += 7;
-   SDL_FillRect(gpScreen, &rect, 0xBD);
+      rect.y += 7;
+      SDL_FillRect(gpScreen, &rect, 0xBD);
 
-   //
-   // Draw the Time meter bar
-   //
-   if (iTimeMeter >= 100)
-   {
-      rect.x = PAL_X(pos) + 33;
-      rect.y = PAL_Y(pos) + 6;
-      rect.w = 36;
-      rect.h = 2;
-      SDL_FillRect(gpScreen, &rect, 0x2C);
-   }
-   else if (iTimeMeter > 0)
-   {
-      rect.x = PAL_X(pos) + 33;
-      rect.y = PAL_Y(pos) + 5;
-      rect.w = iTimeMeter * 36 / 100;
-      rect.h = 4;
-      SDL_FillRect(gpScreen, &rect, bTimeMeterColor);
+      //
+      // Draw the Time meter bar
+      //
+      if (iTimeMeter >= 100)
+      {
+         rect.x = PAL_X(pos) + 33;
+         rect.y = PAL_Y(pos) + 6;
+         rect.w = 36;
+         rect.h = 2;
+         SDL_FillRect(gpScreen, &rect, 0x2C);
+      }
+      else if (iTimeMeter > 0)
+      {
+         rect.x = PAL_X(pos) + 33;
+         rect.y = PAL_Y(pos) + 5;
+         rect.w = iTimeMeter * 36 / 100;
+         rect.h = 4;
+         SDL_FillRect(gpScreen, &rect, bTimeMeterColor);
+      }
    }
-#endif
 
    //
    // Draw the HP and MP value
    //
-#ifdef PAL_CLASSIC
-   PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen,
-      PAL_XY(PAL_X(pos) + 49, PAL_Y(pos) + 6));
-   PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMaxHP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 47, PAL_Y(pos) + 8), kNumColorYellow, kNumAlignRight);
-   PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 26, PAL_Y(pos) + 5), kNumColorYellow, kNumAlignRight);
-
-   PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen,
-      PAL_XY(PAL_X(pos) + 49, PAL_Y(pos) + 22));
-   PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMaxMP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 47, PAL_Y(pos) + 24), kNumColorCyan, kNumAlignRight);
-   PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 26, PAL_Y(pos) + 21), kNumColorCyan, kNumAlignRight);
-#else
    PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen,
-      PAL_XY(PAL_X(pos) + 49, PAL_Y(pos) + 14));
+      PAL_XY(PAL_X(pos) + 49, PAL_Y(pos) + (gConfig.fIsClassic ? 6 : 14)));
    PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMaxHP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 47, PAL_Y(pos) + 16), kNumColorYellow, kNumAlignRight);
+      PAL_XY(PAL_X(pos) + 47, PAL_Y(pos) + (gConfig.fIsClassic ? 8 : 16)), kNumColorYellow, kNumAlignRight);
    PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwHP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 26, PAL_Y(pos) + 13), kNumColorYellow, kNumAlignRight);
+      PAL_XY(PAL_X(pos) + 26, PAL_Y(pos) + (gConfig.fIsClassic ? 5 : 13)), kNumColorYellow, kNumAlignRight);
 
    PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, SPRITENUM_SLASH), gpScreen,
-      PAL_XY(PAL_X(pos) + 49, PAL_Y(pos) + 24));
+      PAL_XY(PAL_X(pos) + 49, PAL_Y(pos) + (gConfig.fIsClassic ? 22 : 24)));
    PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMaxMP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 47, PAL_Y(pos) + 26), kNumColorCyan, kNumAlignRight);
+      PAL_XY(PAL_X(pos) + 47, PAL_Y(pos) + (gConfig.fIsClassic ? 24 : 26)), kNumColorCyan, kNumAlignRight);
    PAL_DrawNumber(gpGlobals->g.PlayerRoles.rgwMP[wPlayerRole], 4,
-      PAL_XY(PAL_X(pos) + 26, PAL_Y(pos) + 23), kNumColorCyan, kNumAlignRight);
-#endif
+      PAL_XY(PAL_X(pos) + 26, PAL_Y(pos) + (gConfig.fIsClassic ? 21 : 23)), kNumColorCyan, kNumAlignRight);
 
    //
    // Draw Statuses
@@ -315,19 +300,13 @@ PAL_BattleUIIsActionValid(
       {
          w = gpGlobals->rgParty[i].wPlayerRole;
 
-#ifndef PAL_CLASSIC
          if (gpGlobals->g.PlayerRoles.rgwHP[w] < gpGlobals->g.PlayerRoles.rgwMaxHP[w] / 5 ||
             gpGlobals->rgPlayerStatus[w][kStatusSleep] != 0 ||
             gpGlobals->rgPlayerStatus[w][kStatusConfused] != 0 ||
             gpGlobals->rgPlayerStatus[w][kStatusSilence] != 0 ||
-            g_Battle.rgPlayer[i].flTimeMeter < 100 ||
-            g_Battle.rgPlayer[i].state == kFighterAct)
-#else
-         if (gpGlobals->g.PlayerRoles.rgwHP[w] < gpGlobals->g.PlayerRoles.rgwMaxHP[w] / 5 ||
-            gpGlobals->rgPlayerStatus[w][kStatusSleep] != 0 ||
-            gpGlobals->rgPlayerStatus[w][kStatusConfused] != 0 ||
-            gpGlobals->rgPlayerStatus[w][kStatusSilence] != 0)
-#endif
+            (!gConfig.fIsClassic && (g_Battle.rgPlayer[i].flTimeMeter < 100 ||
+                              g_Battle.rgPlayer[i].state == kFighterAct)
+            ))
          {
             return FALSE;
          }
@@ -363,7 +342,6 @@ PAL_BattleUIDrawMiscMenu(
    int           i;
    BYTE          bColor;
 
-#ifdef PAL_CLASSIC
    MENUITEM rgMenuItem[] = {
       // value   label                     enabled   position
       {  0,      BATTLEUI_LABEL_AUTO,      TRUE,     PAL_XY(16, 32)  },
@@ -372,16 +350,6 @@ PAL_BattleUIDrawMiscMenu(
       {  3,      BATTLEUI_LABEL_FLEE,      TRUE,     PAL_XY(16, 86)  },
       {  4,      BATTLEUI_LABEL_STATUS,    TRUE,     PAL_XY(16, 104) }
    };
-#else
-   MENUITEM rgMenuItem[] = {
-      // value   label                   enabled   position
-      {  0,      BATTLEUI_LABEL_ITEM,    TRUE,     PAL_XY(16, 32)  },
-      {  1,      BATTLEUI_LABEL_DEFEND,  TRUE,     PAL_XY(16, 50)  },
-      {  2,      BATTLEUI_LABEL_AUTO,    TRUE,     PAL_XY(16, 68)  },
-      {  3,      BATTLEUI_LABEL_FLEE,    TRUE,     PAL_XY(16, 86)  },
-      {  4,      BATTLEUI_LABEL_STATUS,  TRUE,     PAL_XY(16, 104) }
-   };
-#endif
 
    //
    // Draw the box
@@ -497,11 +465,7 @@ PAL_BattleUIMiscItemSubMenuUpdate(
    //
    // Draw the menu
    //
-#ifdef PAL_CLASSIC
    PAL_BattleUIDrawMiscMenu(1, TRUE);
-#else
-   PAL_BattleUIDrawMiscMenu(0, TRUE);
-#endif
    PAL_CreateBox(PAL_XY(30, 50), 1, PAL_MenuTextMaxWidth(rgMenuItem, 2) - 1, 0, FALSE);
 
    //
@@ -595,27 +559,24 @@ PAL_BattleUIPlayerReady(
 
 --*/
 {
-#ifndef PAL_CLASSIC
    WORD w = gpGlobals->rgParty[wPlayerIndex].wPlayerRole;
-#endif
 
    g_Battle.UI.wCurPlayerIndex = wPlayerIndex;
    g_Battle.UI.state = kBattleUISelectMove;
    g_Battle.UI.wSelectedAction = 0;
    g_Battle.UI.MenuState = kBattleMenuMain;
 
-#ifndef PAL_CLASSIC
    //
    // Play a sound which indicates the player is ready
    //
-   if (gpGlobals->rgPlayerStatus[w][kStatusPuppet] == 0 &&
+   if (!gConfig.fIsClassic &&
+      gpGlobals->rgPlayerStatus[w][kStatusPuppet] == 0 &&
       gpGlobals->rgPlayerStatus[w][kStatusSleep] == 0 &&
       gpGlobals->rgPlayerStatus[w][kStatusConfused] == 0 &&
       !g_Battle.UI.fAutoAttack && !gpGlobals->fAutoBattle)
    {
       SOUND_PlayChannel(78, 1);
    }
-#endif
 }
 
 static VOID
@@ -654,11 +615,7 @@ PAL_BattleUIUseItem(
          }
          else
          {
-#ifdef PAL_CLASSIC
-            g_Battle.UI.wSelectedIndex = 0;
-#else
-            g_Battle.UI.wSelectedIndex = g_Battle.UI.wCurPlayerIndex;
-#endif
+            g_Battle.UI.wSelectedIndex = gConfig.fIsClassic ? 0 : g_Battle.UI.wCurPlayerIndex;
             g_Battle.UI.state = kBattleUISelectTargetPlayer;
          }
       }
@@ -867,14 +824,12 @@ PAL_BattleUIUpdate(
       g_Battle.UI.MenuState = kBattleMenuMain;
    }
 
-#ifdef PAL_CLASSIC
-   if (g_Battle.Phase == kBattlePhasePerformAction)
+   if (gConfig.fIsClassic && g_Battle.Phase == kBattlePhasePerformAction)
    {
       goto end;
    }
 
-   if (!g_Battle.UI.fAutoAttack)
-#endif
+   if (!gConfig.fIsClassic || !g_Battle.UI.fAutoAttack)
    {
       //
       // Draw the player info boxes.
@@ -886,16 +841,17 @@ PAL_BattleUIUpdate(
 
          j = TIMEMETER_COLOR_DEFAULT;
 
-#ifndef PAL_CLASSIC
-         if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusHaste] > 0)
+         if (!gConfig.fIsClassic)
          {
-            j = TIMEMETER_COLOR_HASTE;
-         }
-         else if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSlow] > 0)
-         {
-            j = TIMEMETER_COLOR_SLOW;
+            if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusHaste] > 0)
+            {
+               j = TIMEMETER_COLOR_HASTE;
+            }
+            else if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSlow] > 0)
+            {
+               j = TIMEMETER_COLOR_SLOW;
+            }
          }
-#endif
 
          if (gpGlobals->rgPlayerStatus[wPlayerRole][kStatusSleep] != 0 ||
             gpGlobals->rgPlayerStatus[wPlayerRole][kStatusConfused] != 0 ||
@@ -1134,11 +1090,7 @@ PAL_BattleUIUpdate(
                      }
                      else
                      {
-#ifdef PAL_CLASSIC
-                        g_Battle.UI.wSelectedIndex = 0;
-#else
-                        g_Battle.UI.wSelectedIndex = g_Battle.UI.wCurPlayerIndex;
-#endif
+                        g_Battle.UI.wSelectedIndex = gConfig.fIsClassic ? 0 : g_Battle.UI.wCurPlayerIndex;
                         g_Battle.UI.state = kBattleUISelectTargetPlayer;
                      }
                   }
@@ -1211,36 +1163,23 @@ PAL_BattleUIUpdate(
             {
                PAL_BattleCommitAction(TRUE);
             }
-#ifdef PAL_CLASSIC
             else if (g_InputState.dwKeyPress & kKeyMenu)
             {
-               g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
-               g_Battle.UI.state = kBattleUIWait;
-
-               if (g_Battle.UI.wCurPlayerIndex > 0)
+               if (gConfig.fIsClassic)
                {
-                  //
-                  // Revert to the previous player
-                  //
-                  do
-                  {
-                     g_Battle.rgPlayer[--g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
+                  g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
+                  g_Battle.UI.state = kBattleUIWait;
 
-                     if (g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.ActionType == kBattleActionThrowItem)
-                     {
-                        for (i = 0; i < MAX_INVENTORY; i++)
-                        {
-                           if (gpGlobals->rgInventory[i].wItem ==
-                              g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID)
-                           {
-                              gpGlobals->rgInventory[i].nAmountInUse--;
-                              break;
-                           }
-                        }
-                     }
-                     else if (g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.ActionType == kBattleActionUseItem)
+                  if (g_Battle.UI.wCurPlayerIndex > 0)
+                  {
+                     //
+                     // Revert to the previous player
+                     //
+                     do
                      {
-                        if (gpGlobals->g.rgObject[g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID].item.wFlags & kItemFlagConsuming)
+                        g_Battle.rgPlayer[--g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
+
+                        if (g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.ActionType == kBattleActionThrowItem)
                         {
                            for (i = 0; i < MAX_INVENTORY; i++)
                            {
@@ -1252,44 +1191,57 @@ PAL_BattleUIUpdate(
                               }
                            }
                         }
-                     }
-                  } while (g_Battle.UI.wCurPlayerIndex > 0 &&
-                     (gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole] == 0 ||
-                      gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusConfused] > 0 ||
-                      gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusSleep] > 0 ||
-                      gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusParalyzed] > 0));
+                        else if (g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.ActionType == kBattleActionUseItem)
+                        {
+                           if (gpGlobals->g.rgObject[g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID].item.wFlags & kItemFlagConsuming)
+                           {
+                              for (i = 0; i < MAX_INVENTORY; i++)
+                              {
+                                 if (gpGlobals->rgInventory[i].wItem ==
+                                    g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].action.wActionID)
+                                 {
+                                    gpGlobals->rgInventory[i].nAmountInUse--;
+                                    break;
+                                 }
+                              }
+                           }
+                        }
+                     } while (g_Battle.UI.wCurPlayerIndex > 0 &&
+                        (gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole] == 0 ||
+                         gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusConfused] > 0 ||
+                         gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusSleep] > 0 ||
+                         gpGlobals->rgPlayerStatus[gpGlobals->rgParty[g_Battle.UI.wCurPlayerIndex].wPlayerRole][kStatusParalyzed] > 0));
+                  }
                }
-            }
-#else
-            else if (g_InputState.dwKeyPress & kKeyMenu)
-            {
-               float flMin = -1;
-               j = -1;
-
-               for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
+               else
                {
-                  if (g_Battle.rgPlayer[i].flTimeMeter >= 100)
-                  {
-                     g_Battle.rgPlayer[i].flTimeMeter += 100; // HACKHACK: Prevent the time meter from going below 100
+                  float flMin = -1;
+                  j = -1;
 
-                     if ((g_Battle.rgPlayer[i].flTimeMeter < flMin || flMin < 0) &&
-                        i != (int)g_Battle.UI.wCurPlayerIndex &&
-                        g_Battle.rgPlayer[i].state == kFighterWait)
+                  for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
+                  {
+                     if (g_Battle.rgPlayer[i].flTimeMeter >= 100)
                      {
-                        flMin = g_Battle.rgPlayer[i].flTimeMeter;
-                        j = i;
+                        g_Battle.rgPlayer[i].flTimeMeter += 100; // HACKHACK: Prevent the time meter from going below 100
+
+                        if ((g_Battle.rgPlayer[i].flTimeMeter < flMin || flMin < 0) &&
+                           i != (int)g_Battle.UI.wCurPlayerIndex &&
+                           g_Battle.rgPlayer[i].state == kFighterWait)
+                        {
+                           flMin = g_Battle.rgPlayer[i].flTimeMeter;
+                           j = i;
+                        }
                      }
                   }
-               }
 
-               if (j != -1)
-               {
-                  g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].flTimeMeter = flMin - 99;
-                  g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
-                  g_Battle.UI.state = kBattleUIWait;
+                  if (j != -1)
+                  {
+                     g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].flTimeMeter = flMin - 99;
+                     g_Battle.rgPlayer[g_Battle.UI.wCurPlayerIndex].state = kFighterWait;
+                     g_Battle.UI.state = kBattleUIWait;
+                  }
                }
             }
-#endif
             break;
 
          case kBattleMenuMagicSelect:
@@ -1324,11 +1276,7 @@ PAL_BattleUIUpdate(
                      }
                      else
                      {
-#ifdef PAL_CLASSIC
-                        g_Battle.UI.wSelectedIndex = 0;
-#else
-                        g_Battle.UI.wSelectedIndex = g_Battle.UI.wCurPlayerIndex;
-#endif
+                        g_Battle.UI.wSelectedIndex = gConfig.fIsClassic ? 0 : g_Battle.UI.wCurPlayerIndex;
                         g_Battle.UI.state = kBattleUISelectTargetPlayer;
                      }
                   }
@@ -1353,32 +1301,20 @@ PAL_BattleUIUpdate(
 
                switch (w)
                {
-#ifdef PAL_CLASSIC
+               case 1: // auto
+                  g_Battle.UI.fAutoAttack = TRUE;
+                  break;
+
                case 2: // item
-#else
-               case 1: // item
-#endif
                   g_Battle.UI.MenuState = kBattleMenuMiscItemSubMenu;
                   g_iCurSubMenuItem = 0;
                   break;
 
-#ifdef PAL_CLASSIC
                case 3: // defend
-#else
-               case 2: // defend
-#endif
                   g_Battle.UI.wActionType = kBattleActionDefend;
                   PAL_BattleCommitAction(FALSE);
                   break;
 
-#ifdef PAL_CLASSIC
-               case 1: // auto
-#else
-               case 3: // auto
-#endif
-                  g_Battle.UI.fAutoAttack = TRUE;
-                  break;
-
                case 4: // flee
                   g_Battle.UI.wActionType = kBattleActionFlee;
                   PAL_BattleCommitAction(FALSE);
@@ -1444,17 +1380,15 @@ PAL_BattleUIUpdate(
          }
       }
 
-#ifdef PAL_CLASSIC
       //
       // Don't bother selecting when only 1 enemy left
       //
-      if (y == 1)
+      if (gConfig.fIsClassic && y == 1)
       {
          g_Battle.UI.wPrevEnemyTarget = (WORD)x;
          PAL_BattleCommitAction(FALSE);
          break;
       }
-#endif
       if (g_Battle.UI.wSelectedIndex > x)
       {
          g_Battle.UI.wSelectedIndex = x;
@@ -1523,16 +1457,14 @@ PAL_BattleUIUpdate(
       break;
 
    case kBattleUISelectTargetPlayer:
-#ifdef PAL_CLASSIC
       //
       // Don't bother selecting when only 1 player is in the party
       //
-      if (gpGlobals->wMaxPartyMemberIndex == 0)
+      if (gConfig.fIsClassic && gpGlobals->wMaxPartyMemberIndex == 0)
       {
          g_Battle.UI.wSelectedIndex = 0;
          PAL_BattleCommitAction(FALSE);
       }
-#endif
 
       j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER;
       if (s_iFrame & 1)
@@ -1582,101 +1514,107 @@ PAL_BattleUIUpdate(
       break;
 
    case kBattleUISelectTargetEnemyAll:
-#ifdef PAL_CLASSIC
-      //
-      // Don't bother selecting
-      //
-      g_Battle.UI.wSelectedIndex = (WORD)-1;
-      PAL_BattleCommitAction(FALSE);
-#else
-      if (g_Battle.UI.wActionType == kBattleActionCoopMagic)
-      {
-         if (!PAL_BattleUIIsActionValid(kBattleActionCoopMagic))
-         {
-            g_Battle.UI.state = kBattleUISelectMove;
-            break;
-         }
-      }
-
-      if (s_iFrame & 1)
+      if (gConfig.fIsClassic)
       {
          //
-         // Highlight all enemies
+         // Don't bother selecting
          //
-         for (i = g_Battle.wMaxEnemyIndex; i >= 0; i--)
+         g_Battle.UI.wSelectedIndex = (WORD)-1;
+         PAL_BattleCommitAction(FALSE);
+      }
+      else
+      {
+         if (g_Battle.UI.wActionType == kBattleActionCoopMagic)
          {
-            if (g_Battle.rgEnemy[i].wObjectID == 0)
+            if (!PAL_BattleUIIsActionValid(kBattleActionCoopMagic))
             {
-               continue;
+               g_Battle.UI.state = kBattleUISelectMove;
+               break;
             }
+         }
 
-            x = PAL_X(g_Battle.rgEnemy[i].pos);
-            y = PAL_Y(g_Battle.rgEnemy[i].pos);
+         if (s_iFrame & 1)
+         {
+            //
+            // Highlight all enemies
+            //
+            for (i = g_Battle.wMaxEnemyIndex; i >= 0; i--)
+            {
+               if (g_Battle.rgEnemy[i].wObjectID == 0)
+               {
+                  continue;
+               }
+
+               x = PAL_X(g_Battle.rgEnemy[i].pos);
+               y = PAL_Y(g_Battle.rgEnemy[i].pos);
 
-            x -= PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2;
-            y -= PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame));
+               x -= PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2;
+               y -= PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame));
 
-            PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
-               gpScreen, PAL_XY(x, y), 7);
+               PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
+                  gpScreen, PAL_XY(x, y), 7);
+            }
+         }
+         if (g_InputState.dwKeyPress & kKeyMenu)
+         {
+            g_Battle.UI.state = kBattleUISelectMove;
+         }
+         else if (g_InputState.dwKeyPress & kKeySearch)
+         {
+            g_Battle.UI.wSelectedIndex = (WORD)-1;
+            PAL_BattleCommitAction(FALSE);
          }
       }
-      if (g_InputState.dwKeyPress & kKeyMenu)
-      {
-         g_Battle.UI.state = kBattleUISelectMove;
-      }
-      else if (g_InputState.dwKeyPress & kKeySearch)
-      {
-         g_Battle.UI.wSelectedIndex = (WORD)-1;
-         PAL_BattleCommitAction(FALSE);
-      }
-#endif
       break;
 
    case kBattleUISelectTargetPlayerAll:
-#ifdef PAL_CLASSIC
-      //
-      // Don't bother selecting
-      //
-      g_Battle.UI.wSelectedIndex = (WORD)-1;
-      PAL_BattleCommitAction(FALSE);
-#else
-      j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER;
-      if (s_iFrame & 1)
+      if (gConfig.fIsClassic)
       {
-         j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER_RED;
+         //
+         // Don't bother selecting
+         //
+         g_Battle.UI.wSelectedIndex = (WORD)-1;
+         PAL_BattleCommitAction(FALSE);
       }
-      for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
+      else
       {
-         if (g_Battle.UI.wActionType == kBattleActionMagic)
+         j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER;
+         if (s_iFrame & 1)
          {
-            w = gpGlobals->g.rgObject[g_Battle.UI.wObjectID].magic.wMagicNumber;
-
-            if (gpGlobals->g.lprgMagic[w].wType == kMagicTypeTrance)
+            j = SPRITENUM_BATTLE_ARROW_SELECTEDPLAYER_RED;
+         }
+         for (i = 0; i <= gpGlobals->wMaxPartyMemberIndex; i++)
+         {
+            if (g_Battle.UI.wActionType == kBattleActionMagic)
             {
-               if (i != g_Battle.UI.wCurPlayerIndex)
-                  continue;
+               w = gpGlobals->g.rgObject[g_Battle.UI.wObjectID].magic.wMagicNumber;
+
+               if (gpGlobals->g.lprgMagic[w].wType == kMagicTypeTrance)
+               {
+                  if (i != g_Battle.UI.wCurPlayerIndex)
+                     continue;
+               }
             }
-         }
 
-         //
-         // Draw arrows on all players, despite of dead or not
-         //
-         x = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][i][0] - 8;
-         y = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][i][1] - 67;
+            //
+            // Draw arrows on all players, despite of dead or not
+            //
+            x = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][i][0] - 8;
+            y = g_rgPlayerPos[gpGlobals->wMaxPartyMemberIndex][i][1] - 67;
 
-         PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, j), gpScreen, PAL_XY(x, y));
-      }
+            PAL_RLEBlitToSurface(PAL_SpriteGetFrame(gpSpriteUI, j), gpScreen, PAL_XY(x, y));
+         }
 
-      if (g_InputState.dwKeyPress & kKeyMenu)
-      {
-         g_Battle.UI.state = kBattleUISelectMove;
-      }
-      else if (g_InputState.dwKeyPress & kKeySearch)
-      {
-         g_Battle.UI.wSelectedIndex = (WORD)-1;
-         PAL_BattleCommitAction(FALSE);
+         if (g_InputState.dwKeyPress & kKeyMenu)
+         {
+            g_Battle.UI.state = kBattleUISelectMove;
+         }
+         else if (g_InputState.dwKeyPress & kKeySearch)
+         {
+            g_Battle.UI.wSelectedIndex = (WORD)-1;
+            PAL_BattleCommitAction(FALSE);
+         }
       }
-#endif
       break;
    }
 
@@ -1684,37 +1622,38 @@ end:
    //
    // Show the text message if there is one.
    //
-#ifndef PAL_CLASSIC
-   if (!SDL_TICKS_PASSED(SDL_GetTicks(), g_Battle.UI.dwMsgShowTime))
+   if (!gConfig.fIsClassic)
    {
-      //
-      // The text should be shown in a small window at the center of the screen
-      //
-      PAL_POS    pos;
-	  int        i, w = wcslen(g_Battle.UI.szMsg), len = 0;
+      if (!SDL_TICKS_PASSED(SDL_GetTicks(), g_Battle.UI.dwMsgShowTime))
+      {
+         //
+         // The text should be shown in a small window at the center of the screen
+         //
+         PAL_POS    pos;
+         int        i, w = wcslen(g_Battle.UI.szMsg), len = 0;
 
-	  for (i = 0; i < w; i++)
-		  len += PAL_CharWidth(g_Battle.UI.szMsg[i]) >> 3;
+         for (i = 0; i < w; i++)
+            len += PAL_CharWidth(g_Battle.UI.szMsg[i]) >> 3;
 
-      //
-      // Create the window box
-      //
-      pos = PAL_XY(160 - len * 4, 40);
-      PAL_CreateSingleLineBox(pos, (len + 1) / 2, FALSE);
+         //
+         // Create the window box
+         //
+         pos = PAL_XY(160 - len * 4, 40);
+         PAL_CreateSingleLineBox(pos, (len + 1) / 2, FALSE);
 
-      //
-      // Show the text on the screen
-      //
-      pos = PAL_XY(PAL_X(pos) + 8 + ((len & 1) << 2), PAL_Y(pos) + 10);
-      PAL_DrawText(g_Battle.UI.szMsg, pos, 0, FALSE, FALSE, FALSE);
-   }
-   else if (g_Battle.UI.szNextMsg[0] != '\0')
-   {
-      wcscpy(g_Battle.UI.szMsg, g_Battle.UI.szNextMsg);
-      g_Battle.UI.dwMsgShowTime = SDL_GetTicks() + g_Battle.UI.wNextMsgDuration;
-      g_Battle.UI.szNextMsg[0] = '\0';
+         //
+         // Show the text on the screen
+         //
+         pos = PAL_XY(PAL_X(pos) + 8 + ((len & 1) << 2), PAL_Y(pos) + 10);
+         PAL_DrawText(g_Battle.UI.szMsg, pos, 0, FALSE, FALSE, FALSE);
+      }
+      else if (g_Battle.UI.szNextMsg[0] != L'\0')
+      {
+         wcscpy(g_Battle.UI.szMsg, g_Battle.UI.szNextMsg);
+         g_Battle.UI.dwMsgShowTime = SDL_GetTicks() + g_Battle.UI.wNextMsgDuration;
+         g_Battle.UI.szNextMsg[0] = L'\0';
+      }
    }
-#endif
 
    //
    // Draw the numbers