Browse Source

Unicode support as well as japanese support

louyihua 9 years ago
parent
commit
89f3082a20
19 changed files with 67821 additions and 3926 deletions
  1. 4175 0
      codepage.h
  2. 16 1
      common.h
  3. 23 8
      fight.c
  4. 364 209
      font.c
  5. 13 0
      font.h
  6. 58918 0
      fontglyph.h
  7. 13 1
      global.c
  8. 11 0
      global.h
  9. 16 1
      itemmenu.c
  10. 16 1
      magicmenu.c
  11. 3 1
      main.c
  12. 3524 3461
      script.c
  13. 385 5
      text.c
  14. 29 1
      text.h
  15. 17 0
      ui.c
  16. 244 234
      ui.h
  17. 25 0
      uibattle.c
  18. 11 0
      uibattle.h
  19. 18 3
      video.c

File diff suppressed because it is too large
+ 4175 - 0
codepage.h


+ 16 - 1
common.h

@@ -17,12 +17,15 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #ifndef _COMMON_H
 #define _COMMON_H
 
-//#define PAL_WIN95          1 // not valid for now
+//#define PAL_WIN95          1
 //#define PAL_CLASSIC        1
+#define PAL_UNICODE        1
 
 #ifdef __cplusplus
 extern "C"
@@ -214,6 +217,8 @@ typedef void               *LPVOID;
 typedef const void         *LPCVOID;
 typedef CHAR               *LPSTR;
 typedef const CHAR         *LPCSTR;
+typedef USHORT             *LPWSTR;
+typedef const USHORT       *LPCWSTR;
 
 #endif
 
@@ -223,6 +228,16 @@ typedef const CHAR         *LPCSTR;
 #define PAL_LARGE           /* */
 #endif
 
+#define __WIDETEXT(quote) L##quote
+#define WIDETEXT(quote) __WIDETEXT(quote)
+
+typedef enum tagCODEPAGE {
+	CP_BIG5 = 0,
+	CP_GBK = 1,
+	CP_SHIFTJIS = 2,
+	CP_MAX = 3
+} CODEPAGE;
+
 #ifdef __cplusplus
 }
 #endif

+ 23 - 8
fight.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 #include <math.h>
@@ -4854,7 +4856,11 @@ PAL_BattleStealFromEnemy(
 {
    int   iPlayerIndex = g_Battle.wMovingPlayerIndex;
    int   offset, x, y, i;
+#ifdef PAL_UNICODE
+   WCHAR s[256] = L"";
+#else
    char  s[256] = "";
+#endif
 
    g_Battle.rgPlayer[iPlayerIndex].wCurrentFrame = 10;
    offset = ((INT)wTarget - iPlayerIndex) * 8;
@@ -4905,11 +4911,15 @@ PAL_BattleStealFromEnemy(
 
          if (c > 0)
          {
-            strcpy(s, PAL_GetWord(34));
-            strcat(s, " ");
-            strcat(s, va("%d", c));
-            strcat(s, " ");
-            strcat(s, PAL_GetWord(10));
+#        ifdef PAL_UNICODE
+			 swprintf(s, 256, L"%s %d %s", PAL_GetWord(34), c, PAL_GetWord(10));
+#        else
+			 strcpy(s, PAL_GetWord(34));
+			 strcat(s, " ");
+			 strcat(s, va("%d", c));
+			 strcat(s, " ");
+			 strcat(s, PAL_GetWord(10));
+#        endif
          }
       }
       else
@@ -4920,9 +4930,14 @@ PAL_BattleStealFromEnemy(
          g_Battle.rgEnemy[wTarget].e.nStealItem--;
          PAL_AddItemToInventory(g_Battle.rgEnemy[wTarget].e.wStealItem, 1);
 
-         strcpy(s, PAL_GetWord(34));
-         strcat(s, PAL_GetWord(g_Battle.rgEnemy[wTarget].e.wStealItem));
-      }
+#     ifdef PAL_UNICODE
+		 wcscpy(s, PAL_GetWord(34));
+         wcscat(s, PAL_GetWord(g_Battle.rgEnemy[wTarget].e.wStealItem));
+#     else
+		 strcpy(s, PAL_GetWord(34));
+		 strcat(s, PAL_GetWord(g_Battle.rgEnemy[wTarget].e.wStealItem));
+#     endif
+	  }
 
       if (s[0] != '\0')
       {

+ 364 - 209
font.c

@@ -18,78 +18,15 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "font.h"
-#include "ascii.h"
 #include "util.h"
 
-#ifdef PAL_WIN95
-
-/*
- * Portions based on:
- *
- * YH - Console Chinese Environment -
- * Copyright (C) 1999 Red Flag Linux (office@sonata.iscas.ac.cn)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY RED FLAG LINUX ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
+#if defined(PAL_UNICODE)
 
-/*
- * Portions based on:
- *
- * KON2 - Kanji ON Console -
- * Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp)
- *
- * CCE - Console Chinese Environment -
- * Copyright (C) 1998-1999 Rui He (herui@cs.duke.edu)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY TAKASHI MANABE ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- */
-
-#include "gbfont.h"
-#include "big5font.h"
-
-BOOL fIsBig5 = FALSE;
+#include "fontglyph.h"
 
 INT
 PAL_InitFont(
@@ -106,25 +43,10 @@ PAL_InitFont(
 
   Return value:
 
-    0 if succeed, -1 if cannot allocate memory, -2 if cannot load files.
+    0 if succeed.
 
 --*/
 {
-   FILE *fp;
-
-   fp = fopen(PAL_PREFIX "word.dat", "rb");
-   if (!fp)
-   {
-      return 0;
-   }
-
-   fseek(fp, 0x1E, SEEK_SET);
-   if (fgetc(fp) == 0xAA)
-   {
-      fIsBig5 = TRUE;
-   }
-
-   fclose(fp);
    return 0;
 }
 
@@ -149,15 +71,6 @@ PAL_FreeFont(
 {
 }
 
-static BOOL is_gb(unsigned char b1, unsigned char b2)
-{
-   if (b1 < 0xa1 || b1 > 0xfe)
-      return FALSE;
-   if (b2 < 0xa1 || b2 > 0xfe)
-      return FALSE;
-   return TRUE;
-}
-
 VOID
 PAL_DrawCharOnSurface(
    WORD                     wChar,
@@ -168,11 +81,11 @@ PAL_DrawCharOnSurface(
 /*++
   Purpose:
 
-    Draw a BIG-5 Chinese character on a surface.
+    Draw a Unicode character on a surface.
 
   Parameters:
 
-    [IN]  wChar - the character to be drawn (in GB2312/BIG5).
+    [IN]  wChar - the unicode character to be drawn.
 
     [OUT] lpSurface - the destination surface.
 
@@ -186,147 +99,389 @@ PAL_DrawCharOnSurface(
 
 --*/
 {
-   int       i, j, dx;
-   int       x = PAL_X(pos), y = PAL_Y(pos);
-   LPBYTE    pChar;
-   BYTE      ch1, ch2;
+	int       i, j;
+	int       x = PAL_X(pos), y = PAL_Y(pos);
+
+	//
+	// Check for NULL pointer & invalid char code.
+	//
+	if (lpSurface == NULL || (wChar >= 0xd800 && wChar < unicode_upper_base) || wChar >= unicode_upper_top)
+	{
+		return;
+	}
+
+	//
+	// Locate for this character in the font lib.
+	//
+	if (wChar >= unicode_upper_base)
+	{
+		wChar -= (unicode_upper_base - 0xd800);
+	}
+
+	//
+	// Draw the character to the surface.
+	//
+	LPBYTE dest = (LPBYTE)lpSurface->pixels + y * lpSurface->pitch + x;
+	if (font_width[wChar] == 32)
+	{
+		for (i = 0; i < 32; i += 2, dest += lpSurface->pitch)
+		{
+			for (j = 0; j < 8; j++)
+			{
+				if (unicode_font[wChar][i] & (1 << (7 - j)))
+				{
+					dest[j] = bColor;
+				}
+			}
+			for (j = 0; j < 8; j++)
+			{
+				if (unicode_font[wChar][i + 1] & (1 << (7 - j)))
+				{
+					dest[j + 8] = bColor;
+				}
+			}
+		}
+	}
+	else
+	{
+		for (i = 0; i < 16; i++, dest += lpSurface->pitch)
+		{
+			for (j = 0; j < 8; j++)
+			{
+				if (unicode_font[wChar][i] & (1 << (7 - j)))
+				{
+					dest[j] = bColor;
+				}
+			}
+		}
+	}
+}
 
-   //
-   // Check for NULL pointer.
-   //
-   if (lpSurface == NULL)
-   {
-      return;
-   }
+INT
+PAL_CharWidth(
+   WORD                     wChar
+)
+{
+	if ((wChar >= 0xd800 && wChar < unicode_upper_base) || wChar >= unicode_upper_top)
+	{
+		return 0;
+	}
+
+	//
+	// Locate for this character in the font lib.
+	//
+	if (wChar >= unicode_upper_base)
+	{
+		wChar -= (unicode_upper_base - 0xd800);
+	}
+
+	return font_width[wChar] >> 1;
+}
 
-   //
-   // Locate for this character in the font lib.
-   //
-   ch1 = wChar & 0xff;
-   ch2 = wChar >> 8;
+#elif defined(PAL_WIN95)
 
-   if (fIsBig5)
-   {
-      if (ch2 < 0xa1)
-         pChar = &big5font[((ch1 - 0xA1) * 157 + ch2 - 0x40) << 5] + 8;
-      else
-         pChar = &big5font[((ch1 - 0xA1) * 157 + 63 + ch2 - 0xA1) << 5] + 8;
-   }
-   else
-   {
-      if (!is_gb(ch1, ch2))
-      {
-         return;
-      }
-      pChar = &gbfont[((ch1 - 0xa1) * 94 + (ch2 - 0xa1)) * 32];
-   }
+/*
+* Portions based on:
+*
+* YH - Console Chinese Environment -
+* Copyright (C) 1999 Red Flag Linux (office@sonata.iscas.ac.cn)
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY RED FLAG LINUX ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+* SUCH DAMAGE.
+*
+*/
 
-   if (pChar == NULL) return;
+/*
+* Portions based on:
+*
+* KON2 - Kanji ON Console -
+* Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp)
+*
+* CCE - Console Chinese Environment -
+* Copyright (C) 1998-1999 Rui He (herui@cs.duke.edu)
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY TAKASHI MANABE ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+* SUCH DAMAGE.
+* 
+*/
 
-   //
-   // Draw the character to the surface.
-   //
-   if (y >= lpSurface->h) return;
+#include "gbfont.h"
+#include "big5font.h"
 
-   y *= lpSurface->pitch;
-   for (i = 0; i < 32; i++)
-   {
-      dx = x + ((i & 1) << 3);
-      for (j = 0; j < 8; j++)
-      {
-         if (pChar[i] & (1 << (7 - j)))
-         {
-            if (dx < lpSurface->w)
-            {
-               ((LPBYTE)(lpSurface->pixels))[y + dx] = bColor;
-            }
-            else
-            {
-               break;
-            }
-         }
-         dx++;
-      }
-      y += (i & 1) * lpSurface->pitch;
-      if (y / lpSurface->pitch >= lpSurface->h)
-      {
-         break;
-      }
-   }
+BOOL fIsBig5 = FALSE;
+
+INT
+PAL_InitFont(
+VOID
+)
+/*++
+Purpose:
+
+Load the font files.
+
+Parameters:
+
+None.
+
+Return value:
+
+0 if succeed, -1 if cannot allocate memory, -2 if cannot load files.
+
+--*/
+{
+	FILE *fp;
+
+	fp = fopen(PAL_PREFIX "word.dat", "rb");
+	if (!fp)
+	{
+		return 0;
+	}
+
+	fseek(fp, 0x1E, SEEK_SET);
+	if (fgetc(fp) == 0xAA)
+	{
+		fIsBig5 = TRUE;
+	}
+
+	fclose(fp);
+	return 0;
 }
 
 VOID
-PAL_DrawASCIICharOnSurface(
-   BYTE                     bChar,
-   SDL_Surface             *lpSurface,
-   PAL_POS                  pos,
-   BYTE                     bColor
+PAL_FreeFont(
+VOID
 )
 /*++
-  Purpose:
+Purpose:
 
-    Draw a ASCII character on a surface.
+Free the memory used for fonts.
 
-  Parameters:
+Parameters:
 
-    [IN]  bChar - the character to be drawn.
+None.
 
-    [OUT] lpSurface - the destination surface.
+Return value:
 
-    [IN]  pos - the destination location of the surface.
+None.
 
-    [IN]  bColor - the color of the character.
+--*/
+{
+}
 
-  Return value:
+static BOOL is_gb(unsigned char b1, unsigned char b2)
+{
+	if (b1 < 0xa1 || b1 > 0xfe)
+		return FALSE;
+	if (b2 < 0xa1 || b2 > 0xfe)
+		return FALSE;
+	return TRUE;
+}
 
-    None.
+VOID
+PAL_DrawCharOnSurface(
+WORD                     wChar,
+SDL_Surface             *lpSurface,
+PAL_POS                  pos,
+BYTE                     bColor
+)
+/*++
+Purpose:
+
+Draw a BIG-5 Chinese character on a surface.
+
+Parameters:
+
+[IN]  wChar - the character to be drawn (in GB2312/BIG5).
+
+[OUT] lpSurface - the destination surface.
+
+[IN]  pos - the destination location of the surface.
+
+[IN]  bColor - the color of the character.
+
+Return value:
+
+None.
 
 --*/
 {
-   int i, j, dx;
-   int x = PAL_X(pos), y = PAL_Y(pos);
-   LPBYTE pChar;
+	int       i, j, dx;
+	int       x = PAL_X(pos), y = PAL_Y(pos);
+	LPBYTE    pChar;
+	BYTE      ch1, ch2;
+
+	//
+	// Check for NULL pointer.
+	//
+	if (lpSurface == NULL)
+	{
+		return;
+	}
+
+	//
+	// Locate for this character in the font lib.
+	//
+	ch1 = wChar & 0xff;
+	ch2 = wChar >> 8;
+
+	if (fIsBig5)
+	{
+		if (ch2 < 0xa1)
+			pChar = &big5font[((ch1 - 0xA1) * 157 + ch2 - 0x40) << 5] + 8;
+		else
+			pChar = &big5font[((ch1 - 0xA1) * 157 + 63 + ch2 - 0xA1) << 5] + 8;
+	}
+	else
+	{
+		if (!is_gb(ch1, ch2))
+		{
+			return;
+		}
+		pChar = &gbfont[((ch1 - 0xa1) * 94 + (ch2 - 0xa1)) * 32];
+	}
+
+	if (pChar == NULL) return;
+
+	//
+	// Draw the character to the surface.
+	//
+	if (y >= lpSurface->h) return;
+
+	y *= lpSurface->pitch;
+	for (i = 0; i < 32; i++)
+	{
+		dx = x + ((i & 1) << 3);
+		for (j = 0; j < 8; j++)
+		{
+			if (pChar[i] & (1 << (7 - j)))
+			{
+				if (dx < lpSurface->w)
+				{
+					((LPBYTE)(lpSurface->pixels))[y + dx] = bColor;
+				}
+				else
+				{
+					break;
+				}
+			}
+			dx++;
+		}
+		y += (i & 1) * lpSurface->pitch;
+		if (y / lpSurface->pitch >= lpSurface->h)
+		{
+			break;
+		}
+	}
+}
 
-   pChar = &iso_font[(int)(bChar & ~128) * 15];
+VOID
+PAL_DrawASCIICharOnSurface(
+BYTE                     bChar,
+SDL_Surface             *lpSurface,
+PAL_POS                  pos,
+BYTE                     bColor
+)
+/*++
+Purpose:
 
-   //
-   // Check for NULL pointer.
-   //
-   if (lpSurface == NULL)
-   {
-      return;
-   }
+Draw a ASCII character on a surface.
 
-   //
-   // Draw the character to the surface.
-   //
-   if (y >= lpSurface->h) return;
+Parameters:
 
-   y *= lpSurface->pitch;
-   for (i = 0; i < 15; i++)
-   {
-      dx = x;
-      for (j = 0; j < 8; j++)
-      {
-         if (pChar[i] & (1 << j))
-         {
-            if (dx < lpSurface->w)
-            {
-               ((LPBYTE)(lpSurface->pixels))[y + dx] = bColor;
-            }
-            else
-            {
-               break;
-            }
-         }
-         dx++;
-      }
-      y += lpSurface->pitch;
-      if (y / lpSurface->pitch >= lpSurface->h)
-      {
-         break;
-      }
-   }
+[IN]  bChar - the character to be drawn.
+
+[OUT] lpSurface - the destination surface.
+
+[IN]  pos - the destination location of the surface.
+
+[IN]  bColor - the color of the character.
+
+Return value:
+
+None.
+
+--*/
+{
+	int i, j, dx;
+	int x = PAL_X(pos), y = PAL_Y(pos);
+	LPBYTE pChar;
+
+	pChar = &iso_font[(int)(bChar & ~128) * 15];
+
+	//
+	// Check for NULL pointer.
+	//
+	if (lpSurface == NULL)
+	{
+		return;
+	}
+
+	//
+	// Draw the character to the surface.
+	//
+	if (y >= lpSurface->h) return;
+
+	y *= lpSurface->pitch;
+	for (i = 0; i < 15; i++)
+	{
+		dx = x;
+		for (j = 0; j < 8; j++)
+		{
+			if (pChar[i] & (1 << j))
+			{
+				if (dx < lpSurface->w)
+				{
+					((LPBYTE)(lpSurface->pixels))[y + dx] = bColor;
+				}
+				else
+				{
+					break;
+				}
+			}
+			dx++;
+		}
+		y += lpSurface->pitch;
+		if (y / lpSurface->pitch >= lpSurface->h)
+		{
+			break;
+		}
+	}
 }
 
 #else

+ 13 - 0
font.h

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #ifndef FONT_H
 #define FONT_H
@@ -48,6 +50,15 @@ PAL_DrawCharOnSurface(
    BYTE                     bColor
 );
 
+#ifdef PAL_UNICODE
+
+INT
+PAL_CharWidth(
+   WORD                     wChar
+);
+
+#else
+
 VOID
 PAL_DrawASCIICharOnSurface(
    BYTE                     bChar,
@@ -56,6 +67,8 @@ PAL_DrawASCIICharOnSurface(
    BYTE                     bColor
 );
 
+#endif
+
 #ifdef __cplusplus
 }
 #endif

File diff suppressed because it is too large
+ 58918 - 0
fontglyph.h


+ 13 - 1
global.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 
@@ -37,7 +39,12 @@ LPGLOBALVARS gpGlobals = NULL;
 
 INT
 PAL_InitGlobals(
+#ifdef PAL_UNICODE
+   CODEPAGE      iCodePage,
+   DWORD         dwWordLength
+#else
    VOID
+#endif
 )
 /*++
   Purpose:
@@ -46,7 +53,8 @@ PAL_InitGlobals(
 
   Parameters:
 
-    None.
+    [IN]  iCodePage - the code page for text conversion.
+	[IN]  dwWordLength - the length of each word.
 
   Return value:
 
@@ -78,6 +86,10 @@ PAL_InitGlobals(
    gpGlobals->lpObjectDesc = PAL_LoadObjectDesc(va("%s%s", PAL_PREFIX, "desc.dat"));
 #endif
    gpGlobals->bCurrentSaveSlot = 1;
+#ifdef PAL_UNICODE
+   gpGlobals->iCodePage = iCodePage;
+   gpGlobals->dwWordLength = dwWordLength;
+#endif
 
    return 0;
 }

+ 11 - 0
global.h

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #ifndef GLOBAL_H
 #define GLOBAL_H
@@ -563,6 +565,10 @@ typedef struct tagGLOBALVARS
    LPOBJECTDESC     lpObjectDesc;
 #endif
    DWORD            dwFrameNum;
+#ifdef PAL_UNICODE
+   CODEPAGE         iCodePage;
+   DWORD            dwWordLength;
+#endif
 } GLOBALVARS, *LPGLOBALVARS;
 
 typedef struct tagSAVEDGAME
@@ -600,7 +606,12 @@ extern LPGLOBALVARS gpGlobals;
 
 INT
 PAL_InitGlobals(
+#ifdef PAL_UNICODE
+   CODEPAGE      iCodePage,
+   DWORD         dwWordLength
+#else
    VOID
+#endif
 );
 
 VOID

+ 16 - 1
itemmenu.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 
@@ -227,18 +229,31 @@ PAL_ItemSelectMenuUpdate(
 #ifndef PAL_WIN95
    if (!g_fNoDesc && gpGlobals->lpObjectDesc != NULL)
    {
+#  ifdef PAL_UNICODE
+	  WCHAR szDesc[512], *next;
+	  const WCHAR *d = PAL_GetObjectDesc(gpGlobals->lpObjectDesc, wObject);
+#  else
       char szDesc[512], *next;
       const char *d = PAL_GetObjectDesc(gpGlobals->lpObjectDesc, wObject);
+#  endif
 
       if (d != NULL)
       {
          k = 150;
+#     ifdef PAL_UNICODE
+		 wcscpy(szDesc, d);
+#     else
          strcpy(szDesc, d);
+#     endif
          d = szDesc;
 
          while (TRUE)
          {
-            next = strchr(d, '*');
+#        ifdef PAL_UNICODE
+			next = wcschr(d, '*');
+#        else
+			next = strchr(d, '*');
+#        endif
             if (next != NULL)
             {
                *next = '\0';

+ 16 - 1
magicmenu.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 
@@ -131,8 +133,13 @@ PAL_MagicSelectionMenuUpdate(
    }
    else
    {
+#  ifdef PAL_UNICODE
+      WCHAR szDesc[512], *next;
+      const WCHAR *d = PAL_GetObjectDesc(gpGlobals->lpObjectDesc, rgMagicItem[g_iCurrentItem].wMagic);
+#  else
       char szDesc[512], *next;
       const char *d = PAL_GetObjectDesc(gpGlobals->lpObjectDesc, rgMagicItem[g_iCurrentItem].wMagic);
+#  endif
 
       //
       // Draw the magic description.
@@ -140,12 +147,20 @@ PAL_MagicSelectionMenuUpdate(
       if (d != NULL)
       {
          k = 3;
+#     ifdef PAL_UNICODE
+		 wcscpy(szDesc, d);
+#     else
          strcpy(szDesc, d);
+#     endif
          d = szDesc;
 
          while (TRUE)
          {
-            next = strchr(d, '*');
+#        ifdef PAL_UNICODE
+			next = wcschr(d, '*');
+#        else
+			next = strchr(d, '*');
+#        endif
             if (next != NULL)
             {
                *next = '\0';

+ 3 - 1
main.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 #include "getopt.h"
@@ -114,7 +116,7 @@ PAL_Init(
 
    SDL_WM_SetCaption("Loading...", NULL);
 
-   e = PAL_InitGlobals();
+   e = PAL_InitGlobals(CP_BIG5, 10);	// TODO: Fix it for dynamic loading from configuration file
    if (e != 0)
    {
       TerminateOnError("Could not initialize global data: %d.\n", e);

File diff suppressed because it is too large
+ 3524 - 3461
script.c


+ 385 - 5
text.c

@@ -21,10 +21,14 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 
+#ifndef PAL_UNICODE
 #define WORD_LENGTH      10
+#endif
 
 #define   FONT_COLOR_DEFAULT        0x4F
 #define   FONT_COLOR_YELLOW         0x2D
@@ -34,6 +38,17 @@
 
 BOOL      g_fUpdatedInBattle      = FALSE;
 
+#ifdef PAL_UNICODE
+#define INCLUDE_CODEPAGE_H
+#include "codepage.h"
+
+static const WCHAR* gc_rgszAdditionalWords[CP_MAX][6] = {
+   { L"\x6230\x9B25\x901F\x5EA6", L"\x4E00", L"\x4E8C", L"\x4E09", L"\x56DB", L"\x4E94" },
+   { L"\x6218\x6597\x901F\x5EA6", L"\x4E00", L"\x4E8C", L"\x4E09", L"\x56DB", L"\x4E94" },
+   { L"\x6226\x95D8\x901F\x5EA6", L"\x4E00", L"\x4E8C", L"\x4E09", L"\x56DB", L"\x4E94" },
+};
+static const WCHAR** g_rgszAdditionalWords;
+#else
 static const char g_rgszAdditionalWords[][WORD_LENGTH + 1] = {
    {0xBE, 0xD4, 0xB0, 0xAB, 0xB3, 0x74, 0xAB, 0xD7, 0x00, 0x00, 0x00}, // Battle Speed
    {0xA4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 1
@@ -42,12 +57,18 @@ static const char g_rgszAdditionalWords[][WORD_LENGTH + 1] = {
    {0xA5, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 4
    {0xA4, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 5
 };
+#endif
 
 typedef struct tagTEXTLIB
 {
+#ifdef PAL_UNICODE
+   LPWSTR*         lpWordBuf;
+   LPWSTR*         lpMsgBuf;
+#else
    LPBYTE          lpWordBuf;
    LPBYTE          lpMsgBuf;
    LPDWORD         lpMsgOffset;
+#endif
 
    int             nWords;
    int             nMsgs;
@@ -89,6 +110,12 @@ PAL_InitText(
 --*/
 {
    FILE       *fpMsg, *fpWord;
+#ifdef PAL_UNICODE
+   DWORD      *offsets;
+   LPBYTE      temp;
+   LPWSTR      tmp;
+   int         wlen, wpos;
+#endif
    int         i;
 
    //
@@ -103,45 +130,94 @@ PAL_InitText(
    fseek(fpWord, 0, SEEK_END);
    i = ftell(fpWord);
 
+#ifdef PAL_UNICODE
+   //
+   // Each word has 10 or 16 bytes
+   //
+   g_TextLib.nWords = (i + (gpGlobals->dwWordLength - 1)) / gpGlobals->dwWordLength;
+#else
    //
    // Each word has 10 bytes
    //
    g_TextLib.nWords = (i + (WORD_LENGTH - 1)) / WORD_LENGTH;
+#endif
 
    //
    // Read the words
    //
+#ifdef PAL_UNICODE
+   temp = (LPBYTE)malloc(i);
+   if (temp == NULL)
+#else
    g_TextLib.lpWordBuf = (LPBYTE)malloc(i);
    if (g_TextLib.lpWordBuf == NULL)
+#endif
    {
       fclose(fpWord);
       fclose(fpMsg);
       return -1;
    }
    fseek(fpWord, 0, SEEK_SET);
+#ifdef PAL_UNICODE
+   fread(temp, i, 1, fpWord);
+#else
    fread(g_TextLib.lpWordBuf, i, 1, fpWord);
+#endif
 
    //
    // Close the words file
    //
    fclose(fpWord);
 
+#ifdef PAL_UNICODE
+   // Split the words and do code page conversion
+   for (i = 0, wlen = 0; i < g_TextLib.nWords; i++)
+   {
+	   int base = i * gpGlobals->dwWordLength;
+	   int pos = base + gpGlobals->dwWordLength - 1;
+	   while (pos >= base && temp[pos] == ' ') temp[pos--] = 0;
+	   wlen += PAL_MultiByteToWideChar(temp + base, gpGlobals->dwWordLength, NULL, 0) + 1;
+   }
+   g_TextLib.lpWordBuf = (LPWSTR*)malloc(g_TextLib.nWords * sizeof(LPWSTR));
+   tmp = (LPWSTR)malloc(wlen * sizeof(WCHAR));
+   for (i = 0, wpos = 0; i < g_TextLib.nWords; i++)
+   {
+	   int l;
+	   g_TextLib.lpWordBuf[i] = tmp + wpos;
+	   l = PAL_MultiByteToWideChar(temp + i * gpGlobals->dwWordLength, gpGlobals->dwWordLength, g_TextLib.lpWordBuf[i], wlen - wpos);
+	   if (l > 0 && g_TextLib.lpWordBuf[i][l - 1] == '1')
+		   g_TextLib.lpWordBuf[i][l - 1] = 0;
+	   g_TextLib.lpWordBuf[i][l] = 0;
+	   wpos += l + 1;
+   }
+   free(temp);
+#endif
+
    //
    // Read the message offsets. The message offsets are in SSS.MKF #3
    //
    i = PAL_MKFGetChunkSize(3, gpGlobals->f.fpSSS) / sizeof(DWORD);
    g_TextLib.nMsgs = i - 1;
 
+#ifdef PAL_UNICODE
+   offsets = (LPDWORD)malloc(i * sizeof(DWORD));
+   if (offsets == NULL)
+#else
    g_TextLib.lpMsgOffset = (LPDWORD)malloc(i * sizeof(DWORD));
    if (g_TextLib.lpMsgOffset == NULL)
+#endif
    {
       free(g_TextLib.lpWordBuf);
       fclose(fpMsg);
       return -1;
    }
 
+#ifdef PAL_UNICODE
+   PAL_MKFReadChunk((LPBYTE)(offsets), i * sizeof(DWORD), 3, gpGlobals->f.fpSSS);
+#else
    PAL_MKFReadChunk((LPBYTE)(g_TextLib.lpMsgOffset), i * sizeof(DWORD), 3,
       gpGlobals->f.fpSSS);
+#endif
 
    //
    // Read the messages.
@@ -149,20 +225,56 @@ PAL_InitText(
    fseek(fpMsg, 0, SEEK_END);
    i = ftell(fpMsg);
 
+#ifdef PAL_UNICODE
+   temp = (LPBYTE)malloc(i);
+   if (temp == NULL)
+#else
    g_TextLib.lpMsgBuf = (LPBYTE)malloc(i);
    if (g_TextLib.lpMsgBuf == NULL)
+#endif
    {
+#ifdef PAL_UNICODE
+      free(offsets);
+	  free(g_TextLib.lpWordBuf[0]);
+#else
       free(g_TextLib.lpMsgOffset);
+#endif
       free(g_TextLib.lpWordBuf);
       fclose(fpMsg);
       return -1;
    }
 
    fseek(fpMsg, 0, SEEK_SET);
+#ifdef PAL_UNICODE
+   fread(temp, 1, i, fpMsg);
+#else
    fread(g_TextLib.lpMsgBuf, 1, i, fpMsg);
+#endif
 
    fclose(fpMsg);
 
+#ifdef PAL_UNICODE
+   // Split messages and do code page conversion here
+   for (i = 0, wlen = 0; i < g_TextLib.nMsgs; i++)
+   {
+	   wlen += PAL_MultiByteToWideChar(temp + SWAP32(offsets[i]), SWAP32(offsets[i + 1]) - SWAP32(offsets[i]), NULL, 0) + 1;
+   }
+   g_TextLib.lpMsgBuf = (LPWSTR*)malloc(g_TextLib.nMsgs * sizeof(LPWSTR));
+   tmp = (LPWSTR)malloc(wlen * sizeof(WCHAR));
+   for (i = 0, wpos = 0; i < g_TextLib.nMsgs; i++)
+   {
+	   int l;
+	   g_TextLib.lpMsgBuf[i] = tmp + wpos;
+	   l = PAL_MultiByteToWideChar(temp + SWAP32(offsets[i]), SWAP32(offsets[i + 1]) - SWAP32(offsets[i]), g_TextLib.lpMsgBuf[i], wlen - wpos);
+	   g_TextLib.lpMsgBuf[i][l] = 0;
+	   wpos += l + 1;
+   }
+   free(temp);
+   free(offsets);
+
+   g_rgszAdditionalWords = gc_rgszAdditionalWords[gpGlobals->iCodePage];
+#endif
+
    g_TextLib.bCurrentFontColor = FONT_COLOR_DEFAULT;
    g_TextLib.bIcon = 0;
    g_TextLib.posIcon = 0;
@@ -199,24 +311,34 @@ PAL_FreeText(
 {
    if (g_TextLib.lpMsgBuf != NULL)
    {
+#  ifdef PAL_UNICODE
+      free(g_TextLib.lpMsgBuf[0]);
+#  endif
       free(g_TextLib.lpMsgBuf);
       g_TextLib.lpMsgBuf = NULL;
    }
-
+#ifndef PAL_UNICODE
    if (g_TextLib.lpMsgOffset != NULL)
    {
       free(g_TextLib.lpMsgOffset);
       g_TextLib.lpMsgOffset = NULL;
    }
-
+#endif
    if (g_TextLib.lpWordBuf != NULL)
    {
+#  ifdef PAL_UNICODE
+      free(g_TextLib.lpWordBuf[0]);
+#  endif
       free(g_TextLib.lpWordBuf);
       g_TextLib.lpWordBuf = NULL;
    }
 }
 
+#ifdef PAL_UNICODE
+LPCWSTR
+#else
 LPCSTR
+#endif
 PAL_GetWord(
    WORD       wNumWord
 )
@@ -235,7 +357,9 @@ PAL_GetWord(
 
 --*/
 {
+#ifndef PAL_UNICODE
    static char buf[WORD_LENGTH + 1];
+#endif
 
    if (wNumWord >= PAL_ADDITIONAL_WORD_FIRST)
    {
@@ -247,6 +371,9 @@ PAL_GetWord(
       return NULL;
    }
 
+#ifdef PAL_UNICODE
+   return g_TextLib.lpWordBuf[wNumWord];
+#else
    memcpy(buf, &g_TextLib.lpWordBuf[wNumWord * WORD_LENGTH], WORD_LENGTH);
    buf[WORD_LENGTH] = '\0';
 
@@ -261,9 +388,14 @@ PAL_GetWord(
    }
 
    return buf;
+#endif
 }
 
+#ifdef PAL_UNICODE
+LPCWSTR
+#else
 LPCSTR
+#endif
 PAL_GetMsg(
    WORD       wNumMsg
 )
@@ -282,6 +414,9 @@ PAL_GetMsg(
 
 --*/
 {
+#ifdef PAL_UNICODE
+	return (wNumMsg >= g_TextLib.nMsgs) ? NULL : g_TextLib.lpMsgBuf[wNumMsg];
+#else
    static char    buf[256];
    DWORD          dwOffset, dwSize;
 
@@ -298,11 +433,16 @@ PAL_GetMsg(
    buf[dwSize] = '\0';
 
    return buf;
+#endif
 }
 
 VOID
 PAL_DrawText(
+#ifdef PAL_UNICODE
+   LPCWSTR    lpszText,
+#else
    LPCSTR     lpszText,
+#endif
    PAL_POS    pos,
    BYTE       bColor,
    BOOL       fShadow,
@@ -332,14 +472,16 @@ PAL_DrawText(
 --*/
 {
    SDL_Rect   rect, urect;
+#ifndef PAL_UNICODE
    WORD       wChar;
+#endif
 
    rect.x = PAL_X(pos);
    rect.y = PAL_Y(pos);
 
    urect.x = rect.x;
    urect.y = rect.y;
-#ifdef PAL_WIN95
+#if defined(PAL_WIN95) || defined(PAL_UNICODE)
    urect.h = 17;
 #else
    urect.h = 16;
@@ -351,6 +493,19 @@ PAL_DrawText(
       //
       // Draw the character
       //
+#  ifdef PAL_UNICODE
+	  int char_width = PAL_CharWidth(*lpszText);
+
+      if (fShadow)
+      {
+		  PAL_DrawCharOnSurface(*lpszText, gpScreen, PAL_XY(rect.x + 1, rect.y + 1), 0);
+		  PAL_DrawCharOnSurface(*lpszText, gpScreen, PAL_XY(rect.x + 1, rect.y), 0);
+      }
+	  PAL_DrawCharOnSurface(*lpszText, gpScreen, PAL_XY(rect.x, rect.y), bColor);
+      lpszText++;
+	  rect.x += char_width;
+	  urect.w += char_width;
+#  else
       if (*lpszText & 0x80)
       {
          //
@@ -382,6 +537,7 @@ PAL_DrawText(
          rect.x += 8;
          urect.w += 8;
       }
+#  endif
    }
 
    //
@@ -645,7 +801,11 @@ PAL_DialogWaitForKey(
 
 VOID
 PAL_ShowDialogText(
+#ifdef PAL_UNICODE
+   LPCWSTR      lpszText
+#else
    LPCSTR       lpszText
+#endif
 )
 /*++
   Purpose:
@@ -663,7 +823,11 @@ PAL_ShowDialogText(
 --*/
 {
    SDL_Rect        rect;
+#ifdef PAL_UNICODE
+   int             x, y;
+#else
    int             x, y, len = strlen(lpszText);
+#endif
 
    PAL_ClearKeyState();
    g_TextLib.bIcon = 0;
@@ -706,7 +870,12 @@ PAL_ShowDialogText(
       {
          PAL_POS    pos;
          LPBOX      lpBox;
+#     ifdef PAL_UNICODE
+		 int        i, w = wcslen(lpszText), len = 0;
 
+		 for (i = 0; i < w; i++)
+            len += PAL_CharWidth(lpszText[i]) >> 3;
+#     endif
          //
          // Create the window box
          //
@@ -738,12 +907,19 @@ PAL_ShowDialogText(
    }
    else
    {
+#  ifdef PAL_UNICODE
+      int len = wcslen(lpszText);
+#  endif
       if (g_TextLib.nCurrentDialogLine == 0 &&
          g_TextLib.bDialogPosition != kDialogCenter &&
+#  ifdef PAL_UNICODE
+		 (lpszText[len - 1] == 0xff1a ||
+#  else
          (((BYTE)lpszText[len - 1] == 0x47 && (BYTE)lpszText[len - 2] == 0xA1) ||
           ((BYTE)lpszText[len - 1] == 0xBA && (BYTE)lpszText[len - 2] == 0xA3) ||
           ((BYTE)lpszText[len - 1] == 0xC3 && (BYTE)lpszText[len - 2] == 0xA1) ||
-          ((BYTE)lpszText[len - 1] == ':')))
+#  endif
+		  lpszText[len - 1] == ':'))
       {
          //
          // name of character
@@ -755,7 +931,11 @@ PAL_ShowDialogText(
          //
          // normal texts
          //
+#     ifdef PAL_UNICODE
+         WCHAR text[2];
+#     else
          char text[3];
+#     endif
 
          if (!g_TextLib.fPlayingRNG && g_TextLib.nCurrentDialogLine == 0)
          {
@@ -818,7 +998,11 @@ PAL_ShowDialogText(
                //
                // Set the delay time of text-displaying
                //
+#           ifdef PAL_UNICODE
+               g_TextLib.iDelayTime = wcstol(lpszText + 1, NULL, 10) * 10 / 7;
+#           else
                g_TextLib.iDelayTime = atoi(lpszText + 1) * 10 / 7;
+#           endif
                lpszText += 3;
                break;
 
@@ -826,8 +1010,12 @@ PAL_ShowDialogText(
                //
                // Delay for a period and quit
                //
+#           ifdef PAL_UNICODE
+               UTIL_Delay(wcstol(lpszText + 1, NULL, 10) * 80 / 7);
+#           else
                UTIL_Delay(atoi(lpszText + 1) * 80 / 7);
-               g_TextLib.nCurrentDialogLine = 0;
+#           endif
+			   g_TextLib.nCurrentDialogLine = 0;
                g_TextLib.fUserSkip = FALSE;
                return; // don't go further
 
@@ -851,6 +1039,10 @@ PAL_ShowDialogText(
                lpszText++;
 
             default:
+#           ifdef PAL_UNICODE
+               text[0] = *lpszText++;
+			   text[1] = 0;
+#           else
                if (*lpszText & 0x80)
                {
                   text[0] = lpszText[0];
@@ -864,9 +1056,14 @@ PAL_ShowDialogText(
                   text[1] = '\0';
                   lpszText++;
                }
+#           endif
 
                PAL_DrawText(text, PAL_XY(x, y), g_TextLib.bCurrentFontColor, TRUE, TRUE);
+#           ifdef PAL_UNICODE
+			   x += PAL_CharWidth(text[0]);
+#           else
                x += ((text[0] & 0x80) ? 16 : 8);
+#           endif
 
                if (!g_TextLib.fUserSkip)
                {
@@ -1001,3 +1198,186 @@ PAL_DialogIsPlayingRNG(
 {
    return g_TextLib.fPlayingRNG;
 }
+
+#ifdef PAL_UNICODE
+INT
+PAL_MultiByteToWideChar(
+   unsigned char *mbs,
+   int           mbslength,
+   WCHAR         *wcs,
+   int           wcslength
+)
+/*++
+  Purpose:
+
+    Convert multi-byte string into the corresponding unicode string.
+
+  Parameters:
+
+    [IN]  mbs - .
+	[IN]  mbslength - .
+	[IN]  wcs - .
+	[IN]  wcslength - .
+
+  Return value:
+
+    The length
+
+--*/
+{
+	int i = 0, j = 0, state = 0, wlen = 0, null = 0;
+
+	if (mbslength == -1)
+	{
+		mbslength = strlen(mbs);
+		null = 1;
+	}
+
+	if (!wcs)
+	{
+		switch (gpGlobals->iCodePage)
+		{
+		case CP_SHIFTJIS:
+			for (i = 0; i < mbslength && mbs[i]; i++)
+			{
+				if (state == 0)
+				{
+					if (mbs[i] <= 0x80 || mbs[i] >= 0xfd || (mbs[i] >= 0xa0 && mbs[i] <= 0xdf))
+						wlen++;
+					else
+						state = 1;
+				}
+				else
+				{
+					wlen++;
+					state = 0;
+				}
+			}
+			return wlen + null + state;
+		case CP_GBK:
+		case CP_BIG5:
+			for (i = 0; i < mbslength && mbs[i]; i++)
+			{
+				if (state == 0)
+				{
+					if (mbs[i] <= 0x80 || mbs[i] == 0xff)
+						wlen++;
+					else
+						state = 1;
+				}
+				else
+				{
+					wlen++;
+					state = 0;
+				}
+			}
+			return wlen + null + state;
+		default:
+			return -1;
+		}
+	}
+	else
+	{
+		unsigned short invalid_char;
+		switch (gpGlobals->iCodePage)
+		{
+		case CP_SHIFTJIS:
+			invalid_char = 0x30fb;
+			for (i = 0; i < mbslength && wlen < wcslength && mbs[i]; i++)
+			{
+				if (state == 0)
+				{
+					if (mbs[i] <= 0x80)
+						wcs[wlen++] = mbs[i];
+					else if (mbs[i] >= 0xa0 && mbs[i] <= 0xdf)
+						wcs[wlen++] = cptbl_jis_half[mbs[i] - 0xa0];
+					else if (mbs[i] == 0xfd)
+						wcs[wlen++] = 0xf8f1;
+					else if (mbs[i] == 0xfe)
+						wcs[wlen++] = 0xf8f2;
+					else if (mbs[i] == 0xff)
+						wcs[wlen++] = 0xf8f3;
+					else
+						state = 1;
+				}
+				else
+				{
+					if (mbs[i] < 0x40)
+						wcs[wlen++] = 0x30fb;
+					else if (mbs[i - 1] < 0xa0)
+						wcs[wlen++] = cptbl_jis[mbs[i - 1] - 0x81][mbs[i] - 0x40];
+					else
+						wcs[wlen++] = cptbl_jis[mbs[i - 1] - 0xc1][mbs[i] - 0x40];
+					state = 0;
+				}
+			}
+			break;
+		case CP_GBK:
+			invalid_char = 0x3f;
+			for (i = 0; i < mbslength && wlen < wcslength && mbs[i]; i++)
+			{
+				if (state == 0)
+				{
+					if (mbs[i] < 0x80)
+						wcs[wlen++] = mbs[i];
+					else if (mbs[i] == 0x80)
+						wcs[wlen++] = 0x20ac;
+					else if (mbs[i] == 0xff)
+						wcs[wlen++] = 0xf8f5;
+					else
+						state = 1;
+				}
+				else
+				{
+					if (mbs[i] < 0x40)
+						wcs[wlen++] = invalid_char;
+					else
+						wcs[wlen++] = cptbl_gbk[mbs[i - 1] - 0x81][mbs[i] - 0x40];
+					state = 0;
+				}
+			}
+			break;
+		case CP_BIG5:
+			invalid_char = 0x3f;
+			for (i = 0; i < mbslength && wlen < wcslength && mbs[i]; i++)
+			{
+				if (state == 0)
+				{
+					if (mbs[i] <= 0x80)
+						wcs[wlen++] = mbs[i];
+					else if (mbs[i] == 0xff)
+						wcs[wlen++] = 0xf8f8;
+					else
+						state = 1;
+				}
+				else
+				{
+					if (mbs[i] < 0x40 || (mbs[i] >= 0x7f && mbs[i] <= 0xa0))
+						wcs[wlen++] = invalid_char;
+					else if (mbs[i] <= 0x7e)
+						wcs[wlen++] = cptbl_big5[mbs[i - 1] - 0x81][mbs[i] - 0x40];
+					else
+						wcs[wlen++] = cptbl_big5[mbs[i - 1] - 0x81][mbs[i] - 0x60];
+					state = 0;
+				}
+			}
+			break;
+		default:
+			return -1;
+		}
+		if (state == 1 && wlen < wcslength)
+		{
+			wcs[wlen++] = invalid_char;
+		}
+		if (null)
+		{
+			if (wlen < wcslength)
+				wcs[wlen++] = 0;
+			else
+				wcs[wlen - 1] = 0;
+		}
+		return wlen;
+
+	}
+}
+#endif

+ 29 - 1
text.h

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #ifndef _TEXT_H
 #define _TEXT_H
@@ -42,19 +44,31 @@ PAL_FreeText(
    VOID
 );
 
+#ifdef PAL_UNICODE
+LPCWSTR
+#else
 LPCSTR
+#endif
 PAL_GetWord(
    WORD       wNumWord
 );
 
+#ifdef PAL_UNICODE
+LPCWSTR
+#else
 LPCSTR
+#endif
 PAL_GetMsg(
    WORD       wNumMsg
 );
 
 VOID
 PAL_DrawText(
+#ifdef PAL_UNICODE
+   LPCWSTR    lpszText,
+#else
    LPCSTR     lpszText,
+#endif
    PAL_POS    pos,
    BYTE       bColor,
    BOOL       fShadow,
@@ -76,7 +90,11 @@ PAL_StartDialog(
 
 VOID
 PAL_ShowDialogText(
-   LPCSTR       szText
+#ifdef PAL_UNICODE
+   LPCWSTR    lpszText
+#else
+   LPCSTR     lpszText
+#endif
 );
 
 VOID
@@ -99,4 +117,14 @@ PAL_DialogIsPlayingRNG(
    VOID
 );
 
+#ifdef PAL_UNICODE
+INT
+PAL_MultiByteToWideChar(
+   unsigned char *mbs,
+   int           mbslength,
+   WCHAR         *wcs,
+   int           wcslength
+);
+#endif
+
 #endif

+ 17 - 0
ui.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 
@@ -720,6 +722,9 @@ PAL_LoadObjectDesc(
    //
    while (fgets(buf, 512, fp) != NULL)
    {
+#  ifdef PAL_UNICODE
+      int wlen;
+#  endif
       p = strchr(buf, '=');
       if (p == NULL)
       {
@@ -728,12 +733,20 @@ PAL_LoadObjectDesc(
 
       *p = '\0';
       p++;
+#  ifdef PAL_UNICODE
+	  wlen = PAL_MultiByteToWideChar(p, -1, NULL, 0);
+#  endif
 
       pNew = UTIL_calloc(1, sizeof(OBJECTDESC));
 
       sscanf(buf, "%x", &i);
       pNew->wObjectID = i;
+#  ifdef PAL_UNICODE
+	  pNew->lpDesc = (LPWSTR)malloc(wlen * sizeof(WCHAR));
+	  PAL_MultiByteToWideChar(p, -1, pNew->lpDesc, wlen);
+#  else
       pNew->lpDesc = strdup(p);
+#  endif
 
       pNew->next = lpDesc;
       lpDesc = pNew;
@@ -773,7 +786,11 @@ PAL_FreeObjectDesc(
    }
 }
 
+#ifdef PAL_UNICODE
+LPCWSTR
+#else
 LPCSTR
+#endif
 PAL_GetObjectDesc(
    LPOBJECTDESC   lpObjectDesc,
    WORD           wObjectID

+ 244 - 234
ui.h

@@ -1,237 +1,247 @@
-/* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */
-//
-// Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
-// All rights reserved.
-//
-// This file is part of SDLPAL.
-//
-// SDLPAL is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef UI_H
-#define UI_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "common.h"
-
-#define CHUNKNUM_SPRITEUI                  9
-
-#define MENUITEM_COLOR                     0x4F
-#define MENUITEM_COLOR_INACTIVE            0x1C
-#define MENUITEM_COLOR_CONFIRMED           0x2C
-#define MENUITEM_COLOR_SELECTED_INACTIVE   0x1F
-#define MENUITEM_COLOR_SELECTED_FIRST      0xF9
-#define MENUITEM_COLOR_SELECTED_TOTALNUM   6
-
-#define MENUITEM_COLOR_SELECTED                                    \
-   (MENUITEM_COLOR_SELECTED_FIRST +                                \
-      SDL_GetTicks() / (600 / MENUITEM_COLOR_SELECTED_TOTALNUM)    \
-      % MENUITEM_COLOR_SELECTED_TOTALNUM)
-
-#define MENUITEM_COLOR_EQUIPPEDITEM        0xC8
-
-#define DESCTEXT_COLOR                     0x2E
-
-#ifdef PAL_WIN95
+/* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */
+//
+// Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
+// All rights reserved.
+//
+// This file is part of SDLPAL.
+//
+// SDLPAL is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
+
+#ifndef UI_H
+#define UI_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "common.h"
+
+#define CHUNKNUM_SPRITEUI                  9
+
+#define MENUITEM_COLOR                     0x4F
+#define MENUITEM_COLOR_INACTIVE            0x1C
+#define MENUITEM_COLOR_CONFIRMED           0x2C
+#define MENUITEM_COLOR_SELECTED_INACTIVE   0x1F
+#define MENUITEM_COLOR_SELECTED_FIRST      0xF9
+#define MENUITEM_COLOR_SELECTED_TOTALNUM   6
+
+#define MENUITEM_COLOR_SELECTED                                    \
+   (MENUITEM_COLOR_SELECTED_FIRST +                                \
+      SDL_GetTicks() / (600 / MENUITEM_COLOR_SELECTED_TOTALNUM)    \
+      % MENUITEM_COLOR_SELECTED_TOTALNUM)
+
+#define MENUITEM_COLOR_EQUIPPEDITEM        0xC8
+
+#define DESCTEXT_COLOR                     0x2E
+
+#ifdef PAL_WIN95
 #define MAINMENU_BACKGROUND_FBPNUM         2
 #else
 #define MAINMENU_BACKGROUND_FBPNUM         60
-#endif
-#define RIX_NUM_OPENINGMENU                4
-#define MAINMENU_LABEL_NEWGAME             7
-#define MAINMENU_LABEL_LOADGAME            8
-
-#define LOADMENU_LABEL_SLOT_FIRST          43
-
-#define CONFIRMMENU_LABEL_NO               19
-#define CONFIRMMENU_LABEL_YES              20
-
-#define CASH_LABEL                         21
-
-#define SWITCHMENU_LABEL_DISABLE           17
-#define SWITCHMENU_LABEL_ENABLE            18
-
-#define GAMEMENU_LABEL_STATUS              3
-#define GAMEMENU_LABEL_MAGIC               4
-#define GAMEMENU_LABEL_INVENTORY           5
-#define GAMEMENU_LABEL_SYSTEM              6
-
-#define SYSMENU_LABEL_SAVE                 11
-#define SYSMENU_LABEL_LOAD                 12
-#define SYSMENU_LABEL_MUSIC                13
-#define SYSMENU_LABEL_SOUND                14
-#define SYSMENU_LABEL_QUIT                 15
-#define SYSMENU_LABEL_BATTLEMODE           (PAL_ADDITIONAL_WORD_FIRST)
-
-#define BATTLESPEEDMENU_LABEL_1            (PAL_ADDITIONAL_WORD_FIRST + 1)
-#define BATTLESPEEDMENU_LABEL_2            (PAL_ADDITIONAL_WORD_FIRST + 2)
-#define BATTLESPEEDMENU_LABEL_3            (PAL_ADDITIONAL_WORD_FIRST + 3)
-#define BATTLESPEEDMENU_LABEL_4            (PAL_ADDITIONAL_WORD_FIRST + 4)
-#define BATTLESPEEDMENU_LABEL_5            (PAL_ADDITIONAL_WORD_FIRST + 5)
-
-#define INVMENU_LABEL_USE                  23
-#define INVMENU_LABEL_EQUIP                22
-
-#define STATUS_BACKGROUND_FBPNUM           0
-#define STATUS_LABEL_EXP                   2
-#define STATUS_LABEL_LEVEL                 48
-#define STATUS_LABEL_HP                    49
-#define STATUS_LABEL_MP                    50
-#define STATUS_LABEL_ATTACKPOWER           51
-#define STATUS_LABEL_MAGICPOWER            52
-#define STATUS_LABEL_RESISTANCE            53
-#define STATUS_LABEL_DEXTERITY             54
-#define STATUS_LABEL_FLEERATE              55
-#define STATUS_COLOR_EQUIPMENT             0xBE
-
-#define BUYMENU_LABEL_CURRENT              35
-#define SELLMENU_LABEL_PRICE               25
-
-#define SPRITENUM_SLASH                    39
-#define SPRITENUM_ITEMBOX                  70
-#define SPRITENUM_CURSOR_YELLOW            68
-#define SPRITENUM_CURSOR                   69
-#define SPRITENUM_PLAYERINFOBOX            18
-#define SPRITENUM_PLAYERFACE_FIRST         48
-
-#define EQUIPMENU_BACKGROUND_FBPNUM        1
-
-#define ITEMUSEMENU_COLOR_STATLABEL        0xBB
-
-#define BATTLEWIN_GETEXP_LABEL             30
-#define BATTLEWIN_BEATENEMY_LABEL          9
-#define BATTLEWIN_DOLLAR_LABEL             10
-#define BATTLEWIN_LEVELUP_LABEL            32
-#define BATTLEWIN_ADDMAGIC_LABEL           33
-#define BATTLEWIN_LEVELUP_LABEL_COLOR      0x39
-#define SPRITENUM_ARROW                    47
-
-#define BATTLE_LABEL_ESCAPEFAIL            31
-
-typedef struct tagBOX
-{
-   PAL_POS        pos;
-   WORD           wWidth, wHeight;
-   SDL_Surface   *lpSavedArea;
-} BOX, *LPBOX;
-
-typedef struct tagMENUITEM
-{
-   WORD          wValue;
-   WORD          wNumWord;
-   BOOL          fEnabled;
-   PAL_POS       pos;
-} MENUITEM, *LPMENUITEM;
-
-typedef struct tagOBJECTDESC
-{
-   WORD                        wObjectID;
-   LPSTR                       lpDesc;
-   struct tagOBJECTDESC       *next;
-} OBJECTDESC, *LPOBJECTDESC;
-
-typedef VOID (*LPITEMCHANGED_CALLBACK)(WORD);
-
-#define MENUITEM_VALUE_CANCELLED      0xFFFF
-
-typedef enum tagNUMCOLOR
-{
-   kNumColorYellow,
-   kNumColorBlue,
-   kNumColorCyan
-} NUMCOLOR;
-
-typedef enum tagNUMALIGN
-{
-   kNumAlignLeft,
-   kNumAlignMid,
-   kNumAlignRight
-} NUMALIGN;
-
-INT
-PAL_InitUI(
-   VOID
-);
-
-VOID
-PAL_FreeUI(
-   VOID
-);
-
-LPBOX
-PAL_CreateBox(
-   PAL_POS        pos,
-   INT            nRows,
-   INT            nColumns,
-   INT            iStyle,
-   BOOL           fSaveScreen
-);
-
-LPBOX
-PAL_CreateSingleLineBox(
-   PAL_POS        pos,
-   INT            nLen,
-   BOOL           fSaveScreen
-);
-
-VOID
-PAL_DeleteBox(
-   LPBOX          lpBox
-);
-
-WORD
-PAL_ReadMenu(
-   LPITEMCHANGED_CALLBACK    lpfnMenuItemChanged,
-   LPMENUITEM                rgMenuItem,
-   INT                       nMenuItem,
-   WORD                      wDefaultItem,
-   BYTE                      bLabelColor
-);
-
-VOID
-PAL_DrawNumber(
-   UINT            iNum,
-   UINT            nLength,
-   PAL_POS         pos,
-   NUMCOLOR        color,
-   NUMALIGN        align
-);
-
-LPOBJECTDESC
-PAL_LoadObjectDesc(
-   LPCSTR          lpszFileName
-);
-
-VOID
-PAL_FreeObjectDesc(
-   LPOBJECTDESC    lpObjectDesc
-);
-
-LPCSTR
-PAL_GetObjectDesc(
-   LPOBJECTDESC   lpObjectDesc,
-   WORD           wObjectID
-);
-
-extern LPSPRITE gpSpriteUI;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#endif
+#define RIX_NUM_OPENINGMENU                4
+#define MAINMENU_LABEL_NEWGAME             7
+#define MAINMENU_LABEL_LOADGAME            8
+
+#define LOADMENU_LABEL_SLOT_FIRST          43
+
+#define CONFIRMMENU_LABEL_NO               19
+#define CONFIRMMENU_LABEL_YES              20
+
+#define CASH_LABEL                         21
+
+#define SWITCHMENU_LABEL_DISABLE           17
+#define SWITCHMENU_LABEL_ENABLE            18
+
+#define GAMEMENU_LABEL_STATUS              3
+#define GAMEMENU_LABEL_MAGIC               4
+#define GAMEMENU_LABEL_INVENTORY           5
+#define GAMEMENU_LABEL_SYSTEM              6
+
+#define SYSMENU_LABEL_SAVE                 11
+#define SYSMENU_LABEL_LOAD                 12
+#define SYSMENU_LABEL_MUSIC                13
+#define SYSMENU_LABEL_SOUND                14
+#define SYSMENU_LABEL_QUIT                 15
+#define SYSMENU_LABEL_BATTLEMODE           (PAL_ADDITIONAL_WORD_FIRST)
+
+#define BATTLESPEEDMENU_LABEL_1            (PAL_ADDITIONAL_WORD_FIRST + 1)
+#define BATTLESPEEDMENU_LABEL_2            (PAL_ADDITIONAL_WORD_FIRST + 2)
+#define BATTLESPEEDMENU_LABEL_3            (PAL_ADDITIONAL_WORD_FIRST + 3)
+#define BATTLESPEEDMENU_LABEL_4            (PAL_ADDITIONAL_WORD_FIRST + 4)
+#define BATTLESPEEDMENU_LABEL_5            (PAL_ADDITIONAL_WORD_FIRST + 5)
+
+#define INVMENU_LABEL_USE                  23
+#define INVMENU_LABEL_EQUIP                22
+
+#define STATUS_BACKGROUND_FBPNUM           0
+#define STATUS_LABEL_EXP                   2
+#define STATUS_LABEL_LEVEL                 48
+#define STATUS_LABEL_HP                    49
+#define STATUS_LABEL_MP                    50
+#define STATUS_LABEL_ATTACKPOWER           51
+#define STATUS_LABEL_MAGICPOWER            52
+#define STATUS_LABEL_RESISTANCE            53
+#define STATUS_LABEL_DEXTERITY             54
+#define STATUS_LABEL_FLEERATE              55
+#define STATUS_COLOR_EQUIPMENT             0xBE
+
+#define BUYMENU_LABEL_CURRENT              35
+#define SELLMENU_LABEL_PRICE               25
+
+#define SPRITENUM_SLASH                    39
+#define SPRITENUM_ITEMBOX                  70
+#define SPRITENUM_CURSOR_YELLOW            68
+#define SPRITENUM_CURSOR                   69
+#define SPRITENUM_PLAYERINFOBOX            18
+#define SPRITENUM_PLAYERFACE_FIRST         48
+
+#define EQUIPMENU_BACKGROUND_FBPNUM        1
+
+#define ITEMUSEMENU_COLOR_STATLABEL        0xBB
+
+#define BATTLEWIN_GETEXP_LABEL             30
+#define BATTLEWIN_BEATENEMY_LABEL          9
+#define BATTLEWIN_DOLLAR_LABEL             10
+#define BATTLEWIN_LEVELUP_LABEL            32
+#define BATTLEWIN_ADDMAGIC_LABEL           33
+#define BATTLEWIN_LEVELUP_LABEL_COLOR      0x39
+#define SPRITENUM_ARROW                    47
+
+#define BATTLE_LABEL_ESCAPEFAIL            31
+
+typedef struct tagBOX
+{
+   PAL_POS        pos;
+   WORD           wWidth, wHeight;
+   SDL_Surface   *lpSavedArea;
+} BOX, *LPBOX;
+
+typedef struct tagMENUITEM
+{
+   WORD          wValue;
+   WORD          wNumWord;
+   BOOL          fEnabled;
+   PAL_POS       pos;
+} MENUITEM, *LPMENUITEM;
+
+typedef struct tagOBJECTDESC
+{
+   WORD                        wObjectID;
+#ifdef PAL_UNICODE
+   LPWSTR                      lpDesc;
+#else
+   LPSTR                       lpDesc;
+#endif
+   struct tagOBJECTDESC       *next;
+} OBJECTDESC, *LPOBJECTDESC;
+
+typedef VOID (*LPITEMCHANGED_CALLBACK)(WORD);
+
+#define MENUITEM_VALUE_CANCELLED      0xFFFF
+
+typedef enum tagNUMCOLOR
+{
+   kNumColorYellow,
+   kNumColorBlue,
+   kNumColorCyan
+} NUMCOLOR;
+
+typedef enum tagNUMALIGN
+{
+   kNumAlignLeft,
+   kNumAlignMid,
+   kNumAlignRight
+} NUMALIGN;
+
+INT
+PAL_InitUI(
+   VOID
+);
+
+VOID
+PAL_FreeUI(
+   VOID
+);
+
+LPBOX
+PAL_CreateBox(
+   PAL_POS        pos,
+   INT            nRows,
+   INT            nColumns,
+   INT            iStyle,
+   BOOL           fSaveScreen
+);
+
+LPBOX
+PAL_CreateSingleLineBox(
+   PAL_POS        pos,
+   INT            nLen,
+   BOOL           fSaveScreen
+);
+
+VOID
+PAL_DeleteBox(
+   LPBOX          lpBox
+);
+
+WORD
+PAL_ReadMenu(
+   LPITEMCHANGED_CALLBACK    lpfnMenuItemChanged,
+   LPMENUITEM                rgMenuItem,
+   INT                       nMenuItem,
+   WORD                      wDefaultItem,
+   BYTE                      bLabelColor
+);
+
+VOID
+PAL_DrawNumber(
+   UINT            iNum,
+   UINT            nLength,
+   PAL_POS         pos,
+   NUMCOLOR        color,
+   NUMALIGN        align
+);
+
+LPOBJECTDESC
+PAL_LoadObjectDesc(
+   LPCSTR          lpszFileName
+);
+
+VOID
+PAL_FreeObjectDesc(
+   LPOBJECTDESC    lpObjectDesc
+);
+
+#ifdef PAL_UNICODE
+LPCWSTR
+#else
+LPCSTR
+#endif
+PAL_GetObjectDesc(
+   LPOBJECTDESC   lpObjectDesc,
+   WORD           wObjectID
+);
+
+extern LPSPRITE gpSpriteUI;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 25 - 0
uibattle.c

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #include "main.h"
 
@@ -544,7 +546,11 @@ PAL_BattleUIMiscItemSubMenuUpdate(
 
 VOID
 PAL_BattleUIShowText(
+#ifdef PAL_UNICODE
+   LPCWSTR       lpszText,
+#else
    LPCSTR        lpszText,
+#endif
    WORD          wDuration
 )
 /*++
@@ -566,12 +572,20 @@ PAL_BattleUIShowText(
 {
    if (SDL_GetTicks() < g_Battle.UI.dwMsgShowTime)
    {
+#  ifdef PAL_UNICODE
+      wcscpy(g_Battle.UI.szNextMsg, lpszText);
+#  else
       strcpy(g_Battle.UI.szNextMsg, lpszText);
+#  endif
       g_Battle.UI.wNextMsgDuration = wDuration;
    }
    else
    {
+#  ifdef PAL_UNICODE
+      wcscpy(g_Battle.UI.szMsg, lpszText);
+#  else
       strcpy(g_Battle.UI.szMsg, lpszText);
+#  endif
       g_Battle.UI.dwMsgShowTime = SDL_GetTicks() + wDuration;
    }
 }
@@ -1691,7 +1705,14 @@ end:
       // The text should be shown in a small window at the center of the screen
       //
       PAL_POS    pos;
+#  ifdef PAL_UNICODE
+	  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;
+#  else
       int        len = strlen(g_Battle.UI.szMsg);
+#  endif
 
       //
       // Create the window box
@@ -1707,7 +1728,11 @@ end:
    }
    else if (g_Battle.UI.szNextMsg[0] != '\0')
    {
+#  ifdef PAL_UNICODE
+      wcscpy(g_Battle.UI.szMsg, g_Battle.UI.szNextMsg);
+#  else
       strcpy(g_Battle.UI.szMsg, g_Battle.UI.szNextMsg);
+#  endif
       g_Battle.UI.dwMsgShowTime = SDL_GetTicks() + g_Battle.UI.wNextMsgDuration;
       g_Battle.UI.szNextMsg[0] = '\0';
    }

+ 11 - 0
uibattle.h

@@ -18,6 +18,8 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
+// Modified by Lou Yihua <louyihua@21cn.com> with Unicode support, 2015
+//
 
 #ifndef UIBATTLE_H
 #define UIBATTLE_H
@@ -97,8 +99,13 @@ typedef struct tagBATTLEUI
    BATTLEUISTATE    state;
    BATTLEMENUSTATE  MenuState;
 
+#ifdef PAL_UNICODE
+   WCHAR            szMsg[256];           // message to be shown on the screen
+   WCHAR            szNextMsg[256];       // next message to be shown on the screen
+#else
    CHAR             szMsg[256];           // message to be shown on the screen
    CHAR             szNextMsg[256];       // next message to be shown on the screen
+#endif
    DWORD            dwMsgShowTime;        // the end time of showing the message
    WORD             wNextMsgDuration;     // duration of the next message
 
@@ -126,7 +133,11 @@ PAL_PlayerInfoBox(
 
 VOID
 PAL_BattleUIShowText(
+#ifdef PAL_UNICODE
+   LPCWSTR       lpszText,
+#else
    LPCSTR        lpszText,
+#endif
    WORD          wDuration
 );
 

+ 18 - 3
video.c

@@ -198,12 +198,12 @@ VIDEO_Init(
       // Totally ugly hack to satisfy M$'s silly requirements.
       // No need to understand this crap.
       //
-#ifdef PAL_WIN95
+#if defined(PAL_WIN95) && !defined(PAL_UNICODE)
       extern BOOL fIsBig5;
 #endif
       SDL_Color palette[256] = { 0 };
       SDL_Surface *p;
-#ifdef PAL_WIN95
+#if defined(PAL_WIN95) && !defined(PAL_UNICODE)
       fIsBig5 = TRUE;
 #endif
       palette[0].r = palette[0].g = palette[0].b = palette[0].a = 0;
@@ -212,11 +212,26 @@ VIDEO_Init(
       VIDEO_SetPalette(palette);
       p = gpScreen;
       gpScreen = gpScreenBak;
+#  ifdef PAL_UNICODE
+	  switch(gpGlobals->iCodePage)
+	  {
+	  case CP_BIG5:
+		  PAL_DrawText(L"\x518D\x6B21\x6309 Back \x7D50\x675F", PAL_XY(30, 30), 1, FALSE, FALSE);
+		  break;
+	  case CP_GBK:
+		  PAL_DrawText(L"\x518D\x6B21\x6309 Back \x7ED3\x675F", PAL_XY(30, 30), 1, FALSE, FALSE);
+		  break;
+	  case CP_SHIFTJIS:
+		  PAL_DrawText(L"Press Back again to end", PAL_XY(30, 30), 1, FALSE, FALSE);	// TODO: Japanese string
+		  break;
+	  }
+#  else
       PAL_DrawText("\xA6\x41\xA6\xB8\xAB\xF6 Back \xB5\xB2\xA7\xF4", PAL_XY(30, 30), 1, FALSE, FALSE);
+#  endif
       gpScreen = p;
       gpBackKeyMessage = SDL_CreateTextureFromSurface(gpRenderer, gpScreenBak);
       SDL_FillRect(gpScreenBak, NULL, 0);
-#ifdef PAL_WIN95
+#if defined(PAL_WIN95) && !defined(PAL_UNICODE)
       fIsBig5 = FALSE;
 #endif
    }