From 897bb4c463ee35b5d8c77cf4d6ae9fe6071a8441 Mon Sep 17 00:00:00 2001 From: TakaRikka <38417346+TakaRikka@users.noreply.github.com> Date: Sat, 29 Nov 2025 22:59:04 -0800 Subject: [PATCH] shieldD revolution OS mostly done (#2892) * begin revolution sdk setup * wii rvl test * revo OS mostly done for shieldD --- config/ShieldD/splits.txt | 2 +- configure.py | 100 + include/revolution/base/PPCArch.h | 3 +- include/revolution/dvd.h | 28 + include/revolution/esp.h | 138 + include/revolution/hw_regs.h | 14 +- include/revolution/nand.h | 167 + include/revolution/os.h | 42 +- include/revolution/os/OSAlarm.h | 4 +- include/revolution/os/OSInterrupt.h | 125 +- include/revolution/os/OSIpc.h | 19 + include/revolution/os/OSMemory.h | 6 +- include/revolution/os/OSModule.h | 8 +- include/revolution/os/OSNandbootInfo.h | 40 + include/revolution/os/OSPlayRecord.h | 19 + include/revolution/os/OSPlayTime.h | 25 + include/revolution/os/OSReset.h | 26 +- include/revolution/os/OSResetSW.h | 1 + include/revolution/os/OSStateFlags.h | 26 + include/revolution/private/iosresclt.h | 9 + include/revolution/private/iosrestypes.h | 89 + include/revolution/private/iostypes.h | 43 + include/revolution/sc.h | 134 +- src/revolution/dvd/__dvd.h | 56 + src/revolution/os/OS.c | 966 ++++ src/revolution/os/OSAddress.c | 34 + src/revolution/os/OSAlarm.c | 324 ++ src/revolution/os/OSAlloc.c | 608 +++ src/revolution/os/OSArena.c | 87 + src/revolution/os/OSAudioSystem.c | 192 + src/revolution/os/OSCache.c | 639 +++ src/revolution/os/OSContext.c | 653 +++ src/revolution/os/OSError.c | 215 + src/revolution/os/OSExec.c | 795 +++ src/revolution/os/OSFatal.c | 256 + src/revolution/os/OSFont.c | 748 +++ src/revolution/os/OSInterrupt.c | 519 ++ src/revolution/os/OSIpc.c | 18 + src/revolution/os/OSLaunch.c | 91 + src/revolution/os/OSLink.c | 537 ++ src/revolution/os/OSMemory.c | 680 +++ src/revolution/os/OSMessage.c | 70 + src/revolution/os/OSMutex.c | 256 + src/revolution/os/OSNandbootInfo.c | 67 + src/revolution/os/OSNet.c | 300 + src/revolution/os/OSPlayRecord.c | 259 + src/revolution/os/OSPlayTime.c | 350 ++ src/revolution/os/OSReboot.c | 38 + src/revolution/os/OSReset.c | 339 ++ src/revolution/os/OSRtc.c | 564 ++ src/revolution/os/OSStateFlags.c | 74 + src/revolution/os/OSStateTM.c | 307 ++ src/revolution/os/OSStopwatch.c | 55 + src/revolution/os/OSSync.c | 33 + src/revolution/os/OSThread.c | 877 +++ src/revolution/os/OSTime.c | 201 + src/revolution/os/OSUtf.c | 6374 ++++++++++++++++++++++ src/revolution/os/__os.h | 150 + src/revolution/os/__ppc_eabi_init.cpp | 47 + 59 files changed, 18747 insertions(+), 100 deletions(-) create mode 100644 include/revolution/esp.h create mode 100644 include/revolution/nand.h create mode 100644 include/revolution/os/OSIpc.h create mode 100644 include/revolution/os/OSNandbootInfo.h create mode 100644 include/revolution/os/OSPlayRecord.h create mode 100644 include/revolution/os/OSPlayTime.h create mode 100644 include/revolution/os/OSStateFlags.h create mode 100644 include/revolution/private/iosresclt.h create mode 100644 include/revolution/private/iosrestypes.h create mode 100644 include/revolution/private/iostypes.h create mode 100644 src/revolution/dvd/__dvd.h create mode 100644 src/revolution/os/OS.c create mode 100644 src/revolution/os/OSAddress.c create mode 100644 src/revolution/os/OSAlarm.c create mode 100644 src/revolution/os/OSAlloc.c create mode 100644 src/revolution/os/OSArena.c create mode 100644 src/revolution/os/OSAudioSystem.c create mode 100644 src/revolution/os/OSCache.c create mode 100644 src/revolution/os/OSContext.c create mode 100644 src/revolution/os/OSError.c create mode 100644 src/revolution/os/OSExec.c create mode 100644 src/revolution/os/OSFatal.c create mode 100644 src/revolution/os/OSFont.c create mode 100644 src/revolution/os/OSInterrupt.c create mode 100644 src/revolution/os/OSIpc.c create mode 100644 src/revolution/os/OSLaunch.c create mode 100644 src/revolution/os/OSLink.c create mode 100644 src/revolution/os/OSMemory.c create mode 100644 src/revolution/os/OSMessage.c create mode 100644 src/revolution/os/OSMutex.c create mode 100644 src/revolution/os/OSNandbootInfo.c create mode 100644 src/revolution/os/OSNet.c create mode 100644 src/revolution/os/OSPlayRecord.c create mode 100644 src/revolution/os/OSPlayTime.c create mode 100644 src/revolution/os/OSReboot.c create mode 100644 src/revolution/os/OSReset.c create mode 100644 src/revolution/os/OSRtc.c create mode 100644 src/revolution/os/OSStateFlags.c create mode 100644 src/revolution/os/OSStateTM.c create mode 100644 src/revolution/os/OSStopwatch.c create mode 100644 src/revolution/os/OSSync.c create mode 100644 src/revolution/os/OSThread.c create mode 100644 src/revolution/os/OSTime.c create mode 100644 src/revolution/os/OSUtf.c create mode 100644 src/revolution/os/__os.h create mode 100644 src/revolution/os/__ppc_eabi_init.cpp diff --git a/config/ShieldD/splits.txt b/config/ShieldD/splits.txt index 9589b57f24..e2980dc623 100644 --- a/config/ShieldD/splits.txt +++ b/config/ShieldD/splits.txt @@ -4108,7 +4108,7 @@ revolution/os/OSPlayTime.c: revolution/os/OSLaunch.c: .text start:0x805C95C0 end:0x805C9810 -revolution/os/__ppc_eabi_init.c: +revolution/os/__ppc_eabi_init.cpp: .text start:0x805C9810 end:0x805C9920 revolution/exi/EXIBios.c: diff --git a/configure.py b/configure.py index c70f7d28f9..0200b527bf 100755 --- a/configure.py +++ b/configure.py @@ -358,6 +358,50 @@ cflags_dolphin = [ "-DSDK_REVISION=2", ] +# Revolution library flags +cflags_revolution_base = [ + "-nodefaults", + "-proc gekko", + "-align powerpc", + "-enum int", + "-fp hardware", + "-Cpp_exceptions off", + '-pragma "cats off"', + '-pragma "warn_notinlined off"', + "-maxerrors 1", + "-nosyspath", + #"-char unsigned", + "-sym on", + "-inline auto", + "-ipa file", + "-i include", + f"-i build/{config.version}/include", + "-ir src/revolution", + "-i src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include", + "-i src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common_Embedded/Math/Include", + "-i src/PowerPC_EABI_Support/MSL/MSL_C/PPC_EABI/Include", + "-i src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include", + "-i src/PowerPC_EABI_Support/Runtime/Inc", + "-i src/PowerPC_EABI_Support/MetroTRK", + "-i include/revolution", + f"-DVERSION={version_num}", + "-D__GEKKO__", + "-D__REVOLUTION_SDK__", +] + +cflags_revolution_retail = [ + *cflags_revolution_base, + "-O4,p", + "-DSDK_SEP2006", +] + +cflags_revolution_debug = [ + *cflags_revolution_base, + "-opt off", + "-DDEBUG=1", + "-DSDK_AUG2010", +] + # Framework flags cflags_framework = [ *cflags_base, @@ -426,6 +470,23 @@ def DolphinLib(lib_name: str, objects: List[Object]) -> Dict[str, Any]: "objects": objects, } +def RevolutionLib(lib_name: str, objects: List[Object]) -> Dict[str, Any]: + if config.version == "ShieldD": + return { + "lib": lib_name, + "mw_version": "Wii/1.0", + "cflags": cflags_revolution_debug, + "progress_category": "sdk", + "objects": objects, + } + else: + return { + "lib": lib_name, + "mw_version": "GC/3.0a3", + "cflags": cflags_revolution_retail, + "progress_category": "sdk", + "objects": objects, + } # Helper function for REL script objects def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: @@ -1391,6 +1452,45 @@ config.libs = [ Object(MatchingFor(ALL_GCN), "dolphin/gd/GDGeometry.c"), ], ), + RevolutionLib( + "os", + [ + Object(MatchingFor("ShieldD"), "revolution/os/OS.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSAddress.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSAlarm.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSAlloc.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSArena.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSAudioSystem.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSCache.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSContext.c"), + Object(NonMatching, "revolution/os/OSError.c"), + Object(NonMatching, "revolution/os/OSExec.c"), + Object(NonMatching, "revolution/os/OSFatal.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSFont.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSInterrupt.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSLink.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSMessage.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSMemory.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSMutex.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSReboot.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSReset.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSRtc.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSStopwatch.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSSync.c"), + Object(NonMatching, "revolution/os/OSThread.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSTime.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSUtf.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSIpc.c"), + Object(NonMatching, "revolution/os/OSStateTM.c"), + Object(NonMatching, "revolution/os/OSPlayRecord.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSStateFlags.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSNet.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSNandbootInfo.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSPlayTime.c"), + Object(MatchingFor("ShieldD"), "revolution/os/OSLaunch.c"), + Object(MatchingFor("ShieldD"), "revolution/os/__ppc_eabi_init.cpp"), + ], + ), { "lib": "Runtime.PPCEABI.H", "mw_version": MWVersion(config.version), diff --git a/include/revolution/base/PPCArch.h b/include/revolution/base/PPCArch.h index 65afa27995..cd25faae2d 100644 --- a/include/revolution/base/PPCArch.h +++ b/include/revolution/base/PPCArch.h @@ -1,7 +1,7 @@ #ifndef _REVOLUTION_PPCARCH #define _REVOLUTION_PPCARCH -#include "dolphin/types.h" +#include "revolution/types.h" #ifdef __cplusplus extern "C" { @@ -508,6 +508,7 @@ void PPCMtpmc1(u32 newPmc1); void PPCMtpmc2(u32 newPmc1); void PPCMtpmc3(u32 newPmc1); void PPCMtpmc4(u32 newPmc1); +void PPCMthid4(u32); void PPCMtmmcr0(u32 newMmcr0); void PPCMtmmcr1(u32 newMmcr0); void PPCMtdmaU(u32 newdmau); diff --git a/include/revolution/dvd.h b/include/revolution/dvd.h index 67e8bd21be..3ab240ec37 100644 --- a/include/revolution/dvd.h +++ b/include/revolution/dvd.h @@ -2,6 +2,7 @@ #define _REVOLUTION_DVD_H_ #include +#include #ifdef __cplusplus extern "C" { @@ -136,6 +137,26 @@ typedef struct DVDDriveInfo { /* 0x08 */ u8 padding[24]; } DVDDriveInfo; +typedef struct DVDGamePartition { + ESTicket ticket; + u32 tmdSize; + ESTitleMeta* tmd; + u32 certBlobSize; + void* certBlob; + u8* h3Hashes; + u8* encryptedArea; +} DVDGamePartition; + +typedef struct DVDPartitionInfo { + DVDGamePartition* gamePartition; + u32 type; +} DVDPartitionInfo; + +typedef struct DVDGameTOC { + u32 numGamePartitions; + DVDPartitionInfo* partitionInfos; +} DVDGameTOC; + // DVD void DVDInit(void); int DVDReadAbsAsyncPrio(DVDCommandBlock* block, void* addr, s32 length, s32 offset, DVDCBCallback callback, s32 prio); @@ -229,6 +250,13 @@ u32 DVDLowGetCoverStatus(void); // DVD QUEUE void DVDDumpWaitingQueue(void); + +// unsorted revo +BOOL DVDLowUnencryptedRead(void*, u32, u32, DVDLowCallback); +BOOL DVDLowClosePartition(DVDLowCallback); +BOOL DVDLowOpenPartitionWithTmdAndTicketView(const u32, const ESTicketView* const, const u32, const ESTitleMeta* const, const u32, const u8* const, DVDLowCallback); +BOOL DVDLowOpenPartition(const u32, const ESTicket* const, const u32, const u8* const, ESTitleMeta*, DVDLowCallback); + #ifdef __cplusplus } #endif diff --git a/include/revolution/esp.h b/include/revolution/esp.h new file mode 100644 index 0000000000..802a028630 --- /dev/null +++ b/include/revolution/esp.h @@ -0,0 +1,138 @@ +#ifndef ESP_H +#define ESP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef u32 ESId; +typedef u32 ESContentId; +typedef u64 ESTitleId; +typedef u64 ESTicketId; +typedef u8 ESVersion; +typedef u16 ESTitleVersion; +typedef ESTitleId ESSysVersion; +typedef u32 ESTitleType; +typedef u16 ESContentType; +typedef u8 ESTmdReserved[62]; +typedef u8 ESTicketReserved[48]; +typedef u8 ESSysAccessMask[2]; +typedef u8 ESCidxMask[64]; + +#pragma pack(push, 4) + +typedef struct { + ESVersion version; + ESSysVersion sysVersion; + ESTitleId titleId; + ESTitleType type; + u16 groupId; + ESTmdReserved reserved; + ESTitleVersion titleVersion; + u16 numContents; +} ESTmdViewHeader; + +typedef struct { + ESContentId cid; + u16 index; + ESContentType type; + u64 size; +} ESCmdView; + +typedef struct { + u32 code; + u32 limit; +} ESLpEntry; + +typedef struct { + ESVersion version; + ESTicketId ticketID; + ESId devID; + ESTitleId titleID; + ESSysAccessMask sysAccessMask; + u16 ticketVer; + u32 accTitleID; + u32 accTitleMask; + u8 license; + ESTicketReserved reserved; + u8 audit; + ESCidxMask cidxMask; + ESLpEntry limits[8]; +} ESTicketView; + +typedef struct { + ESTmdViewHeader head; + ESCmdView contents[512]; +} ESTmdView; + +typedef struct { + ESContentId cid; + u16 index; + ESContentType type; + u64 size; + IOSCHash hash; +} ESContentMeta; + +typedef struct { + ESVersion version; + ESVersion caCrlVersion; + ESVersion signerCrlVersion; + ESSysVersion sysVersion; + ESTitleId titleId; + ESTitleType type; + u16 groupId; + ESTmdReserved reserved; + u32 accessRights; + ESTitleVersion titleVersion; + u16 numContents; + u16 bootIndex; +} ESTitleMetaHeader; + +typedef struct { + IOSCSigRsa2048 sig; + ESTitleMetaHeader head; + ESContentMeta contents[512]; +} ESTitleMeta; + +typedef struct { + IOSCSigRsa2048 sig; + IOSCEccPublicKey serverPubKey; + ESVersion version; + ESVersion caCrlVersion; + ESVersion signerCrlVersion; + IOSCAesKey titleKey; + ESTicketId ticketId; + ESId deviceId; + ESTitleId titleId; + ESSysAccessMask sysAccessMask; + u16 ticketVersion; + u32 accessTitleId; + u32 accessTitleMask; + u8 licenseType; + ESTicketReserved reserved; + u8 audit; + ESCidxMask cidxMask; + ESLpEntry limits[8]; +} ESTicket; + +#pragma pack(pop) + +s32 ESP_InitLib(void); +s32 ESP_CloseLib(void); +s32 ESP_LaunchTitle(u64, ESTicketView*); +s32 ESP_GetTicketViews(ESTitleId, ESTicketView*, u32*); +s32 ESP_DiGetTicketView(const void*, ESTicketView*); +s32 ESP_DiGetTmd(ESTitleMeta*, u32*); +s32 ESP_GetTmdView(ESTitleId, ESTmdView*, u32*); +s32 ESP_GetDataDir(ESTitleId, char*); +s32 ESP_GetTitleId(ESTitleId*); +s32 ESP_GetConsumption(ESTicketId, ESLpEntry*, u32*); + +#ifdef __cplusplus +} +#endif + +#endif // ESP_H diff --git a/include/revolution/hw_regs.h b/include/revolution/hw_regs.h index fd81060f15..1bf8658f9f 100644 --- a/include/revolution/hw_regs.h +++ b/include/revolution/hw_regs.h @@ -8,19 +8,21 @@ volatile u16 __VIRegs[59] AT_ADDRESS(0xCC002000); volatile u32 __PIRegs[12] AT_ADDRESS(0xCC003000); volatile u16 __MEMRegs[64] AT_ADDRESS(0xCC004000); volatile u16 __DSPRegs[] AT_ADDRESS(0xCC005000); -volatile u32 __DIRegs[] AT_ADDRESS(0xCC006000); +volatile u32 __DIRegs[] AT_ADDRESS(0xCD006000); volatile u32 __SIRegs[0x100] AT_ADDRESS(0xCC006400); -volatile u32 __EXIRegs[0x40] AT_ADDRESS(0xCC006800); -volatile u32 __AIRegs[8] AT_ADDRESS(0xCC006C00); +volatile u32 __EXIRegs[0x40] AT_ADDRESS(0xCD006800); +volatile u32 __AIRegs[8] AT_ADDRESS(0xCD006C00); +volatile u32 __IPCRegs[4] AT_ADDRESS(0xCD000000); #else #define __VIRegs ((volatile u16 *)0xCC002000) #define __PIRegs ((volatile u32 *)0xCC003000) #define __MEMRegs ((volatile u16 *)0xCC004000) #define __DSPRegs ((volatile u16 *)0xCC005000) -#define __DIRegs ((volatile u32 *)0xCC006000) +#define __DIRegs ((volatile u32 *)0xCD006000) #define __SIRegs ((volatile u32 *)0xCC006400) -#define __EXIRegs ((volatile u32 *)0xCC006800) -#define __AIRegs ((volatile u32 *)0xCC006C00) +#define __EXIRegs ((volatile u32 *)0xCD006800) +#define __AIRegs ((volatile u32 *)0xCD006C00) +#define __IPCRegs ((volatile u32 *)0xCD000000) #endif // Offsets for __VIRegs diff --git a/include/revolution/nand.h b/include/revolution/nand.h new file mode 100644 index 0000000000..0f095e14ab --- /dev/null +++ b/include/revolution/nand.h @@ -0,0 +1,167 @@ +#ifndef _REVOLUTION_NAND_H_ +#define _REVOLUTION_NAND_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NAND_RESULT_OK 0 +#define NAND_RESULT_ACCESS (-1) +#define NAND_RESULT_ALLOC_FAILED (-2) +#define NAND_RESULT_BUSY (-3) +#define NAND_RESULT_CORRUPT (-4) +#define NAND_RESULT_ECC_CRIT (-5) +#define NAND_RESULT_EXISTS (-6) +#define NAND_RESULT_INVALID (-8) +#define NAND_RESULT_MAXBLOCKS (-9) +#define NAND_RESULT_MAXFD (-10) +#define NAND_RESULT_MAXFILES (-11) +#define NAND_RESULT_NOEXISTS (-12) +#define NAND_RESULT_NOTEMPTY (-13) +#define NAND_RESULT_OPENFD (-14) +#define NAND_RESULT_AUTHENTICATION (-15) +#define NAND_RESULT_MAXDEPTH (-16) +#define NAND_RESULT_UNKNOWN (-64) +#define NAND_RESULT_FATAL_ERROR (-128) + +#define NAND_MAX_PATH 64 + +#define NAND_CHECK_HOME_INSSPACE 0x00000001 +#define NAND_CHECK_HOME_INSINODE 0x00000002 +#define NAND_CHECK_SYS_INSSPACE 0x00000004 +#define NAND_CHECK_SYS_INSINODE 0x00000008 + +typedef enum { + NAND_ACCESS_NONE, + NAND_ACCESS_READ, + NAND_ACCESS_WRITE, + NAND_ACCESS_RW +} NANDAccessType; + +typedef enum { + // Read/write by owner + NAND_PERM_RUSR = (NAND_ACCESS_READ << 4), + NAND_PERM_WUSR = (NAND_ACCESS_WRITE << 4), + // Read/write by group + NAND_PERM_RGRP = (NAND_ACCESS_READ << 2), + NAND_PERM_WGRP = (NAND_ACCESS_WRITE << 2), + // Read/write by other + NAND_PERM_ROTH = (NAND_ACCESS_READ << 0), + NAND_PERM_WOTH = (NAND_ACCESS_WRITE << 0), + // Read/write by all + NAND_PERM_RALL = NAND_PERM_RUSR | NAND_PERM_RGRP | NAND_PERM_ROTH, + NAND_PERM_WALL = NAND_PERM_WUSR | NAND_PERM_WGRP | NAND_PERM_WOTH, + NAND_PERM_RWALL = NAND_PERM_RALL | NAND_PERM_WALL +} NANDPermission; + +typedef struct NANDFileInfo { + s32 fileDescriptor; + s32 origFd; + char origPath[NAND_MAX_PATH]; + char tmpPath[NAND_MAX_PATH]; + u8 accType; + u8 stage; + u8 mark; +} NANDFileInfo; + +typedef struct NANDCommandBlock { + void* userData; + void* callback; + void* fileInfo; + void* bytes; + void* inodes; + void* status; + u32 ownerId; + u16 groupId; + u8 nextStage; + u32 attr; + u32 ownerAcc; + u32 groupAcc; + u32 othersAcc; + u32 num; + char absPath[NAND_MAX_PATH]; + u32* length; + u32* pos; + int state; + void* copyBuf; + u32 bufLength; + u8* type; + u32 uniqNo; + u32 reqBlocks; + u32 reqInodes; + u32* answer; + u32 homeBlocks; + u32 homeInodes; + u32 userBlocks; + u32 userInodes; + u32 workBlocks; + u32 workInodes; + const char* *dir; + BOOL simpleFlag; +} NANDCommandBlock; + +typedef struct NANDStatus { + u32 ownerId; + u16 groupId; + u8 attribute; + u8 permission; +} NANDStatus; + +typedef struct { + u32 signature; + u32 flag; + u16 iconSpeed; + u8 reserved[22]; + u16 comment[2][32]; + u8 bannerTexture[192 * 64 * 2]; + u8 iconTexture[8][48 * 48 * 2]; +} NANDBanner; + +typedef void (*NANDCallback)(s32, NANDCommandBlock*); +typedef void (*NANDAsyncCallback)(s32 result, struct NANDCommandBlock* block); + +s32 NANDInit(void); + +s32 NANDCreate(const char*, u8, u8); +s32 NANDPrivateCreate(const char*, u8, u8); + +s32 NANDOpen(const char*, NANDFileInfo*, u8); +s32 NANDPrivateOpen(const char*, NANDFileInfo*, u8); +s32 NANDOpenAsync(const char*, NANDFileInfo*, u8, NANDCallback, NANDCommandBlock*); +s32 NANDPrivateOpenAsync(const char*, NANDFileInfo*, const u8, NANDCallback, NANDCommandBlock*); + +s32 NANDClose(NANDFileInfo*); +s32 NANDCloseAsync(NANDFileInfo*, NANDCallback, NANDCommandBlock*); +s32 NANDRead(NANDFileInfo*, void*, u32); +s32 NANDReadAsync(NANDFileInfo*, void*, u32, NANDCallback, NANDCommandBlock*); + +s32 NANDGetLength(NANDFileInfo*, u32*); + +s32 NANDDelete(const char*); + +s32 NANDMove(const char*, const char*); + +s32 NANDCheck(u32, u32, u32*); + +s32 NANDWrite(NANDFileInfo*, const void*, u32); +s32 NANDWriteAsync(NANDFileInfo*, const void*, u32, NANDCallback, NANDCommandBlock*); + +s32 NANDSeekAsync(NANDFileInfo*, s32, s32, NANDCallback, NANDCommandBlock*); + +s32 NANDPrivateGetStatus(const char*, NANDStatus*); +s32 NANDPrivateDelete(const char*); +s32 NANDPrivateCreate(const char*, u8, u8); + +s32 NANDGetHomeDir(char[NAND_MAX_PATH]); + +s32 NANDGetStatus(const char*, NANDStatus*); + +s32 NANDSecretGetUsage(const char*, u32*, u32*); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/revolution/os.h b/include/revolution/os.h index f2525f8668..93def45f21 100644 --- a/include/revolution/os.h +++ b/include/revolution/os.h @@ -42,6 +42,10 @@ typedef u32 OSTick; #include #include #include +#include +#include +#include +#include // private macro, maybe shouldn't be defined here? #define OFFSET(addr, align) (((u32)(addr) & ((align)-1))) @@ -96,11 +100,20 @@ void* OSGetArenaHi(void); void* OSGetArenaLo(void); void OSSetArenaHi(void* newHi); void OSSetArenaLo(void* newLo); + +void OSSetMEM1ArenaHi(void* newHi); +void OSSetMEM1ArenaLo(void* newLo); +void OSSetMEM2ArenaHi(void* newHi); +void OSSetMEM2ArenaLo(void* newLo); + +void* OSGetMEM1ArenaLo(void); +void* OSGetMEM1ArenaHi(void); +void* OSGetMEM2ArenaLo(void); +void* OSGetMEM2ArenaHi(void); + void* OSAllocFromMEM1ArenaLo(u32 size, u32 align); void* OSAllocFromMEM1ArenaHi(u32 size, u32 align); -u32 OSGetPhysicalMemSize(void); - void __OSPSInit(void); void __OSFPRInit(void); u32 __OSGetDIConfig(void); @@ -133,6 +146,16 @@ typedef struct OSBootInfo_s { u32 FSTMaxLength; } OSBootInfo; +typedef struct OSIOSRev { + u8 reserved; + u8 major; + u8 minor; + u8 micro; + u8 month; + u8 date; + u16 year; +} OSIOSRev; + typedef struct OSStopwatch { char* name; u32 hits; @@ -187,6 +210,8 @@ BOOL OSRestoreInterrupts(BOOL level); u32 OSGetSoundMode(void); void OSSetSoundMode(u32 mode); +u8 OSGetAppType(void); + __declspec(weak) void OSReport(const char* msg, ...); __declspec(weak) void OSVReport(const char* msg, va_list list); __declspec(weak) void OSPanic(const char* file, int line, const char* msg, ...); @@ -243,21 +268,16 @@ void* OSUncachedToCached(void* ucaddr); #define OSUncachedToCached(ucaddr) ((void*) ((u8*)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED))) #endif +#define OSIsMEM1Region(addr) (((u32)(addr) & 0x30000000) == 0x00000000) +#define OSIsMEM2Region(addr) (((u32)(addr) & 0x30000000) == 0x10000000) + // unsorted externs extern OSTime __OSGetSystemTime(void); __declspec(weak) extern int __OSIsGcam; extern OSExecParams __OSRebootParams; extern OSTime __OSStartTime; extern int __OSInIPL; - -// helper for assert line numbers in different revisions -#if SDK_REVISION < 1 - #define LINE(l0, l1, l2) (l0) -#elif SDK_REVISION < 2 - #define LINE(l0, l1, l2) (l1) -#else - #define LINE(l0, l1, l2) (l2) -#endif +extern BOOL __OSInReboot; #ifdef DEBUG #define ASSERTLINE(line, cond) \ diff --git a/include/revolution/os/OSAlarm.h b/include/revolution/os/OSAlarm.h index 1f1ad948ad..ad6b0abd90 100644 --- a/include/revolution/os/OSAlarm.h +++ b/include/revolution/os/OSAlarm.h @@ -17,10 +17,10 @@ struct OSAlarm { OSAlarm* next; OSTime period; OSTime start; + void* userData; }; BOOL OSCheckAlarmQueue(void); -void OSInitAlarm(void); void OSCreateAlarm(OSAlarm* alarm); void OSSetAlarm(OSAlarm* alarm, OSTime tick, OSAlarmHandler handler); void OSSetAbsAlarm(OSAlarm* alarm, OSTime time, OSAlarmHandler handler); @@ -28,6 +28,8 @@ void OSSetPeriodicAlarm(OSAlarm* alarm, OSTime start, OSTime period, OSAlarmHand void OSCancelAlarm(OSAlarm *alarm); void OSSetAlarmTag(OSAlarm* alarm, u32 tag); void OSCancelAlarms(u32 tag); +void OSSetAlarmUserData(OSAlarm* alarm, void* userData); +void* OSGetAlarmUserData(const OSAlarm* alarm); #ifdef __cplusplus } diff --git a/include/revolution/os/OSInterrupt.h b/include/revolution/os/OSInterrupt.h index babf3fe1ff..0c954c74c0 100644 --- a/include/revolution/os/OSInterrupt.h +++ b/include/revolution/os/OSInterrupt.h @@ -38,61 +38,84 @@ typedef u32 OSInterruptMask; #define __OS_INTERRUPT_PI_VI 24 #define __OS_INTERRUPT_PI_DEBUG 25 #define __OS_INTERRUPT_PI_HSP 26 +#define __OS_INTERRUPT_PI_ACR 27 #define __OS_INTERRUPT_MAX 32 #define OS_INTERRUPTMASK(interrupt) (0x80000000u >> (interrupt)) -#define OS_INTERRUPTMASK_MEM_0 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0) -#define OS_INTERRUPTMASK_MEM_1 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_1) -#define OS_INTERRUPTMASK_MEM_2 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_2) -#define OS_INTERRUPTMASK_MEM_3 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_3) -#define OS_INTERRUPTMASK_MEM_ADDRESS OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_ADDRESS) -#define OS_INTERRUPTMASK_MEM_RESET \ - (OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | \ - OS_INTERRUPTMASK_MEM_3) -#define OS_INTERRUPTMASK_MEM \ - (OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | \ - OS_INTERRUPTMASK_MEM_3 | OS_INTERRUPTMASK_MEM_ADDRESS) -#define OS_INTERRUPTMASK_DSP_AI OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_AI) -#define OS_INTERRUPTMASK_DSP_ARAM OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_ARAM) -#define OS_INTERRUPTMASK_DSP_DSP OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_DSP) -#define OS_INTERRUPTMASK_DSP \ - (OS_INTERRUPTMASK_DSP_AI | OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP) -#define OS_INTERRUPTMASK_AI_AI OS_INTERRUPTMASK(__OS_INTERRUPT_AI_AI) -#define OS_INTERRUPTMASK_AI (OS_INTERRUPTMASK_AI_AI) -#define OS_INTERRUPTMASK_EXI_0_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXI) -#define OS_INTERRUPTMASK_EXI_0_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_TC) -#define OS_INTERRUPTMASK_EXI_0_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXT) -#define OS_INTERRUPTMASK_EXI_0 \ - (OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT) -#define OS_INTERRUPTMASK_EXI_1_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXI) -#define OS_INTERRUPTMASK_EXI_1_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_TC) -#define OS_INTERRUPTMASK_EXI_1_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXT) -#define OS_INTERRUPTMASK_EXI_1 \ - (OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT) -#define OS_INTERRUPTMASK_EXI_2_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_EXI) -#define OS_INTERRUPTMASK_EXI_2_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_TC) -#define OS_INTERRUPTMASK_EXI_2 (OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC) -#define OS_INTERRUPTMASK_EXI \ - (OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT | \ - OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT | \ - OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC) -#define OS_INTERRUPTMASK_PI_PE_TOKEN OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_TOKEN) -#define OS_INTERRUPTMASK_PI_PE_FINISH OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_FINISH) -#define OS_INTERRUPTMASK_PI_PE (OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH) -#define OS_INTERRUPTMASK_PI_CP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_CP) -#define OS_INTERRUPTMASK_PI_SI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_SI) -#define OS_INTERRUPTMASK_PI_DI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DI) -#define OS_INTERRUPTMASK_PI_RSW OS_INTERRUPTMASK(__OS_INTERRUPT_PI_RSW) -#define OS_INTERRUPTMASK_PI_ERROR OS_INTERRUPTMASK(__OS_INTERRUPT_PI_ERROR) -#define OS_INTERRUPTMASK_PI_VI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_VI) -#define OS_INTERRUPTMASK_PI_DEBUG OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DEBUG) -#define OS_INTERRUPTMASK_PI_HSP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_HSP) -#define OS_INTERRUPTMASK_PI \ - (OS_INTERRUPTMASK_PI_CP | OS_INTERRUPTMASK_PI_SI | OS_INTERRUPTMASK_PI_DI | \ - OS_INTERRUPTMASK_PI_RSW | OS_INTERRUPTMASK_PI_ERROR | OS_INTERRUPTMASK_PI_VI | \ - OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH | OS_INTERRUPTMASK_PI_DEBUG | \ - OS_INTERRUPTMASK_PI_HSP) +#define OS_INTERRUPTMASK_MEM_0 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0) +#define OS_INTERRUPTMASK_MEM_1 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_1) +#define OS_INTERRUPTMASK_MEM_2 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_2) +#define OS_INTERRUPTMASK_MEM_3 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_3) +#define OS_INTERRUPTMASK_MEM_ADDRESS OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_ADDRESS) +#define OS_INTERRUPTMASK_MEM_RESET (OS_INTERRUPTMASK_MEM_0 | \ + OS_INTERRUPTMASK_MEM_1 | \ + OS_INTERRUPTMASK_MEM_2 | \ + OS_INTERRUPTMASK_MEM_3) +#define OS_INTERRUPTMASK_MEM (OS_INTERRUPTMASK_MEM_0 | \ + OS_INTERRUPTMASK_MEM_1 | \ + OS_INTERRUPTMASK_MEM_2 | \ + OS_INTERRUPTMASK_MEM_3 | \ + OS_INTERRUPTMASK_MEM_ADDRESS) +#define OS_INTERRUPTMASK_DSP_AI OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_AI) +#define OS_INTERRUPTMASK_DSP_ARAM OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_ARAM) +#define OS_INTERRUPTMASK_DSP_DSP OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_DSP) +#define OS_INTERRUPTMASK_DSP (OS_INTERRUPTMASK_DSP_AI | \ + OS_INTERRUPTMASK_DSP_ARAM | \ + OS_INTERRUPTMASK_DSP_DSP) + +#define OS_INTERRUPTMASK_AI_AI OS_INTERRUPTMASK(__OS_INTERRUPT_AI_AI) +#define OS_INTERRUPTMASK_AI (OS_INTERRUPTMASK_AI_AI) + +#define OS_INTERRUPTMASK_EXI_0_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXI) +#define OS_INTERRUPTMASK_EXI_0_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_TC) +#define OS_INTERRUPTMASK_EXI_0_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXT) +#define OS_INTERRUPTMASK_EXI_0 (OS_INTERRUPTMASK_EXI_0_EXI | \ + OS_INTERRUPTMASK_EXI_0_TC | \ + OS_INTERRUPTMASK_EXI_0_EXT) +#define OS_INTERRUPTMASK_EXI_1_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXI) +#define OS_INTERRUPTMASK_EXI_1_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_TC) +#define OS_INTERRUPTMASK_EXI_1_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXT) +#define OS_INTERRUPTMASK_EXI_1 (OS_INTERRUPTMASK_EXI_1_EXI | \ + OS_INTERRUPTMASK_EXI_1_TC | \ + OS_INTERRUPTMASK_EXI_1_EXT) +#define OS_INTERRUPTMASK_EXI_2_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_EXI) +#define OS_INTERRUPTMASK_EXI_2_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_TC) +#define OS_INTERRUPTMASK_EXI_2 (OS_INTERRUPTMASK_EXI_2_EXI | \ + OS_INTERRUPTMASK_EXI_2_TC) +#define OS_INTERRUPTMASK_EXI (OS_INTERRUPTMASK_EXI_0_EXI | \ + OS_INTERRUPTMASK_EXI_0_TC | \ + OS_INTERRUPTMASK_EXI_0_EXT | \ + OS_INTERRUPTMASK_EXI_1_EXI | \ + OS_INTERRUPTMASK_EXI_1_TC | \ + OS_INTERRUPTMASK_EXI_1_EXT | \ + OS_INTERRUPTMASK_EXI_2_EXI | \ + OS_INTERRUPTMASK_EXI_2_TC) + +#define OS_INTERRUPTMASK_PI_PE_TOKEN OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_TOKEN) +#define OS_INTERRUPTMASK_PI_PE_FINISH OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_FINISH) +#define OS_INTERRUPTMASK_PI_PE (OS_INTERRUPTMASK_PI_PE_TOKEN | \ + OS_INTERRUPTMASK_PI_PE_FINISH) +#define OS_INTERRUPTMASK_PI_CP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_CP) +#define OS_INTERRUPTMASK_PI_SI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_SI) +#define OS_INTERRUPTMASK_PI_DI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DI) +#define OS_INTERRUPTMASK_PI_RSW OS_INTERRUPTMASK(__OS_INTERRUPT_PI_RSW) +#define OS_INTERRUPTMASK_PI_ERROR OS_INTERRUPTMASK(__OS_INTERRUPT_PI_ERROR) +#define OS_INTERRUPTMASK_PI_VI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_VI) +#define OS_INTERRUPTMASK_PI_DEBUG OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DEBUG) +#define OS_INTERRUPTMASK_PI_HSP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_HSP) +#define OS_INTERRUPTMASK_PI_ACR OS_INTERRUPTMASK(__OS_INTERRUPT_PI_ACR) +#define OS_INTERRUPTMASK_PI (OS_INTERRUPTMASK_PI_CP | \ + OS_INTERRUPTMASK_PI_SI | \ + OS_INTERRUPTMASK_PI_DI | \ + OS_INTERRUPTMASK_PI_RSW | \ + OS_INTERRUPTMASK_PI_ERROR | \ + OS_INTERRUPTMASK_PI_VI | \ + OS_INTERRUPTMASK_PI_PE_TOKEN | \ + OS_INTERRUPTMASK_PI_PE_FINISH | \ + OS_INTERRUPTMASK_PI_DEBUG | \ + OS_INTERRUPTMASK_PI_HSP | \ + OS_INTERRUPTMASK_PI_ACR ) typedef void (*__OSInterruptHandler)(__OSInterrupt interrupt, OSContext* context); diff --git a/include/revolution/os/OSIpc.h b/include/revolution/os/OSIpc.h new file mode 100644 index 0000000000..05a7126060 --- /dev/null +++ b/include/revolution/os/OSIpc.h @@ -0,0 +1,19 @@ +#ifndef _REVOLUTION_OSIPC_H_ +#define _REVOLUTION_OSIPC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void* __OSGetIPCBufferHi(void); +void* __OSGetIPCBufferLo(void); +void __OSInitIPCBuffer(void); + +#ifdef __cplusplus +} +#endif + + +#endif // _REVOLUTION_OSIPC_H_ diff --git a/include/revolution/os/OSMemory.h b/include/revolution/os/OSMemory.h index 9d4bbdd881..4066543a29 100644 --- a/include/revolution/os/OSMemory.h +++ b/include/revolution/os/OSMemory.h @@ -18,8 +18,10 @@ extern "C" { #define OS_PROTECT_CONTROL_RDWR (OS_PROTECT_CONTROL_READ | OS_PROTECT_CONTROL_WRITE) void OSProtectRange(u32 chan, void* addr, u32 nBytes, u32 control); -u32 OSGetPhysicalMemSize(void); -u32 OSGetConsoleSimulatedMemSize(void); +u32 OSGetPhysicalMem1Size(void); +u32 OSGetPhysicalMem2Size(void); +u32 OSGetConsoleSimulatedMem1Size(void); +u32 OSGetConsoleSimulatedMem2Size(void); #ifdef __cplusplus } diff --git a/include/revolution/os/OSModule.h b/include/revolution/os/OSModule.h index 079a259ba3..86cf6e5f57 100644 --- a/include/revolution/os/OSModule.h +++ b/include/revolution/os/OSModule.h @@ -90,10 +90,10 @@ struct OSRel { u32 addend; }; -#define R_REVOLUTION_NOP 201 // C9h current offset += OSRel.offset -#define R_REVOLUTION_SECTION 202 // CAh current section = OSRel.section -#define R_REVOLUTION_END 203 // CBh -#define R_REVOLUTION_MRKREF 204 // CCh +#define R_DOLPHIN_NOP 201 // C9h current offset += OSRel.offset +#define R_DOLPHIN_SECTION 202 // CAh current section = OSRel.section +#define R_DOLPHIN_END 203 // CBh +#define R_DOLPHIN_MRKREF 204 // CCh void OSSetStringTable(void* stringTable); BOOL OSLink(OSModuleInfo* newModule, void* bss); diff --git a/include/revolution/os/OSNandbootInfo.h b/include/revolution/os/OSNandbootInfo.h new file mode 100644 index 0000000000..dbc2c6b74e --- /dev/null +++ b/include/revolution/os/OSNandbootInfo.h @@ -0,0 +1,40 @@ +#ifndef _REVOLUTION_OSNANDBOOT_H_ +#define _REVOLUTION_OSNANDBOOT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + u32 CheckSum; + u32 ArgOffset; + u8 reserved[2]; + u8 LastAppType; + u8 ReturnType; + u32 ArgValue; + u8 padding[8]; + u64 LastTitleId; + u8 args[0x1000]; +} OSNandbootInfo; + +typedef struct { + u32 CheckSum; + u32 ArgOffset; + u8 reserved[2]; + u8 LastAppType; + u8 ReturnType; + u32 ArgValue; + u8 padding[8]; + u64 LastTitleId; +} OSNandbootInfoHeader; + +BOOL __OSCreateNandbootInfo(void); +BOOL __OSWriteNandbootInfo(OSNandbootInfo*); + +#ifdef __cplusplus +} +#endif + +#endif // _REVOLUTION_OSNANDBOOT_H_ diff --git a/include/revolution/os/OSPlayRecord.h b/include/revolution/os/OSPlayRecord.h new file mode 100644 index 0000000000..1cbfb15ee5 --- /dev/null +++ b/include/revolution/os/OSPlayRecord.h @@ -0,0 +1,19 @@ +#ifndef OSPLAYRECORD_H +#define OSPLAYRECORD_H + +#include + +typedef struct { + u32 checkSum; + u16 titleName[2][21]; + OSTime playStartTime; + OSTime playTime; + char gameCode[4]; + char companyCode[2]; + char res[18]; +} OSPlayRecord; + +void __OSStartPlayRecord(void); +void __OSStopPlayRecord(void); + +#endif // OSPLAYRECORD_H diff --git a/include/revolution/os/OSPlayTime.h b/include/revolution/os/OSPlayTime.h new file mode 100644 index 0000000000..22438b75ae --- /dev/null +++ b/include/revolution/os/OSPlayTime.h @@ -0,0 +1,25 @@ +#ifndef _REVOLUTION_OSPLAYTIME_H_ +#define _REVOLUTION_OSPLAYTIME_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + OSPLAYTIME_PERMANENT = 0, + OSPLAYTIME_LIMITED = 1, + OSPLAYTIME_LIMITED_LAUNCH = 4, + OSPLAYTIME_OTHER = 9 +} __OSPlayTimeType; + +typedef void (*OSPlayTimeCallbackFunc)(void); + +BOOL OSPlayTimeIsLimited(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/revolution/os/OSReset.h b/include/revolution/os/OSReset.h index 9e3f9ead45..2964bb8638 100644 --- a/include/revolution/os/OSReset.h +++ b/include/revolution/os/OSReset.h @@ -11,26 +11,30 @@ extern "C" { #define OS_RESET_HOTRESET 1 #define OS_RESET_SHUTDOWN 2 -typedef struct OSResetFunctionInfo OSResetFunctionInfo; -typedef struct OSResetFunctionQueue { - OSResetFunctionInfo* head; - OSResetFunctionInfo* tail; -} OSResetFunctionQueue; +typedef struct OSShutdownFunctionInfo OSShutdownFunctionInfo; +typedef struct OSShutdownFunctionQueue { + OSShutdownFunctionInfo* head; + OSShutdownFunctionInfo* tail; +} OSShutdownFunctionQueue; -typedef BOOL (*OSResetFunction)(BOOL); +typedef BOOL (*OSResetFunction)(BOOL, u32); -struct OSResetFunctionInfo { +struct OSShutdownFunctionInfo { OSResetFunction func; u32 priority; - OSResetFunctionInfo* next; - OSResetFunctionInfo* prev; + OSShutdownFunctionInfo* next; + OSShutdownFunctionInfo* prev; }; -void OSRegisterResetFunction(OSResetFunctionInfo* info); -void OSUnregisterResetFunction(OSResetFunctionInfo* info); +void OSRegisterShutdownFunction(OSShutdownFunctionInfo* info); +void OSUnregisterShutdownFunction(OSShutdownFunctionInfo* info); void OSResetSystem(int reset, u32 resetCode, BOOL forceMenu); u32 OSGetResetCode(); u32 OSSetBootDol(u32 dolOffset); +void OSReturnToMenu(void); + +#define OSIsRestart() \ + ((OSGetResetCode() & 0x80000000) ? TRUE : FALSE) #ifdef __cplusplus } diff --git a/include/revolution/os/OSResetSW.h b/include/revolution/os/OSResetSW.h index 6124c02b4d..c6fc2d027f 100644 --- a/include/revolution/os/OSResetSW.h +++ b/include/revolution/os/OSResetSW.h @@ -8,6 +8,7 @@ extern "C" { #endif typedef void (*OSResetCallback)(void); +typedef void (*OSPowerCallback)(void); OSResetCallback OSSetResetCallback(OSResetCallback callback); BOOL OSGetResetSwitchState(void); diff --git a/include/revolution/os/OSStateFlags.h b/include/revolution/os/OSStateFlags.h new file mode 100644 index 0000000000..60446ee980 --- /dev/null +++ b/include/revolution/os/OSStateFlags.h @@ -0,0 +1,26 @@ +#ifndef _REVOLUTION_OSSTATEFLAGS_H_ +#define _REVOLUTION_OSSTATEFLAGS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + u32 checkSum; + u8 lastBootApp; + u8 lastShutdown; + u8 lastDiscState; + u8 menuMode; + u8 reserved[24]; +} OSStateFlags; + +BOOL __OSWriteStateFlags(OSStateFlags*); +BOOL __OSReadStateFlags(OSStateFlags*); + +#ifdef __cplusplus +} +#endif + +#endif // OSSTATEFLAGS_H diff --git a/include/revolution/private/iosresclt.h b/include/revolution/private/iosresclt.h new file mode 100644 index 0000000000..d9fbb621c1 --- /dev/null +++ b/include/revolution/private/iosresclt.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include + +typedef IOSError (*IOSIpcCb) (IOSError, void *); + +s32 IOS_Read(s32, void*, u32); diff --git a/include/revolution/private/iosrestypes.h b/include/revolution/private/iosrestypes.h new file mode 100644 index 0000000000..679ed63cf7 --- /dev/null +++ b/include/revolution/private/iosrestypes.h @@ -0,0 +1,89 @@ +#pragma once + +#include + +typedef u32 IOSUid; +typedef u16 IOSGid; +typedef u32 IOSResourceHandle; + +#define IOS_ERROR_OK 0 +#define IOS_ERROR_ACCESS -1 +#define IOS_ERROR_EXISTS -2 +#define IOS_ERROR_INTR -3 +#define IOS_ERROR_INVALID -4 +#define IOS_ERROR_MAX -5 +#define IOS_ERROR_NOEXISTS -6 +#define IOS_ERROR_QEMPTY -7 +#define IOS_ERROR_QFULL -8 +#define IOS_ERROR_UNKNOWN -9 +#define IOS_ERROR_NOTREADY -10 +#define IOS_ERROR_ECC -11 +#define IOS_ERROR_ECC_CRIT -12 +#define IOS_ERROR_BADBLOCK -13 + +#define IOS_ERROR_INVALID_OBJTYPE -14 +#define IOS_ERROR_INVALID_RNG -15 +#define IOS_ERROR_INVALID_FLAG -16 +#define IOS_ERROR_INVALID_FORMAT -17 +#define IOS_ERROR_INVALID_VERSION -18 +#define IOS_ERROR_INVALID_SIGNER -19 +#define IOS_ERROR_FAIL_CHECKVALUE -20 +#define IOS_ERROR_FAIL_INTERNAL -21 +#define IOS_ERROR_FAIL_ALLOC -22 +#define IOS_ERROR_INVALID_SIZE -23 + +typedef struct { + u8 *path; + u32 flags; + IOSUid uid; + IOSGid gid; +} IOSResourceOpen; + +typedef struct { + u8 *outPtr; + u32 outLen; +} IOSResourceRead; + +typedef struct { + u8 *inPtr; + u32 inLen; +} IOSResourceWrite; + +typedef struct { + s32 offset; + u32 whence; +} IOSResourceSeek; + +typedef struct { + u32 cmd; + u8 *inPtr; + u32 inLen; + u8 *outPtr; + u32 outLen; +} IOSResourceIoctl; + +typedef struct { + u8 *base; + u32 length; +} IOSIoVector; + +typedef struct { + u32 cmd; + u32 readCount; + u32 writeCount; + IOSIoVector *vector; +} IOSResourceIoctlv; + +typedef struct { + u32 cmd; + s32 status; + IOSResourceHandle handle; + union { + IOSResourceOpen open; + IOSResourceRead read; + IOSResourceWrite write; + IOSResourceSeek seek; + IOSResourceIoctl ioctl; + IOSResourceIoctlv ioctlv; + } args; +} IOSResourceRequest; diff --git a/include/revolution/private/iostypes.h b/include/revolution/private/iostypes.h new file mode 100644 index 0000000000..6c57627407 --- /dev/null +++ b/include/revolution/private/iostypes.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +typedef s32 IOSError; +typedef s32 IOSCid; +typedef s32 IOSFd; +typedef s32 IOSMessageQueueId; +typedef s32 IOSMessage; +typedef s32 IOSTimerId; +typedef s32 IOSHeapId; +typedef s32 IOSThreadId; +typedef s32 IOSProcessId; +typedef s32 IOSInterfaceId; +typedef u32 IOSTime; +typedef u32 IOSEvent; + +typedef u8 IOSCName[64]; +typedef u8 IOSCSigDummy[60]; +typedef u8 IOSCHash[20]; + +typedef u8 CSLOSEccPublicKey[60]; +typedef u8 CSLOSRsaSig2048[256]; + +typedef u8 CSLOSAesKey[16]; + +typedef CSLOSEccPublicKey IOSCEccPublicKey; +typedef CSLOSRsaSig2048 IOSCRsaSig2048; + +typedef CSLOSAesKey IOSCAesKey; + +typedef enum { + IOSC_SIG_RSA4096 = 0x00010000, + IOSC_SIG_RSA2048, + IOSC_SIG_ECC +} IOSCCertSigType; + +typedef struct { + IOSCCertSigType sigType; + IOSCRsaSig2048 sig; + IOSCSigDummy dummy; + IOSCName issuer; +} IOSCSigRsa2048; diff --git a/include/revolution/sc.h b/include/revolution/sc.h index dd389bb3eb..7a8da096d2 100644 --- a/include/revolution/sc.h +++ b/include/revolution/sc.h @@ -1,31 +1,141 @@ #ifndef _REVOLUTION_SC_H_ #define _REVOLUTION_SC_H_ -#include +#include +#include #ifdef __cplusplus extern "C" { #endif +typedef u8 SCType; + +typedef struct { + u8 mode; + u8 led; +} SCIdleModeInfo; + +typedef struct { + union { + u8 type_u8; + s8 type_s8; + u16 type_u16; + s16 type_s16; + u32 type_u32; + s32 type_s32; + u64 type_u64; + s64 type_s64; + u8 longPrecision64[sizeof(u64)]; + } integer; + + SCType typeInteger; + SCType typeByteArray; + u32 nameLen; + u32 dataSize; + char* name; + u8* data; + u32 packedSize; +} SCItem; + +typedef void (*SCReloadConfFileCallback)(s32 result); +typedef void (*SCFlushCallback)(u32 result); + +typedef enum { + SC_ITEM_ID_IPL_COUNTER_BIAS, + SC_ITEM_ID_IPL_ASPECT_RATIO, + SC_ITEM_ID_IPL_AUTORUN_MODE, + SC_ITEM_ID_IPL_CONFIG_DONE, + SC_ITEM_ID_IPL_CONFIG_DONE2, + SC_ITEM_ID_IPL_DISPLAY_OFFSET_H, + SC_ITEM_ID_IPL_EURGB60_MODE, + SC_ITEM_ID_IPL_EULA, + SC_ITEM_ID_IPL_FREE_CHANNEL_APP_COUNT, + SC_ITEM_ID_IPL_IDLE_MODE, + SC_ITEM_ID_IPL_INSTALLED_CHANNEL_APP_COUNT, + SC_ITEM_ID_IPL_LANGUAGE, + SC_ITEM_ID_IPL_OWNER_NICKNAME, + SC_ITEM_ID_IPL_PARENTAL_CONTROL, + SC_ITEM_ID_IPL_PROGRESSIVE_MODE, + SC_ITEM_ID_IPL_SCREEN_SAVER_MODE, + SC_ITEM_ID_IPL_SIMPLE_ADDRESS, + SC_ITEM_ID_IPL_SOUND_MODE, + SC_ITEM_ID_IPL_UPDATE_TYPE, + SC_ITEM_ID_NET_CONFIG, + SC_ITEM_ID_NET_CONTENT_RESTRICTIONS, + SC_ITEM_ID_NET_PROFILE, + SC_ITEM_ID_NET_WC_RESTRICTION, + SC_ITEM_ID_NET_WC_FLAGS, + SC_ITEM_ID_DEV_BOOT_MODE, + SC_ITEM_ID_DEV_VIDEO_MODE, + SC_ITEM_ID_DEV_COUNTRY_CODE, + SC_ITEM_ID_DEV_DRIVESAVING_MODE, + SC_ITEM_ID_BT_DEVICE_INFO, + SC_ITEM_ID_BT_CMPDEV_INFO, + SC_ITEM_ID_BT_DPD_SENSIBILITY, + SC_ITEM_ID_BT_SPEAKER_VOLUME, + SC_ITEM_ID_BT_MOTOR_MODE, + SC_ITEM_ID_BT_SENSOR_BAR_POSITION, + SC_ITEM_ID_DVD_CONFIG, + SC_ITEM_ID_WWW_RESTRICTION, + SC_ITEM_ID_MAX_PLUS1 +} SCItemID; + +typedef struct { + OSThreadQueue threadQueue; + NANDFileInfo nandFileInfo; + NANDCommandBlock nandCommandBlock; + + union { + u8 nandType; + NANDStatus nandStatus; + } u; + + u8 nandStep; + u8 nandNeedClose; + u8 reloadFileCount; + SCReloadConfFileCallback reloadCallback; + s32 reloadResult; + const char* reloadFileName[2]; + u8* reloadBufp[2]; + u32 reloadSizeExpected[2]; + u32 reloadedSize[2]; + SCFlushCallback flushCallback; + u32 flushResult; + u32 flushSize; +} SCControl; + + + +#define SC_LANG_JAPANESE 0u +#define SC_LANG_ENGLISH 1u +#define SC_LANG_GERMAN 2u +#define SC_LANG_FRENCH 3u +#define SC_LANG_SPANISH 4u +#define SC_LANG_ITALIAN 5u +#define SC_LANG_DUTCH 6u +#define SC_LANG_SIMP_CHINESE 7u +#define SC_LANG_TRAD_CHINESE 8u +#define SC_LANG_KOREAN 9u + void SCInit(void); u32 SCCheckStatus(void); -int SCReloadConfFileAsync(void* bufp, u32 bufSize, int); -BOOL SCFindByteArrayItem(u8* data, u32, u32 itemID); -BOOL SCFindIntegerItem(int* data, u32 itemID, u8 type); -BOOL SCFindU8Item(u8* data, u32 itemID); -BOOL SCFindS8Item(s8* data, u32 itemID); -BOOL SCFindU32Item(u32* data, u32 itemID); +s32 SCReloadConfFileAsync(u8* bufp, u32 bufSize, SCReloadConfFileCallback); +BOOL SCFindByteArrayItem(void* data, u32, SCItemID itemID); +BOOL SCFindIntegerItem(int* data, SCItemID itemID, u8 type); +BOOL SCFindU8Item(u8* data, SCItemID itemID); +BOOL SCFindS8Item(s8* data, SCItemID itemID); +BOOL SCFindU32Item(u32* data, SCItemID itemID); u8 SCGetAspectRatio(void); -u8 SCGetDisplayOffsetH(void); -BOOL SCGetIdleMode(u8* data); +s8 SCGetDisplayOffsetH(void); +BOOL SCGetIdleMode(SCIdleModeInfo* data); u8 SCGetLanguage(void); u8 SCGetProgressiveMode(void); u8 SCGetScreenSaverMode(void); u8 SCGetSoundMode(void); -u8 SCGetCounterBias(void); +u32 SCGetCounterBias(void); BOOL SCGetProductAreaString(const char*, int); -u32 SCGetProductArea(void); -u32 SCGetProductGameRegion(void); +s8 SCGetProductArea(void); +s8 SCGetProductGameRegion(void); #ifdef __cplusplus } diff --git a/src/revolution/dvd/__dvd.h b/src/revolution/dvd/__dvd.h new file mode 100644 index 0000000000..6443d85b68 --- /dev/null +++ b/src/revolution/dvd/__dvd.h @@ -0,0 +1,56 @@ +#ifndef _DOLPHIN_DVD_INTERNAL_H_ +#define _DOLPHIN_DVD_INTERNAL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// DVD +DVDCommandChecker __DVDSetOptionalCommandChecker(DVDCommandChecker func); +void __DVDSetImmCommand(u32 command); +void __DVDSetDmaCommand(u32 command); +void* __DVDGetIssueCommandAddr(void); +void __DVDAudioBufferConfig(DVDCommandBlock* block, u32 enable, u32 size, DVDCBCallback callback); +void __DVDPrepareResetAsync(DVDCBCallback callback); +int __DVDTestAlarm(const OSAlarm* alarm); + +// DVD ERROR +void __DVDStoreErrorCode(u32 error); + +// DVD FATAL +void __DVDPrintFatalMessage(void); + +// DVD FS +extern OSThreadQueue __DVDThreadQueue; +extern u32 __DVDLongFileNameFlag; + +void __DVDFSInit(void); + +// DVD LOW +void __DVDInitWA(void); +void __DVDInterruptHandler(__OSInterrupt interrupt, OSContext* context); +void __DVDLowSetWAType(u32 type, s32 seekLoc); +int __DVDLowTestAlarm(const OSAlarm* alarm); + +// DVD QUEUE +void __DVDClearWaitingQueue(void); +int __DVDPushWaitingQueue(s32 prio, DVDCommandBlock* block); +DVDCommandBlock* __DVDPopWaitingQueue(void); +int __DVDCheckWaitingQueue(void); +int __DVDDequeueWaitingQueue(DVDCommandBlock* block); +int __DVDIsBlockInWaitingQueue(DVDCommandBlock* block); + +// FST LOAD +void __fstLoad(void); + +// unsorted +u32 __DVDGetCoverStatus(void); + +#ifdef __cplusplus +} +#endif + +#endif // _DOLPHIN_DVD_INTERNAL_H_ diff --git a/src/revolution/os/OS.c b/src/revolution/os/OS.c new file mode 100644 index 0000000000..4c9cb76097 --- /dev/null +++ b/src/revolution/os/OS.c @@ -0,0 +1,966 @@ +#include +#include +#include +#include +#include +#include + +#include "__os.h" + +#define NOP 0x60000000 + +// external functions +extern void EnableMetroTRKInterrupts(void); +extern void __OSInitMemoryProtection(void); +extern void IPCCltInit(void); +extern BOOL __DVDCheckDevice(void); + +#define DB_EXCEPTIONRET_OFFSET 0xC +#define DB_EXCEPTIONDEST_OFFSET 0x8 +#define OS_CURRENTCONTEXT_PADDR 0x00C0 +#define OS_EXCEPTIONTABLE_ADDR 0x3000 +#define OS_DBJUMPPOINT_ADDR 0x60 + +#ifdef SDK_AUG2010 +#define BUILD_DATE "Aug 23 2010" +#define BUILD_TIME "17:27:45" +#elif SDK_SEP2006 +#define BUILD_DATE "Sep 21 2006" +#define BUILD_TIME "14:32:13" +#endif + +#ifdef SDK_AUG2010 +const char* __OSVersion = "<< RVL_SDK - OS \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>"; +#elif SDK_SEP2006 +const char* __OSVersion = "<< RVL_SDK - OS \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>"; +#endif + +static DVDDriveInfo DriveInfo; +static DVDCommandBlock DriveBlock; +OSExecParams __OSRebootParams; + +#ifdef SDK_SEP2006 +static char GameNameBuffer[5]; +#endif + +extern u32 __DVDLongFileNameFlag; +extern u32 __PADSpec; + +// defined in link script +extern u8 __ArenaLo[]; +extern char _stack_addr[]; +extern u8 __ArenaHi[]; + +OSTime __OSStartTime; + +static OSBootInfo* BootInfo; +static u32* BI2DebugFlag; +static u32 BI2DebugFlagHolder; + +void (**OSExceptionTable)(u8, OSContext*); +BOOL AreWeInitialized; +f32 ZeroPS[2]; +f64 ZeroF; +BOOL __OSIsGcam; +BOOL __OSInNandBoot; +BOOL __OSInIPL; + +// prototypes +static void __OSInitFPRs(void); +static void OSExceptionInit(void); + +// dummy entry points to the OS Exception vector +void __OSEVStart(void); +void __OSEVEnd(void); +void __OSEVSetNumber(void); +void __OSExceptionVector(void); +void __DBVECTOR(void); +void __OSDBINTSTART(void); +void __OSDBINTEND(void); +void __OSDBJUMPSTART(void); +void __OSDBJUMPEND(void); + +/* clang-format off */ +#ifdef __GEKKO__ +asm void __OSFPRInit(void) { + // clang-format off + nofralloc + + mfmsr r3 + ori r3, r3, 0x2000 + mtmsr r3 + + mfspr r3, 0x398 + rlwinm. r3, r3, 3, 0x1f, 0x1f + beq skip_ps_init + + lis r3, ZeroPS@ha + addi r3, r3, ZeroPS@l + psq_l f0, 0(r3), 0, 0 + ps_mr f1, f0 + ps_mr f2, f0 + ps_mr f3, f0 + ps_mr f4, f0 + ps_mr f5, f0 + ps_mr f6, f0 + ps_mr f7, f0 + ps_mr f8, f0 + ps_mr f9, f0 + ps_mr f10, f0 + ps_mr f11, f0 + ps_mr f12, f0 + ps_mr f13, f0 + ps_mr f14, f0 + ps_mr f15, f0 + ps_mr f16, f0 + ps_mr f17, f0 + ps_mr f18, f0 + ps_mr f19, f0 + ps_mr f20, f0 + ps_mr f21, f0 + ps_mr f22, f0 + ps_mr f23, f0 + ps_mr f24, f0 + ps_mr f25, f0 + ps_mr f26, f0 + ps_mr f27, f0 + ps_mr f28, f0 + ps_mr f29, f0 + ps_mr f30, f0 + ps_mr f31, f0 + +skip_ps_init: + lfd f0, ZeroF(r13) + fmr f1, f0 + fmr f2, f0 + fmr f3, f0 + fmr f4, f0 + fmr f5, f0 + fmr f6, f0 + fmr f7, f0 + fmr f8, f0 + fmr f9, f0 + fmr f10, f0 + fmr f11, f0 + fmr f12, f0 + fmr f13, f0 + fmr f14, f0 + fmr f15, f0 + fmr f16, f0 + fmr f17, f0 + fmr f18, f0 + fmr f19, f0 + fmr f20, f0 + fmr f21, f0 + fmr f22, f0 + fmr f23, f0 + fmr f24, f0 + fmr f25, f0 + fmr f26, f0 + fmr f27, f0 + fmr f28, f0 + fmr f29, f0 + fmr f30, f0 + fmr f31, f0 + + mtfsf 0xff, f0 + blr + // clang-format on +} +#endif + +static void DisableWriteGatherPipe(void) { + u32 hid2; + + hid2 = PPCMfhid2(); + hid2 &= ~0x40000000; + PPCMthid2(hid2); +} + +u32 __OSGetHollywoodRev(void) { + return *(u32*)OSPhysicalToCached(0x3138); +} + +void __OSGetIOSRev(OSIOSRev* rev) { + u32 iosVer, iosBuild; + iosVer = *(u32*)OSPhysicalToUncached(0x3140); + iosBuild = *(u32*)OSPhysicalToUncached(0x3144); + + rev->reserved = ((iosVer >> 24) & 0xFF); + rev->major = ((iosVer >> 16) & 0xFF); + rev->minor = ((iosVer >> 8) & 0xFF); + rev->micro = (iosVer & 0xFF); + + rev->month = (((iosBuild >> 20) & 0xF) * 10 + ((iosBuild >> 16) & 0xF)); + rev->date = (((iosBuild >> 12) & 0xF) * 10 + ((iosBuild >> 8) & 0xF)); + rev->year = (((iosBuild >> 4) & 0xF) * 10 + (iosBuild & 0xF) + 2000); +} + +// needed for assert +#undef NULL +#define NULL 0 + +u32 OSGetConsoleType(void) { + u32 hwRev; + u32 gddrSize; + + if (BootInfo == NULL || BootInfo->consoleType == 0) { + return 0x10000002; + } + + hwRev = __OSGetHollywoodRev(); + + if (__OSDeviceCode & 0x8000) { + switch (__OSDeviceCode & ~0x8000) { + case 2: + case 3: + case 0x203: + switch (hwRev) { + case 0: + return 0x10; + case 1: + return 0x11; + case 2: + return 0x12; + case 0x10: + return 0x20; + case 0x11: + return 0x21; + } + + if (hwRev > 0x11) { + return 0x21; + } + + case 0x202: + case 0x201: + switch (hwRev) { + case 0: + return 0x10000010; + case 1: + return 0x10000011; + case 2: + return 0x10000012; + case 0x10: + return 0x10000020; + case 0x11: + return 0x10000021; + } + + if (hwRev > 0x11) { + return 0x10000021; + } + + #if SDK_AUG2010 + case 0x300: + return 0x100; + #endif + + default: + break; + } + } + + gddrSize = OSGetPhysicalMem2Size(); + + switch (hwRev) { + case 0: + if (gddrSize == 0x4000000) { + return 0x10; + } + else { + return 0x10000010; + } + + case 0x1: + if (gddrSize == 0x4000000) { + return 0x11; + } + else { + return 0x10000011; + } + + case 0x2: + if (gddrSize == 0x4000000) { + return 0x12; + } + else { + return 0x10000012; + } + + case 0x10: + if (gddrSize == 0x4000000) { + return 0x20; + } + else { + return 0x10000020; + } + + case 0x11: + if (gddrSize == 0x4000000) { + return 0x21; + } + else { + return 0x10000021; + } + } + + if (hwRev > 0x11) { + if (gddrSize == 0x4000000) { + return 0x21; + } + else { + return 0x10000021; + } + } + + return BootInfo->consoleType; +} + +static void MemClear(void* base, u32 size) { + void* lastBase = (size > 0x40000) ? (void*)((u32)base + size - 0x40000) : base; + DCZeroRange(base, size); + DCFlushRange(lastBase, 0x40000); +} + +static void ClearArena(void) { + if (!OSIsRestart()) { + MemClear(OSGetArenaLo(), (u32)OSGetArenaHi() - (u32)OSGetArenaLo()); + return; + } + + if (__OSRebootParams.regionStart == NULL || !OSIsMEM1Region((void*)__OSRebootParams.regionStart)) { + MemClear(OSGetArenaLo(), (u32)OSGetArenaHi() - (u32)OSGetArenaLo()); + return; + } + + ASSERTLINE(1068, __OSRebootParams.regionEnd != NULL); + + if ((u32)OSGetArenaLo() < (u32)__OSRebootParams.regionStart) { + if ((u32)OSGetArenaHi() <= (u32)__OSRebootParams.regionStart) { + MemClear(OSGetArenaLo(), (u32)OSGetArenaHi() - (u32)OSGetArenaLo()); + } else { + MemClear(OSGetArenaLo(), (u32)__OSRebootParams.regionStart - (u32)OSGetArenaLo()); + + if ((u32)OSGetArenaHi() > (u32)__OSRebootParams.regionEnd) { + MemClear(__OSRebootParams.regionEnd, (u32)OSGetArenaHi() - (u32)__OSRebootParams.regionEnd); + } + } + } +} + +static void ClearMEM2Arena(void) { + if (!OSIsRestart()) { + MemClear(OSGetMEM2ArenaLo(), (u32)OSGetMEM2ArenaHi() - (u32)OSGetMEM2ArenaLo()); + return; + } + + if (__OSRebootParams.regionStart == NULL || !OSIsMEM2Region((void*)__OSRebootParams.regionStart)) { + MemClear(OSGetMEM2ArenaLo(), (u32)OSGetMEM2ArenaHi() - (u32)OSGetMEM2ArenaLo()); + return; + } + + ASSERTLINE(1106, __OSRebootParams.regionEnd != NULL); + + if ((u32)OSGetMEM2ArenaLo() < (u32)__OSRebootParams.regionStart) { + if ((u32)OSGetMEM2ArenaHi() <= (u32)__OSRebootParams.regionStart) { + MemClear(OSGetMEM2ArenaLo(), (u32)OSGetMEM2ArenaHi() - (u32)OSGetMEM2ArenaLo()); + } else { + MemClear(OSGetMEM2ArenaLo(), (u32)__OSRebootParams.regionStart - (u32)OSGetMEM2ArenaLo()); + + if ((u32)OSGetMEM2ArenaHi() > (u32)__OSRebootParams.regionEnd) { + MemClear(__OSRebootParams.regionEnd, (u32)OSGetMEM2ArenaHi() - (u32)__OSRebootParams.regionEnd); + } + } + } +} + +static void InquiryCallback(s32, DVDCommandBlock* block) { + switch (block->state) { + case 0: + __OSDeviceCode = (u16)(0x8000 | DriveInfo.deviceCode); + break; + default: + __OSDeviceCode = 1; + break; + } +} + +static void CheckTargets(void) { + switch (*(u8*)OSPhysicalToCached(0x315C)) { + case 0x80: + break; + case 0x81: + OSReport("OS ERROR: boot program is not for RVL target. Please use correct boot program.\n"); + OSPanic(__FILE__, 1160, "Failed to run app"); + break; + default: + break; + } + + switch (*(u8*)OSPhysicalToCached(0x315D)) { + case 0x80: + break; + case 0x81: + OSReport("OS ERROR: apploader[D].img is not for RVL target. Please use correct apploader[D].img.\n"); + OSPanic(__FILE__, 1178, "Failed to run app"); + break; + default: + break; + } +} + +#ifdef SDK_AUG2010 +static void CheckFirmare(void) { + OSIOSRev iosRev; + u32 firmware; + GXColor bg = {0x00, 0x00, 0xFF, 0x00}; + GXColor fg = {0xFF, 0xFF, 0xFF, 0x00}; + + __OSGetIOSRev(&iosRev); + firmware = iosRev.major << 0x10; + firmware |= iosRev.minor << 0x8; + firmware |= iosRev.micro; + + if (iosRev.major != (*(u32*)0x80003188 >> 0x10) || (iosRev.major == (*(u32*)0x80003188 >> 0x10) && firmware < *(u32*)0x80003188)) { + OSReport("OS ERROR: This firmware is an improper version for this SDK. Please use a correct Firmware.\n"); + OSFatal(fg, bg, "\n\nERROR #002\nAn error has occurred.\nPress the Eject Button, remove the\nGame Disc, and turn off the power to \nthe console. \nPlease read the Wii Operations Manual \nfor further instructions.\n"); + OSPanic(__FILE__, 1243, "Failed to run app"); + } +} +#endif + +static void ReportOSInfo(void) { + u32 consoleType; + u32 sysMemSize; + OSIOSRev ios; + + OSReport("\nRevolution OS\n"); + OSReport("Kernel built : %s %s\n", BUILD_DATE, BUILD_TIME); + OSReport("Console Type : " ); + + consoleType = OSGetConsoleType(); + + switch (consoleType & 0xF0000000) { + case 0: + switch (consoleType) { + case 0x11: + OSReport("Pre-production board 1\n"); + break; + case 0x12: + OSReport("Pre-production board 2-1\n"); + break; + case 0x20: + OSReport("Pre-production board 2-2\n"); + break; + #if SDK_AUG2010 + case 0x100: + OSReport("RVA 1\n"); + break; + #endif + default: + OSReport("Retail %d\n", consoleType); + break; + } + break; + case 0x10000000: + switch (consoleType) { + case 0x10000021: + OSReport("NDEV 2.1\n"); + break; + case 0x10000020: + OSReport("NDEV 2.0\n"); + break; + case 0x10000012: + OSReport("NDEV 1.2\n"); + break; + case 0x10000011: + OSReport("NDEV 1.1\n"); + break; + case 0x10000010: + OSReport("NDEV 1.0\n"); + break; + case 0x10000008: + OSReport("Revolution Emulator\n"); + break; + default: + OSReport("Emulation platform (%08x)\n", consoleType); + break; + } + break; + case 0x20000000: + OSReport("TDEV-based emulation HW%d\n", (consoleType & ~0xF0000000) - 3); + break; + default: + OSReport("%08x\n", consoleType); + break; + } + + __OSGetIOSRev(&ios); + OSReport("Firmware : %d.%d.%d ", ios.major, ios.minor, ios.micro); + OSReport("(%d/%d/%d)\n", ios.month, ios.date, ios.year); + sysMemSize = (OSGetConsoleSimulatedMem1Size() + OSGetConsoleSimulatedMem2Size()); + OSReport("Memory %d MB\n", sysMemSize/(1024*1024)); + + OSReport("MEM1 Arena : 0x%x - 0x%x\n", OSGetMEM1ArenaLo(), OSGetMEM1ArenaHi()); + OSReport("MEM2 Arena : 0x%x - 0x%x\n", OSGetMEM2ArenaLo(), OSGetMEM2ArenaHi()); +} + +void OSInit(void) { + void* bi2StartAddr; + void* var_r31; + void* arenaAddr = (void*)OSRoundUp32B(__ArenaLo); + u32 sp10 = 0x81730000; + + if (AreWeInitialized == FALSE) { + AreWeInitialized = TRUE; + + __OSStartTime = __OSGetSystemTime(); + OSDisableInterrupts(); + + __OSGetExecParams(&__OSRebootParams); + PPCMtmmcr0(0); + PPCMtmmcr1(0); + PPCMtpmc1(0); + PPCMtpmc2(0); + PPCMtpmc3(0); + PPCMtpmc4(0); + PPCMthid4(0x83900000); + PPCDisableSpeculation(); + PPCSetFpNonIEEEMode(); + + BootInfo = (OSBootInfo*)OSPhysicalToCached(0); + BI2DebugFlag = 0; + __DVDLongFileNameFlag = 0; + + bi2StartAddr = (void*)(*(u32*)OSPhysicalToCached(0xF4)); + if (bi2StartAddr) { + BI2DebugFlag = (void*)((char*)bi2StartAddr + 0xC); + __PADSpec = ((u32*)bi2StartAddr)[9]; + *(u8*)OSPhysicalToCached(0x30E8) = *BI2DebugFlag; + *(u8*)OSPhysicalToCached(0x30E9) = __PADSpec; + } else if (BootInfo->arenaHi) { + BI2DebugFlagHolder = *(u8*)OSPhysicalToCached(0x30E8); + BI2DebugFlag = &BI2DebugFlagHolder; + __PADSpec = *(u8*)OSPhysicalToCached(0x30E9); + } + + __DVDLongFileNameFlag = 1; + + var_r31 = (void*)*(u32*)OSPhysicalToCached(0x310C); + if (var_r31 == NULL) { + if (OSIsMEM1Region(arenaAddr)) { + var_r31 = !BootInfo->arenaLo ? arenaAddr : BootInfo->arenaLo; + + if (!BootInfo->arenaLo && (BI2DebugFlag && (*(BI2DebugFlag) < 2))) { + var_r31 = (void*)OSRoundUp32B(_stack_addr); + } + } else { + var_r31 = (void*)0x80004000; + } + } + + OSSetMEM1ArenaLo(var_r31); + + var_r31 = (void*)*(u32*)OSPhysicalToCached(0x3110); + if (var_r31 == NULL) { + var_r31 = !BootInfo->arenaHi ? (void*)sp10 : BootInfo->arenaHi; + } + + OSSetMEM1ArenaHi(var_r31); + + var_r31 = (void*)*(u32*)OSPhysicalToCached(0x3124); + if (var_r31 != 0) { + if (OSIsMEM2Region(arenaAddr)) { + var_r31 = arenaAddr; + + if ((BI2DebugFlag && (*(BI2DebugFlag) < 2))) { + var_r31 = (void*)OSRoundUp32B(_stack_addr); + } + } + else { + if ((u32)var_r31 >= 0x90000000 && (u32)var_r31 < 0x90000800) { + var_r31 = (void*)0x90000800; + } + } + + OSSetMEM2ArenaLo(var_r31); + } + + + var_r31 = (void*)*(u32*)OSPhysicalToCached(0x3128); + if (var_r31 != 0) { + OSSetMEM2ArenaHi(var_r31); + } + + __OSInitIPCBuffer(); + OSExceptionInit(); + __OSInitSystemCall(); + __OSInitAlarm(); + __OSModuleInit(); + __OSInterruptInit(); + __OSContextInit(); + __OSCacheInit(); + EXIInit(); + SIInit(); + __OSInitSram(); + __OSThreadInit(); + __OSInitAudioSystem(); + + DisableWriteGatherPipe(); + + if (!__OSInIPL) { + __OSInitMemoryProtection(); + } + + ReportOSInfo(); + OSRegisterVersion(__OSVersion); + + // if location of debug flag exists, and flag is >= 2, enable MetroTRKInterrupts + if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) { + EnableMetroTRKInterrupts(); + } + + if (!__OSInNandBoot && !__OSInReboot) { + ClearArena(); + ClearMEM2Arena(); + } + + OSEnableInterrupts(); + IPCCltInit(); + + if (!__OSInNandBoot && !__OSInReboot) { + __OSInitSTM(); + + SCInit(); + + /* do nothing until SC is not busy */ + while (SCCheckStatus() == 1) {} + + __OSInitNet(); + } + + if (!__OSInIPL) { + CheckTargets(); + #ifdef SDK_AUG2010 + CheckFirmare(); + #endif + DVDInit(); + + if (__OSIsGcam) { + __OSDeviceCode = 0x9000; + } else if (!__OSDeviceCode) { + DCInvalidateRange(&DriveInfo, sizeof(DriveInfo)); + DVDInquiryAsync(&DriveBlock, &DriveInfo, InquiryCallback); + } + + if (OSGetAppType() == 0x80 && !__OSInReboot) { + if (!__DVDCheckDevice()) { + OSReturnToMenu(); + } + } + } + + if (!__OSInIPL && !__OSInNandBoot) { + __OSInitPlayTime(); + } + + if (!__OSInIPL && !__OSInNandBoot && !__OSInReboot) { + __OSStartPlayRecord(); + } + } +} + +static u32 __OSExceptionLocations[] = { + 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000800, + 0x00000900, 0x00000C00, 0x00000D00, 0x00000F00, 0x00001300, 0x00001400, 0x00001700, +}; + +#if DEBUG +char * __OSExceptionNames[17] = { + "System reset", + "MachineCheck", + "DSI", + "ISI", + "External Int.", + "Alignment", + "Program", + "FP Unavailable", + "Decrementer", + "System call", + "Trace", + "Perf mon", + "IABR", + "SMI", + "Thermal Int.", + "Protection error", + "FP Exception", +}; +#endif + +static void OSExceptionInit(void) { + __OSException exception; + void* destAddr; + + // These two vars help us change the exception number embedded + // in the exception handler code. + u32* opCodeAddr; + u32 oldOpCode; + + // Address range of the actual code to be copied. + u8* handlerStart; + u32 handlerSize; + + ASSERTMSGLINE(1830, ((u32)&__OSEVEnd - (u32)&__OSEVStart) <= 0x100, "OSExceptionInit(): too big exception vector code."); + + // Install the first level exception vector. + opCodeAddr = (u32*)__OSEVSetNumber; + oldOpCode = *opCodeAddr; + handlerStart = (u8*)__OSEVStart; + handlerSize = (u32)((u8*)__OSEVEnd - (u8*)__OSEVStart); + + // Install the DB integrator, only if we are the first OSInit to be run + destAddr = (void*)OSPhysicalToCached(OS_DBJUMPPOINT_ADDR); + if (*(u32*)destAddr == 0) // Lomem should be zero cleared only once by BS2 + { + memcpy(destAddr, (void*)__OSDBINTSTART, (u32)__OSDBINTEND - (u32)__OSDBINTSTART); + DCFlushRangeNoSync(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART); + __sync(); + ICInvalidateRange(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART); + } + + // Copy the right vector into the table + for (exception = 0; exception < __OS_EXCEPTION_MAX; exception++) { + if (BI2DebugFlag && (*BI2DebugFlag >= 2)) { + continue; + } + + // Modify the copy of code in text before transferring + // to the exception table. + *opCodeAddr = oldOpCode | exception; + + // Modify opcodes at __DBVECTOR if necessary + // make sure the opcodes are still nop + { + u32* ops = (u32*)__DBVECTOR; + int cb; + + for (cb = 0; cb < (u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART; cb += sizeof(u32)) { + *ops++ = NOP; + } + } + + // Install the modified handler. + destAddr = (void*)OSPhysicalToCached(__OSExceptionLocations[(u32)exception]); + memcpy(destAddr, handlerStart, handlerSize); + DCFlushRangeNoSync(destAddr, handlerSize); + __sync(); + ICInvalidateRange(destAddr, handlerSize); + } + // initialize pointer to exception table + OSExceptionTable = (void*)OSPhysicalToCached(OS_EXCEPTIONTABLE_ADDR); + + // install default exception handlers + for (exception = 0; exception < __OS_EXCEPTION_MAX; exception++) { + __OSSetExceptionHandler(exception, OSDefaultExceptionHandler); + } + + // restore the old opcode, so that we can re-start an application without + // downloading the text segments + *opCodeAddr = oldOpCode; +} + +#ifdef __GEKKO__ +static asm void __OSDBIntegrator(void) { + nofralloc +entry __OSDBINTSTART + li r5, OS_DBINTERFACE_ADDR + mflr r3 + stw r3, DB_EXCEPTIONRET_OFFSET(r5) + lwz r3, DB_EXCEPTIONDEST_OFFSET(r5) + oris r3, r3, OS_CACHED_REGION_PREFIX + mtlr r3 + li r3, 0x30 // MSR_IR | MSR_DR // turn on memory addressing + mtmsr r3 + blr +entry __OSDBINTEND +} +#endif + +#ifdef __GEKKO__ +static asm void __OSDBJump(void) { + nofralloc +entry __OSDBJUMPSTART + bla OS_DBJUMPPOINT_ADDR +entry __OSDBJUMPEND +} +#endif + +__OSExceptionHandler __OSSetExceptionHandler(__OSException exception, __OSExceptionHandler handler) { + __OSExceptionHandler oldHandler; + + ASSERTMSGLINE(1974, exception < __OS_EXCEPTION_MAX, "__OSSetExceptionHandler(): unknown exception."); + + oldHandler = OSExceptionTable[exception]; + OSExceptionTable[exception] = handler; + return oldHandler; +} + +__OSExceptionHandler __OSGetExceptionHandler(__OSException exception) { + ASSERTMSGLINE(1997, exception < __OS_EXCEPTION_MAX, "__OSGetExceptionHandler(): unknown exception."); + return OSExceptionTable[exception]; +} + +#ifdef __GEKKO__ +static asm void OSExceptionVector(void) { + nofralloc + +entry __OSEVStart + // Save r4 into SPRG0 + mtsprg 0, r4 + + // Load current context physical address into r4 + lwz r4, OS_CURRENTCONTEXT_PADDR + + // Save r3 - r5 into the current context + stw r3, OS_CONTEXT_R3(r4) + mfsprg r3, 0 + stw r3, OS_CONTEXT_R4(r4) + stw r5, OS_CONTEXT_R5(r4) + + lhz r3, OS_CONTEXT_STATE(r4) + ori r3, r3, OS_CONTEXT_STATE_EXC + sth r3, OS_CONTEXT_STATE(r4) + + // Save misc registers + mfcr r3 + stw r3, OS_CONTEXT_CR(r4) + mflr r3 + stw r3, OS_CONTEXT_LR(r4) + mfctr r3 + stw r3, OS_CONTEXT_CTR(r4) + mfxer r3 + stw r3, OS_CONTEXT_XER(r4) + mfsrr0 r3 + stw r3, OS_CONTEXT_SRR0(r4) + mfsrr1 r3 + stw r3, OS_CONTEXT_SRR1(r4) + mr r5, r3 + +entry __DBVECTOR + nop + + // Set SRR1[IR|DR] to turn on address + // translation at the next RFI + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + // This lets us change the exception number based on the + // exception we're installing. +entry __OSEVSetNumber + addi r3, 0, 0x0000 + + // Load current context virtual address into r4 + lwz r4, 0xD4 + + // Check non-recoverable interrupt + rlwinm. r5, r5, 0, MSR_RI_BIT, MSR_RI_BIT + bne recoverable + addis r5, 0, OSDefaultExceptionHandler@ha + addi r5, r5, OSDefaultExceptionHandler@l + mtsrr0 r5 + rfi + // NOT REACHED HERE + +recoverable: + // Locate exception handler. + rlwinm r5, r3, 2, 22, 29 // r5 contains exception*4 + lwz r5, OS_EXCEPTIONTABLE_ADDR(r5) + mtsrr0 r5 + + // Final state + // r3 - exception number + // r4 - pointer to context + // r5 - garbage + // srr0 - exception handler + // srr1 - address translation enalbed, not yet recoverable + + rfi + // NOT REACHED HERE + // The handler will restore state + +entry __OSEVEnd + nop +} +#endif + +void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar); + +#ifdef __GEKKO__ +asm void OSDefaultExceptionHandler(register __OSException exception, register OSContext* context) { + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + mfdsisr r5 + mfdar r6 + + stwu r1, -8(r1) + b __OSUnhandledException +} +#endif + +#ifdef __GEKKO__ +void __OSPSInit(void) { + PPCMthid2(PPCMfhid2() | 0x80000000 | 0x20000000); + ICFlashInvalidate(); + __sync(); + + asm + { + li r3, 0 + mtspr GQR0, r3 + mtspr GQR1, r3 + mtspr GQR2, r3 + mtspr GQR3, r3 + mtspr GQR4, r3 + mtspr GQR5, r3 + mtspr GQR6, r3 + mtspr GQR7, r3 + } +} +#endif + +u32 __OSGetDIConfig(void) { + return (__DIRegs[9] & 0xFF); +} + +void OSRegisterVersion(const char* id) { + OSReport("%s\n", id); +} + +#if SDK_SEP2006 +static const char* AppGameNameForSysMenu = "HAEA"; + +const char* OSGetAppGamename(void) { + const char* appNameSrc = (char*)OSPhysicalToCached(0x3180); + + if (__OSInIPL) { + appNameSrc = AppGameNameForSysMenu; + } + + GameNameBuffer[0] = *appNameSrc++; + GameNameBuffer[1] = *appNameSrc++; + GameNameBuffer[2] = *appNameSrc++; + GameNameBuffer[3] = *appNameSrc; + GameNameBuffer[4] = 0x00; + return GameNameBuffer; +} +#endif + +u8 OSGetAppType(void) { + if (__OSInIPL) { + return 0x40; + } + + return *((u8*)OSPhysicalToCached(0x3184)) & 0xFF; +} diff --git a/src/revolution/os/OSAddress.c b/src/revolution/os/OSAddress.c new file mode 100644 index 0000000000..03a2a9c887 --- /dev/null +++ b/src/revolution/os/OSAddress.c @@ -0,0 +1,34 @@ +#include + +// undefine the macros so they do not error the file. +#undef OSPhysicalToCached +#undef OSPhysicalToUncached +#undef OSCachedToPhysical +#undef OSUncachedToPhysical +#undef OSCachedToUncached +#undef OSUncachedToCached + +void* OSPhysicalToCached(u32 paddr) { + ASSERTMSGLINE(56, paddr < 0x20000000U, "OSPhysicalToCached(): illegal address."); + return (void*)(paddr + 0x80000000); +} + +void* OSPhysicalToUncached(u32 paddr) { + ASSERTMSGLINE(71, paddr < 0x20000000U, "OSPhysicalToUncached(): illegal address."); + return (void*)(paddr - 0x40000000); +} + +u32 OSCachedToPhysical(void* caddr) { + ASSERTMSGLINE(86, 0x80000000U <= (u32)caddr && (u32)caddr < 0xA0000000U, "OSCachedToPhysical(): illegal address."); + return (u32)caddr + 0x80000000; +} + +u32 OSUncachedToPhysical(void* ucaddr) { + ASSERTMSGLINE(101, 0xC0000000U <= (u32)ucaddr && (u32)ucaddr < 0xE0000000U, "OSUncachedToPhysical(): illegal address."); + return (u32)ucaddr + 0x40000000; +} + +void* OSCachedToUncached(void* caddr) { + ASSERTMSGLINE(116, 0x80000000U <= (u32)caddr && (u32)caddr < 0xA0000000U, "OSCachedToUncached(): illegal address."); + return (void*)((u32)caddr + 0x40000000); +} diff --git a/src/revolution/os/OSAlarm.c b/src/revolution/os/OSAlarm.c new file mode 100644 index 0000000000..5bebab4b6a --- /dev/null +++ b/src/revolution/os/OSAlarm.c @@ -0,0 +1,324 @@ +#include +#include + +#include "__os.h" +#include "__dvd.h" + +typedef struct { + OSAlarm* head; + OSAlarm* tail; +} OSAlarmQueue; + +// prototypes +static void SetTimer(OSAlarm * alarm); +static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler); +static void DecrementerExceptionCallback(register __OSException exception, register OSContext* context); +static void DecrementerExceptionHandler(__OSException exception, OSContext* context); +static BOOL OnReset(BOOL final, u32 event); + +static OSShutdownFunctionInfo ResetFunctionInfo = {OnReset, 0xFFFFFFFF, NULL, NULL}; +static OSAlarmQueue AlarmQueue; + +#define ASSERTREPORT(line, cond) \ + if (!(cond)) { OSReport("OSCheckAlarmQueue: Failed " #cond " in %d", line); return 0; } + +BOOL OSCheckAlarmQueue(void) { + OSAlarm* alarm; + + ASSERTREPORT(181, AlarmQueue.head == NULL && AlarmQueue.tail == NULL || AlarmQueue.head != NULL && AlarmQueue.tail != NULL); + ASSERTREPORT(182, AlarmQueue.head == NULL || AlarmQueue.head->prev == NULL); + ASSERTREPORT(183, AlarmQueue.tail == NULL || AlarmQueue.tail->next == NULL); + + for (alarm = AlarmQueue.head; alarm; alarm = alarm->next) { + ASSERTREPORT(186, alarm->next == NULL || alarm->next->prev == alarm); + ASSERTREPORT(187, alarm->next != NULL || AlarmQueue.tail == alarm); + } + return TRUE; +} + +static void SetTimer(OSAlarm* alarm) { + OSTime delta = alarm->fire - __OSGetSystemTime(); + + if (delta < 0) { + PPCMtdec(0); + } else if (delta < 0x80000000) { + PPCMtdec((u32)delta); + } else { + PPCMtdec(0x7fffffff); + } +} + +void __OSInitAlarm(void) { + if (__OSGetExceptionHandler(8) != DecrementerExceptionHandler) { + AlarmQueue.head = AlarmQueue.tail = NULL; + __OSSetExceptionHandler(8, DecrementerExceptionHandler); + OSRegisterShutdownFunction(&ResetFunctionInfo); + } +} + +void OSCreateAlarm(OSAlarm* alarm) { + alarm->handler = 0; + alarm->tag = 0; +} + +static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler) { + OSAlarm* next; + OSAlarm* prev; + + if (0 < alarm->period) { + OSTime time = __OSGetSystemTime(); + + fire = alarm->start; + if (alarm->start < time) { + fire += alarm->period * ((time - alarm->start) / alarm->period + 1); + } + } + + ASSERTLINE(290, alarm->handler == 0); + + alarm->handler = handler; + alarm->fire = fire; + + for (next = AlarmQueue.head; next; next = next->next) { + if (next->fire <= fire) { + continue; + } + + alarm->prev = next->prev; + next->prev = alarm; + alarm->next = next; + prev = alarm->prev; + + if (prev) { + prev->next = alarm; + } else { + AlarmQueue.head = alarm; + SetTimer(alarm); + } + + return; + } + + ASSERTLINE(319, next == 0); + + alarm->next = 0; + prev = AlarmQueue.tail; + AlarmQueue.tail = alarm; + alarm->prev = prev; + + if (prev) { + prev->next = alarm; + } else { + AlarmQueue.head = AlarmQueue.tail = alarm; + SetTimer(alarm); + } +} + +void OSSetAlarm(OSAlarm* alarm, OSTime tick, OSAlarmHandler handler) { + BOOL enabled; + ASSERTMSGLINE(352, tick > 0, "OSSetAlarm(): tick was less than zero."); + ASSERTMSGLINE(353, handler, "OSSetAlarm(): null handler was specified."); + enabled = OSDisableInterrupts(); + alarm->period = 0; + InsertAlarm(alarm, __OSGetSystemTime() + tick, handler); + ASSERTLINE(360, OSCheckAlarmQueue()); + OSRestoreInterrupts(enabled); +} + +void OSSetAbsAlarm(OSAlarm* alarm, OSTime time, OSAlarmHandler handler) { + BOOL enabled; + + ASSERTMSGLINE(343, handler, "OSSetAbsAlarm(): null handler was specified."); + enabled = OSDisableInterrupts(); + alarm->period = 0; + InsertAlarm(alarm, __OSTimeToSystemTime(time), handler); + ASSERTLINE(350, OSCheckAlarmQueue()); + OSRestoreInterrupts(enabled); +} + +void OSSetPeriodicAlarm(OSAlarm* alarm, OSTime start, OSTime period, OSAlarmHandler handler) { + BOOL enabled; + ASSERTMSGLINE(413, period > 0, "OSSetPeriodicAlarm(): period was less than zero."); + ASSERTMSGLINE(414, handler, "OSSetPeriodicAlarm(): null handler was specified."); + enabled = OSDisableInterrupts(); + alarm->period = period; + alarm->start = __OSTimeToSystemTime(start); + InsertAlarm(alarm, 0, handler); + ASSERTLINE(422, OSCheckAlarmQueue()); + OSRestoreInterrupts(enabled); +} + +void OSCancelAlarm(OSAlarm* alarm) { + OSAlarm* next; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + if (alarm->handler == 0) { + OSRestoreInterrupts(enabled); + return; + } + + next = alarm->next; + if (next == 0) { + AlarmQueue.tail = alarm->prev; + } else { + next->prev = alarm->prev; + } + if (alarm->prev) { + alarm->prev->next = next; + } else { + AlarmQueue.head = next; + if (next) { + SetTimer(next); + } + } + alarm->handler = 0; + ASSERTLINE(473, OSCheckAlarmQueue()); + OSRestoreInterrupts(enabled); +} + +static void DecrementerExceptionCallback(register __OSException exception, + register OSContext* context) { + OSAlarm* alarm; + OSAlarm* next; + OSAlarmHandler handler; + OSTime time; + OSContext exceptionContext; + + time = __OSGetSystemTime(); + alarm = AlarmQueue.head; + if (alarm == 0) { + OSLoadContext(context); + } + + if (time < alarm->fire) { + SetTimer(alarm); + OSLoadContext(context); + } + + next = alarm->next; + AlarmQueue.head = next; + if (next == 0) { + AlarmQueue.tail = 0; + } else { + next->prev = 0; + } + + ASSERTLINE(531, OSCheckAlarmQueue()); + + handler = alarm->handler; + alarm->handler = 0; + if (0 < alarm->period) { + InsertAlarm(alarm, 0, handler); + ASSERTLINE(541, OSCheckAlarmQueue()); + } + + if (AlarmQueue.head) { + SetTimer(AlarmQueue.head); + } + + OSDisableScheduler(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + handler(alarm, context); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); +} + +#ifdef __GEKKO__ +static asm void DecrementerExceptionHandler(register __OSException exception, + register OSContext* context) { + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + stwu r1, -8(r1) + b DecrementerExceptionCallback +} +#endif + +void OSSetAlarmTag(OSAlarm* alarm, u32 tag) { + alarm->tag = tag; +} + +void OSCancelAlarms(u32 tag) { + BOOL enabled; + OSAlarm* alarm; + OSAlarm* next; + + ASSERTMSGLINE(569, tag != 0, "OSCancelAlarms(): invalid tag. (this tag is used by the operating system.)"); + + if (tag != 0) { + enabled = OSDisableInterrupts(); + ASSERTLINE(575, OSCheckAlarmQueue()); + + alarm = AlarmQueue.head; + next = (alarm) ? alarm->next : NULL; + + while (alarm != 0) { + if (alarm->tag == tag) { + OSCancelAlarm(alarm); + } + + alarm = next; + next = (alarm) ? alarm->next : NULL; + } + + ASSERTLINE(585, OSCheckAlarmQueue()); + OSRestoreInterrupts(enabled); + } +} + +static BOOL OnReset(BOOL final, u32 event) { + OSAlarm* alarm; + OSAlarm* next; + + if (final != FALSE) { + ASSERTLINE(656, OSCheckAlarmQueue()); + + for (alarm = AlarmQueue.head, next = alarm ? alarm->next : 0; alarm; alarm = next, next = alarm ? alarm->next : 0) { + if (!__DVDTestAlarm(alarm)) { + OSCancelAlarm(alarm); + } + } + + ASSERTLINE(668, OSCheckAlarmQueue()); + } + + return TRUE; +} + +void __OSCancelInternalAlarms(void* userdata) { + BOOL enabled = OSDisableInterrupts(); + OSAlarm* alarm; + OSAlarm* next; + + ASSERTLINE(723, OSCheckAlarmQueue()); + + for (alarm = AlarmQueue.head, next = alarm ? alarm->next : 0; alarm; alarm = next, next = alarm ? alarm->next : 0) { + if (alarm->tag == -1 && alarm->userData == userdata) { + OSCancelAlarm(alarm); + } + } + + ASSERTLINE(737, OSCheckAlarmQueue()); + OSRestoreInterrupts(enabled); +} + +// NOTE: these functions don't exist in tp debug, OSReports are made up to create string data +void OSSetAlarmUserData(OSAlarm* alarm, void* userData) { + #if DEBUG + OSReport("OSSetAlarmUserData"); + OSReport("NULL pointer is detected at %s"); + #endif + alarm->userData = userData; +} + +void* OSGetAlarmUserData(const OSAlarm* alarm) { + #if DEBUG + OSReport("OSGetAlarmUserData"); + #endif + return alarm->userData; +} diff --git a/src/revolution/os/OSAlloc.c b/src/revolution/os/OSAlloc.c new file mode 100644 index 0000000000..e1294521c9 --- /dev/null +++ b/src/revolution/os/OSAlloc.c @@ -0,0 +1,608 @@ +#include +#include + +#define ALIGNMENT 32 + +#define InRange(cell, arenaStart, arenaEnd) \ + ((u32) arenaStart <= (u32) cell) && ((u32) cell < (u32) arenaEnd) + +#define HEADERSIZE 32u +#define MINOBJSIZE 64u + +#ifdef DEBUG +#define ENABLE_HEAPDESC +#endif + +typedef struct Cell Cell; +typedef struct HeapDesc HeapDesc; +struct Cell { + Cell* prev; + Cell* next; + s32 size; +#ifdef ENABLE_HEAPDESC + HeapDesc* hd; + s32 requested; +#endif +}; + +struct HeapDesc { + s32 size; + Cell* free; + Cell* allocated; +#ifdef ENABLE_HEAPDESC + u32 paddingBytes; + u32 headerBytes; + u32 payloadBytes; +#endif +}; + +volatile int __OSCurrHeap = -1; + +static HeapDesc* HeapArray; +static int NumHeaps; +static void* ArenaStart; +static void* ArenaEnd; + +// prototypes +static Cell* DLAddFront(Cell* list, Cell* cell); +static Cell* DLLookup(Cell* list, Cell* cell); +static Cell* DLExtract(Cell* list, Cell* cell); +static Cell* DLInsert(Cell* list, Cell* cell); +static int DLOverlap(Cell* list, void* start, void* end); +static s32 DLSize(Cell* list); + +static Cell* DLAddFront(Cell* list, Cell* cell) { + cell->next = list; + cell->prev = 0; + if (list) { + list->prev = cell; + } + return cell; +} + +static Cell* DLLookup(Cell* list, Cell* cell) { + for(; list; list = list->next) { + if (list == cell) { + return list; + } + } + return NULL; +} + +static Cell* DLExtract(Cell* list, Cell* cell) { + if (cell->next) { + cell->next->prev = cell->prev; + } + if (cell->prev == NULL) { + return cell->next; + } + cell->prev->next = cell->next; + return list; +} + +static Cell* DLInsert(Cell* list, Cell* cell) { + Cell* prev; + Cell* next; + + for(next = list, prev = NULL; next != 0; prev = next, next = next->next) { + if (cell <= next) { + break; + } + } + + cell->next = next; + cell->prev = prev; + if (next) { + next->prev = cell; + if ((u8*)cell + cell->size == (u8*)next) { + cell->size += next->size; + next = next->next; + cell->next = next; + if (next) { + next->prev = cell; + } + } + } + if (prev) { + prev->next = cell; + if ((u8*)prev + prev->size == (u8*)cell) { + prev->size += cell->size; + prev->next = next; + if (next) { + next->prev = prev; + } + } + return list; + } + return cell; +} + +static int DLOverlap(Cell* list, void* start, void* end) { + Cell* cell = list; + + while(cell) { + if (((start <= cell) + && (cell < end)) + || ((start < (void* ) ((u8*)cell + cell->size)) + && ((void* ) ((u8*)cell + cell->size) <= end))) { + return 1; + } + cell = cell->next; + } + return 0; +} + +static s32 DLSize(Cell* list) { + Cell* cell; + s32 size; + + size = 0; + cell = list; + + while(cell) { + size += cell->size; + cell = cell->next; + } + + return size; +} + +void* OSAllocFromHeap(int heap, u32 size) { + HeapDesc* hd; + Cell* cell; + Cell* newCell; + s32 leftoverSize; + s32 requested; + + requested = size; + ASSERTMSGLINE(337, HeapArray, "OSAllocFromHeap(): heap is not initialized."); + ASSERTMSGLINE(338, (s32)size > 0, "OSAllocFromHeap(): invalid size."); + ASSERTMSGLINE(339, heap >= 0 && heap < NumHeaps, "OSAllocFromHeap(): invalid heap handle."); + ASSERTMSGLINE(340, HeapArray[heap].size >= 0, "OSAllocFromHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + size += 0x20; + size = (size + 0x1F) & 0xFFFFFFE0; + + for(cell = hd->free; cell != NULL; cell = cell->next) { + if ((signed)size <= (signed)cell->size) { + break; + } + } + + if (cell == NULL) { +#if DEBUG + OSReport("OSAllocFromHeap: Warning- failed to allocate %d bytes\n", size); +#endif + return NULL; + } + ASSERTMSGLINE(364, !((s32)cell & 0x1F), "OSAllocFromHeap(): heap is broken."); + ASSERTMSGLINE(365, cell->hd == NULL, "OSAllocFromHeap(): heap is broken."); + + leftoverSize = cell->size - size; + if (leftoverSize < 0x40U) { + hd->free = DLExtract(hd->free, cell); + } else { + cell->size = size; + newCell = (void*)((u8*)cell + size); + newCell->size = leftoverSize; +#ifdef ENABLE_HEAPDESC + newCell->hd = 0; +#endif + newCell->prev = cell->prev; + newCell->next = cell->next; + if (newCell->next != NULL) { + newCell->next->prev = newCell; + } + if (newCell->prev != NULL) { + newCell->prev->next = newCell; + } else { + ASSERTMSGLINE(394, hd->free == cell, "OSAllocFromHeap(): heap is broken."); + hd->free = newCell; + } + } + + hd->allocated = DLAddFront(hd->allocated, cell); +#ifdef ENABLE_HEAPDESC + cell->hd = hd; + cell->requested = requested; + hd->headerBytes += 0x20; + hd->paddingBytes += (cell->size - (requested + 0x20)); + hd->payloadBytes += requested; +#endif + return (u8*)cell + 0x20; +} + +void* OSAllocFixed(void* rstart, void* rend) { + int i; + Cell* cell; + Cell* newCell; + HeapDesc* hd; + void* start; + void* end; + void* cellEnd; + + start = (void*)((*(u32*)rstart) & ~((32)-1)); + end = (void*)((*(u32*)rend + 0x1FU) & ~((32)-1)); + + ASSERTMSGLINE(436, HeapArray, "OSAllocFixed(): heap is not initialized."); + ASSERTMSGLINE(437, (u32)start < (u32)end, "OSAllocFixed(): invalid range."); + ASSERTMSGLINE(439, ((u32) ArenaStart <= (u32) start) && ((u32) end <= (u32) ArenaEnd), "OSAllocFixed(): invalid range."); + + for(i = 0; i < NumHeaps; i++) { + hd = &HeapArray[i]; + if(hd->size >= 0) { + if (DLOverlap(hd->allocated, start, end)) { +#if DEBUG + OSReport("OSAllocFixed: Warning - failed to allocate from %p to %p\n", start, end); +#endif + return NULL; + } + } + } + + for(i = 0; i < NumHeaps; i++) { + hd = &HeapArray[i]; + if (hd->size >= 0) { + for(cell = hd->free; cell; cell = cell->next) { + cellEnd = ((u8*)cell + cell->size); + if(cellEnd > start) { + if (end <= cell) { + break; + } + if ((char*)start-0x20 <= (char*)cell && cell < end && (start <= cellEnd) && (cellEnd < ((char*)end + 0x40))) { + if (cell < start) { + start = cell; + } + if (end < cellEnd) { + end = cellEnd; + } + hd->free = DLExtract(hd->free, cell); + hd->size -= cell->size; + } else if((char*)start-0x20 <= (char*)cell && cell < end) { + if (cell < start) { + start = cell; + } + ASSERTLINE(503, MINOBJSIZE <= (char*) cellEnd - (char*) end); + newCell = (Cell*)end; + + newCell->size = (s32) ((char*)cellEnd - (char*)end); +#ifdef ENABLE_HEAPDESC + newCell->hd = 0; +#endif + newCell->next = cell->next; + if (newCell->next) { + newCell->next->prev = newCell; + } + newCell->prev = cell->prev; + if (newCell->prev) { + newCell->prev->next = newCell; + } else { + hd->free = newCell; + } + hd->size -= ((char*)end - (char*)cell); + break; + } else { + if ((start <= cellEnd) && (cellEnd < ((char*)end + 0x40U))) { + if (end < cellEnd) { + end = cellEnd; + } + ASSERTLINE(528, MINOBJSIZE <= (char*) start - (char*) cell); + hd->size -= ((char*)cellEnd - (char*)start); + cell->size = ((char*)start - (char*)cell); + } else { + ASSERTLINE(535, MINOBJSIZE <= (char*) cellEnd - (char*) end); + newCell = (Cell*)end; + newCell->size = ((char*)cellEnd - (char*)end); +#ifdef ENABLE_HEAPDESC + newCell->hd = 0; +#endif + newCell->next = cell->next; + if (newCell->next) { + newCell->next->prev = newCell; + } + newCell->prev = cell; + cell->next = newCell; + cell->size = ((char*)start - (char*)cell); + hd->size -= ((char*)end - (char*)start); + break; + } + } + } + } + ASSERTLINE(550, 0 <= hd->size); + } + } + ASSERTLINE(553, OFFSET(start, ALIGNMENT) == 0); + ASSERTLINE(554, OFFSET(end, ALIGNMENT) == 0); + ASSERTLINE(555, start < end); + *(u32*)rstart = (u32)start; + *(u32*)rend = (u32)end; + return (void*)*(u32*)rstart; +} + +void OSFreeToHeap(int heap, void* ptr) { + HeapDesc* hd; + Cell* cell; + + ASSERTMSGLINE(589, HeapArray, "OSFreeToHeap(): heap is not initialized."); + ASSERTMSGLINE(591, ((u32)ArenaStart+0x20) <= (u32)ptr && (u32)ptr < (u32)ArenaEnd, "OSFreeToHeap(): invalid pointer."); + ASSERTMSGLINE(592, OFFSET(ptr, ALIGNMENT) == 0, "OSFreeToHeap(): invalid pointer."); + ASSERTMSGLINE(593, HeapArray[heap].size >= 0, "OSFreeToHeap(): invalid heap handle."); + cell = (void*)((u32)ptr-0x20); + hd = &HeapArray[heap]; + ASSERTMSGLINE(598, cell->hd == hd, "OSFreeToHeap(): invalid pointer."); + ASSERTMSGLINE(599, DLLookup(hd->allocated, cell), "OSFreeToHeap(): invalid pointer."); +#ifdef ENABLE_HEAPDESC + cell->hd = 0; + hd->headerBytes -= 0x20; + hd->paddingBytes -= (cell->size - (cell->requested + 0x20)); + hd->payloadBytes -= cell->requested; +#endif + hd->allocated = DLExtract(hd->allocated, cell); + hd->free = DLInsert(hd->free, cell); +} + +int OSSetCurrentHeap(int heap) { + int prev; + + ASSERTMSGLINE(631, HeapArray, "OSSetCurrentHeap(): heap is not initialized."); + ASSERTMSGLINE(632, (heap >= 0) && (heap < NumHeaps), "OSSetCurrentHeap(): invalid heap handle."); + ASSERTMSGLINE(633, HeapArray[heap].size >= 0, "OSSetCurrentHeap(): invalid heap handle."); + prev = __OSCurrHeap; + __OSCurrHeap = heap; + return prev; +} + +void* OSInitAlloc(void* arenaStart, void* arenaEnd, int maxHeaps) { + u32 arraySize; + int i; + + ASSERTMSGLINE(659, maxHeaps > 0, "OSInitAlloc(): invalid number of heaps."); + ASSERTMSGLINE(661, (u32)arenaStart < (u32)arenaEnd, "OSInitAlloc(): invalid range."); + ASSERTMSGLINE(664, maxHeaps <= (((u32)arenaEnd - (u32)arenaStart) / 24U), "OSInitAlloc(): too small range."); + arraySize = maxHeaps * sizeof(HeapDesc); + HeapArray = arenaStart; + NumHeaps = maxHeaps; + + for (i = 0; i < NumHeaps; i++) { + HeapDesc* hd = &HeapArray[i]; + hd->size = -1; + hd->free = hd->allocated = 0; +#ifdef ENABLE_HEAPDESC + hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0; +#endif + } + __OSCurrHeap = -1; + arenaStart = (void*) ((u32)((char*)HeapArray + arraySize)); + arenaStart = (void*) (((u32)arenaStart + 0x1F) & 0xFFFFFFE0); + ArenaStart = arenaStart; + ArenaEnd = (void*) ((u32)arenaEnd & 0xFFFFFFE0); + ASSERTMSGLINE(692, ((u32)ArenaEnd - (u32)ArenaStart) >= 0x40U, "OSInitAlloc(): too small range."); + return arenaStart; +} + +int OSCreateHeap(void* start, void* end) { + int heap; + HeapDesc* hd; + Cell* cell; + + ASSERTMSGLINE(717, HeapArray, "OSCreateHeap(): heap is not initialized."); + ASSERTMSGLINE(718, (u32)start < (u32)end, "OSCreateHeap(): invalid range."); + + start = (void*)(((u32)start + 0x1FU) & ~((32)-1)); + end = (void*)(((u32)end) & ~((32)-1)); + + ASSERTMSGLINE(721, (u32)start < (u32)end, "OSCreateHeap(): invalid range."); + ASSERTMSGLINE(723, (u32)ArenaStart <= (u32)start && (u32)end <= (u32)ArenaEnd, "OSCreateHeap(): invalid range."); + ASSERTMSGLINE(725, ((u32)end - (u32)start) >= 0x40U, "OSCreateHeap(): too small range."); + +#if DEBUG + for(heap = 0; heap < NumHeaps; heap++) { + if (HeapArray[heap].size >= 0) { + ASSERTMSGLINE(735, !DLOverlap(HeapArray[heap].free, start, end), "OSCreateHeap(): invalid range."); + ASSERTMSGLINE(737, !DLOverlap(HeapArray[heap].allocated, start, end), "OSCreateHeap(): invalid range."); + } + } +#endif + + for(heap = 0; heap < NumHeaps; heap++) { + hd = &HeapArray[heap]; + if (hd->size < 0) { + hd->size = (u32)end - (u32)start; + cell = start; + cell->prev = 0; + cell->next = 0; + cell->size = hd->size; +#ifdef ENABLE_HEAPDESC + cell->hd = 0; +#endif + hd->free = cell; + hd->allocated = 0; +#ifdef ENABLE_HEAPDESC + hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0; +#endif + return heap; + } + } +#if DEBUG + OSReport("OSCreateHeap: Warning - Failed to find free heap descriptor."); +#endif + return -1; +} + +void OSDestroyHeap(int heap) { + HeapDesc* hd; + s32 size; + + ASSERTMSGLINE(782, HeapArray, "OSDestroyHeap(): heap is not initialized."); + ASSERTMSGLINE(783, (heap >= 0) && (heap < NumHeaps), "OSDestroyHeap(): invalid heap handle."); + ASSERTMSGLINE(784, HeapArray[heap].size >= 0, "OSDestroyHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; +#if DEBUG + size = DLSize(hd->free); + + if (hd->size != size) { + OSReport("OSDestroyHeap(%d): Warning - free list size %d, heap size %d\n", heap, size, hd->size); + } +#endif + + hd->size = -1; + hd->free = hd->allocated = 0; +#ifdef ENABLE_HEAPDESC + hd->paddingBytes = hd->headerBytes = hd->payloadBytes = 0; + if (__OSCurrHeap == heap) { + __OSCurrHeap = -1; + } +#endif +} + +void OSAddToHeap(int heap, void* start, void* end) { + HeapDesc* hd; + Cell* cell; + int i; + + ASSERTMSGLINE(830, HeapArray, "OSAddToHeap(): heap is not initialized."); + ASSERTMSGLINE(831, (heap >= 0) && (heap < NumHeaps), "OSAddToHeap(): invalid heap handle."); + ASSERTMSGLINE(832, HeapArray[heap].size >= 0, "OSAddToHeap(): invalid heap handle."); + + hd = &HeapArray[heap]; + + ASSERTMSGLINE(836, (u32)start < (u32)end, "OSAddToHeap(): invalid range."); + + start = (void*)(((u32)start + 0x1F) & ~((32)-1)); + end = (void*)(((u32)end) & ~((32)-1)); + + ASSERTMSGLINE(840, ((u32)end - (u32)start) >= 0x40U, "OSAddToHeap(): too small range."); + ASSERTMSGLINE(842, (u32)ArenaStart <= (u32)start && (u32)end <= (u32)ArenaEnd, "OSAddToHeap(): invalid range."); + +#if DEBUG + for(i = 0; i < NumHeaps; i++) { + if (HeapArray[i].size >= 0) { + ASSERTMSGLINE(852, !DLOverlap(HeapArray[i].free, start, end), "OSAddToHeap(): invalid range."); + ASSERTMSGLINE(854, !DLOverlap(HeapArray[i].allocated, start, end), "OSAddToHeap(): invalid range."); + } + } +#endif + cell = (Cell*)start; + cell->size = ((char*)end - (char*)start); +#ifdef ENABLE_HEAPDESC + cell->hd = 0; +#endif + hd->size += cell->size; + hd->free = DLInsert(hd->free, cell); +} + +// custom macro for OSCheckHeap +#define ASSERTREPORT(line, cond) \ + if (!(cond)) { OSReport("OSCheckHeap: Failed " #cond " in %d", line); return -1; } + +s32 OSCheckHeap(int heap) { + HeapDesc* hd; + Cell* cell; + s32 total = 0; + s32 free = 0; + + ASSERTREPORT(898, HeapArray); + ASSERTREPORT(899, 0 <= heap && heap < NumHeaps); + hd = &HeapArray[heap]; + ASSERTREPORT(902, 0 <= hd->size); + + ASSERTREPORT(0x388, hd->allocated == NULL || hd->allocated->prev == NULL); + + for(cell = hd->allocated; cell; cell = cell->next) { + ASSERTREPORT(907, InRange(cell, ArenaStart, ArenaEnd)); + ASSERTREPORT(908, OFFSET(cell, ALIGNMENT) == 0); + ASSERTREPORT(909, cell->next == NULL || cell->next->prev == cell); + ASSERTREPORT(910, MINOBJSIZE <= cell->size); + ASSERTREPORT(911, OFFSET(cell->size, ALIGNMENT) == 0); + total += cell->size; + ASSERTREPORT(914, 0 < total && total <= hd->size); +#ifdef ENABLE_HEAPDESC + ASSERTREPORT(917, cell->hd == hd); + ASSERTREPORT(918, HEADERSIZE + cell->requested <= cell->size); +#endif + } + + + ASSERTREPORT(922, hd->free == NULL || hd->free->prev == NULL); + + for(cell = hd->free; cell; cell = cell->next) { + ASSERTREPORT(925, InRange(cell, ArenaStart, ArenaEnd)); + ASSERTREPORT(926, OFFSET(cell, ALIGNMENT) == 0); + ASSERTREPORT(927, cell->next == NULL || cell->next->prev == cell); + ASSERTREPORT(928, MINOBJSIZE <= cell->size); + ASSERTREPORT(929, OFFSET(cell->size, ALIGNMENT) == 0); + ASSERTREPORT(930, cell->next == NULL || (char*) cell + cell->size < (char*) cell->next); + total += cell->size; + free = (cell->size + free); + free -= HEADERSIZE; + ASSERTREPORT(934, 0 < total && total <= hd->size); +#ifdef ENABLE_HEAPDESC + ASSERTREPORT(937, cell->hd == NULL); +#endif + } + ASSERTREPORT(941, total == hd->size); + return free; +} + +u32 OSReferentSize(void* ptr) { + Cell* cell; + + ASSERTMSGLINE(960, HeapArray, "OSReferentSize(): heap is not initialized."); + ASSERTMSGLINE(962, InRange(ptr, ArenaStart+HEADERSIZE, ArenaEnd), "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(963, !OFFSET(ptr, 32), "OSReferentSize(): invalid pointer."); + cell = (void*)((u32)ptr-HEADERSIZE); + ASSERTMSGLINE(967, cell->hd, "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(969, !(((u32)cell->hd - (u32)HeapArray) % 24), "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(971, ((u32)HeapArray <= (u32)cell->hd) && ((u32)cell->hd < (u32)((u32)HeapArray + (NumHeaps * 0x18))), "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(972, cell->hd->size >= 0, "OSReferentSize(): invalid pointer."); + ASSERTMSGLINE(974, DLLookup(cell->hd->allocated, cell), "OSReferentSize(): invalid pointer."); + return (s32)((u32)cell->size-HEADERSIZE); +} + +void OSDumpHeap(int heap) { + HeapDesc* hd; + Cell* cell; + + OSReport("\nOSDumpHeap(%d):\n", heap); + ASSERTMSGLINE(995, HeapArray, "OSDumpHeap(): heap is not initialized."); + ASSERTMSGLINE(996, (heap >= 0) && (heap < NumHeaps), "OSDumpHeap(): invalid heap handle."); + hd = &HeapArray[heap]; + if (hd->size < 0) { + OSReport("--------Inactive\n"); + return; + } + ASSERTMSGLINE(1005, OSCheckHeap(heap) >= 0, "OSDumpHeap(): heap is broken."); +#ifdef ENABLE_HEAPDESC + OSReport("padding %d/(%f%%) header %d/(%f%%) payload %d/(%f%%)\n", + hd->paddingBytes, (100.0 * hd->paddingBytes / hd->size), hd->headerBytes, (100.0 * hd->headerBytes / hd->size), hd->payloadBytes, + (100.0 * hd->payloadBytes / hd->size)); +#endif + OSReport("addr size end prev next\n"); + OSReport("--------Allocated\n"); + + ASSERTMSGLINE(1018, hd->allocated == NULL || hd->allocated->prev == NULL, "OSDumpHeap(): heap is broken."); + + for(cell = hd->allocated; cell; cell = cell->next) { + OSReport("%x %d %x %x %x\n", cell, cell->size, (char*)cell + cell->size, cell->prev, cell->next); + } + OSReport("--------Free\n"); + for(cell = hd->free; cell; cell = cell->next) { + OSReport("%x %d %x %x %x\n", cell, cell->size, (char*)cell + cell->size, cell->prev, cell->next); + } +} + +void OSVisitAllocated(void (*visitor)(void*, u32)) { + u32 heap; + Cell* cell; + + for(heap = 0; heap < NumHeaps; heap++) { + if (HeapArray[heap].size >= 0) { + for(cell = HeapArray[heap].allocated; cell; cell = cell->next) { + visitor((char*)cell+HEADERSIZE, cell->size); + } + } + } +} diff --git a/src/revolution/os/OSArena.c b/src/revolution/os/OSArena.c new file mode 100644 index 0000000000..42bcc2ae44 --- /dev/null +++ b/src/revolution/os/OSArena.c @@ -0,0 +1,87 @@ +#include +#include + +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) + +static void* s_mem2ArenaHi; +static void* __OSArenaHi; + +static void* __OSArenaLo = (void*)-1; +static void* s_mem2ArenaLo = (void*)-1; + +void* OSGetMEM1ArenaHi(void) { + ASSERTMSGLINE(71, (u32)__OSArenaLo != -1, "OSGetArenaHi(): OSInit() must be called in advance."); + ASSERTMSGLINE(73, (u32)__OSArenaLo <= (u32)__OSArenaHi, "OSGetArenaHi(): invalid arena (hi < lo)."); + return __OSArenaHi; +} + +void* OSGetMEM2ArenaHi(void) { + return s_mem2ArenaHi; +} + +void* OSGetArenaHi(void) { + return OSGetMEM1ArenaHi(); +} + +void* OSGetMEM1ArenaLo(void) { + ASSERTMSGLINE(99, (u32)__OSArenaLo != -1, "OSGetArenaLo(): OSInit() must be called in advance."); + ASSERTMSGLINE(101, (u32)__OSArenaLo <= (u32)__OSArenaHi, "OSGetArenaLo(): invalid arena (hi < lo)."); + return __OSArenaLo; +} + +void* OSGetMEM2ArenaLo(void) { + return s_mem2ArenaLo; +} + +void* OSGetArenaLo(void) { + return OSGetMEM1ArenaLo(); +} + +void OSSetMEM1ArenaHi(void* newHi) { + __OSArenaHi = newHi; +} + +void OSSetMEM2ArenaHi(void* newHi) { + s_mem2ArenaHi = newHi; +} + +void OSSetArenaHi(void* newHi) { + OSSetMEM1ArenaHi(newHi); +} + +void OSSetMEM1ArenaLo(void* newLo) { + __OSArenaLo = newLo; +} + +void OSSetMEM2ArenaLo(void* newLo) { + s_mem2ArenaLo = newLo; +} + +void OSSetArenaLo(void* newLo) { + OSSetMEM1ArenaLo(newLo); +} + +void* OSAllocFromMEM1ArenaLo(u32 size, u32 align) { + void* ptr; + u8* arenaLo; + + ptr = OSGetMEM1ArenaLo(); + arenaLo = ptr = (void*)ROUND(ptr, align); + arenaLo += size; + arenaLo = (u8*)ROUND(arenaLo, align); + OSSetMEM1ArenaLo(arenaLo); + return ptr; +} + +void* OSAllocFromMEM1ArenaHi(u32 size, u32 align) { + void* ptr; + u8* arenaHi; + + arenaHi = OSGetMEM1ArenaHi(); + arenaHi = (u8*)TRUNC(arenaHi, align); + arenaHi -= size; + arenaHi = ptr = (void*)TRUNC(arenaHi, align); + OSSetMEM1ArenaHi(arenaHi); + return ptr; +} diff --git a/src/revolution/os/OSAudioSystem.c b/src/revolution/os/OSAudioSystem.c new file mode 100644 index 0000000000..d9e1df68c9 --- /dev/null +++ b/src/revolution/os/OSAudioSystem.c @@ -0,0 +1,192 @@ +#include +#include + +#include "__os.h" + +// prototypes +void __AIClockInit(u32); + +static u8 DSPInitCode[128] = { + 0x02, 0x9F, 0x00, 0x10, 0x02, 0x9F, 0x00, 0x33, 0x02, 0x9F, 0x00, 0x34, 0x02, 0x9F, 0x00, 0x35, + 0x02, 0x9F, 0x00, 0x36, 0x02, 0x9F, 0x00, 0x37, 0x02, 0x9F, 0x00, 0x38, 0x02, 0x9F, 0x00, 0x39, + 0x12, 0x06, 0x12, 0x03, 0x12, 0x04, 0x12, 0x05, 0x00, 0x80, 0x80, 0x00, 0x00, 0x88, 0xFF, 0xFF, + 0x00, 0x84, 0x10, 0x00, 0x00, 0x64, 0x00, 0x1D, 0x02, 0x18, 0x00, 0x00, 0x81, 0x00, 0x1C, 0x1E, + 0x00, 0x44, 0x1B, 0x1E, 0x00, 0x84, 0x08, 0x00, 0x00, 0x64, 0x00, 0x27, 0x19, 0x1E, 0x00, 0x00, + 0x00, 0xDE, 0xFF, 0xFC, 0x02, 0xA0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x28, 0x16, 0xFC, 0x00, 0x54, + 0x16, 0xFD, 0x43, 0x48, 0x00, 0x21, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0xFF, + 0x02, 0xFF, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void waitMicroSec(u32 usec) { + OSTick start_tick = OSGetTick(); + while (OSTicksToMicroseconds(OSGetTick() - start_tick) < usec); +} + +#define PPCACR_OFFSET (OS_BASE_UNCACHED + 0x800000) +#define PPCACR (0xD000000 + PPCACR_OFFSET) + +#define busRd32(addr) (*(volatile u32 *)(addr)) +#define busWrt32(addr, val) (*(volatile u32 *)(addr)) = (val) + +void __AIClockInit(u32 compatB) { + u32 reg; + + reg = busRd32(PPCACR + 0x180); + reg &= ~((u32)1 << 8); + reg |= ((u32)compatB << 8); + reg &= ~((u32)1 << 7); + busWrt32(PPCACR + 0x180, reg); + + reg = busRd32(PPCACR + 0x1D0); + reg &= ~((u32)1 << 31); + reg &= ~((u32)1 << 30); + busWrt32(PPCACR + 0x1D0, reg); + + waitMicroSec(100); + + if (compatB == 0) { + reg = busRd32(PPCACR + 0x1CC); + reg &= ~0x3FFC0; + reg |= ((u32)63 << 6); + reg &= ~0x3F; + reg &= ~0x7FC0000; + reg |= ((u32)281 << 18); + busWrt32(PPCACR + 0x1CC, reg); + } else { + reg = busRd32(PPCACR + 0x1CC); + reg &= ~0x3FFC0; + reg |= ((u32)1023 << 6); + reg &= ~0x3F; + reg |= ((u32)14); + reg &= ~0x7FC0000; + reg |= ((u32)300 << 18); + busWrt32(PPCACR + 0x1CC, reg); + } + + waitMicroSec(100); + + reg = busRd32(PPCACR + 0x1D0); + reg &= ~((u32)1 << 28); + busWrt32(PPCACR + 0x1D0, reg); + + waitMicroSec(1000); + + reg = busRd32(PPCACR + 0x1D0); + reg &= ~((u32)1 << 30); + reg |= ((u32)1 << 30); + busWrt32(PPCACR + 0x1D0, reg); + + waitMicroSec(1000); + + reg = busRd32(PPCACR + 0x1D0); + reg &= ~((u32)1 << 31); + reg |= ((u32)1 << 31); + busWrt32(PPCACR + 0x1D0, reg); + + waitMicroSec(1000); +} + +#define __DSPWorkBuffer (void*)0x81000000 + +void __OSInitAudioSystem(void) { + u8 errFlag; + u16 reg16; + u32 start_tick; + + if (!__OSInIPL) { + __AIClockInit(1); + } + + memcpy((void*)((u32)OSGetArenaHi() - 0x80), __DSPWorkBuffer, sizeof(DSPInitCode)); + memcpy(__DSPWorkBuffer, (void*)DSPInitCode, sizeof(DSPInitCode)); + DCFlushRange(__DSPWorkBuffer, sizeof(DSPInitCode)); + + __DSPRegs[9] = 0x43; + ASSERTMSGLINE(253, !(__DSPRegs[5] & 0x200), "__OSInitAudioSystem(): ARAM DMA already in progress"); + ASSERTMSGLINE(257, !(__DSPRegs[5] & 0x400), "__OSInitAudioSystem(): DSP DMA already in progress"); + ASSERTMSGLINE(261, (__DSPRegs[5] & 0x004), "__OSInitAudioSystem(): DSP already working"); + + __DSPRegs[5] = 0x8AC; + __DSPRegs[5] |= 1; + + while (__DSPRegs[5] & 1); + __DSPRegs[0] = 0; + + while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000); + + *(u32*)&__DSPRegs[16] = 0x1000000; + *(u32*)&__DSPRegs[18] = 0; + *(u32*)&__DSPRegs[20] = 0x20; + + reg16 = __DSPRegs[5]; + while (!(reg16 & 0x20)) + reg16 = __DSPRegs[5]; + + __DSPRegs[5] = reg16; + + start_tick = OSGetTick(); + while ((s32)(OSGetTick() - start_tick) < 0x892); + + *(u32*)&__DSPRegs[16] = 0x1000000; + *(u32*)&__DSPRegs[18] = 0; + *(u32*)&__DSPRegs[20] = 0x20; + + reg16 = __DSPRegs[5]; + while (!(reg16 & 0x20)) { + reg16 = __DSPRegs[5]; + } + __DSPRegs[5] = reg16; + + __DSPRegs[5] &= ~0x800; + while ((__DSPRegs[5]) & 0x400); + + __DSPRegs[5] &= ~4; + errFlag = 0; + + reg16 = __DSPRegs[2]; + + while (!(reg16 & 0x8000)) { + reg16 = __DSPRegs[2]; + } + + if(((u32)((reg16 << 16) | __DSPRegs[3]) + 0x7FAC0000U) != 0x4348) { + ASSERTMSGLINE(333, 0, "__OSInitAudioSystem(): DSP returns invalid message"); + } + + __DSPRegs[5] |= 4; + __DSPRegs[5] = 0x8AC; + __DSPRegs[5] |= 1; + while (__DSPRegs[5] & 1); + + memcpy(__DSPWorkBuffer, (void*)((u32)OSGetArenaHi() - 0x80), sizeof(DSPInitCode)); +} + +void __OSStopAudioSystem(void) { + u16 reg16; + u32 start_tick; + + #define waitUntil(load, mask) \ + reg16 = (load); \ + while (reg16 & (mask)) { \ + reg16 = (load); \ + } + + __DSPRegs[5] = 0x804; + reg16 = __DSPRegs[27]; + __DSPRegs[27] = reg16 & ~0x8000; + waitUntil(__DSPRegs[5], 0x400); + waitUntil(__DSPRegs[5], 0x200); + __DSPRegs[5] = 0x8ac; + __DSPRegs[0] = 0; + + while (((__DSPRegs[2] << 16) | __DSPRegs[3]) & 0x80000000); + + start_tick = OSGetTick(); + while ((s32)(OSGetTick() - start_tick) < 0x2c); + + reg16 = __DSPRegs[5]; + __DSPRegs[5] = reg16 | 1; + waitUntil(__DSPRegs[5], 0x001); + + #undef waitUntil +} diff --git a/src/revolution/os/OSCache.c b/src/revolution/os/OSCache.c new file mode 100644 index 0000000000..dbdd1281c6 --- /dev/null +++ b/src/revolution/os/OSCache.c @@ -0,0 +1,639 @@ +#include +#include +#include + +#include "__os.h" + +#define HID2 920 + +// prototypes +void DMAErrorHandler(OSError error, OSContext* context, ...); + +#ifdef __GEKKO__ +asm void DCFlashInvalidate(void) { + nofralloc + mfspr r3, HID0 + ori r3, r3, 0x400 + mtspr HID0, r3 + blr +} + +asm void DCEnable(void) { + nofralloc + sync + mfspr r3, HID0 + ori r3, r3, 0x4000 + mtspr HID0, r3 + blr +} + +asm void DCDisable(void) { + nofralloc + sync + mfspr r3, HID0 + rlwinm r3, r3, 0, 18, 16 + mtspr HID0, r3 + blr +} + +asm void DCFreeze(void) { + nofralloc + sync + mfspr r3, HID0 + ori r3, r3, 0x1000 + mtspr HID0, r3 + blr +} + +asm void DCUnfreeze(void) { + nofralloc + mfspr r3, HID0 + rlwinm r3, r3, 0, 20, 18 + mtspr HID0, r3 + blr +} + +asm void DCTouchLoad(register void* addr) { + nofralloc + dcbt r0, addr + blr +} + +asm void DCBlockZero(register void* addr) { + nofralloc + dcbz r0, addr + blr +} + +asm void DCBlockStore(register void* addr) { + nofralloc + dcbst r0, addr + blr +} + +asm void DCBlockFlush(register void* addr) { + nofralloc + dcbf r0, addr + blr +} + +asm void DCBlockInvalidate(register void* addr) { + nofralloc + dcbi r0, addr + blr +} + +asm void DCInvalidateRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbi r0, addr + addi addr, addr, 32 + bdnz @1 + blr +} + +asm void DCFlushRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbf r0, addr + addi addr, addr, 32 + bdnz @1 + sc + blr +} + +asm void DCStoreRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbst r0, addr + addi addr, addr, 32 + bdnz @1 + sc + + blr +} + +asm void DCFlushRangeNoSync(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbf r0, addr + addi addr, addr, 32 + bdnz @1 + blr +} + +asm void DCStoreRangeNoSync(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbst r0, addr + addi addr, addr, 32 + bdnz @1 + + blr +} + +asm void DCZeroRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbz r0, addr + addi addr, addr, 32 + bdnz @1 + + blr +} + +asm void DCTouchRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + dcbt r0, addr + addi addr, addr, 32 + bdnz @1 + + blr +} + +asm void ICInvalidateRange(register void* addr, register u32 nBytes) { + nofralloc + cmplwi nBytes, 0 + blelr + clrlwi r5, addr, 27 + add nBytes, nBytes, r5 + addi nBytes, nBytes, 31 + srwi nBytes, nBytes, 5 + mtctr nBytes + +@1 + icbi r0, addr + addi addr, addr, 32 + bdnz @1 + sync + isync + + blr +} + +asm void ICFlashInvalidate(void) { + nofralloc + mfspr r3, HID0 + ori r3, r3, 0x800 + mtspr HID0, r3 + blr +} + +asm void ICEnable(void) { + nofralloc + isync + mfspr r3, HID0 + ori r3, r3, 0x8000 + mtspr HID0, r3 + blr +} + +asm void ICDisable(void) { + nofralloc + isync + mfspr r3, HID0 + rlwinm r3, r3, 0, 17, 15 + mtspr HID0, r3 + blr +} + +asm void ICFreeze(void) { + nofralloc + isync + mfspr r3, HID0 + ori r3, r3, 0x2000 + mtspr HID0, r3 + blr +} + +asm void ICUnfreeze(void) { + nofralloc + mfspr r3, HID0 + rlwinm r3, r3, 0, 19, 17 + mtspr HID0, r3 + blr +} + +asm void ICBlockInvalidate(register void* addr) { + nofralloc + icbi r0, addr + blr +} + +asm void ICSync(void) { + nofralloc + isync + blr +} + +#define LC_LINES 512 +#define CACHE_LINES 1024 + +static asm void __LCEnable(void) { + nofralloc + mfmsr r5 + ori r5, r5, 0x1000 + mtmsr r5 + + lis r3, OS_CACHED_REGION_PREFIX + li r4, CACHE_LINES + mtctr r4 +_touchloop: + dcbt 0,r3 + dcbst 0,r3 + addi r3,r3,32 + bdnz _touchloop + mfspr r4, HID2 + oris r4, r4, 0x100F + mtspr HID2, r4 + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + lis r3, LC_BASE_PREFIX + ori r3, r3, 0x0002 + mtspr DBAT3L, r3 + ori r3, r3, 0x01fe + mtspr DBAT3U, r3 + isync + lis r3, LC_BASE_PREFIX + li r6, LC_LINES + mtctr r6 + li r6, 0 + +_lockloop: + dcbz_l r6, r3 + addi r3, r3, 32 + bdnz+ _lockloop + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + blr +} + +void LCEnable(void) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + __LCEnable(); + OSRestoreInterrupts(enabled); +} + +asm void LCDisable(void) { + nofralloc + lis r3, LC_BASE_PREFIX + li r4, LC_LINES + mtctr r4 +@1 + dcbi r0, r3 + addi r3, r3, 32 + bdnz @1 + mfspr r4, HID2 + rlwinm r4, r4, 0, 4, 2 + mtspr HID2, r4 + blr +} + +asm void LCAllocOneTag(register BOOL invalidate, register void* tag) { + nofralloc + cmpwi invalidate, 0 + beq @1 + dcbi r0, tag +@1 + dcbz_l r0, tag + blr +} + +asm void LCAllocTags(register BOOL invalidate, register void* startTag, register u32 numBlocks) { + nofralloc + mflr r6 + cmplwi numBlocks, 0 + ble @3 + mtctr numBlocks + cmpwi invalidate, 0 + beq @2 +@1 + dcbi r0, startTag + dcbz_l r0, startTag + addi startTag, startTag, 32 + bdnz @1 + b @3 +@2 + dcbz_l r0, startTag + addi startTag, startTag, 32 + bdnz @2 +@3 + mtlr r6 + blr +} + +asm void LCLoadBlocks(register void* destTag, register void* srcAddr, register u32 numBlocks) { + nofralloc + rlwinm r6, numBlocks, 30, 27, 31 + rlwinm srcAddr, srcAddr, 0, 4, 31 + or r6, r6, srcAddr + mtspr DMA_U, r6 + rlwinm r6, numBlocks, 2, 28, 29 + or r6, r6, destTag + ori r6, r6, 0x12 + mtspr DMA_L, r6 + blr +} + +asm void LCStoreBlocks(register void* destAddr, register void* srcTag, register u32 numBlocks) { + nofralloc + rlwinm r6, numBlocks, 30, 27, 31 + rlwinm destAddr, destAddr, 0, 3, 31 + or r6, r6, destAddr + mtspr DMA_U, r6 + rlwinm r6, numBlocks, 2, 28, 29 + or r6, r6, srcTag + ori r6, r6, 0x2 + mtspr DMA_L, r6 + blr +} +#endif + +void LCAlloc(void* addr, u32 nBytes) { + u32 numBlocks = nBytes >> 5; + u32 hid2 = PPCMfhid2(); + + ASSERTMSGLINE(1319, !((u32)addr & 31), "LCAlloc(): addr must be 32 byte aligned"); + ASSERTMSGLINE(1321, !((u32)nBytes & 31), "LCAlloc(): nBytes must be 32 byte aligned"); + + if ((hid2 & 0x10000000) == 0) { + LCEnable(); + } + LCAllocTags(TRUE, addr, numBlocks); +} + +void LCAllocNoInvalidate(void* addr, u32 nBytes) { + u32 numBlocks = nBytes >> 5; + u32 hid2 = PPCMfhid2(); + + ASSERTMSGLINE(1366, !((u32)addr & 31), "LCAllocNoFlush(): addr must be 32 byte aligned"); + ASSERTMSGLINE(1368, !((u32)nBytes & 31), "LCAllocNoFlush(): nBytes must be 32 byte aligned"); + + if ((hid2 & 0x10000000) == 0) { + LCEnable(); + } + LCAllocTags(FALSE, addr, numBlocks); +} + +u32 LCLoadData(void* destAddr, void* srcAddr, u32 nBytes) { + u32 numBlocks = (nBytes + 31) / 32; + u32 numTransactions = (numBlocks + 128 - 1) / 128; + + ASSERTMSGLINE(1426, !((u32)srcAddr & 31), "LCLoadData(): srcAddr not 32 byte aligned"); + ASSERTMSGLINE(1428, !((u32)destAddr & 31), "LCLoadData(): destAddr not 32 byte aligned"); + + while (numBlocks > 0) { + if (numBlocks < 128) { + LCLoadBlocks(destAddr, srcAddr, numBlocks); + numBlocks = 0; + } else { + LCLoadBlocks(destAddr, srcAddr, 0); + numBlocks -= 128; + destAddr = (void*)((u32)destAddr + 4096); + srcAddr = (void*)((u32)srcAddr + 4096); + } + } + + return numTransactions; +} + +u32 LCStoreData(void* destAddr, void* srcAddr, u32 nBytes) { + u32 numBlocks = (nBytes + 31) / 32; + u32 numTransactions = (numBlocks + 128 - 1) / 128; + + ASSERTMSGLINE(1534, !((u32)srcAddr & 31), "LCStoreData(): srcAddr not 32 byte aligned"); + ASSERTMSGLINE(1536, !((u32)destAddr & 31), "LCStoreData(): destAddr not 32 byte aligned"); + + while (numBlocks > 0) { + if (numBlocks < 128) { + LCStoreBlocks(destAddr, srcAddr, numBlocks); + numBlocks = 0; + } else { + LCStoreBlocks(destAddr, srcAddr, 0); + numBlocks -= 128; + destAddr = (void*)((u32)destAddr + 4096); + srcAddr = (void*)((u32)srcAddr + 4096); + } + } + + return numTransactions; +} + +#ifdef __GEKKO__ +asm u32 LCQueueLength(void) { + nofralloc + mfspr r4, HID2 + rlwinm r3, r4, 8, 28, 31 + blr +} + +asm void LCQueueWait(register u32 len) { + nofralloc +@1 + mfspr r4, HID2 + rlwinm r4, r4, 8, 28, 31 + cmpw r4, r3 + bgt @1 + blr +} +#endif + +void LCFlushQueue() { + union { + u32 val; + struct { + u32 lcAddr : 27; + u32 dmaLd : 1; + u32 dmaLenL : 2; + u32 dmaTrigger : 1; + u32 dmaFlush : 1; + } f; + } dmaL; + + dmaL.val = 0; + dmaL.f.dmaFlush = 1; + PPCMtdmaU(0); + PPCMtdmaL(dmaL.val); + PPCSync(); +} + +static void L2Init(void) { + u32 oldMSR; + oldMSR = PPCMfmsr(); + __sync(); + PPCMtmsr(MSR_IR | MSR_DR); + __sync(); + L2Disable(); + L2GlobalInvalidate(); + PPCMtmsr(oldMSR); +} + +void L2Enable(void) { + PPCMtl2cr((PPCMfl2cr() | L2CR_L2E) & ~L2CR_L2I); +} + +void L2Disable(void) { + __sync(); + PPCMtl2cr(PPCMfl2cr() & ~0x80000000); + __sync(); +} + +void L2GlobalInvalidate(void) { + L2Disable(); + PPCMtl2cr(PPCMfl2cr() | 0x00200000); + while (PPCMfl2cr() & 0x00000001u); + + PPCMtl2cr(PPCMfl2cr() & ~0x00200000); + while (PPCMfl2cr() & 0x00000001u) { + + } +} + +void L2SetDataOnly(BOOL dataOnly) { + if (dataOnly) { + PPCMtl2cr(PPCMfl2cr() | 0x400000); + return; + } + PPCMtl2cr(PPCMfl2cr() & 0xFFBFFFFF); +} + +void L2SetWriteThrough(BOOL writeThrough) { + if (writeThrough) { + PPCMtl2cr(PPCMfl2cr() | 0x80000); + return; + } + PPCMtl2cr(PPCMfl2cr() & 0xFFF7FFFF); +} + +void DMAErrorHandler(OSError error, OSContext* context, ...) { + u32 hid2 = PPCMfhid2(); + + OSReport("Machine check received\n"); + OSReport("HID2 = 0x%x SRR1 = 0x%x\n", hid2, context->srr1); + if (!(hid2 & (HID2_DCHERR | HID2_DNCERR | HID2_DCMERR | HID2_DQOERR)) || !(context->srr1 & SRR1_DMA_BIT)) { + OSReport("Machine check was not DMA/locked cache related\n"); + OSDumpContext(context); + PPCHalt(); + } + + OSReport("DMAErrorHandler(): An error occurred while processing DMA.\n"); + OSReport("The following errors have been detected and cleared :\n"); + + if (hid2 & HID2_DCHERR) { + OSReport("\t- Requested a locked cache tag that was already in the cache\n"); + } + + if (hid2 & HID2_DNCERR) { + OSReport("\t- DMA attempted to access normal cache\n"); + } + + if (hid2 & HID2_DCMERR) { + OSReport("\t- DMA missed in data cache\n"); + } + + if (hid2 & HID2_DQOERR) { + OSReport("\t- DMA queue overflowed\n"); + } + + // write hid2 back to clear the error bits + PPCMthid2(hid2); +} + +void __OSCacheInit() { + if (!(PPCMfhid0() & HID0_ICE)) { + ICEnable(); + } + + if (!(PPCMfhid0() & HID0_DCE)) { + DCEnable(); + } + + if (!(PPCMfl2cr() & L2CR_L2E)) { + L2Init(); + L2Enable(); + } + + OSSetErrorHandler(OS_ERROR_MACHINE_CHECK, DMAErrorHandler); +} diff --git a/src/revolution/os/OSContext.c b/src/revolution/os/OSContext.c new file mode 100644 index 0000000000..887215ab60 --- /dev/null +++ b/src/revolution/os/OSContext.c @@ -0,0 +1,653 @@ +#include +#include + +#include "__os.h" + +// external functions +extern void __RAS_OSDisableInterrupts_begin(); +extern void __RAS_OSDisableInterrupts_end(); +extern void DBPrintf(char*, ...); + +#define HID2 920 + +volatile OSContext* __OSCurrentContext AT_ADDRESS(OS_BASE_CACHED | 0x00D4); +volatile OSContext* __OSFPUContext AT_ADDRESS(OS_BASE_CACHED | 0x00D8); + +#ifdef __GEKKO__ +static asm void __OSLoadFPUContext(register u32 dummy, register OSContext* fpucontext) { + nofralloc + lhz r5, fpucontext->state; + clrlwi. r5, r5, 31 + beq _return + + lfd fp0, OS_CONTEXT_FPSCR(fpucontext) + mtfsf 0xFF, fp0 + mfspr r5, HID2 + rlwinm. r5, r5, 3, 31, 31 + beq _regular_FPRs + + psq_l fp0, OS_CONTEXT_PSF0(fpucontext), 0, 0 + psq_l fp1, OS_CONTEXT_PSF1(fpucontext), 0, 0 + psq_l fp2, OS_CONTEXT_PSF2(fpucontext), 0, 0 + psq_l fp3, OS_CONTEXT_PSF3(fpucontext), 0, 0 + psq_l fp4, OS_CONTEXT_PSF4(fpucontext), 0, 0 + psq_l fp5, OS_CONTEXT_PSF5(fpucontext), 0, 0 + psq_l fp6, OS_CONTEXT_PSF6(fpucontext), 0, 0 + psq_l fp7, OS_CONTEXT_PSF7(fpucontext), 0, 0 + psq_l fp8, OS_CONTEXT_PSF8(fpucontext), 0, 0 + psq_l fp9, OS_CONTEXT_PSF9(fpucontext), 0, 0 + psq_l fp10, OS_CONTEXT_PSF10(fpucontext), 0, 0 + psq_l fp11, OS_CONTEXT_PSF11(fpucontext), 0, 0 + psq_l fp12, OS_CONTEXT_PSF12(fpucontext), 0, 0 + psq_l fp13, OS_CONTEXT_PSF13(fpucontext), 0, 0 + psq_l fp14, OS_CONTEXT_PSF14(fpucontext), 0, 0 + psq_l fp15, OS_CONTEXT_PSF15(fpucontext), 0, 0 + psq_l fp16, OS_CONTEXT_PSF16(fpucontext), 0, 0 + psq_l fp17, OS_CONTEXT_PSF17(fpucontext), 0, 0 + psq_l fp18, OS_CONTEXT_PSF18(fpucontext), 0, 0 + psq_l fp19, OS_CONTEXT_PSF19(fpucontext), 0, 0 + psq_l fp20, OS_CONTEXT_PSF20(fpucontext), 0, 0 + psq_l fp21, OS_CONTEXT_PSF21(fpucontext), 0, 0 + psq_l fp22, OS_CONTEXT_PSF22(fpucontext), 0, 0 + psq_l fp23, OS_CONTEXT_PSF23(fpucontext), 0, 0 + psq_l fp24, OS_CONTEXT_PSF24(fpucontext), 0, 0 + psq_l fp25, OS_CONTEXT_PSF25(fpucontext), 0, 0 + psq_l fp26, OS_CONTEXT_PSF26(fpucontext), 0, 0 + psq_l fp27, OS_CONTEXT_PSF27(fpucontext), 0, 0 + psq_l fp28, OS_CONTEXT_PSF28(fpucontext), 0, 0 + psq_l fp29, OS_CONTEXT_PSF29(fpucontext), 0, 0 + psq_l fp30, OS_CONTEXT_PSF30(fpucontext), 0, 0 + psq_l fp31, OS_CONTEXT_PSF31(fpucontext), 0, 0 + +_regular_FPRs: + lfd fp0, fpucontext->fpr[0] + lfd fp1, fpucontext->fpr[1] + lfd fp2, fpucontext->fpr[2] + lfd fp3, fpucontext->fpr[3] + lfd fp4, fpucontext->fpr[4] + lfd fp5, fpucontext->fpr[5] + lfd fp6, fpucontext->fpr[6] + lfd fp7, fpucontext->fpr[7] + lfd fp8, fpucontext->fpr[8] + lfd fp9, fpucontext->fpr[9] + lfd fp10, fpucontext->fpr[10] + lfd fp11, fpucontext->fpr[11] + lfd fp12, fpucontext->fpr[12] + lfd fp13, fpucontext->fpr[13] + lfd fp14, fpucontext->fpr[14] + lfd fp15, fpucontext->fpr[15] + lfd fp16, fpucontext->fpr[16] + lfd fp17, fpucontext->fpr[17] + lfd fp18, fpucontext->fpr[18] + lfd fp19, fpucontext->fpr[19] + lfd fp20, fpucontext->fpr[20] + lfd fp21, fpucontext->fpr[21] + lfd fp22, fpucontext->fpr[22] + lfd fp23, fpucontext->fpr[23] + lfd fp24, fpucontext->fpr[24] + lfd fp25, fpucontext->fpr[25] + lfd fp26, fpucontext->fpr[26] + lfd fp27, fpucontext->fpr[27] + lfd fp28, fpucontext->fpr[28] + lfd fp29, fpucontext->fpr[29] + lfd fp30, fpucontext->fpr[30] + lfd fp31, fpucontext->fpr[31] +_return: + blr +} + +static asm void __OSSaveFPUContext(register u32 dummy1, register u32 dummy2, register OSContext* fpucontext) { + nofralloc + + lhz r3, fpucontext->state + ori r3, r3, 1 + sth r3, fpucontext->state + + stfd fp0, fpucontext->fpr[0] + stfd fp1, fpucontext->fpr[1] + stfd fp2, fpucontext->fpr[2] + stfd fp3, fpucontext->fpr[3] + stfd fp4, fpucontext->fpr[4] + stfd fp5, fpucontext->fpr[5] + stfd fp6, fpucontext->fpr[6] + stfd fp7, fpucontext->fpr[7] + stfd fp8, fpucontext->fpr[8] + stfd fp9, fpucontext->fpr[9] + stfd fp10, fpucontext->fpr[10] + stfd fp11, fpucontext->fpr[11] + stfd fp12, fpucontext->fpr[12] + stfd fp13, fpucontext->fpr[13] + stfd fp14, fpucontext->fpr[14] + stfd fp15, fpucontext->fpr[15] + stfd fp16, fpucontext->fpr[16] + stfd fp17, fpucontext->fpr[17] + stfd fp18, fpucontext->fpr[18] + stfd fp19, fpucontext->fpr[19] + stfd fp20, fpucontext->fpr[20] + stfd fp21, fpucontext->fpr[21] + stfd fp22, fpucontext->fpr[22] + stfd fp23, fpucontext->fpr[23] + stfd fp24, fpucontext->fpr[24] + stfd fp25, fpucontext->fpr[25] + stfd fp26, fpucontext->fpr[26] + stfd fp27, fpucontext->fpr[27] + stfd fp28, fpucontext->fpr[28] + stfd fp29, fpucontext->fpr[29] + stfd fp30, fpucontext->fpr[30] + stfd fp31, fpucontext->fpr[31] + + mffs fp0 + stfd fp0, OS_CONTEXT_FPSCR(fpucontext) + + lfd fp0, fpucontext->fpr[0] + + mfspr r3, HID2 + rlwinm. r3, r3, 3, 31, 31 + bc 12, 2, _return + + psq_st fp0, OS_CONTEXT_PSF0(fpucontext), 0, 0 + psq_st fp1, OS_CONTEXT_PSF1(fpucontext), 0, 0 + psq_st fp2, OS_CONTEXT_PSF2(fpucontext), 0, 0 + psq_st fp3, OS_CONTEXT_PSF3(fpucontext), 0, 0 + psq_st fp4, OS_CONTEXT_PSF4(fpucontext), 0, 0 + psq_st fp5, OS_CONTEXT_PSF5(fpucontext), 0, 0 + psq_st fp6, OS_CONTEXT_PSF6(fpucontext), 0, 0 + psq_st fp7, OS_CONTEXT_PSF7(fpucontext), 0, 0 + psq_st fp8, OS_CONTEXT_PSF8(fpucontext), 0, 0 + psq_st fp9, OS_CONTEXT_PSF9(fpucontext), 0, 0 + psq_st fp10, OS_CONTEXT_PSF10(fpucontext), 0, 0 + psq_st fp11, OS_CONTEXT_PSF11(fpucontext), 0, 0 + psq_st fp12, OS_CONTEXT_PSF12(fpucontext), 0, 0 + psq_st fp13, OS_CONTEXT_PSF13(fpucontext), 0, 0 + psq_st fp14, OS_CONTEXT_PSF14(fpucontext), 0, 0 + psq_st fp15, OS_CONTEXT_PSF15(fpucontext), 0, 0 + psq_st fp16, OS_CONTEXT_PSF16(fpucontext), 0, 0 + psq_st fp17, OS_CONTEXT_PSF17(fpucontext), 0, 0 + psq_st fp18, OS_CONTEXT_PSF18(fpucontext), 0, 0 + psq_st fp19, OS_CONTEXT_PSF19(fpucontext), 0, 0 + psq_st fp20, OS_CONTEXT_PSF20(fpucontext), 0, 0 + psq_st fp21, OS_CONTEXT_PSF21(fpucontext), 0, 0 + psq_st fp22, OS_CONTEXT_PSF22(fpucontext), 0, 0 + psq_st fp23, OS_CONTEXT_PSF23(fpucontext), 0, 0 + psq_st fp24, OS_CONTEXT_PSF24(fpucontext), 0, 0 + psq_st fp25, OS_CONTEXT_PSF25(fpucontext), 0, 0 + psq_st fp26, OS_CONTEXT_PSF26(fpucontext), 0, 0 + psq_st fp27, OS_CONTEXT_PSF27(fpucontext), 0, 0 + psq_st fp28, OS_CONTEXT_PSF28(fpucontext), 0, 0 + psq_st fp29, OS_CONTEXT_PSF29(fpucontext), 0, 0 + psq_st fp30, OS_CONTEXT_PSF30(fpucontext), 0, 0 + psq_st fp31, OS_CONTEXT_PSF31(fpucontext), 0, 0 + +_return: + blr +} + +asm void OSLoadFPUContext(register OSContext* fpucontext) { + nofralloc + addi r4, fpucontext, 0 + b __OSLoadFPUContext +} + +asm void OSSaveFPUContext(register OSContext* fpucontext) { + nofralloc + addi r5, fpucontext, 0 + b __OSSaveFPUContext +} + +asm void OSSetCurrentContext(register OSContext* context){ + nofralloc + + addis r4, r0, OS_CACHED_REGION_PREFIX + + stw context, 0x00D4(r4) + + clrlwi r5, context, 2 + stw r5, 0x00C0(r4) + + lwz r5, 0x00D8(r4) + cmpw r5, context + bne _disableFPU + + lwz r6, context->srr1 + ori r6, r6, 0x2000 + stw r6, context->srr1 + mfmsr r6 + ori r6, r6, 2 + mtmsr r6 + blr + +_disableFPU: + lwz r6, context->srr1 + rlwinm r6, r6, 0, 19, 17 + stw r6, context->srr1 + mfmsr r6 + rlwinm r6, r6, 0, 19, 17 + ori r6, r6, 2 + mtmsr r6 + isync + blr +} +#endif + +OSContext* OSGetCurrentContext(void) { + return (OSContext*)__OSCurrentContext; +} + +#ifdef __GEKKO__ +asm u32 OSSaveContext(register OSContext* context) { + nofralloc + stmw r13, context->gpr[13] + mfspr r0, GQR1 + stw r0, context->gqr[1] + mfspr r0, GQR2 + stw r0, context->gqr[2] + mfspr r0, GQR3 + stw r0, context->gqr[3] + mfspr r0, GQR4 + stw r0, context->gqr[4] + mfspr r0, GQR5 + stw r0, context->gqr[5] + mfspr r0, GQR6 + stw r0, context->gqr[6] + mfspr r0, GQR7 + stw r0, context->gqr[7] + mfcr r0 + stw r0, context->cr + mflr r0 + stw r0, context->lr + stw r0, context->srr0 + mfmsr r0 + stw r0, context->srr1 + mfctr r0 + stw r0, context->ctr + mfxer r0 + stw r0, context->xer + stw r1, context->gpr[1] + stw r2, context->gpr[2] + li r0, 0x1 + stw r0, context->gpr[3] + li r3, 0 + blr +} + +asm void OSLoadContext(register OSContext* context) { + nofralloc + + lis r4,__RAS_OSDisableInterrupts_begin@ha + lwz r6,context->srr0 + addi r5,r4,__RAS_OSDisableInterrupts_begin@l + cmplw r6,r5 + ble _notInRAS + lis r4,__RAS_OSDisableInterrupts_end@ha + addi r0,r4,__RAS_OSDisableInterrupts_end@l + cmplw r6,r0 + bge _notInRAS + stw r5,context->srr0 + +_notInRAS: + + lwz r0, context->gpr[0] + lwz r1, context->gpr[1] + lwz r2, context->gpr[2] + + lhz r4, context->state + rlwinm. r5, r4, 0, 30, 30 + beq notexc + rlwinm r4, r4, 0, 31, 29 + sth r4, context->state + lmw r5, context->gpr[5] + b misc +notexc: + lmw r13, context->gpr[13] + misc: + + lwz r4, context->gqr[1] + mtspr GQR1, r4 + lwz r4, context->gqr[2] + mtspr GQR2, r4 + lwz r4, context->gqr[3] + mtspr GQR3, r4 + lwz r4, context->gqr[4] + mtspr GQR4, r4 + lwz r4, context->gqr[5] + mtspr GQR5, r4 + lwz r4, context->gqr[6] + mtspr GQR6, r4 + lwz r4, context->gqr[7] + mtspr GQR7, r4 + + lwz r4, context->cr + mtcr r4 + lwz r4, context->lr + mtlr r4 + lwz r4, context->ctr + mtctr r4 + lwz r4, context->xer + mtxer r4 + + mfmsr r4 + rlwinm r4, r4, 0, 17, 15 + rlwinm r4, r4, 0, 31, 29 + mtmsr r4 + + lwz r4, context->srr0 + mtsrr0 r4 + lwz r4, context->srr1 + mtsrr1 r4 + + lwz r4, context->gpr[4] + lwz r3, context->gpr[3] + + rfi +} + +asm u32 OSGetStackPointer() { + nofralloc + mr r3, r1 + blr +} + +asm u32 OSSwitchStack(register u32 newsp) { + nofralloc + mr r5, r1 + mr r1, newsp + mr r3, r5 + blr +} + +asm int OSSwitchFiber(register u32 pc, register u32 newsp) { + nofralloc + mflr r0 + mr r5, r1 + stwu r5, -8(newsp) + mr r1, newsp + stw r0, 4(r5) + mtlr pc + blrl + lwz r5, 0(r1) + lwz r0, 4(r5) + mtlr r0 + mr r1, r5 + blr +} +#endif + +#ifdef __GEKKO__ +asm void OSSwitchFiberEx(register u32 param_0, register u32 param_1, register u32 param_2, register u32 param_3, register u32 pc, register u32 newsp) { + nofralloc + + mflr r0 + + // Back chain + mr r9, r1 + stwu r9, -8(newsp) + + // LR save + mr r1, newsp + stw r0, 4(r9) + + // Call function + mtlr pc + blrl + + // Switch back + lwz r5, 0(r1) + lwz r0, 4(r5) + mtlr r0 + mr r1, r5 + + blr +} +#endif + +void OSClearContext(register OSContext* context) { + context->mode = 0; + context->state = 0; + if (context == __OSFPUContext) + __OSFPUContext = NULL; +} + +#ifdef __GEKKO__ +asm void OSInitContext(register OSContext* context, register u32 pc, register u32 newsp) { + nofralloc + + stw pc, OS_CONTEXT_SRR0(context) + stw newsp, OS_CONTEXT_R1(context) + li r11, 0 + ori r11, r11, 0x00008000 | 0x00000020 | 0x00000010 | 0x00000002 | 0x00001000 + stw r11, OS_CONTEXT_SRR1(context) + li r0, 0x0 + stw r0, OS_CONTEXT_CR(context) + stw r0, OS_CONTEXT_XER(context) + + + stw r2, OS_CONTEXT_R2(context) + stw r13, OS_CONTEXT_R13(context) + + stw r0, OS_CONTEXT_R3(context) + stw r0, OS_CONTEXT_R4(context) + stw r0, OS_CONTEXT_R5(context) + stw r0, OS_CONTEXT_R6(context) + stw r0, OS_CONTEXT_R7(context) + stw r0, OS_CONTEXT_R8(context) + stw r0, OS_CONTEXT_R9(context) + stw r0, OS_CONTEXT_R10(context) + stw r0, OS_CONTEXT_R11(context) + stw r0, OS_CONTEXT_R12(context) + + stw r0, OS_CONTEXT_R14(context) + stw r0, OS_CONTEXT_R15(context) + stw r0, OS_CONTEXT_R16(context) + stw r0, OS_CONTEXT_R17(context) + stw r0, OS_CONTEXT_R18(context) + stw r0, OS_CONTEXT_R19(context) + stw r0, OS_CONTEXT_R20(context) + stw r0, OS_CONTEXT_R21(context) + stw r0, OS_CONTEXT_R22(context) + stw r0, OS_CONTEXT_R23(context) + stw r0, OS_CONTEXT_R24(context) + stw r0, OS_CONTEXT_R25(context) + stw r0, OS_CONTEXT_R26(context) + stw r0, OS_CONTEXT_R27(context) + stw r0, OS_CONTEXT_R28(context) + stw r0, OS_CONTEXT_R29(context) + stw r0, OS_CONTEXT_R30(context) + stw r0, OS_CONTEXT_R31(context) + + stw r0, OS_CONTEXT_GQR0(context) + stw r0, OS_CONTEXT_GQR1(context) + stw r0, OS_CONTEXT_GQR2(context) + stw r0, OS_CONTEXT_GQR3(context) + stw r0, OS_CONTEXT_GQR4(context) + stw r0, OS_CONTEXT_GQR5(context) + stw r0, OS_CONTEXT_GQR6(context) + stw r0, OS_CONTEXT_GQR7(context) + + b OSClearContext +} +#endif + +void OSDumpContext(OSContext* context) { + u32 i; + u32* p; + + OSReport("------------------------- Context 0x%08x -------------------------\n", context); + + for (i = 0; i < 16; ++i) { + OSReport("r%-2d = 0x%08x (%14d) r%-2d = 0x%08x (%14d)\n", i, context->gpr[i], + context->gpr[i], i + 16, context->gpr[i + 16], context->gpr[i + 16]); + } + + OSReport("LR = 0x%08x CR = 0x%08x\n", context->lr, context->cr); + OSReport("SRR0 = 0x%08x SRR1 = 0x%08x\n", context->srr0, context->srr1); + + OSReport("\nGQRs----------\n"); + for (i = 0; i < 4; ++i) { + OSReport("gqr%d = 0x%08x \t gqr%d = 0x%08x\n", i, context->gqr[i], i + 4, context->gqr[i + 4]); + } + + if (context->state & OS_CONTEXT_STATE_FPSAVED) { + OSContext* currentContext; + OSContext fpucontext; + BOOL enabled; + + enabled = OSDisableInterrupts(); + currentContext = OSGetCurrentContext(); + OSClearContext(&fpucontext); + OSSetCurrentContext(&fpucontext); + + OSReport("\n\nFPRs----------\n"); + for (i = 0; i < 32; i += 2) { + OSReport("fr%d \t= %d \t fr%d \t= %d\n", i, (u32)context->fpr[i], i + 1, + (u32)context->fpr[i + 1]); + } + OSReport("\n\nPSFs----------\n"); + for (i = 0; i < 32; i += 2) { + OSReport("ps%d \t= 0x%x \t ps%d \t= 0x%x\n", i, (u32)context->psf[i], i + 1, + (u32)context->psf[i + 1]); + } + + OSClearContext(&fpucontext); + OSSetCurrentContext(currentContext); + OSRestoreInterrupts(enabled); + } + + OSReport("\nAddress: Back Chain LR Save\n"); + for (i = 0, p = (u32*)context->gpr[1]; p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) { + OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]); + } +} + +#ifdef __GEKKO__ +static asm void OSSwitchFPUContext(register __OSException exception, register OSContext* context) { + nofralloc + mfmsr r5 + ori r5, r5, 0x2000 + mtmsr r5 + isync + lwz r5, OS_CONTEXT_SRR1(context) + ori r5, r5, 0x2000 + mtsrr1 r5 + addis r3, r0, OS_CACHED_REGION_PREFIX + lwz r5, 0x00D8(r3) + stw context, 0x00D8(r3) + cmpw r5, r4 + beq _restoreAndExit + cmpwi r5, 0x0 + beq _loadNewFPUContext + bl __OSSaveFPUContext +_loadNewFPUContext: + bl __OSLoadFPUContext +_restoreAndExit: + lwz r3, OS_CONTEXT_CR(context) + mtcr r3 + lwz r3, OS_CONTEXT_LR(context) + mtlr r3 + lwz r3, OS_CONTEXT_SRR0(context) + mtsrr0 r3 + lwz r3, OS_CONTEXT_CTR(context) + mtctr r3 + lwz r3, OS_CONTEXT_XER(context) + mtxer r3 + lhz r3, context->state + rlwinm r3, r3, 0, 31, 29 + sth r3, context->state + lwz r5, OS_CONTEXT_R5(context) + lwz r3, OS_CONTEXT_R3(context) + lwz r4, OS_CONTEXT_R4(context) + rfi +} +#endif + +void __OSContextInit(void) { + __OSSetExceptionHandler(__OS_EXCEPTION_FLOATING_POINT, OSSwitchFPUContext); + __OSFPUContext = NULL; +} + +#ifdef __GEKKO__ +asm void OSFillFPUContext(register OSContext* context) { + nofralloc + mfmsr r5 + ori r5, r5, 0x2000 + mtmsr r5 + isync + + stfd fp0, context->fpr[0] + stfd fp1, context->fpr[1] + stfd fp2, context->fpr[2] + stfd fp3, context->fpr[3] + stfd fp4, context->fpr[4] + stfd fp5, context->fpr[5] + stfd fp6, context->fpr[6] + stfd fp7, context->fpr[7] + stfd fp8, context->fpr[8] + stfd fp9, context->fpr[9] + stfd fp10, context->fpr[10] + stfd fp11, context->fpr[11] + stfd fp12, context->fpr[12] + stfd fp13, context->fpr[13] + stfd fp14, context->fpr[14] + stfd fp15, context->fpr[15] + stfd fp16, context->fpr[16] + stfd fp17, context->fpr[17] + stfd fp18, context->fpr[18] + stfd fp19, context->fpr[19] + stfd fp20, context->fpr[20] + stfd fp21, context->fpr[21] + stfd fp22, context->fpr[22] + stfd fp23, context->fpr[23] + stfd fp24, context->fpr[24] + stfd fp25, context->fpr[25] + stfd fp26, context->fpr[26] + stfd fp27, context->fpr[27] + stfd fp28, context->fpr[28] + stfd fp29, context->fpr[29] + stfd fp30, context->fpr[30] + stfd fp31, context->fpr[31] + + mffs fp0 + stfd fp0, OS_CONTEXT_FPSCR(context) + + lfd fp0, context->fpr[0] + + mfspr r5, HID2 + rlwinm. r5, r5, 3, 31, 31 + bc 12, 2, _return + + psq_st fp0, OS_CONTEXT_PSF0(context), 0, 0 + psq_st fp1, OS_CONTEXT_PSF1(context), 0, 0 + psq_st fp2, OS_CONTEXT_PSF2(context), 0, 0 + psq_st fp3, OS_CONTEXT_PSF3(context), 0, 0 + psq_st fp4, OS_CONTEXT_PSF4(context), 0, 0 + psq_st fp5, OS_CONTEXT_PSF5(context), 0, 0 + psq_st fp6, OS_CONTEXT_PSF6(context), 0, 0 + psq_st fp7, OS_CONTEXT_PSF7(context), 0, 0 + psq_st fp8, OS_CONTEXT_PSF8(context), 0, 0 + psq_st fp9, OS_CONTEXT_PSF9(context), 0, 0 + psq_st fp10, OS_CONTEXT_PSF10(context), 0, 0 + psq_st fp11, OS_CONTEXT_PSF11(context), 0, 0 + psq_st fp12, OS_CONTEXT_PSF12(context), 0, 0 + psq_st fp13, OS_CONTEXT_PSF13(context), 0, 0 + psq_st fp14, OS_CONTEXT_PSF14(context), 0, 0 + psq_st fp15, OS_CONTEXT_PSF15(context), 0, 0 + psq_st fp16, OS_CONTEXT_PSF16(context), 0, 0 + psq_st fp17, OS_CONTEXT_PSF17(context), 0, 0 + psq_st fp18, OS_CONTEXT_PSF18(context), 0, 0 + psq_st fp19, OS_CONTEXT_PSF19(context), 0, 0 + psq_st fp20, OS_CONTEXT_PSF20(context), 0, 0 + psq_st fp21, OS_CONTEXT_PSF21(context), 0, 0 + psq_st fp22, OS_CONTEXT_PSF22(context), 0, 0 + psq_st fp23, OS_CONTEXT_PSF23(context), 0, 0 + psq_st fp24, OS_CONTEXT_PSF24(context), 0, 0 + psq_st fp25, OS_CONTEXT_PSF25(context), 0, 0 + psq_st fp26, OS_CONTEXT_PSF26(context), 0, 0 + psq_st fp27, OS_CONTEXT_PSF27(context), 0, 0 + psq_st fp28, OS_CONTEXT_PSF28(context), 0, 0 + psq_st fp29, OS_CONTEXT_PSF29(context), 0, 0 + psq_st fp30, OS_CONTEXT_PSF30(context), 0, 0 + psq_st fp31, OS_CONTEXT_PSF31(context), 0, 0 + +_return: + blr +} +#endif diff --git a/src/revolution/os/OSError.c b/src/revolution/os/OSError.c new file mode 100644 index 0000000000..fd26236fba --- /dev/null +++ b/src/revolution/os/OSError.c @@ -0,0 +1,215 @@ +#include +#include +#include + +#include "__os.h" + +OSErrorHandler __OSErrorTable[17]; + +#define FPSCR_ENABLE (FPSCR_VE | FPSCR_OE | FPSCR_UE | FPSCR_ZE | FPSCR_XE) +u32 __OSFpscrEnableBits = FPSCR_ENABLE; + +__declspec(weak) void OSReport(const char* msg, ...) { + va_list marker; + va_start(marker, msg); + vprintf(msg, marker); + va_end(marker); +} + +__declspec(weak) void OSVReport(const char* msg, va_list list) { + vprintf(msg, list); +} + +__declspec(weak) void OSPanic(const char* file, int line, const char* msg, ...) { + va_list marker; + u32 i; + u32* p; + + OSDisableInterrupts(); + va_start(marker, msg); + vprintf(msg, marker); + va_end(marker); + OSReport(" in \"%s\" on line %d.\n", file, line); + + OSReport("\nAddress: Back Chain LR Save\n"); + for (i = 0, p = (u32*)OSGetStackPointer(); p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) { + OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]); + } + + PPCHalt(); +} + +OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) { + OSErrorHandler oldHandler; + int enabled; + + ASSERTMSGLINE(215, error < 17, "OSSetErrorHandler(): unknown error."); + + enabled = OSDisableInterrupts(); + oldHandler = __OSErrorTable[error]; + __OSErrorTable[error] = handler; + + if (error == __OS_EXCEPTION_FLOATING_POINT_EXCEPTION) { + u32 msr; + u32 fpscr; + OSThread* thread; + int i; + + msr = PPCMfmsr(); + PPCMtmsr(msr | MSR_FP); + fpscr = PPCMffpscr(); + + if (handler) { + for (thread = __OSActiveThreadQueue.head; thread; + thread = thread->linkActive.next) + { + thread->context.srr1 |= MSR_FE0 | MSR_FE1; + if ((thread->context.state & OS_CONTEXT_STATE_FPSAVED) == 0) { + thread->context.state |= OS_CONTEXT_STATE_FPSAVED; + for (i = 0; i < 32; ++i) { + *(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL; + *(u64*)&thread->context.psf[i] = (u64)0xffffffffffffffffLL; + } + thread->context.fpscr = FPSCR_NI; + } + thread->context.fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE; + thread->context.fpscr &= + ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | + FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | + FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + } + fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE; + msr |= MSR_FE0 | MSR_FE1; + } else { + for (thread = __OSActiveThreadQueue.head; thread; + thread = thread->linkActive.next) + { + thread->context.srr1 &= ~(MSR_FE0 | MSR_FE1); + thread->context.fpscr &= ~FPSCR_ENABLE; + thread->context.fpscr &= + ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | + FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | + FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + } + fpscr &= ~FPSCR_ENABLE; + msr &= ~(MSR_FE0 | MSR_FE1); + } + + fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | + FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX | + FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + + PPCMtfpscr(fpscr); + PPCMtmsr(msr); + } + + OSRestoreInterrupts(enabled); + return oldHandler; +} + +volatile OSContext* __OSFPUContext AT_ADDRESS(OS_BASE_CACHED | 0x00D8); + +void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar) { + OSTime now; + now = OSGetTime(); + + if (!(context->srr1 & MSR_RI)) { + OSReport("Non-recoverable Exception %d", exception); + } else { + u32 fpscr; + u32 msr; + if (exception == __OS_EXCEPTION_PROGRAM && (context->srr1 & (0x80000000 >> 11)) && + __OSErrorTable[__OS_EXCEPTION_FLOATING_POINT_EXCEPTION] != 0) + { + exception = __OS_EXCEPTION_FLOATING_POINT_EXCEPTION; + + msr = PPCMfmsr(); + PPCMtmsr(msr | 0x2000); + + if (__OSFPUContext) { + OSSaveFPUContext((OSContext*)__OSFPUContext); + } + + fpscr = PPCMffpscr(); + fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | + FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | + FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + PPCMtfpscr(fpscr); + + PPCMtmsr(msr); + + if (__OSFPUContext == context) { + OSDisableScheduler(); + __OSErrorTable[exception](exception, context, dsisr, dar); + context->srr1 &= ~0x2000; + __OSFPUContext = NULL; + + context->fpscr &= + ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI | + FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | + FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI); + OSEnableScheduler(); + __OSReschedule(); + } else { + context->srr1 &= ~0x2000; + __OSFPUContext = NULL; + } + + OSLoadContext(context); + } + + if (__OSErrorTable[exception]) { + OSDisableScheduler(); + __OSErrorTable[exception](exception, context, dsisr, dar); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); + } + if (exception == __OS_EXCEPTION_DECREMENTER) { + OSLoadContext(context); + } + OSReport("Unhandled Exception %d", exception); + } +#if DEBUG + OSReport("(%s)", __OSExceptionNames[exception]); +#endif + OSReport("\n"); + OSDumpContext(context); + OSReport("\nDSISR = 0x%08x DAR = 0x%08x\n", dsisr, dar); + OSReport("TB = 0x%016llx\n", now); + + switch(exception) { + case __OS_EXCEPTION_DSI: + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access " + "invalid address 0x%x (read from DAR)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_ISI: + OSReport("\nAttempted to fetch instruction from invalid address 0x%x " + "(read from SRR0)\n", + context->srr0); + break; + case __OS_EXCEPTION_ALIGNMENT: + OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access " + "unaligned address 0x%x (read from DAR)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_PROGRAM: + OSReport("\nProgram exception : Possible illegal instruction/operation " + "at or around 0x%x (read from SRR0)\n", + context->srr0, dar); + break; + case __OS_EXCEPTION_MEMORY_PROTECTION: + OSReport("\n"); + OSReport("AI DMA Address = 0x%04x%04x\n", __DSPRegs[DSP_DMA_START_HI], + __DSPRegs[DSP_DMA_START_LO]); + OSReport("ARAM DMA Address = 0x%04x%04x\n", __DSPRegs[DSP_ARAM_DMA_MM_HI], + __DSPRegs[DSP_ARAM_DMA_MM_LO]); + OSReport("DI DMA Address = 0x%08x\n", __DIRegs[5]); + break; + } + + OSReport("\nLast interrupt (%d): SRR0 = 0x%08x TB = 0x%016llx\n", __OSLastInterrupt, + __OSLastInterruptSrr0, __OSLastInterruptTime); + PPCHalt(); +} diff --git a/src/revolution/os/OSExec.c b/src/revolution/os/OSExec.c new file mode 100644 index 0000000000..db8588957c --- /dev/null +++ b/src/revolution/os/OSExec.c @@ -0,0 +1,795 @@ +#include +#include +#include + +#include "__os.h" +#include "__dvd.h" + +// extern +extern size_t wcslen(const wchar_t *); +extern int __DVDLayoutFormat; + +extern volatile u32 BOOT_REGION_START AT_ADDRESS(0x812FDFF0); +extern volatile u32 BOOT_REGION_END AT_ADDRESS(0x812FDFEC); +extern volatile u8 g_unk_800030E2 AT_ADDRESS(0x800030E2); + +DVDDiskID id; + +static int Prepared; +BOOL __OSInReboot; +u32 __OSNextPartitionType = 0; + +static int PackArgs(void* addr, s32 argc, char** argv) { + s32 numArgs; + char* bootInfo2; + char* ptr; + char** list; + u32 i; + + bootInfo2 = (char*)addr; + memset(bootInfo2, 0, 0x2000); + + if (argc == 0) { + *(u32*)(bootInfo2 + 8) = 0; + } else { + numArgs = argc; + ptr = bootInfo2 + 0x2000; + while (--argc >= 0) { + ptr -= strlen(argv[argc]) + 1; + strcpy(ptr, argv[argc]); + argv[argc] = (char*)(ptr - bootInfo2); + } + + ptr = bootInfo2 + ((ptr - bootInfo2) & ~0x3); + ptr -= ((numArgs + 1) * 4); + list = (char**)ptr; + + for (i = 0; i < numArgs + 1; i++) { + list[i] = argv[i]; + } + + ptr -= 4; + *(u32*)ptr = numArgs; + + ASSERTMSGLINE(401, ptr - bootInfo2 >= 0x1000U, "OSExec: Argument list is too long"); + + *(u32*)(bootInfo2 + 8) = (ptr - bootInfo2); + } + + return 1; +} + +static BOOL Utf16ToArg(char* dstArg, u16* srcName) { + char* srcPtr, *dstPtr; + u8 i, mask, shift; + + if (srcName != 0) { + srcPtr = (char*)srcName; + dstPtr = dstArg; + + while (*srcPtr || *(srcPtr + 1)) { + for (i = 0; i < 4; i++) { + mask = (u8)((i & 0x1) ? 0xF : 0xF0); + shift = (u8)((i & 0x1) ? 0 : 4); + + if (0 <= ((*srcPtr & mask) >> shift) && ((*srcPtr & mask) >> shift) < 0xA) { + *dstPtr = (char)(((*srcPtr & mask) >> shift) + 0x30); + } + else if(0xA <= ((*srcPtr & mask) >> shift) && ((*srcPtr & mask) >> shift) < 0x10) { + *dstPtr = (char)(((*srcPtr & mask) >> shift) + 0x57); + } + else { + return FALSE; + } + + dstPtr++; + + if (i & 1) { + srcPtr++; + } + } + } + + *dstPtr++ = 0; + return TRUE; + } + + return FALSE; +} + +BOOL PackInstallerArgs(void* addr, s32 argc, char* argv[]) { + s32 numArgs; + char* bootInfo2; + char* ptr; + char** list; + u32 i; + + bootInfo2 = (char*)addr; + memset(bootInfo2, 0, 0x2000); + + if (argc == 0) { + *(u32*)(bootInfo2 + 8) = 0; + } else { + numArgs = argc; + ptr = bootInfo2 + 0x2000; + + while (--argc >= 0) { + if (argc < 2 || (argc % 2)) { + ptr -= strlen(argv[argc]) + 1; + strcpy(ptr, argv[argc]); + argv[argc] = (char*)(ptr - bootInfo2); + } else { + ptr -= (wcslen((u16*)argv[argc]) * 4 + 1); + Utf16ToArg(ptr, (u16*)argv[argc]); + argv[argc] = (char*)(ptr - bootInfo2); + } + } + + ptr = bootInfo2 + ((ptr - bootInfo2) & ~0x3); + ptr -= ((numArgs + 1) * 4); + list = (char**)ptr; + + for (i = 0; i < numArgs + 1; i++) { + list[i] = argv[i]; + } + + ptr -= 4; + *(u32*)ptr = numArgs; + + ASSERTMSGLINE(524, ptr - bootInfo2 >= 0x1000U, "OSExec: Argument list is too long"); + + *(u32*)(bootInfo2 + 8) = (ptr - bootInfo2); + } + + return TRUE; +} + +#ifdef __GEKKO__ +static asm void Run(register void* entryPoint) { + fralloc + + bl ICFlashInvalidate + sync + isync + mtctr entryPoint + bctr + + frfree + blr +} +#endif + +static void StartDol(const OSExecParams* params, void* entry) { + OSExecParams* paramsWork = OSAllocFromMEM1ArenaLo(sizeof(OSExecParams), 1); + + __OSSetExecParams(params, paramsWork); + __PIRegs[9] = 7; + + OSDisableInterrupts(); + Run(entry); +} + +static void ReadDisc(void* addr, s32 length, s32 offset) { + DVDCommandBlock block; + // NOTE: unsure what these are, but required to match debug + volatile u32 sp18 = 0; + u8 sp14[] = {0xFF, 0xFF, 0xFF, 0x00}; + + DVDReadAbsAsyncPrio(&block, addr, length, offset, NULL, 0); + + while (DVDGetCommandBlockStatus(&block)) { + if (DVDGetCommandBlockStatus(&block) > 2 || DVDGetCommandBlockStatus(&block) < 0) { + __OSReturnToMenuForError(); + } + } +} + +static void Callback(s32, DVDCommandBlock*) { + Prepared = TRUE; +} + +static int IsStreamEnabled() { + if (DVDGetCurrentDiskID()->streaming) { + return TRUE; + } + + return FALSE; +} + +void __OSGetExecParams(OSExecParams* params) { + if (0x80000000 <= (u32)__OSExecParams) { + memcpy(params, __OSExecParams, sizeof(OSExecParams)); + } else { + params->valid = FALSE; + } +} + +void __OSSetExecParams(const OSExecParams* params, OSExecParams* addr) { + memcpy(addr, params, sizeof(OSExecParams)); + __OSExecParams = addr; +} + +static void StopStreaming() { + DVDCommandBlock block; + + if (!__OSIsGcam && IsStreamEnabled()) { + AISetStreamVolLeft(0); + AISetStreamVolRight(0); + DVDCancelStreamAsync(&block, NULL); + + + while (DVDGetCommandBlockStatus(&block)) { + if (!DVDCheckDisk()) { + __OSDoHotReset(0); + } + } + + AISetStreamPlayState(0); + } +} + +static int GetApploaderPosition(void) { + static s32 apploaderPosition; + + if (apploaderPosition != 0) { + return apploaderPosition; + } + + if (__OSAppLoaderOffset != 0) { + u32* tgcHeader; + s32 apploaderOffsetInTGC; + + tgcHeader = OSAllocFromMEM1ArenaLo(0x40, DOLPHIN_ALIGNMENT); + ReadDisc(tgcHeader, 0x40, __OSAppLoaderOffset >> 2); + apploaderOffsetInTGC = tgcHeader[14]; + ASSERTMSGLINE(727, apploaderOffsetInTGC != 0, "OSExec() or OSResetSystem(): Wrong apploader offset. Maybe converted by an\nolder version of gcm2tgc. Use gcm2tgc v.1.20 or later."); + + apploaderPosition = (__OSAppLoaderOffset + apploaderOffsetInTGC) >> 2; + } else { + apploaderPosition = 0x910; + } + + return apploaderPosition; +} + +typedef struct { + char date[16]; + u32 entry; + u32 size; + u32 rebootSize; + u32 reserved2; +} AppLoaderStruct; + +static AppLoaderStruct* LoadApploader() { + AppLoaderStruct* header; + + header = (AppLoaderStruct*)OSAllocFromMEM1ArenaLo(sizeof(AppLoaderStruct), DOLPHIN_ALIGNMENT); + ReadDisc(header, sizeof(AppLoaderStruct), GetApploaderPosition()); + ASSERTMSGLINE(758, header->rebootSize != 0, "OSResetSystem(): old apploader"); + + ReadDisc((void*)0x81200000, OSRoundUp32B(header->size), GetApploaderPosition() + 0x8); + ICInvalidateRange((void*)0x81200000, OSRoundUp32B(header->size)); + return header; +} + +static void* LoadDol(const OSExecParams* params, AppLoaderCallback getInterface) { + appInitCallback appInit; + appGetNextCallback appGetNext; + appGetEntryCallback appGetEntry; + void* addr; + u32 length; + u32 offset; + OSExecParams* paramsWork; + + getInterface(&appInit, &appGetNext, &appGetEntry); + paramsWork = (OSExecParams*)OSAllocFromMEM1ArenaLo(sizeof(OSExecParams), 1); + __OSSetExecParams(params, paramsWork); + appInit((void(*)(char*))OSReport); + OSSetArenaLo(paramsWork); + + while (appGetNext(&addr, &length, &offset) != 0) { + ReadDisc(addr, length, offset >> __DVDLayoutFormat); + } + + return appGetEntry(); +} + +static BOOL IsNewApploader(AppLoaderStruct* header) { + if (strncmp(header->date, "2004/02/01", 10) > 0) { + return TRUE; + } else { + return FALSE; + } +} + +static u32 DVDLowIntType; + +static void callback(u32 param_0) { + DVDLowIntType = param_0; +} + +void CheckDVDLowIntType(int param_0) { + switch (param_0) { + case 1: + break; + case 2: + OSReport("\nDisc error occurred!\n"); + __OSReturnToMenuForError(); + break; + case 16: + OSReport("\nTimeout error occurred!\n"); + __OSReturnToMenuForError(); + break; + default: + OSReport("\nUnexpected error occurred!\n"); + __OSReturnToMenuForError(); + } +} + +// NONMATCHING +void __OSLaunchNextFirmware(void) { + DVDPartitionInfo* var_r30; + int rc = -1; + DVDPartitionInfo* var_r28; + u32 var_r27; + + u32 ticketCnt = 1; + ESSysVersion version = 0x100000003; + ESTicketView* sp30; + ESTicketView* ticket; + + u32 MEM2Size; + u32 MEM2End; + DVDGameTOC* gameTOC; + DVDPartitionInfo* partitionInfo; + ESTitleMeta* meta; + u32 tmd = 0; + + gameTOC = OSAllocFromMEM1ArenaLo(0x20, 0x20); + partitionInfo = OSAllocFromMEM1ArenaLo(0x800, 0x20); + meta = OSAllocFromMEM1ArenaLo(0x4A00, 0x40); + ticket = OSAllocFromMEM1ArenaLo(0xE0, 0x20); + + if (__OSNextPartitionType == *(u32*)0x80003194 && *(u32*)OSPhysicalToCached(0x3198) != 0) { + rc = ESP_InitLib(); + if (!rc) { + rc = ESP_DiGetTicketView(NULL, ticket); + } + + if (!rc) { + rc = ESP_DiGetTmd(NULL, &tmd); + } + + if (!rc) { + rc = ESP_DiGetTmd(meta, &tmd); + } + + ESP_CloseLib(); + + if (OSPlayTimeIsLimited()) { + __OSPlayTimeType type = OSPLAYTIME_PERMANENT; + u32 playTime = -1; + __OSGetPlayTime(ticket, &type, &playTime); + if (playTime == 0) { + __OSWriteExpiredFlag(); + __OSReturnToMenuForError(); + } + } + } + + + if (!rc) { + var_r30 = partitionInfo; + var_r30->type = *(u32*)OSPhysicalToCached(0x3194); + var_r30->gamePartition = (DVDGamePartition*)*(u32*)OSPhysicalToCached(0x3198); + } else { + u8 i; + DVDLowIntType = 0; + DVDLowClosePartition(callback); + while (DVDLowIntType == 0) {} + + CheckDVDLowIntType(DVDLowIntType); + DVDLowIntType = 0; + DVDLowUnencryptedRead(&gameTOC->numGamePartitions, 0x20, 0x10000, callback); + while (DVDLowIntType == 0) {} + + CheckDVDLowIntType(DVDLowIntType); + DVDLowIntType = 0; + DVDLowUnencryptedRead(partitionInfo, 0x800, (u32)gameTOC->partitionInfos, callback); + while (DVDLowIntType == 0) {} + + CheckDVDLowIntType(DVDLowIntType); + + var_r30 = NULL; + var_r28 = partitionInfo; + + for (i = 0; i < gameTOC->numGamePartitions; i++) { + if (var_r28->type == __OSNextPartitionType) { + var_r30 = var_r28; + } + + var_r28++; + } + + if (var_r30 == 0) { + gameTOC++; + var_r28 = partitionInfo + 4; + + for (i = 0; i < gameTOC->numGamePartitions; i++) { + if (var_r28->type == __OSNextPartitionType) { + var_r30 = var_r28; + } + + var_r28 += 2; + } + } + + if (var_r30 == 0) { + OSReport("\nThe specified game doesn\'t exist in the disc\n"); + __OSReturnToMenuForError(); + } + + var_r27 = var_r30->type; + *(u32*)OSPhysicalToCached(0x3194) = var_r27; + + var_r27 = (u32)var_r30->gamePartition; + *(u32*)OSPhysicalToCached(0x3198) = var_r27; + + DVDLowIntType = 0; + + if (*(u8*)0x80003187 == 0x80) { + DVDLowOpenPartitionWithTmdAndTicketView((u32)var_r30->gamePartition, ticket, tmd, meta, 0, 0, callback); + } else { + DVDLowOpenPartition((u32)var_r30->gamePartition, NULL, 0, NULL, meta, callback); + } + + while (DVDLowIntType == 0) {} + CheckDVDLowIntType(DVDLowIntType); + DVDLowIntType = 0; + DVDLowClosePartition(callback); + + while (DVDLowIntType == 0) {} + CheckDVDLowIntType(DVDLowIntType); + } + + version = meta->head.sysVersion; + + rc = ESP_InitLib(); + if (rc) { + OSReport("\nOSExec(): Failed to exec %d in %d\n", rc, 1037); + __OSHotResetForError(); + } + + rc = ESP_GetTicketViews(version, NULL, &ticketCnt); + if (ticketCnt != 1 || rc) { + OSReport("\nOSExec(): Failed to exec %d in %d\n", rc, 1046); + __OSHotResetForError(); + } + + sp30 = OSAllocFromMEM1ArenaLo(OSRoundUp32B(ticketCnt * sizeof(ESTicketView)), 0x20); + rc = ESP_GetTicketViews(version, sp30, &ticketCnt); + if (rc) { + OSReport("\nOSExec(): Failed to exec %d in %d\n", rc, 1055); + __OSHotResetForError(); + } + + DVDLowFinalize(); + + MEM2Size = *(u32*)OSPhysicalToCached(0x311C); + MEM2End = *(u32*)OSPhysicalToCached(0x3120); + DCStoreRange(OSPhysicalToCached(0x3100), 0x100); + + rc = ESP_LaunchTitle(version, sp30); + if (rc) { + OSReport("\nOSExec(): Failed to exec %d in %d\n", rc, 1071); + __OSHotResetForError(); + } + + ESP_CloseLib(); + DCInvalidateRange(OSPhysicalToCached(0x3100), 0x100); + + if (MEM2Size < *(u32*)OSPhysicalToCached(0x311C)) { + var_r27 = *(u32*)OSPhysicalToCached(0x311C); + var_r27 = MEM2Size - (var_r27 - *(u32*)OSPhysicalToCached(0x3120)); + *(u32*)OSPhysicalToCached(0x3120) = var_r27; + + var_r27 = *(u32*)OSPhysicalToCached(0x311C); + var_r27 = MEM2Size - (var_r27 - *(u32*)OSPhysicalToCached(0x3128)); + *(u32*)OSPhysicalToCached(0x3128) = var_r27; + + var_r27 = *(u32*)OSPhysicalToCached(0x311C); + var_r27 = MEM2Size - (var_r27 - *(u32*)OSPhysicalToCached(0x3130)); + *(u32*)OSPhysicalToCached(0x3130) = var_r27; + + var_r27 = *(u32*)OSPhysicalToCached(0x311C); + var_r27 = MEM2Size - (var_r27 - *(u32*)OSPhysicalToCached(0x3134)); + *(u32*)OSPhysicalToCached(0x3134) = var_r27; + + var_r27 = MEM2Size; + *(u32*)OSPhysicalToCached(0x311C) = var_r27; + } + + if (MEM2End < *(u32*)OSPhysicalToCached(0x3120)) { + __OSInitMemoryProtection(); + } + + __OSInitIPCBuffer(); + IPCReInit(); + IPCCltReInit(); + + DVDLowInit(); + DVDLowIntType = 0; + DVDLowReadDiskID(&id, callback); + while (DVDLowIntType == 0) {} + CheckDVDLowIntType(DVDLowIntType); + DVDLowIntType = 0; + + if (*(u8*)0x80003187 == 0x80) { + DVDLowOpenPartitionWithTmdAndTicketView((u32)var_r30->gamePartition, ticket, tmd, meta, 0, 0, callback); + } else { + DVDLowOpenPartition((u32)var_r30->gamePartition, NULL, 0, NULL, meta, callback); + } + + while (DVDLowIntType == 0) {} + + CheckDVDLowIntType(DVDLowIntType); +} + +#define TITLE_ID ((((u64)1) << 32) | (2)) + +void __OSLaunchMenu(void) { + u8 i; + s32 rc; + u32 ticketCnt = 1; + ESTicketView* t; + ESSysVersion version = 0x0000000100000003; + GXColor bg = { 0, 0, 0, 0}; + GXColor fg = { 255, 255, 255, 0 }; + + OSSetArenaLo((void*)0x81280000); + OSSetArenaHi((void*)0x812F0000); + rc = ESP_InitLib(); + + if (rc != 0) { + return; + } + + rc = ESP_GetTicketViews(TITLE_ID, NULL, &ticketCnt); + + if (ticketCnt != 1 || rc != 0) { + return; + } + + t = (ESTicketView*)OSAllocFromMEM1ArenaLo(OSRoundUp32B(sizeof(ESTicketView) * ticketCnt), 32); + rc = ESP_GetTicketViews(TITLE_ID, t, &ticketCnt); + + if (rc != 0) { + return; + } + + rc = ESP_LaunchTitle(TITLE_ID, t); + + if (rc != 0) { + return; + } + + while (1) { + + } +} + +// NONMATCHING - stack issues +void __OSBootDolSimple(u32 doloffset, u32 restartCode, void* regionStart, void* regionEnd, BOOL argsUseDefault, s32 argc, char** argv) { + OSExecParams* params; + void* dolEntry; + OSBootInfo* bootInfo; + char* sp20; + AppLoaderStruct* header; + + OSDisableInterrupts(); + + if (__OSInReboot) { + __OSNextPartitionType = *(u32*)0x80003194; + } + + __OSRestoreCodeExecOnMEM1(0xBA2CF); + + params = (OSExecParams*)OSAllocFromMEM1ArenaLo(sizeof(OSExecParams), 1); + params->valid = TRUE; + params->restartCode = restartCode; + params->regionStart = regionStart; + params->regionEnd = regionEnd; + params->argsUseDefault = argsUseDefault; + + if (!argsUseDefault) { + params->argsAddr = OSAllocFromMEM1ArenaLo(0x2000, 1); + + if (__OSNextPartitionType == 2 && !__OSInReboot) { + PackInstallerArgs(params->argsAddr, argc, argv); + } else { + PackArgs(params->argsAddr, argc, argv); + } + } + + DVDInit(); + DVDSetAutoInvalidation(TRUE); + DVDResume(); + + Prepared = FALSE; + + __DVDPrepareResetAsync(Callback); + __OSMaskInterrupts(0xFFFFFFF0); + __OSUnmaskInterrupts(0x10); + OSEnableInterrupts(); + + while (Prepared != TRUE) {} + + __OSLaunchNextFirmware(); + + if (restartCode == 0xA0000000 && !__OSInReboot) { + ESTitleId titleID; + int rc; + + rc = ESP_InitLib(); + if (rc) { + return; + } + + rc = ESP_GetTitleId(&titleID); + if (rc) { + return; + } + + rc = ESP_CloseLib(); + if (rc) { + return; + } + + sp20 = (u32)params->argsAddr + argv[1]; + snprintf(sp20, 17, "%016llx", titleID); + } + + header = LoadApploader(); + if (IsNewApploader(header)) { + if (doloffset == 0xFFFFFFFF) { + doloffset = GetApploaderPosition() + ((header->size + 0x20) >> 2); + } + + params->bootDol = doloffset; + dolEntry = LoadDol(params, (AppLoaderCallback)header->entry); + + bootInfo = OSPhysicalToCached(0); + *(u32*)OSPhysicalToCached(0x3180) = *(u32*)bootInfo->DVDDiskID.gameName; + *(u8*)OSPhysicalToCached(0x3184) = 0x80; + + StartDol(params, dolEntry); + } else { + BOOT_REGION_START = (u32)regionStart; + BOOT_REGION_END = (u32)regionEnd; + g_unk_800030E2 = 1; + + ReadDisc((void*)0x81330000, OSRoundUp32B(header->rebootSize), GetApploaderPosition() + ((header->size + 0x20) >> 2)); + ICInvalidateRange((void*)0x81330000, OSRoundUp32B(header->rebootSize)); + OSDisableInterrupts(); + ICFlashInvalidate(); + Run((void*)0x81330000); + } +} + +void __OSBootDol(u32 doloffset, u32 restartCode, const char** argv) { + char doloffInString[20]; + s32 argvlen; + char** argvToPass; + s32 i; + void* saveStart; + void* saveEnd; + + OSGetSaveRegion(&saveStart, &saveEnd); + sprintf(doloffInString, "%d", doloffset); + argvlen = 0; + + if (argv != 0) { + while (argv[argvlen] != 0) { + argvlen++; + } + } + + argvlen++; + argvToPass = OSAllocFromMEM1ArenaLo((argvlen + 1) * 4, 1); + *argvToPass = doloffInString; + + for (i = 1; i < argvlen; i++) { + argvToPass[i] = (char*)argv[i - 1]; + } + + __OSBootDolSimple(-1, restartCode, saveStart, saveEnd, FALSE, argvlen, argvToPass); +} + +void OSLaunchDisk(void) { + // NOTE: Function doesn't exist in TP debug, but string data is leftover + OSReport("OSLaunchDisk(): You can't call this API from DVD application. \n"); + OSReport("OSLaunchDisk(): You must call DVDPrepareDisk before launching disc.\n"); + OSReport("OSLaunchDisk(): Specified id is different from one specified to DVDPrepareDisk.\n"); +} + +void OSLaunchDiskl(void) { + // NOTE: Function doesn't exist in TP debug, but string data is leftover + OSReport("0000000000000000"); + OSReport("OSLaunchDiskl(): Arguments too long"); +} + +static void ExecCommon(const char* dolfile, const char** argv) { + DVDFileInfo fileInfo; + u32 doloff; + + if ((s8)*dolfile == '\0') { + doloff = 0; + } else if (DVDOpen((char*)dolfile, &fileInfo)) { + doloff = fileInfo.startAddr; + } else { + ASSERTMSGLINE(0, 0, "Warning: OSExec(): The specified file doesn't exist. \n"); + return; + } + + __OSBootDol(doloff, 0xC0000000, argv); +} + +void OSExecv(const char* dolfile, const char** argv) { + ASSERTMSGLINE(0, dolfile != 0, "OSExecv(): null pointer was specified for the dol file name."); + ASSERTMSGLINE(0, argv != 0, "OSExecv(): null pointer was specified for argv."); + + OSDisableScheduler(); + __OSShutdownDevices(FALSE); + OSEnableScheduler(); + OSSetArenaLo((void*)0x81280000); + OSSetArenaHi((void*)0x812F0000); + ExecCommon(dolfile, argv); +} + +void OSExecl(const char* dolfile, const char* arg0, ...) { + va_list vl; + char* ptr; + s32 i; + char** argv; + + ASSERTMSGLINE(0, dolfile != 0, "OSExecl(): null pointer was specified for the dol file name."); + + OSDisableScheduler(); + __OSShutdownDevices(FALSE); + OSEnableScheduler(); + OSSetArenaLo((void*)0x81280000); + OSSetArenaHi((void*)0x812F0000); + + argv = OSAllocFromMEM1ArenaLo(4, 0x1000); + va_start(vl, arg0); + + i = 0; + ptr = (char*)arg0; + goto setarg; + + do { + ptr = va_arg(vl, char*); +setarg: + argv[i++] = ptr; + } while (ptr != 0); + + va_end(vl); + ASSERTMSGLINE(0, i < 0x400U, "OSExecl(): Arguments too long"); + + ExecCommon(dolfile, (const char**)argv); +} + +void OSLaunchPartition(void) { + // NOTE: Function doesn't exist in TP debug, but string data is leftover + OSReport("OSLaunchPartition(): You can't call this API from NAND application. \n"); + OSReport("OSLaunchPartition(): Specified title ID is not DISC application. \n"); + OSReport("/title/%08x/%08x"); + OSReport("\nOSLaunchPartition(): Failed to get free i-nodes number\n"); + OSReport("\nOSLaunchPartition(): There are not enough i-nodes to launch next partition\n"); + OSReport("\nOSLaunchPartition(): Failed to get nand status\n"); +} + +void OSLaunchPartitionl(void) { + // NOTE: Function doesn't exist in TP debug, but string data is leftover + OSReport("OSLaunchPartitionl(): Arguments too long"); +} diff --git a/src/revolution/os/OSFatal.c b/src/revolution/os/OSFatal.c new file mode 100644 index 0000000000..c7224af4de --- /dev/null +++ b/src/revolution/os/OSFatal.c @@ -0,0 +1,256 @@ +#include +#include +#include +#include + +#include "__os.h" +#include + +typedef struct OSFatalParam { + GXColor fg; + GXColor bg; + const char* msg; +} OSFatalParam; + +static OSFatalParam FatalParam; +static OSContext FatalContext; + +// prototypes +static void Halt(); + +static void ScreenClear(void* xfb, u16 xfbW, u16 xfbH, GXColor yuv) { + int i; + int j; + u8* ptr; + + ptr = xfb; + for (i = 0; i < xfbH; i++) { + for (j = 0; j < xfbW; j += 2) { + *ptr++ = yuv.r; + *ptr++ = yuv.g; + *ptr++ = yuv.r; + *ptr++ = yuv.b; + } + } +} + +static void ScreenReport(void* xfb, u16 xfbW, u16 xfbH, GXColor yuv, s32 x, s32 y, s32 leading, const char* string) { + u8* ptr; + s32 width; + u32 i; + u32 j; + u32 image[72]; + u32 k; + u32 l; + u8 Y; + u32 pixel; + s32 col; + +loop_1: + if (xfbH - 24 >= y) { + ptr = (u8*)xfb + ((x + (y * xfbW)) * 2); + col = x; + + while ((s8)*string != 0) { + if ((s8)*string == '\n') { + string++; + y += leading; + goto loop_1; + } + + if (xfbW - 48 < col) { + y += leading; + goto loop_1; + } + + for (i = 0; i < 24; i++) { + j = (i & 7) + ((i >> 3) * 24); + image[j + 0 ] = 0; + image[j + 8 ] = 0; + image[j + 16] = 0; + } + + string = OSGetFontTexel((char*)string, image, 0, 6, &width); + + for (i = 0; i < 24; i++) { + j = (i & 7) + ((i >> 3) * 24); + + for (k = 0; k < 24; k++) { + l = j + 8 * (k / 8); + + Y = (image[l] >> ((7 - (k & 7)) * 4)) & 0xF; + if (Y != 0) { + Y = (((yuv.r * (Y * 0xEF)) / 255) / 15) + 0x10; + pixel = k + (i * xfbW); + ptr[pixel * 2] = Y; + + if ((col + k) & 1) { + ptr[(pixel * 2) - 1] = yuv.g; + ptr[(pixel * 2) + 1] = yuv.b; + } else { + ptr[(pixel * 2) - 1] = yuv.b; + ptr[(pixel * 2) + 1] = yuv.g; + } + } + } + } + + ptr += width * 2; + col += width; + } + } +} + +static void ConfigureVideo(u16 xfbW, u16 xfbH) { + GXRenderModeObj mode; + mode.fbWidth = xfbW; + mode.efbHeight = 480; + mode.xfbHeight = xfbH; + mode.viXOrigin = 40; + mode.viWidth = 640; + mode.viHeight = xfbH; + + switch (VIGetTvFormat()) { + case 2: + case 0: + if (__VIRegs[54] & 1) { + mode.viTVmode = 2; + mode.viYOrigin = 0; + mode.xFBmode = 0; + } else { + mode.viTVmode = 0; + mode.viYOrigin = 0; + mode.xFBmode = 1; + } + break; + case 5: + if (__VIRegs[54] & 1) { + mode.viTVmode = 22; + mode.viYOrigin = 0; + mode.xFBmode = 0; + } else { + mode.viTVmode = 20; + mode.viYOrigin = 0; + mode.xFBmode = 1; + } + break; + case 1: + mode.viTVmode = 4; + mode.viYOrigin = 47; + mode.xFBmode = 1; + break; + } + + VIConfigure(&mode); + VIConfigurePan(0, 0, 640, 480); +} + +static GXColor RGB2YUV(GXColor rgb) { + f32 Y; + f32 Cb; + f32 Cr; + GXColor yuv; + + Y = 0.5f + (16.0f + ((0.098f * (f32) rgb.b) + ((0.257f * (f32) rgb.r) + (0.504f * (f32) rgb.g)))); + Cb = 0.5f + (128.0f + ((0.439f * (f32) rgb.b) + ((-0.148f * (f32) rgb.r) - (0.291f * (f32) rgb.g)))); + Cr = 0.5f + (128.0f + (((0.439f * (f32) rgb.r) - (0.368f * (f32) rgb.g)) - (0.071f * (f32) rgb.b))); + + yuv.r = (Y > 235.0f) ? 235.0f : (Y < 16.0f) ? 16.0f : Y; + yuv.g = (Cb > 240.0f) ? 240.0f : (Cb < 16.0f) ? 16.0f : Cb; + yuv.b = (Cr > 240.0f) ? 240.0f : (Cr < 16.0f) ? 16.0f : Cr; + yuv.a = 0; + + return yuv; +} + +void OSFatal(GXColor fg, GXColor bg, const char* msg) { + OSBootInfo* bootInfo; + u32 count; + OSTime t; + + bootInfo = (OSBootInfo*)OSPhysicalToCached(0); + OSDisableInterrupts(); + OSDisableScheduler(); + OSClearContext(&FatalContext); + OSSetCurrentContext(&FatalContext); + __OSStopAudioSystem(); + VIInit(); + __OSUnmaskInterrupts(0x80); + VISetBlack(TRUE); + VIFlush(); + VISetPreRetraceCallback(NULL); + VISetPostRetraceCallback(NULL); + OSEnableInterrupts(); + + count = VIGetRetraceCount(); + do {} while ((s32)(VIGetRetraceCount() - count) < 1); + + t = OSGetTime(); + while (!__OSCallShutdownFunctions(FALSE, 0) && OSGetTime() - t < OSMillisecondsToTicks(1000)) {} + + OSDisableInterrupts(); + __OSCallShutdownFunctions(TRUE, 0); + EXISetExiCallback(0, NULL); + EXISetExiCallback(2, NULL); + + while (!EXILock(0, 1, NULL)) { + EXISync(0); + EXIDeselect(0); + EXIUnlock(0); + } + EXIUnlock(0); + + do {} while ((__EXIRegs[3] & 1) == 1); + + __OSSetExceptionHandler(8, &OSDefaultExceptionHandler); + GXAbortFrame(); + OSSetArenaLo((void*)0x81400000); + + if (!bootInfo->FSTLocation) { + OSSetArenaHi(*(void**)OSPhysicalToCached(0x3110)); + } else { + OSSetArenaHi(bootInfo->FSTLocation); + } + + FatalParam.fg = fg; + FatalParam.bg = bg; + FatalParam.msg = msg; + OSSwitchFiber((u32)&Halt, (u32)OSGetArenaHi()); +} + +static void Halt() { + u32 count; + OSFontHeader* fontData; + void* xfb; + u32 len; + OSFatalParam* fp; + + OSEnableInterrupts(); + fp = &FatalParam; + len = strlen(fp->msg) + 1; + fp->msg = memmove(OSAllocFromMEM1ArenaLo(len, DOLPHIN_ALIGNMENT), fp->msg, len); + + fontData = OSAllocFromMEM1ArenaLo(0xA1004, DOLPHIN_ALIGNMENT); + OSLoadFont(fontData, OSGetArenaLo()); + + xfb = OSAllocFromMEM1ArenaLo(0x96000, DOLPHIN_ALIGNMENT); + ScreenClear(xfb, 640, 480, RGB2YUV(fp->bg)); + VISetNextFrameBuffer(xfb); + ConfigureVideo(640, 480); + VIFlush(); + + count = VIGetRetraceCount(); + do {} while ((s32)(VIGetRetraceCount() - count) < 2); + + ScreenReport(xfb, 640, 480, RGB2YUV(fp->fg), 48, 100, fontData->leading, fp->msg); + DCFlushRange(xfb, 0x96000); + VISetBlack(FALSE); + VIFlush(); + + count = VIGetRetraceCount(); + do {} while ((s32)(VIGetRetraceCount() - count) < 1); + + OSDisableInterrupts(); + OSReport("%s\n", fp->msg); + PPCHalt(); +} diff --git a/src/revolution/os/OSFont.c b/src/revolution/os/OSFont.c new file mode 100644 index 0000000000..29e1a8192b --- /dev/null +++ b/src/revolution/os/OSFont.c @@ -0,0 +1,748 @@ +#include +#include + +#include "__os.h" + +typedef char* (*ParseStringCallback)(u16, char*, OSFontHeader**, int*); + +static OSFontHeader* FontDataAnsi; +static OSFontHeader* FontDataSjis; +static int FixedPitch; +static ParseStringCallback ParseString; +static u16 FontEncode = 0xFFFF; + +// prototypes +static char* ParseStringS(u16 encode, const char* string, OSFontHeader** pfont, int* pfontCode); +static char* ParseStringW(u16 encode, const char* string, OSFontHeader** pfont, int* pfontCode); + +static u16 HankakuToCode[] + = { 0x20C, 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, + 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21A, 0x21B, + 0x21C, 0x21D, 0x21E, 0x21F, 0x220, 0x221, 0x222, 0x223, + 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22A, 0x22B, + 0x22C, 0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, + 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23A, 0x23B, + 0x23C, 0x23D, 0x23E, 0x23F, 0x240, 0x241, 0x242, 0x243, + 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A, 0x24B, + 0x24C, 0x24D, 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, + 0x254, 0x255, 0x256, 0x257, 0x258, 0x259, 0x25A, 0x25B, + 0x25C, 0x25D, 0x25E, 0x25F, 0x260, 0x261, 0x262, 0x263, + 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, 0x20C, + 0x20C, 0x26B, 0x26C, 0x26D, 0x26E, 0x26F, 0x270, 0x271, + 0x272, 0x273, 0x274, 0x275, 0x276, 0x277, 0x278, 0x279, + 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, + 0x282, 0x283, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, + 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, + 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, + 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, + 0x2A2, 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, + }; + +static u16 Zenkaku2Code[] + = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x008, 0x009, 0x00A, 0x00B, 0x00C, 0x00D, 0x00E, 0x00F, + 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017, + 0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, 0x01F, + 0x020, 0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x027, + 0x028, 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, + 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, + 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, + 0x03F, 0x040, 0x041, 0x042, 0x043, 0x044, 0x045, 0x046, + 0x047, 0x048, 0x049, 0x04A, 0x04B, 0x04C, 0x04D, 0x04E, + 0x04F, 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, + 0x057, 0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, + 0x05F, 0x060, 0x061, 0x062, 0x063, 0x064, 0x065, 0x066, + 0x067, 0x068, 0x069, 0x06A, 0x06B, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x06C, 0x06D, 0x06E, 0x06F, 0x070, 0x071, 0x072, 0x073, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x07B, 0x07C, 0x07D, 0x07E, 0x07F, 0x080, + 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, 0x088, + 0x089, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x08A, 0x08B, 0x08C, 0x08D, 0x08E, 0x08F, 0x090, 0x091, + 0x000, 0x000, 0x000, 0x000, 0x092, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x093, + 0x094, 0x095, 0x096, 0x097, 0x098, 0x099, 0x09A, 0x09B, + 0x09C, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x09D, 0x09E, 0x09F, 0x0A0, 0x0A1, 0x0A2, 0x0A3, 0x0A4, + 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x0AA, 0x0AB, 0x0AC, + 0x0AD, 0x0AE, 0x0AF, 0x0B0, 0x0B1, 0x0B2, 0x0B3, 0x0B4, + 0x0B5, 0x0B6, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x0B7, 0x0B8, 0x0B9, 0x0BA, 0x0BB, 0x0BC, 0x0BD, + 0x0BE, 0x0BF, 0x0C0, 0x0C1, 0x0C2, 0x0C3, 0x0C4, 0x0C5, + 0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, + 0x0CE, 0x0CF, 0x0D0, 0x000, 0x000, 0x000, 0x000, 0x0D1, + 0x0D2, 0x0D3, 0x0D4, 0x0D5, 0x0D6, 0x0D7, 0x0D8, 0x0D9, + 0x0DA, 0x0DB, 0x0DC, 0x0DD, 0x0DE, 0x0DF, 0x0E0, 0x0E1, + 0x0E2, 0x0E3, 0x0E4, 0x0E5, 0x0E6, 0x0E7, 0x0E8, 0x0E9, + 0x0EA, 0x0EB, 0x0EC, 0x0ED, 0x0EE, 0x0EF, 0x0F0, 0x0F1, + 0x0F2, 0x0F3, 0x0F4, 0x0F5, 0x0F6, 0x0F7, 0x0F8, 0x0F9, + 0x0FA, 0x0FB, 0x0FC, 0x0FD, 0x0FE, 0x0FF, 0x100, 0x101, + 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, + 0x10A, 0x10B, 0x10C, 0x10D, 0x10E, 0x10F, 0x110, 0x111, + 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118, 0x119, + 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, + 0x122, 0x123, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, + 0x124, 0x125, 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, + 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, + 0x134, 0x135, 0x136, 0x137, 0x138, 0x139, 0x13A, 0x13B, + 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, 0x142, 0x143, + 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, + 0x14C, 0x14D, 0x14E, 0x14F, 0x150, 0x151, 0x152, 0x153, + 0x154, 0x155, 0x156, 0x157, 0x158, 0x159, 0x15A, 0x15B, + 0x15C, 0x15D, 0x15E, 0x15F, 0x160, 0x161, 0x162, + 0x163, 0x164, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, + 0x16B, 0x16C, 0x16D, 0x16E, 0x16F, 0x170, 0x171, 0x172, + 0x173, 0x174, 0x175, 0x176, 0x177, 0x178, 0x179, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x17A, + 0x17B, 0x17C, 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, + 0x183, 0x184, 0x185, 0x186, 0x187, 0x188, 0x189, 0x18A, + 0x18B, 0x18C, 0x18D, 0x18E, 0x18F, 0x190, 0x191, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x192, + 0x193, 0x194, 0x195, 0x196, 0x197, 0x198, 0x199, 0x19A, + 0x19B, 0x19C, 0x19D, 0x19E, 0x19F, 0x1A0, 0x1A1, 0x1A2, + 0x1A3, 0x1A4, 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, + 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, 0x1B0, 0x1B1, + 0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, + 0x1BA, 0x1BB, 0x1BC, 0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, + 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7, 0x1C8, 0x1C9, + 0x1CA, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x1CB, 0x1CC, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, + 0x1D3, 0x1D4, 0x1D5, 0x1D6, 0x1D7, 0x1D8, 0x1D9, + 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E0, 0x1E1, + 0x1E2, 0x1E3, 0x1E4, 0x1E5, 0x1E6, 0x1E7, 0x1E8, 0x1E9, + 0x1EA, 0x1EB, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1EC, + 0x1ED, 0x1EE, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, + 0x1F5, 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB, 0x1FC, + 0x1FD, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203, 0x204, + 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, 0x20B, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x20C, + 0x20D, 0x20E, 0x20F, 0x210, 0x211, 0x212, 0x213, 0x214, + 0x215, 0x216, 0x217, 0x218, 0x219, 0x21A, 0x21B, 0x21C, + 0x21D, 0x21E, 0x21F, 0x220, 0x221, 0x222, 0x223, 0x224, + 0x225, 0x226, 0x227, 0x228, 0x229, 0x22A, 0x22B, 0x22C, + 0x22D, 0x22E, 0x22F, 0x230, 0x231, 0x232, 0x233, 0x234, + 0x235, 0x236, 0x237, 0x238, 0x239, 0x23A, 0x23B, 0x23C, + 0x23D, 0x23E, 0x23F, 0x240, 0x241, 0x242, 0x243, 0x244, + 0x245, 0x246, 0x247, 0x248, 0x249, 0x24A, 0x24B, + 0x24C, 0x24D, 0x24E, 0x24F, 0x250, 0x251, 0x252, 0x253, + 0x254, 0x255, 0x256, 0x257, 0x258, 0x259, 0x25A, 0x25B, + 0x25C, 0x25D, 0x25E, 0x25F, 0x260, 0x261, 0x262, 0x263, + 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26A, 0x26B, + 0x26C, 0x26D, 0x26E, 0x26F, 0x270, 0x271, 0x272, 0x273, + 0x274, 0x275, 0x276, 0x277, 0x278, 0x279, 0x27A, 0x27B, + 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, + 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, + 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, 0x293, + 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29A, 0x29B, + 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, 0x2A1, 0x2A2, 0x2A3, + 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, + 0x2AC, 0x2AD, 0x2AE, 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, + 0x2B4, 0x2B5, 0x2B6, 0x2B7, 0x2B8, 0x2B9, 0x2BA, 0x2BB, + 0x2BC, 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3, + 0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, + 0x2C9, 0x2CA, 0x2CB, 0x2CC, 0x2CD, 0x2CE, 0x2CF, 0x2D0, + 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8, + 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, + 0x2E1, 0x2E2, 0x2E3, 0x2E4, 0x2E5, 0x2E6, 0x000, 0x2E7, + 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED, 0x2EE, 0x2EF, + 0x2F0, 0x2F1, 0x2F2, 0x2F3, 0x2F4, 0x2F5, 0x2F6, 0x2F7, + 0x2F8, 0x2F9, 0x2FA, 0x2FB, 0x2FC, 0x2FD, 0x000, 0x000, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x2FE, + 0x2FF, 0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, + 0x307, 0x308, 0x309, 0x30A, 0x30B, 0x30C, 0x30D, 0x30E, + 0x30F, 0x310, 0x311, 0x312, 0x313, 0x314, 0x315, 0x316, + 0x317, 0x318, 0x319, 0x31A, 0x31B, 0x000 + }; + +static BOOL IsSjisLeadByte(u8 c) { + return (0x81 <= c && c <= 0x9F) || (0xE0 <= c && c <= 0xFC); +} + +static BOOL IsSjisTrailByte(u8 c) { + return (0x40 <= c && c <= 0xFC) && (c != 0x7F); +} + +static int GetFontCode(u16 encode, u16 code) { + if (encode == OS_FONT_ENCODE_SJIS) { + if (code >= 0x20 && code <= 0xDF) { + return HankakuToCode[code - 0x20]; + } + + if (code > 0x889E && code <= 0x9872) { + int i = ((code >> 8) - 0x88) * 188; + int j = (code & 0xFF); + + if (!IsSjisTrailByte(j)) { + return 0; + } + + j -= 0x40; + if (j >= 0x40) { + j--; + } + + return (i + j + 0x2BE); + } + + if (code >= 0x8140 && code < 0x879E) { + int i = ((code >> 8) - 0x81) * 188; + int j = (code & 0xFF); + + if (!IsSjisTrailByte(j)) { + return 0; + } + + j -= 0x40; + if (j >= 0x40) { + j--; + } + + return Zenkaku2Code[i + j]; + } + } else if (code > 0x20 && code <= 0xFF) { + return code - 0x20; + } + + return 0; +} + +static void Decode(u8* s, u8* d) { + int i; + int j; + int k; + int p; + int q; + int r7; // huh? DWARF info says these 2 variables might be register names and not actual names. + int r25; + int cnt; + int os; + unsigned int flag; + unsigned int code; + + os = *(int*)(s + 0x4); + r7 = *(int*)(s + 0x8); + r25 = *(int*)(s + 0xC); + + q = 0; + flag = 0; + p = 16; + + do { + // Get next mask + if (flag == 0) { + code = *(u32*)(s + p); + p += sizeof(u32); + flag = sizeof(u32) * 8; + } + + // Non-linked chunk + if (code & 0x80000000) { + d[q++] = s[r25++]; + } + // Linked chunk + else { + // Read offset from link table + j = s[r7] << 8 | s[r7 + 1]; + r7 += sizeof(u16); + + // Apply offset + k = q - (j & 0x0FFF); + cnt = j >> 12; + if (cnt == 0) { + cnt = s[r25++] + 0x12; + } else { + cnt += 2; + } + + // Copy chunk + for (i = 0; i < cnt; i++, q++, k++) { + d[q] = d[k - 1]; + } + } + + // Prepare next mask bit + code <<= 1; + flag--; + } while (q < os); +} + +static u32 GetFontSize(u8* buf) { + if (buf[0] == 'Y' && buf[1] == 'a' && buf[2] == 'y') { + return *(u32*)(buf + 0x4); + } + + return 0; +} + +u16 OSGetFontEncode(void) { + if (FontEncode != 0xFFFF) { + return FontEncode; + } + + switch (*(int*)OSPhysicalToCached(0xCC)) { + case VI_NTSC: + FontEncode = (__VIRegs[VI_DTV_STAT] & 2) ? OS_FONT_ENCODE_SJIS : OS_FONT_ENCODE_ANSI; + break; + case VI_PAL: + case VI_MPAL: + default: + FontEncode = OS_FONT_ENCODE_ANSI; + } + + ParseString = (ParseStringCallback)ParseStringS; + return FontEncode; +} + +u16 OSSetFontEncode(u16 encode) { + u16 prev; + + ASSERTLINE(484, encode <= OS_FONT_ENCODE_MAX); + + prev = OSGetFontEncode(); + if (encode <= OS_FONT_ENCODE_MAX) { + FontEncode = encode; + if (encode >= 3 && encode <= OS_FONT_ENCODE_MAX) { + ParseString = (ParseStringCallback)ParseStringW; + } + } + + return prev; +} + +static void ReadROM(void* buf, int length, int offset) { + int len; + while (length > 0) { + len = (length <= 0x100) ? length : 0x100; + length -= len; + + while (!__OSReadROM(buf, len, offset)) { + ; + } + + offset += len; + (u8*)buf += len; + } +} + +static u32 ReadFont(void* img, u16 encode, void* fontData) { + u32 size; +#ifndef DEBUG + u32 padding[1]; +#endif + + if (encode == OS_FONT_ENCODE_SJIS) { + ReadROM(img, OS_FONT_ROM_SIZE_SJIS, 0x1AFF00); + } else { + ReadROM(img, OS_FONT_ROM_SIZE_ANSI, 0x1FCF00); + } + + size = GetFontSize(img); + if (size == 0) { + return 0; + } + + Decode(img, fontData); + if (encode == OS_FONT_ENCODE_SJIS) { + OSFontHeader* font = (OSFontHeader*)fontData; + int fontCode; + u8* imageSrc; + int sheet; + int numChars; + int row; + int column; + int x; + int y; + u8* src; + const u16 imageT[4] = {0x2ABE, 0x003D, 0x003D, 0x003D}; + + fontCode = GetFontCode(encode, 0x54); + sheet = fontCode / (font->sheetColumn * font->sheetRow); + numChars = fontCode - (sheet * (font->sheetColumn * font->sheetRow)); + row = numChars / font->sheetColumn; + column = numChars - (row * font->sheetColumn); + row *= font->cellHeight; + column *= font->cellWidth; + + imageSrc = (u8*)font + font->sheetImage; + imageSrc += ((sheet * font->sheetSize) >> 1); + + for (y = 4; y < 8; y++) { + x = 0; + src = imageSrc + ((((font->sheetWidth / 8) << 5) / 2) * ((row + y) / 8)); + src += ((column + x) / 8) * 0x10; + src += ((row + y) % 8) * 2; + src += ((column + x) % 8) / 4; + + *(u16*)src = imageT[y - 4]; + } + } + + return size; +} + +u32 OSLoadFont(OSFontHeader* fontData, void* tmp) { + u16 encode; + u32 size; + + encode = OSGetFontEncode(); + switch (encode) { + case 0: + FontDataAnsi = fontData; + size = ReadFont(tmp, 0, FontDataAnsi); + break; + case 1: + FontDataSjis = fontData; + size = ReadFont(tmp, 1, FontDataSjis); + break; + case 3: + case 4: + case 5: + FontDataAnsi = fontData; + size = ReadFont(tmp, 0, FontDataAnsi); + if (size != 0) { + FontDataSjis = (OSFontHeader*)((u8*)FontDataAnsi + size); + size += ReadFont(tmp, 1, FontDataSjis); + } + break; + case 2: + default: + size = 0; + break; + } + + return size; +} + +static char* ParseStringS(u16 encode, const char* string, OSFontHeader** pfont, int* pfontCode) { + OSFontHeader* font; + u16 code = 0; + + switch (encode) { + case OS_FONT_ENCODE_ANSI: + font = FontDataAnsi; + code = (u8)*string; + if (code != 0) { + string++; + } + break; + case OS_FONT_ENCODE_SJIS: + font = FontDataSjis; + code = (u8)*string; + if (code == 0) { + break; + } + string++; + + if (IsSjisLeadByte(code) && IsSjisTrailByte(*string)) { + code = (code << 8 | (u8)*string++); + } + break; + } + + *pfont = font; + *pfontCode = GetFontCode(encode, code); + + return (char*)string; +} + +static char* ParseStringW(u16 encode, const char* string, OSFontHeader** pfont, int* pfontCode) { + OSFontHeader* font; + u16 code = 0; + u32 utf32 = 0; + + switch (encode) { + case OS_FONT_ENCODE_ANSI: + font = FontDataAnsi; + code = (u8)*string; + if (code != 0) { + string++; + } + break; + case OS_FONT_ENCODE_SJIS: + font = FontDataSjis; + code = (u8)*string; + if (code == 0) { + break; + } + string++; + + if (IsSjisLeadByte(code) && IsSjisTrailByte(*string)) { + code = (code << 8 | (u8)*string++); + } + break; + case 3: + string = OSUTF8to32(string, &utf32); + break; + case 4: + string = (const char*)OSUTF16to32((u16*)string, &utf32); + break; + case 5: + utf32 = *(u32*)string; + if (utf32 != 0) { + string += 4; + } + break; + } + + if (utf32 != 0) { + encode = 0; + font = FontDataAnsi; + code = OSUTF32toANSI(utf32); + + if (code == 0 || (FixedPitch != 0 && utf32 <= 0x7F)) { + code = OSUTF32toSJIS(utf32); + if (code != 0) { + encode = 1; + font = FontDataSjis; + } + } + } + + *pfont = font; + *pfontCode = GetFontCode(encode, code); + + return (char*)string; +} + +char* OSGetFontTexel(const char* string, void* image, s32 pos, s32 stride, s32* width) { + u16 encode; + OSFontHeader* font; + u8* src; + u8* dst; + int fontCode; + int sheet; + int numChars; + int row; + int column; + int x; + int y; + int offsetSrc; + int offsetDst; + u8* colorIndex; + u8* imageSrc; + + encode = OSGetFontEncode(); + string = ParseString(encode, (char*)string, &font, &fontCode); + colorIndex = &font->c0; + ASSERTLINE(927, font->sheetFormat == GX_TF_I4); + + sheet = fontCode / (font->sheetColumn * font->sheetRow); + numChars = fontCode - (sheet * (font->sheetColumn * font->sheetRow)); + row = numChars / font->sheetColumn; + column = numChars - (row * font->sheetColumn); + row *= font->cellHeight; + column *= font->cellWidth; + + imageSrc = (u8*)font + font->sheetImage; + imageSrc += ((sheet * font->sheetSize) >> 1); + + for (y = 0; y < font->cellHeight; y++) { + for (x = 0; x < font->cellWidth; x++) { + src = imageSrc + (((font->sheetWidth / 8) * 32) / 2) * ((row + y) / 8); + src += ((column + x) / 8) * 16; + src += ((row + y) % 8) * 2; + src += ((column + x) % 8) / 4; + + offsetSrc = (column + x) % 4; + + dst = (u8*)image + ((y / 8) * (((stride * 4) / 8) * 32)); + dst += (((pos + x) / 8) * 32); + dst += ((y % 8) * 4); + dst += ((pos + x) % 8) / 2; + + offsetDst = (pos + x) % 2; + + *dst |= (u8)(colorIndex[*src >> (6 - (offsetSrc * 2)) & 3] & ((offsetDst != 0) ? 0x0F : 0xF0)); + } + } + + if (width != 0) { + *width = ((u8*)font + font->widthTable)[fontCode]; + } + + return (char*)string; +} + +static void ExpandFontSheet(OSFontHeader* font, u8* src, u8* dst) { + int i; + u8* colorIndex = &font->c0; + + if (font->sheetFormat == GX_TF_I4) { + for (i = (s32)(font->sheetFullSize) / 2 - 1; i >= 0; i--) { + dst[i * 2 + 0] = + colorIndex[src[i] >> 6 & 3] & 0xF0 | colorIndex[src[i] >> 4 & 3] & 0x0F; + dst[i * 2 + 1] = + colorIndex[src[i] >> 2 & 3] & 0xF0 | colorIndex[src[i] >> 0 & 3] & 0x0F; + } + } else if (font->sheetFormat == GX_TF_IA4) { + for (i = (s32)(font->sheetFullSize) / 4 - 1; i >= 0; i--) { + dst[i * 4 + 0] = colorIndex[src[i] >> 6 & 3]; + dst[i * 4 + 1] = colorIndex[src[i] >> 4 & 3]; + dst[i * 4 + 2] = colorIndex[src[i] >> 2 & 3]; + dst[i * 4 + 3] = colorIndex[src[i] >> 0 & 3]; + } + } + + DCStoreRange(dst, font->sheetFullSize); +} + +int OSInitFont(OSFontHeader* fontData) { + u16 encode; + u32 size; + void* tmp; + u8* img; + + ASSERTLINE(919, (u32) fontData % 32 == 0); + + encode = OSGetFontEncode(); + switch (encode) { + case 0: + tmp = (void*)((u8*)fontData + 0x1D120); + FontDataAnsi = fontData; + size = ReadFont(tmp, 0, FontDataAnsi); + if (size == 0) { + return 0; + } + + img = (u8*)FontDataAnsi + FontDataAnsi->sheetImage; + FontDataAnsi->sheetImage = OSRoundUp32B(FontDataAnsi->sheetImage); + ExpandFontSheet(FontDataAnsi, img, (u8*)FontDataAnsi + FontDataAnsi->sheetImage); + break; + case 1: + tmp = (void*)((u8*)fontData + 0xD3F00); + FontDataSjis = fontData; + size = ReadFont(tmp, 1, FontDataSjis); + if (size == 0) { + return 0; + } + + img = (u8*)FontDataSjis + FontDataSjis->sheetImage; + FontDataSjis->sheetImage = OSRoundUp32B(FontDataSjis->sheetImage); + ExpandFontSheet(FontDataSjis, img, (u8*)FontDataSjis + FontDataSjis->sheetImage); + break; + case 3: + case 4: + case 5: + tmp = (void*)((u8*)fontData + 0xF4020); + FontDataAnsi = fontData; + size = ReadFont(tmp, 0, FontDataAnsi); + if (size == 0) { + return 0; + } + + img = (u8*)FontDataAnsi + FontDataAnsi->sheetImage; + FontDataAnsi->sheetImage = OSRoundUp32B(FontDataAnsi->sheetImage); + ExpandFontSheet(FontDataAnsi, img, (u8*)FontDataAnsi + FontDataAnsi->sheetImage); + + FontDataSjis = (OSFontHeader*)((u8*)FontDataAnsi + 0x20120); + size = ReadFont(tmp, 1, FontDataSjis); + if (size == 0) { + return 0; + } + + img = (u8*)FontDataSjis + FontDataSjis->sheetImage; + FontDataSjis->sheetImage = OSRoundUp32B(FontDataSjis->sheetImage); + ExpandFontSheet(FontDataSjis, img, (u8*)FontDataSjis + FontDataSjis->sheetImage); + break; + case 2: + default: + break; + } + + return 1; +} + +char* OSGetFontTexture(const char* string, void** image, s32* x, s32* y, s32* width) { + OSFontHeader* font; + u16 encode; + int fontCode; + int sheet; + int numChars; + int row; + int column; + + encode = OSGetFontEncode(); + string = ParseString(encode, (char*)string, &font, &fontCode); + sheet = fontCode / (font->sheetColumn * font->sheetRow); + ((u32*)image)[0] = (u32)font + font->sheetImage + (font->sheetSize * sheet); + numChars = fontCode - (sheet * (font->sheetColumn * font->sheetRow)); + row = numChars / font->sheetColumn; + column = numChars - (row * font->sheetColumn); + *x = column * font->cellWidth; + *y = row * font->cellHeight; + + ASSERTLINE(1016, (u32) *image % 32 == 0); + + if (width != 0) { + *width = ((u8*)font + font->widthTable)[fontCode]; + } + return (char*)string; +} + +char* OSGetFontWidth(const char* string, s32* width) { + OSFontHeader* font; + u16 encode; + int fontCode; + + encode = OSGetFontEncode(); + string = ParseString(encode, (char*)string, &font, &fontCode); + + if (width != 0) { + *width = ((u8*)font + font->widthTable)[fontCode]; + } + + return (char*)string; +} + +int OSSetFontWidth(int fixed) { + int prev = FixedPitch; + FixedPitch = fixed; + return prev; +} diff --git a/src/revolution/os/OSInterrupt.c b/src/revolution/os/OSInterrupt.c new file mode 100644 index 0000000000..17993fd481 --- /dev/null +++ b/src/revolution/os/OSInterrupt.c @@ -0,0 +1,519 @@ +#include +#include + +#include "__os.h" + +#if DEBUG +u64 __OSSpuriousInterrupts = 0; +#endif +static __OSInterruptHandler* InterruptHandlerTable; + +volatile OSTime __OSLastInterruptTime; +volatile __OSInterrupt __OSLastInterrupt; +volatile u32 __OSLastInterruptSrr0; + +static OSInterruptMask InterruptPrioTable[] = { + OS_INTERRUPTMASK_PI_ERROR, + OS_INTERRUPTMASK_PI_DEBUG, + OS_INTERRUPTMASK_MEM, + OS_INTERRUPTMASK_PI_RSW, + OS_INTERRUPTMASK_PI_VI, + 0x10, + OS_INTERRUPTMASK_PI_PE, + OS_INTERRUPTMASK_PI_HSP, + OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP | OS_INTERRUPTMASK_AI | + OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI_SI | OS_INTERRUPTMASK_PI_DI, + OS_INTERRUPTMASK_DSP_AI, + OS_INTERRUPTMASK_PI_CP, + 0xFFFFFFFF, +}; + +#if DEBUG +char* __OSInterruptNames[33] = { + "MEM_0", + "MEM_1", + "MEM_2", + "MEM_3", + "MEM_ADDRESS", + "DSP_AI", + "DSP_ARAM", + "DSP_DSP", + "AI_AI", + "EXI_0_EXI", + "EXI_0_TC", + "EXI_0_EXT", + "EXI_1_EXI", + "EXI_1_TC", + "EXI_1_EXT", + "EXI_2_EXI", + "EXI_2_TC", + "PI_CP", + "PI_PE_TOKEN", + "PI_PE_FINISH", + "PI_SI", + "PI_DI", + "PI_RSW", + "PI_ERROR", + "PI_VI", + "PI_DEBUG", + "PI_HSP", + "PI_ACR", + "unknown", + "unknown", + "unknown", + "unknown", + "unknown", +}; + +char* __OSPIErrors[8] = { + "No Error", + "Misaligned address for CPU request", + "Incorrect transfer type (tt) from CPU", + "Unsupported transfer size", + "Address out of range", + "Write to ROM address space", + "Read from GX Fifo", + "Reserved error code", +}; +#endif + +// prototypes +static void ExternalInterruptHandler(register __OSException exception, register OSContext* context); +extern void __RAS_OSDisableInterrupts_begin(void); +extern void __RAS_OSDisableInterrupts_end(void); + +#ifdef __GEKKO__ +asm BOOL OSDisableInterrupts(void) { + nofralloc +entry __RAS_OSDisableInterrupts_begin + mfmsr r3 + rlwinm r4, r3, 0, 17, 15 + mtmsr r4 +entry __RAS_OSDisableInterrupts_end + rlwinm r3, r3, 17, 31, 31 + blr +} + +asm BOOL OSEnableInterrupts(void) { + nofralloc + + mfmsr r3 + ori r4, r3, 0x8000 + mtmsr r4 + rlwinm r3, r3, 17, 31, 31 + blr +} + +asm BOOL OSRestoreInterrupts(register BOOL level) { + nofralloc + + cmpwi level, 0 + mfmsr r4 + beq _disable + ori r5, r4, 0x8000 + b _restore +_disable: + rlwinm r5, r4, 0, 17, 15 +_restore: + mtmsr r5 + rlwinm r3, r4, 17, 31, 31 + blr +} +#endif + +__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler) { + __OSInterruptHandler oldHandler; + + ASSERTMSGLINE(482, InterruptHandlerTable, "__OSSetInterruptHandler(): OSInit() must be called in advance."); + ASSERTMSGLINE(484, interrupt < 0x20, "__OSSetInterruptHandler(): unknown interrupt."); + + oldHandler = InterruptHandlerTable[interrupt]; + InterruptHandlerTable[interrupt] = handler; + return oldHandler; +} + +__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt) { + ASSERTMSGLINE(504, InterruptHandlerTable, "__OSGetInterruptHandler(): OSInit() must be called in advance."); + ASSERTMSGLINE(506, interrupt < 0x20, "__OSGetInterruptHandler(): unknown interrupt."); + return InterruptHandlerTable[interrupt]; +} + +void __OSInterruptInit(void) { + InterruptHandlerTable = (void*)OSPhysicalToCached(0x3040); + + memset(InterruptHandlerTable, 0, __OS_INTERRUPT_MAX * sizeof(__OSInterruptHandler)); + + *(OSInterruptMask*)OSPhysicalToCached(0x00C4) = 0; + *(OSInterruptMask*)OSPhysicalToCached(0x00C8) = 0; + *(u32*)0xCC003004 = 240; + *(u32*)0xCD000034 = 0x40000000; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM | OS_INTERRUPTMASK_DSP | OS_INTERRUPTMASK_AI | + OS_INTERRUPTMASK_EXI | OS_INTERRUPTMASK_PI); + + __OSSetExceptionHandler(4, ExternalInterruptHandler); + #if DEBUG + __PIRegs[0] = 1; + __OSUnmaskInterrupts(0x100); + #endif +} + +static u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current) { + u32 reg; + + switch (__cntlzw(mask)) { + case __OS_INTERRUPT_MEM_0: + case __OS_INTERRUPT_MEM_1: + case __OS_INTERRUPT_MEM_2: + case __OS_INTERRUPT_MEM_3: + case __OS_INTERRUPT_MEM_ADDRESS: + reg = 0; + if (!(current & OS_INTERRUPTMASK_MEM_0)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_MEM_1)) + reg |= 0x2; + if (!(current & OS_INTERRUPTMASK_MEM_2)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_MEM_3)) + reg |= 0x8; + if (!(current & OS_INTERRUPTMASK_MEM_ADDRESS)) + reg |= 0x10; + __MEMRegs[0x0000000e] = (u16)reg; + mask &= ~OS_INTERRUPTMASK_MEM; + break; + case __OS_INTERRUPT_DSP_AI: + case __OS_INTERRUPT_DSP_ARAM: + case __OS_INTERRUPT_DSP_DSP: + reg = __DSPRegs[0x00000005]; + reg &= ~0x1F8; + if (!(current & OS_INTERRUPTMASK_DSP_AI)) + reg |= 0x10; + if (!(current & OS_INTERRUPTMASK_DSP_ARAM)) + reg |= 0x40; + if (!(current & OS_INTERRUPTMASK_DSP_DSP)) + reg |= 0x100; + __DSPRegs[0x00000005] = (u16)reg; + mask &= ~OS_INTERRUPTMASK_DSP; + break; + case __OS_INTERRUPT_AI_AI: + reg = __AIRegs[0]; + reg &= ~0x2C; + if (!(current & OS_INTERRUPTMASK_AI_AI)) + reg |= 0x4; + __AIRegs[0] = reg; + mask &= ~OS_INTERRUPTMASK_AI; + break; + case __OS_INTERRUPT_EXI_0_EXI: + case __OS_INTERRUPT_EXI_0_TC: + case __OS_INTERRUPT_EXI_0_EXT: + reg = __EXIRegs[0]; + reg &= ~0x2C0F; + if (!(current & OS_INTERRUPTMASK_EXI_0_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_0_TC)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_EXI_0_EXT)) + reg |= 0x400; + __EXIRegs[0] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_0; + break; + case __OS_INTERRUPT_EXI_1_EXI: + case __OS_INTERRUPT_EXI_1_TC: + case __OS_INTERRUPT_EXI_1_EXT: + reg = __EXIRegs[5]; + reg &= ~0xC0F; + + if (!(current & OS_INTERRUPTMASK_EXI_1_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_1_TC)) + reg |= 0x4; + if (!(current & OS_INTERRUPTMASK_EXI_1_EXT)) + reg |= 0x400; + __EXIRegs[5] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_1; + break; + case __OS_INTERRUPT_EXI_2_EXI: + case __OS_INTERRUPT_EXI_2_TC: + reg = __EXIRegs[10]; + reg &= ~0xF; + if (!(current & OS_INTERRUPTMASK_EXI_2_EXI)) + reg |= 0x1; + if (!(current & OS_INTERRUPTMASK_EXI_2_TC)) + reg |= 0x4; + + __EXIRegs[10] = reg; + mask &= ~OS_INTERRUPTMASK_EXI_2; + break; + case __OS_INTERRUPT_PI_CP: + case __OS_INTERRUPT_PI_SI: + case __OS_INTERRUPT_PI_DI: + case __OS_INTERRUPT_PI_RSW: + case __OS_INTERRUPT_PI_ERROR: + case __OS_INTERRUPT_PI_VI: + case __OS_INTERRUPT_PI_DEBUG: + case __OS_INTERRUPT_PI_PE_TOKEN: + case __OS_INTERRUPT_PI_PE_FINISH: + case __OS_INTERRUPT_PI_HSP: + case __OS_INTERRUPT_PI_ACR: + reg = 0xF0; + + if (!(current & OS_INTERRUPTMASK_PI_CP)) { + reg |= 0x800; + } + if (!(current & OS_INTERRUPTMASK_PI_SI)) { + reg |= 0x8; + } + if (!(current & OS_INTERRUPTMASK_PI_DI)) { + reg |= 0x4; + } + if (!(current & OS_INTERRUPTMASK_PI_RSW)) { + reg |= 0x2; + } + if (!(current & OS_INTERRUPTMASK_PI_ERROR)) { + reg |= 0x1; + } + if (!(current & OS_INTERRUPTMASK_PI_VI)) { + reg |= 0x100; + } + if (!(current & OS_INTERRUPTMASK_PI_DEBUG)) { + reg |= 0x1000; + } + if (!(current & OS_INTERRUPTMASK_PI_PE_TOKEN)) { + reg |= 0x200; + } + if (!(current & OS_INTERRUPTMASK_PI_PE_FINISH)) { + reg |= 0x400; + } + if (!(current & OS_INTERRUPTMASK_PI_HSP)) { + reg |= 0x2000; + } + if (!(current & OS_INTERRUPTMASK_PI_ACR)) { + reg |= 0x4000; + } + + __PIRegs[1] = reg; + mask &= ~OS_INTERRUPTMASK_PI; + break; + default: + break; + } + return mask; +} + +OSInterruptMask OSGetInterruptMask(void) { + return *(OSInterruptMask *)OSPhysicalToCached(0x00C8); +} + +OSInterruptMask OSSetInterruptMask(OSInterruptMask local) { + BOOL enabled; + OSInterruptMask global; + OSInterruptMask prev; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + global = *(OSInterruptMask *)OSPhysicalToCached(0x00C4); + prev = *(OSInterruptMask *)OSPhysicalToCached(0x00C8); + mask = (global | prev) ^ local; + *(OSInterruptMask *)OSPhysicalToCached(0x00C8) = local; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +OSInterruptMask __OSMaskInterrupts(OSInterruptMask global) { + BOOL enabled; + OSInterruptMask prev; + OSInterruptMask local; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + prev = *(OSInterruptMask *)OSPhysicalToCached(0x00C4); + local = *(OSInterruptMask *)OSPhysicalToCached(0x00C8); + mask = ~(prev | local) & global; + global |= prev; + *(OSInterruptMask *)OSPhysicalToCached(0x00C4) = global; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global) { + BOOL enabled; + OSInterruptMask prev; + OSInterruptMask local; + OSInterruptMask mask; + + enabled = OSDisableInterrupts(); + prev = *(OSInterruptMask *)OSPhysicalToCached(0x00C4); + local = *(OSInterruptMask *)OSPhysicalToCached(0x00C8); + mask = (prev | local) & global; + global = prev & ~global; + *(OSInterruptMask *)OSPhysicalToCached(0x00C4) = global; + while (mask) { + mask = SetInterruptMask(mask, global | local); + } + OSRestoreInterrupts(enabled); + return prev; +} + +void __OSDispatchInterrupt(__OSException exception, OSContext* context) { + u32 intsr; + u32 mask; + u32 reg; + OSInterruptMask cause; + OSInterruptMask unmasked; + OSInterruptMask* prio; + __OSInterrupt interrupt; + __OSInterruptHandler handler; + + intsr = __PIRegs[0]; + intsr &= ~0x00010000; + mask = __PIRegs[1]; + + if (intsr == 0 || (intsr & mask) == 0) { + #if DEBUG + __OSSpuriousInterrupts++; + #endif + OSLoadContext(context); + } + + cause = 0; + + if (intsr & 0x00000080) { + reg = __MEMRegs[15]; + if (reg & 0x1) + cause |= OS_INTERRUPTMASK_MEM_0; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_MEM_1; + if (reg & 0x4) + cause |= OS_INTERRUPTMASK_MEM_2; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_MEM_3; + if (reg & 0x10) + cause |= OS_INTERRUPTMASK_MEM_ADDRESS; + } + + if (intsr & 0x00000040) { + reg = __DSPRegs[5]; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_DSP_AI; + if (reg & 0x20) + cause |= OS_INTERRUPTMASK_DSP_ARAM; + if (reg & 0x80) + cause |= OS_INTERRUPTMASK_DSP_DSP; + } + + if (intsr & 0x00000020) { + reg = __AIRegs[0]; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_AI_AI; + } + + if (intsr & 0x00000010) { + reg = __EXIRegs[0]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_0_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_0_TC; + if (reg & 0x800) + cause |= OS_INTERRUPTMASK_EXI_0_EXT; + reg = __EXIRegs[5]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_1_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_1_TC; + if (reg & 0x800) + cause |= OS_INTERRUPTMASK_EXI_1_EXT; + reg = __EXIRegs[10]; + if (reg & 0x2) + cause |= OS_INTERRUPTMASK_EXI_2_EXI; + if (reg & 0x8) + cause |= OS_INTERRUPTMASK_EXI_2_TC; + } + + if (intsr & 0x00002000) + cause |= OS_INTERRUPTMASK_PI_HSP; + if (intsr & 0x00001000) + cause |= OS_INTERRUPTMASK_PI_DEBUG; + if (intsr & 0x00000400) + cause |= OS_INTERRUPTMASK_PI_PE_FINISH; + if (intsr & 0x00000200) + cause |= OS_INTERRUPTMASK_PI_PE_TOKEN; + if (intsr & 0x00000100) + cause |= OS_INTERRUPTMASK_PI_VI; + if (intsr & 0x00000008) + cause |= OS_INTERRUPTMASK_PI_SI; + if (intsr & 0x00000004) + cause |= OS_INTERRUPTMASK_PI_DI; + if (intsr & 0x00000002) + cause |= OS_INTERRUPTMASK_PI_RSW; + if (intsr & 0x00000800) + cause |= OS_INTERRUPTMASK_PI_CP; + if (intsr & 0x00000001) + cause |= OS_INTERRUPTMASK_PI_ERROR; + if (intsr & 0x4000) + cause |= OS_INTERRUPTMASK_PI_ACR; + + #if DEBUG + if (cause & OS_INTERRUPTMASK_PI_ERROR) { + OSReport("PI ERROR\n"); + OSDumpContext(context); + OSReport("\nPIESR = 0x%08x PIEAR = 0x%08x\n", __PIRegs[7], __PIRegs[8]); + __PIRegs[0] = 1; + OSReport("PI Error = %s\n", __OSPIErrors[__PIRegs[7]]); + OSReport("Offending address = 0x%x (from PIEAR)\n", __PIRegs[8]); + } + #endif + + unmasked = cause & ~(*(OSInterruptMask *)OSPhysicalToCached(0x00C4) | + *(OSInterruptMask *)OSPhysicalToCached(0x00C8)); + if (unmasked) { + for (prio = InterruptPrioTable;; ++prio) { + if (unmasked & *prio) { + interrupt = (__OSInterrupt)__cntlzw(unmasked & *prio); + break; + } + } + + handler = __OSGetInterruptHandler(interrupt); + if (handler) { + if (__OS_INTERRUPT_MEM_ADDRESS < interrupt) { + __OSLastInterrupt = interrupt; + __OSLastInterruptTime = OSGetTime(); + __OSLastInterruptSrr0 = context->srr0; + } + OSDisableScheduler(); + handler(interrupt, context); + OSEnableScheduler(); + __OSReschedule(); + OSLoadContext(context); + } + } + + #if DEBUG + OSReport("Unhandled Interrupt(s): cause %08x intsr %08x\n", cause, intsr); + while (cause) { + interrupt = __cntlzw(cause); + cause &= ~(1 << (0x1F - __cntlzw(cause))); + OSReport(" %s\n", __OSInterruptNames[interrupt]); + } + #endif + + OSLoadContext(context); +} + +#ifdef __GEKKO__ +static asm void ExternalInterruptHandler(register __OSException exception, + register OSContext* context) { +#pragma unused(exception) + nofralloc + OS_EXCEPTION_SAVE_GPRS(context) + + stwu r1, -0x8(r1) + b __OSDispatchInterrupt +} +#endif diff --git a/src/revolution/os/OSIpc.c b/src/revolution/os/OSIpc.c new file mode 100644 index 0000000000..dab68601d8 --- /dev/null +++ b/src/revolution/os/OSIpc.c @@ -0,0 +1,18 @@ +#include +#include + +static void* IpcBufferHi; +static void* IpcBufferLo = (void*)0xFFFFFFFF; + +void* __OSGetIPCBufferHi(void) { + return IpcBufferHi; +} + +void* __OSGetIPCBufferLo(void) { + return IpcBufferLo; +} + +void __OSInitIPCBuffer(void) { + IpcBufferLo = (void*)*(u32*)OSPhysicalToCached(0x3100 + 0x0030); + IpcBufferHi = (void*)*(u32*)OSPhysicalToCached(0x3100 + 0x0034); +} diff --git a/src/revolution/os/OSLaunch.c b/src/revolution/os/OSLaunch.c new file mode 100644 index 0000000000..163f00d515 --- /dev/null +++ b/src/revolution/os/OSLaunch.c @@ -0,0 +1,91 @@ +#include +#include + +#include "__os.h" + +void __OSRelaunchTitle(u32 resetCode) { + s32 rc = 0; + u32 ticketCnt = 1; + ESTicketView* tik = NULL; + ESTitleId titleId __attribute__ ((aligned (32))); + __OSPlayTimeType type = OSPLAYTIME_PERMANENT; + u32 remain = 0; + u8* bi2 = NULL; + OSNandbootInfo* info = NULL; + OSStateFlags state; + + OSSetArenaLo((void*)0x81280000); + OSSetArenaHi((void*)0x812F0000); + + rc = ESP_InitLib(); + if (rc != 0) { + __OSReturnToMenuForError(); + } + + rc = ESP_GetTitleId(&titleId); + if (rc != 0) { + __OSReturnToMenuForError(); + } + + tik = (ESTicketView*)(OSAllocFromMEM1ArenaLo)(OSRoundUp32B(sizeof(ESTicketView)), 32); + if (tik == NULL) { + __OSReturnToMenuForError(); + } + + memset(tik, 0, OSRoundUp32B(sizeof(ESTicketView))); + rc = ESP_DiGetTicketView(NULL, tik); + if (rc == -1017) { + ESTicketView* tmp = NULL; + rc = ESP_GetTicketViews(titleId, NULL, &ticketCnt); + if (rc != 0) { + __OSReturnToMenuForError(); + } + + tmp = (ESTicketView*)OSAllocFromMEM1ArenaLo(OSRoundUp32B(ticketCnt * sizeof(ESTicketView)), 32); + if (tmp == NULL) { + __OSReturnToMenuForError(); + } + + rc = ESP_GetTicketViews(titleId, tmp, &ticketCnt); + if (rc != 0) { + __OSReturnToMenuForError(); + } + + memcpy(tik, tmp, sizeof(ESTicketView)); + } else if (rc != 0) { + __OSReturnToMenuForError(); + } else { + if (OSPlayTimeIsLimited()) { + __OSPlayTimeType type = OSPLAYTIME_PERMANENT; + u32 remain = 0xFFFFFFFF; + __OSGetPlayTime(tik, &type, &remain); + if (remain == 0) { + __OSWriteExpiredFlag(); + __OSReturnToMenuForError(); + } + } + } + + bi2 = (u8*)OSAllocFromMEM1ArenaLo(0x2000, 64); + info = (OSNandbootInfo*)((u32)bi2 + (0x2000 - sizeof(OSNandbootInfo))); + memset(bi2, 0, 0x2000); + info->LastTitleId = titleId; + info->LastAppType = OSGetAppType(); + info->ReturnType = 1; + info->ArgValue = resetCode | 0x80000000; + + __OSCreateNandbootInfo(); + __OSWriteNandbootInfo(info); + __OSReadStateFlags(&state); + state.lastShutdown = 3; + __OSWriteStateFlags(&state); + rc = ESP_LaunchTitle(titleId, tik); + + if (rc != 0) { + __OSReturnToMenuForError(); + } + + while (1) { + + } +} diff --git a/src/revolution/os/OSLink.c b/src/revolution/os/OSLink.c new file mode 100644 index 0000000000..9791335090 --- /dev/null +++ b/src/revolution/os/OSLink.c @@ -0,0 +1,537 @@ +#include +#include + +#include "__os.h" + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t)) + +// Name Value Field Calculation +#define R_PPC_NONE 0 // none none +#define R_PPC_ADDR32 1 // word32 S + A +#define R_PPC_ADDR24 2 // low24* (S + A) >> 2 +#define R_PPC_ADDR16 3 // half16* S + A +#define R_PPC_ADDR16_LO 4 // half16 #lo(S + A) +#define R_PPC_ADDR16_HI 5 // half16 #hi(S + A) +#define R_PPC_ADDR16_HA 6 // half16 #ha(S + A) +#define R_PPC_ADDR14 7 // low14* (S + A) >> 2 +#define R_PPC_ADDR14_BRTAKEN 8 // low14* (S + A) >> 2 +#define R_PPC_ADDR14_BRNTAKEN 9 // low14* (S + A) >> 2 +#define R_PPC_REL24 10 // low24* (S + A - P) >> 2 +#define R_PPC_REL14 11 // low14* (S + A - P) >> 2 +#define R_PPC_REL14_BRTAKEN 12 // low14* (S + A - P) >> 2 +#define R_PPC_REL14_BRNTAKEN 13 // low14* (S + A - P) >> 2 + +#define R_PPC_GOT16 14 // half16* G + A +#define R_PPC_GOT16_LO 15 // half16 #lo(G + A) +#define R_PPC_GOT16_HI 16 // half16 #hi(G + A) +#define R_PPC_GOT16_HA 17 // half16 #ha(G + A) +#define R_PPC_PLTREL24 18 // low24* (L + A - P) >> 2 +#define R_PPC_COPY 19 // none none +#define R_PPC_GLOB_DAT 20 // word32 S + A +#define R_PPC_JMP_SLOT 21 // none +#define R_PPC_RELATIVE 22 // word32 B + A + +#define R_PPC_LOCAL24PC 23 // low24* + +#define R_PPC_UADDR32 24 // word32 S + A +#define R_PPC_UADDR16 25 // half16* S + A +#define R_PPC_REL32 26 // word32 S + A - P + +#define R_PPC_PLT32 27 // word32 L + A +#define R_PPC_PLTREL32 28 // word32 L + A - P +#define R_PPC_PLT16_LO 29 // half16 #lo(L + A) +#define R_PPL_PLT16_HI 30 // half16 #hi(L + A) +#define R_PPC_PLT16_HA 31 // half16 #ha(L + A) + +#define R_PPC_SDAREL16 32 // half16* S + A - _SDA_BASE_ +#define R_PPC_SECTOFF 33 // half16* R + A +#define R_PPC_SECTOFF_LO 34 // half16 #lo(R + A) +#define R_PPC_SECTOFF_HI 35 // half16 #hi(R + A) +#define R_PPC_SECTOFF_HA 36 // half16 #ha(R + A) +#define R_PPC_ADDR30 37 // word30 (S + A - P) >> 2 + +#define R_PPC_EMB_NADDR32 101 // uword32 N (A - S) +#define R_PPC_EMB_NADDR16 102 // uhalf16 Y (A - S) +#define R_PPC_EMB_NADDR16_LO 103 // uhalf16 N #lo(A - S) +#define R_PPC_EMB_NADDR16_HI 104 // uhalf16 N #hi(A - S) +#define R_PPC_EMB_NADDR16_HA 105 // uhalf16 N #ha(A - S) +#define R_PPC_EMB_SDAI16 106 // uhalf16 Y T +#define R_PPC_EMB_SDA2I16 107 // uhalf16 Y U +#define R_PPC_EMB_SDA2REL 108 // uhalf16 Y S + A - _SDA2_BASE_ +#define R_PPC_EMB_SDA21 109 // ulow21 N +#define R_PPC_EMB_MRKREF 110 // none N +#define R_PPC_EMB_RELSEC16 111 // uhalf16 Y V + A +#define R_PPC_EMB_RELST_LO 112 // uhalf16 N #lo(W + A) +#define R_PPC_EMB_RELST_HI 113 // uhalf16 N #hi(W + A) +#define R_PPC_EMB_RELST_HA 114 // uhalf16 N #ha(W + A) +#define R_PPC_EMB_BIT_FLD 115 // uword32 Y +#define R_PPC_EMB_RELSDA 116 // uhalf16 Y + +OSModuleQueue __OSModuleInfoList AT_ADDRESS(OS_BASE_CACHED | 0x30C8); +const void* __OSStringTable AT_ADDRESS(OS_BASE_CACHED | 0x30D0); + +#define ENQUEUE_INFO(queue, info, link) \ + do { \ + OSModuleInfo* __prev; \ + \ + __prev = (queue)->tail; \ + if (__prev == NULL) \ + (queue)->head = (info); \ + else \ + __prev->link.next = (info); \ + (info)->link.prev = __prev; \ + (info)->link.next = NULL; \ + (queue)->tail = (info); \ + } while (0) + +#define DEQUEUE_INFO(info, queue, link) \ + do { \ + OSModuleInfo* __next; \ + OSModuleInfo* __prev; \ + \ + __next = (info)->link.next; \ + __prev = (info)->link.prev; \ + \ + if (__next == NULL) \ + (queue)->tail = __prev; \ + else \ + __next->link.prev = __prev; \ + \ + if (__prev == NULL) \ + (queue)->head = __next; \ + else \ + __prev->link.next = __next; \ + } while (0) + +#pragma dont_inline on +void OSNotifyLink(OSModuleInfo* module) {} + +void OSNotifyUnlink(OSModuleInfo* module) {} + +void OSNotifyPreLink(OSModuleHeader* newModule, OSModuleHeader* module) {} + +void OSNotifyPostLink(OSModuleHeader* newModule, OSModuleHeader* module) {} +#pragma dont_inline reset + +void OSSetStringTable(void* stringTable) { + __OSStringTable = stringTable; +} + +static BOOL Relocate(OSModuleHeader* newModule, OSModuleHeader* module) { + OSModuleID idNew; + OSImportInfo* imp; + OSRel* rel; + OSSectionInfo* si; + OSSectionInfo* siFlush; + u32* p; + u32 offset; + u32 x; + + idNew = newModule ? newModule->info.id : 0; + for (imp = (OSImportInfo*)module->impOffset; + imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) + { + if (imp->id == idNew) { + goto Found; + } + } + return FALSE; + +Found: + OSNotifyPreLink(newModule, module); + + siFlush = 0; + for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) { + (u8*)p += rel->offset; + if (idNew) { + si = &OSGetSectionInfo(newModule)[rel->section]; + offset = OS_SECTIONINFO_OFFSET(si->offset); + } else { + offset = 0; + } + + switch (rel->type) { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + x = offset + rel->addend; + *p = x; + break; + case R_PPC_ADDR24: + x = offset + rel->addend; + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_ADDR16: + x = offset + rel->addend; + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_LO: + x = offset + rel->addend; + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_HI: + x = offset + rel->addend; + *(u16*)p = (u16)(((x >> 16) & 0xffff)); + break; + case R_PPC_ADDR16_HA: + x = offset + rel->addend; + *(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff); + break; + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + x = offset + rel->addend; + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_PPC_REL24: + x = offset + rel->addend - (u32)p; + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + x = offset + rel->addend - (u32)p; + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_DOLPHIN_NOP: + break; + case R_DOLPHIN_SECTION: + si = &OSGetSectionInfo(module)[rel->section]; + p = (u32*)OS_SECTIONINFO_OFFSET(si->offset); + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0; + break; + default: + OSReport("OSLink: unknown relocation type %3d\n", rel->type); + break; + } + } + + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + + OSNotifyPostLink(newModule, module); + return TRUE; +} + +static BOOL Link(OSModuleInfo* newModule, void* bss, BOOL fixed) { + u32 i; + OSSectionInfo* si; + OSModuleHeader* moduleHeader; + OSModuleInfo* moduleInfo; + OSImportInfo* imp; + + ASSERTLINE(313, newModule->version <= OS_MODULE_VERSION); + + moduleHeader = (OSModuleHeader*)newModule; + moduleHeader->bssSection = 0; + + ASSERTLINE(321, newModule->version < 2 || moduleHeader->align == 0 || (u32) newModule % moduleHeader->align == 0); + ASSERTLINE(324, newModule->version < 2 || moduleHeader->bssAlign == 0 || (u32) bss % moduleHeader->bssAlign == 0); + + if (OS_MODULE_VERSION < newModule->version || + 2 <= newModule->version && + (moduleHeader->align && (u32)newModule % moduleHeader->align != 0 || + moduleHeader->bssAlign && (u32)bss % moduleHeader->bssAlign != 0)) + { + return FALSE; + } + + ENQUEUE_INFO(&__OSModuleInfoList, newModule, link); + newModule->sectionInfoOffset += (u32)moduleHeader; + moduleHeader->relOffset += (u32)moduleHeader; + moduleHeader->impOffset += (u32)moduleHeader; + if (3 <= newModule->version) { + moduleHeader->fixSize += (u32)moduleHeader; + } + + for (i = 1; i < newModule->numSections; i++) { + si = &OSGetSectionInfo(newModule)[i]; + if (si->offset != 0) { + si->offset += (u32)moduleHeader; + } else if (si->size != 0) { + ASSERTLINE(357, moduleHeader->bssSection == 0); + moduleHeader->bssSection = (u8)i; + si->offset = (u32)bss; + } + } + + for (imp = (OSImportInfo*)moduleHeader->impOffset; + imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) + { + imp->offset += (u32)moduleHeader; + } + + if (moduleHeader->prologSection != SHN_UNDEF) { + moduleHeader->prolog += + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->prologSection].offset); + } + + if (moduleHeader->epilogSection != SHN_UNDEF) { + moduleHeader->epilog += + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(newModule)[moduleHeader->epilogSection].offset); + } + + if (moduleHeader->unresolvedSection != SHN_UNDEF) { + moduleHeader->unresolved += OS_SECTIONINFO_OFFSET( + OSGetSectionInfo(newModule)[moduleHeader->unresolvedSection].offset); + } + + if (__OSStringTable) { + newModule->nameOffset += (u32)__OSStringTable; + } + + Relocate(0, moduleHeader); + + for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Relocate(moduleHeader, (OSModuleHeader*)moduleInfo); + if (moduleInfo != newModule) { + Relocate((OSModuleHeader*)moduleInfo, moduleHeader); + } + } + + if (fixed) { + for (imp = (OSImportInfo*)moduleHeader->impOffset; + imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) + { + if (imp->id == 0 || imp->id == newModule->id) { + moduleHeader->impSize = (u32)((u8*)imp - (u8*)moduleHeader->impOffset); + break; + } + } + } + + memset(bss, 0, moduleHeader->bssSize); + + OSNotifyLink(newModule); + return TRUE; +} + +BOOL OSLink(OSModuleInfo* newModule, void* bss) { + return Link(newModule, bss, FALSE); +} + +BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss) { + ASSERTLINE(431, newModule->version <= OS_MODULE_VERSION && 3 <= newModule->version); + + if (OS_MODULE_VERSION < newModule->version || newModule->version < 3) { + return FALSE; + } + return Link(newModule, bss, TRUE); +} + +static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) { + OSModuleID idNew; + OSImportInfo* imp; + OSRel* rel; + OSSectionInfo* si; + OSSectionInfo* siFlush; + u32* p; + u32 offset; + u32 x; + + ASSERTLINE(465, newModule); + + idNew = newModule->info.id; + ASSERTLINE(467, idNew); + + for (imp = (OSImportInfo*)module->impOffset; + imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) + { + if (imp->id == idNew) { + goto Found; + } + } + return FALSE; + +Found: + OSNotifyPreLink(newModule, module); + siFlush = 0; + for (rel = (OSRel*)imp->offset; rel->type != R_DOLPHIN_END; rel++) { + (u8*)p += rel->offset; + si = &OSGetSectionInfo(newModule)[rel->section]; + offset = OS_SECTIONINFO_OFFSET(si->offset); + x = 0; + switch (rel->type) { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + *p = x; + break; + case R_PPC_ADDR24: + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_ADDR16: + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_LO: + *(u16*)p = (u16)(x & 0xffff); + break; + case R_PPC_ADDR16_HI: + *(u16*)p = (u16)(((x >> 16) & 0xffff)); + break; + case R_PPC_ADDR16_HA: + *(u16*)p = (u16)(((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xffff); + break; + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_PPC_REL24: + if (module->unresolvedSection != SHN_UNDEF) { + x = (u32)module->unresolved - (u32)p; + } + *p = (*p & ~0x03fffffc) | (x & 0x03fffffc); + break; + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + *p = (*p & ~0x0000fffc) | (x & 0x0000fffc); + break; + case R_DOLPHIN_NOP: + break; + case R_DOLPHIN_SECTION: + si = &OSGetSectionInfo(module)[rel->section]; + p = (u32*)OS_SECTIONINFO_OFFSET(si->offset); + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + siFlush = (si->offset & OS_SECTIONINFO_EXEC) ? si : 0; + break; + default: + OSReport("OSUnlink: unknown relocation type %3d\n", rel->type); + break; + } + } + + if (siFlush) { + offset = OS_SECTIONINFO_OFFSET(siFlush->offset); + DCFlushRange((void*)offset, siFlush->size); + ICInvalidateRange((void*)offset, siFlush->size); + } + + OSNotifyPostLink(newModule, module); + return TRUE; +} + +BOOL OSUnlink(OSModuleInfo* oldModule) { + OSModuleHeader* moduleHeader; + OSModuleInfo* moduleInfo; + u32 i; + OSSectionInfo* si; + OSImportInfo* imp; + + ASSERTLINE(584, oldModule->version <= OS_MODULE_VERSION); + + moduleHeader = (OSModuleHeader*)oldModule; + + DEQUEUE_INFO(oldModule, &__OSModuleInfoList, link); + + for (moduleInfo = __OSModuleInfoList.head; moduleInfo; moduleInfo = moduleInfo->link.next) { + Undo(moduleHeader, (OSModuleHeader*)moduleInfo); + } + + OSNotifyUnlink(oldModule); + + if (__OSStringTable) { + oldModule->nameOffset -= (u32)__OSStringTable; + } + + if (moduleHeader->prologSection != SHN_UNDEF) { + moduleHeader->prolog -= + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->prologSection].offset); + } + + if (moduleHeader->epilogSection != SHN_UNDEF) { + moduleHeader->epilog -= + OS_SECTIONINFO_OFFSET(OSGetSectionInfo(oldModule)[moduleHeader->epilogSection].offset); + } + + if (moduleHeader->unresolvedSection != SHN_UNDEF) { + moduleHeader->unresolved -= OS_SECTIONINFO_OFFSET( + OSGetSectionInfo(oldModule)[moduleHeader->unresolvedSection].offset); + } + + for (imp = (OSImportInfo*)moduleHeader->impOffset; + imp < (OSImportInfo*)(moduleHeader->impOffset + moduleHeader->impSize); imp++) + { + imp->offset -= (u32)moduleHeader; + } + + for (i = 1; i < oldModule->numSections; i++) { + si = &OSGetSectionInfo(oldModule)[i]; + if (i == moduleHeader->bssSection) { + ASSERTLINE(627, si->size != 0); + moduleHeader->bssSection = 0; + si->offset = 0; + } else if (si->offset != 0) { + si->offset -= (u32)moduleHeader; + } + } + moduleHeader->relOffset -= (u32)moduleHeader; + moduleHeader->impOffset -= (u32)moduleHeader; + oldModule->sectionInfoOffset -= (u32)moduleHeader; + + return TRUE; +} + +void __OSModuleInit(void) { + __OSModuleInfoList.head = __OSModuleInfoList.tail = 0; + __OSStringTable = 0; +} + +OSModuleInfo* OSSearchModule(void* ptr, u32* section, u32* offset) { + OSModuleInfo* moduleInfo; + OSSectionInfo* sectionInfo; + u32 i; + u32 baseSection; + + if (ptr == NULL) { + return NULL; + } + + moduleInfo = __OSModuleInfoList.head; + while (moduleInfo != 0) { + sectionInfo = (OSSectionInfo*)moduleInfo->sectionInfoOffset; + for (i = 0; i < moduleInfo->numSections; i++) { + if (sectionInfo->size != 0) { + baseSection = sectionInfo->offset & 0xFFFFFFFE; + if (baseSection <= (u32)ptr && (u32)ptr < baseSection + sectionInfo->size) { + if (section != 0) { + *section = i; + } + + if (offset != 0) { + *offset = (u32)ptr - baseSection; + } + + return moduleInfo; + } + } + sectionInfo++; + } + moduleInfo = moduleInfo->link.next; + } + + return NULL; +} diff --git a/src/revolution/os/OSMemory.c b/src/revolution/os/OSMemory.c new file mode 100644 index 0000000000..76309cffc8 --- /dev/null +++ b/src/revolution/os/OSMemory.c @@ -0,0 +1,680 @@ +#include +#include +#include + +#include "__os.h" + +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) + +static BOOL OnShutdown(BOOL final, u32 event); + +static OSShutdownFunctionInfo ShutdownFunctionInfo = { + OnShutdown, + 0x7F, + NULL, + NULL +}; + +u32 OSGetPhysicalMem1Size(void) { + u32 memSize = *(u32*)OSPhysicalToCached(0x3100); + return memSize; +} + +u32 OSGetPhysicalMem2Size(void) { + u32 memSize = *(u32*)OSPhysicalToCached(0x3118); + return memSize; +} + +u32 OSGetConsoleSimulatedMem1Size(void) { + u32 memSize = *(u32*)OSPhysicalToCached(0x3104); + return memSize; +} + +u32 OSGetConsoleSimulatedMem2Size(void) { + u32 memSize = *(u32*)OSPhysicalToCached(0x311C); + return memSize; +} + +static BOOL OnShutdown(BOOL final, u32 event) { + if (final != FALSE) { + __MEMRegs[8] = 0xFF; + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM_RESET); + } + return TRUE; +} + +static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { + u32 addr; + u32 cause; + + cause = __MEMRegs[0xf]; + addr = (((u32)__MEMRegs[0x12] & 0x3ff) << 16) | __MEMRegs[0x11]; + __MEMRegs[0x10] = 0; + + if (__OSErrorTable[__OS_EXCEPTION_MEMORY_PROTECTION]) { + __OSErrorTable[__OS_EXCEPTION_MEMORY_PROTECTION](__OS_EXCEPTION_MEMORY_PROTECTION, context, cause, addr); + return; + } + + __OSUnhandledException(__OS_EXCEPTION_MEMORY_PROTECTION, context, cause, addr); +} + +void OSProtectRange(u32 chan, void* addr, u32 nBytes, u32 control) { + BOOL enabled; + u32 start; + u32 end; + u16 reg; + + ASSERTLINE(388, chan < 4); + ASSERTLINE(389, (control & ~(OS_PROTECT_CONTROL_RDWR)) == 0); + + if (4 <= chan) { + return; + } + + control &= 3; + + end = (u32)addr + nBytes; + start = TRUNC(addr, 1u << 10); + end = ROUND(end, 1u << 10); + + DCFlushRange((void*)start, end - start); + + enabled = OSDisableInterrupts(); + + __OSMaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + + __MEMRegs[0 + 2 * chan] = (u16)(start >> 10); + __MEMRegs[1 + 2 * chan] = (u16)(end >> 10); + + reg = __MEMRegs[8]; + reg &= ~(3 << 2 * chan); + reg |= control << 2 * chan; + __MEMRegs[8] = reg; + + if (control != 3) { + __OSUnmaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + } + + OSRestoreInterrupts(enabled); +} + +#ifdef __GEKKO__ +static asm void ConfigMEM1_24MB(void) { + nofralloc + addi r7, r0, 0 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x800001ff@ha + addi r3,r3,0x800001ff@l + + addis r6,r0,0x01000002@ha + addi r6,r6,0x01000002@l + addis r5,r0,0x810000ff@ha + addi r5,r5,0x810000ff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mtspr dbat2u,r7 + mtspr dbat2l,r6 + mtspr dbat2u,r5 + isync + + mtspr ibat2u,r7 + mtspr ibat2l,r6 + mtspr ibat2u,r5 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM1_48MB(void) { + nofralloc + + addi r7,r0, 0 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x800003ff@ha + addi r3,r3,0x800003ff@l + + addis r6,r0,0x02000002@ha + addi r6,r6,0x02000002@l + addis r5,r0,0x820001ff@ha + addi r5,r5,0x820001ff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mtspr dbat2u,r7 + mtspr dbat2l,r6 + mtspr dbat2u,r5 + isync + + mtspr ibat2u,r7 + mtspr ibat2l,r6 + mtspr ibat2u,r5 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM2_52MB(void) { + nofralloc + + addi r7, r0, 0 + + addis r4,r0,0x10000002@ha + addi r4,r4,0x10000002@l + addis r3,r0,0x900003ff@ha + addi r3,r3,0x900003ff@l + + addis r6,r0,0x1000002a@ha + addi r6,r6,0x1000002a@l + addis r5,r0,0xD00007ff@ha + addi r5,r5,0xD00007ff@l + + isync + + mtspr DBAT4U,r7 + mtspr DBAT4L,r4 + mtspr DBAT4U,r3 + isync + + mtspr IBAT4U,r7 + mtspr IBAT4L,r7 + + isync + + mtspr DBAT5U,r7 + mtspr DBAT5L,r6 + mtspr DBAT5U,r5 + isync + + mtspr IBAT5U,r7 + mtspr IBAT5L,r7 + isync + + addis r4,r0,0x12000002@ha + addi r4,r4,0x12000002@l + addis r3,r0,0x920001ff@ha + addi r3,r3,0x920001ff@l + + addis r6,r0,0x13000002@ha + addi r6,r6,0x13000002@l + addis r5,r0,0x9300007f@ha + addi r5,r5,0x9300007f@l + + isync + + mtspr DBAT6U,r7 + mtspr DBAT6L,r4 + mtspr DBAT6U,r3 + isync + + mtspr IBAT6U,r7 + mtspr IBAT6L,r7 + + isync + + mtspr DBAT7U,r7 + mtspr DBAT7L,r6 + mtspr DBAT7U,r5 + isync + + mtspr IBAT7U,r7 + mtspr IBAT7L,r7 + + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM2_56MB(void) { + nofralloc + + addi r7,r0, 0 + + addis r4,r0,0x10000002@ha + addi r4,r4,0x10000002@l + addis r3,r0,0x900003ff@ha + addi r3,r3,0x900003ff@l + + addis r6,r0,0x1000002a@ha + addi r6,r6,0x1000002a@l + addis r5,r0,0xD00007ff@ha + addi r5,r5,0xD00007ff@l + + isync + + mtspr DBAT4U,r7 + mtspr DBAT4L,r4 + mtspr DBAT4U,r3 + isync + + mtspr IBAT4U,r7 + mtspr IBAT4L,r7 + + isync + + mtspr DBAT5U,r7 + mtspr DBAT5L,r6 + mtspr DBAT5U,r5 + isync + + mtspr IBAT5U,r7 + mtspr IBAT5L,r7 + isync + + addis r4,r0,0x12000002@ha + addi r4,r4,0x12000002@l + addis r3,r0,0x920001ff@ha + addi r3,r3,0x920001ff@l + + addis r6,r0,0x13000002@ha + addi r6,r6,0x13000002@l + addis r5,r0,0x930000ff@ha + addi r5,r5,0x930000ff@l + + isync + + mtspr DBAT6U,r7 + mtspr DBAT6L,r4 + mtspr DBAT6U,r3 + isync + + mtspr IBAT6U,r7 + mtspr IBAT6L,r7 + + isync + + mtspr DBAT7U,r7 + mtspr DBAT7L,r6 + mtspr DBAT7U,r5 + isync + + mtspr IBAT7U,r7 + mtspr IBAT7L,r7 + + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM2_64MB(void) { + nofralloc + + addi r7,r0,0x0000 + + addis r4,r0,0x10000002@ha + addi r4,r4,0x10000002@l + addis r3,r0,0x900007ff@ha + addi r3,r3,0x900007ff@l + + addis r6,r0,0x1000002a@ha + addi r6,r6,0x1000002a@l + addis r5,r0,0xD00007ff@ha + addi r5,r5,0xD00007ff@l + + isync + + mtspr DBAT4U,r7 + mtspr DBAT4L,r4 + mtspr DBAT4U,r3 + isync + + mtspr IBAT4U,r7 + mtspr IBAT4L,r7 + + isync + + mtspr DBAT5U,r7 + mtspr DBAT5L,r6 + mtspr DBAT5U,r5 + isync + + mtspr IBAT5U,r7 + mtspr IBAT5L,r7 + isync + + mtspr IBAT6U,r7 + mtspr IBAT6L,r7 + isync + + mtspr IBAT7U,r7 + mtspr IBAT7L,r7 + isync + + mtspr DBAT6U,r7 + mtspr DBAT6L,r7 + isync + + mtspr DBAT7U,r7 + mtspr DBAT7L,r7 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM2_112MB(void) { + nofralloc + + addi r7, r0, 0 + + addis r4,r0,0x10000002@ha + addi r4,r4,0x10000002@l + addis r3,r0,0x900007ff@ha + addi r3,r3,0x900007ff@l + + addis r6,r0,0x1000002a@ha + addi r6,r6,0x1000002a@l + addis r5,r0,0xD0000fff@ha + addi r5,r5,0xD0000fff@l + + isync + + mtspr DBAT4U,r7 + mtspr DBAT4L,r4 + mtspr DBAT4U,r3 + isync + + mtspr IBAT4U,r7 + mtspr IBAT4L,r7 + + isync + + mtspr DBAT5U,r7 + mtspr DBAT5L,r6 + mtspr DBAT5U,r5 + isync + + mtspr IBAT5U,r7 + mtspr IBAT5L,r7 + isync + + addis r4,r0,0x14000002@ha + addi r4,r4,0x14000002@l + addis r3,r0,0x940003ff@ha + addi r3,r3,0x940003ff@l + + addis r6,r0,0x16000002@ha + addi r6,r6,0x16000002@l + addis r5,r0,0x960001ff@ha + addi r5,r5,0x960001ff@l + + isync + + mtspr DBAT6U,r7 + mtspr DBAT6L,r4 + mtspr DBAT6U,r3 + isync + + mtspr IBAT6U,r7 + mtspr IBAT6L,r7 + isync + + mtspr DBAT7U,r7 + mtspr DBAT7L,r6 + mtspr DBAT7U,r5 + isync + + mtspr IBAT7U,r7 + mtspr IBAT7L,r7 + + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM2_128MB(void) { + nofralloc + + addi r7, r0, 0 + + addis r4,r0,0x10000002@ha + addi r4,r4,0x10000002@l + addis r3,r0,0x90000fff@ha + addi r3,r3,0x90000fff@l + + addis r6,r0,0x1000002a@ha + addi r6,r6,0x1000002a@l + addis r5,r0,0xD0000fff@ha + addi r5,r5,0xD0000fff@l + + isync + + mtspr DBAT4U,r7 + mtspr DBAT4L,r4 + mtspr DBAT4U,r3 + isync + + mtspr IBAT4U,r7 + mtspr IBAT4L,r7 + + isync + + mtspr DBAT5U,r7 + mtspr DBAT5L,r6 + mtspr DBAT5U,r5 + isync + + mtspr IBAT5U,r7 + mtspr IBAT5L,r7 + isync + + mtspr IBAT6U,r7 + mtspr IBAT6L,r7 + isync + + mtspr IBAT7U,r7 + mtspr IBAT7L,r7 + isync + + mtspr DBAT6U,r7 + mtspr DBAT6L,r7 + isync + + mtspr DBAT7U,r7 + mtspr DBAT7L,r7 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void ConfigMEM_ES1_0(void) { + nofralloc + + addi r7, r0, 0 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x80000fff@ha + addi r3,r3,0x80000fff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi +} +#endif + +#ifdef __GEKKO__ +static asm void RealMode(register u32 addr) { + nofralloc + clrlwi addr, addr, 2 + mtsrr0 addr + mfmsr addr + rlwinm addr, addr, 0, 28, 25 + mtsrr1 addr + rfi +} +#endif + +static void BATConfig(u32 param_0) { + u32 size1, size2, prot; + size1 = OSGetConsoleSimulatedMem1Size(); + + if (size1 < OSGetPhysicalMem1Size() && size1 == 25165824) { + DCInvalidateRange((void*)0x81800000, 25165824); + __MEMRegs[0x14] = 2; + } + + if (size1 <= 25165824) { + RealMode((u32)ConfigMEM1_24MB); + } + + size2 = OSGetConsoleSimulatedMem2Size(); + prot = *(u32*)OSPhysicalToCached(0x3120); + + if (size2 <= 67108864) { + if (prot <= 0x93400000) { + RealMode((u32)ConfigMEM2_52MB); + } + else if (prot <= 0x93800000) { + RealMode((u32)ConfigMEM2_56MB); + } + else { + RealMode((u32)ConfigMEM2_64MB); + } + } + else if (size2 <= 134217728) { + if (prot <= 0x97000000) { + RealMode((u32)ConfigMEM2_112MB); + } + else { + RealMode((u32)ConfigMEM2_128MB); + } + } + + while (param_0 != 0xBA2CF) {} +} + +void __OSRestoreCodeExecOnMEM1(u32 param_0) { + RealMode((u32)ConfigMEM1_24MB); + while (param_0 != 0xBA2CF) {} +} + +void __OSInitMemoryProtection(void) { + static BOOL initialized = FALSE; +#ifndef DEBUG + u32 padding[9]; + u32 temp; +#endif + BOOL enabled; + + if (initialized) { + return; + } + + enabled = OSDisableInterrupts(); + + __MEMRegs[16] = 0; + __MEMRegs[8] = 0xFF; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | + OS_INTERRUPTMASK_MEM_3); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_0, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_1, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_2, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_3, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_ADDRESS, MEMIntrruptHandler); + OSRegisterShutdownFunction(&ShutdownFunctionInfo); + + BATConfig(0xBA2CF); + + __OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS); + initialized = TRUE; + OSRestoreInterrupts(enabled); +} diff --git a/src/revolution/os/OSMessage.c b/src/revolution/os/OSMessage.c new file mode 100644 index 0000000000..7935f2fcb4 --- /dev/null +++ b/src/revolution/os/OSMessage.c @@ -0,0 +1,70 @@ +#include +#include + +void OSInitMessageQueue(OSMessageQueue* mq, void* msgArray, s32 msgCount) { + OSInitThreadQueue(&mq->queueSend); + OSInitThreadQueue(&mq->queueReceive); + mq->msgArray = msgArray; + mq->msgCount = msgCount; + mq->firstIndex = 0; + mq->usedCount = 0; +} + +int OSSendMessage(OSMessageQueue* mq, void* msg, s32 flags) { + BOOL enabled; + s32 lastIndex; + + enabled = OSDisableInterrupts(); + while(mq->msgCount <= mq->usedCount) { + if (!(flags & 1)) { + OSRestoreInterrupts(enabled); + return 0; + } + OSSleepThread(&mq->queueSend); + } + lastIndex = (mq->firstIndex + mq->usedCount) % mq->msgCount; + ((u32*)mq->msgArray)[lastIndex] = (u32)msg; + mq->usedCount++; + OSWakeupThread(&mq->queueReceive); + OSRestoreInterrupts(enabled); + return 1; +} + +int OSReceiveMessage(OSMessageQueue* mq, void* msg, s32 flags) { + BOOL enabled = OSDisableInterrupts(); + + while(mq->usedCount == 0) { + if (!(flags & 1)) { + OSRestoreInterrupts(enabled); + return 0; + } + OSSleepThread(&mq->queueReceive); + } + if(msg != NULL) { + *(u32*)msg = ((u32*)mq->msgArray)[mq->firstIndex]; + } + + mq->firstIndex = (mq->firstIndex + 1) % mq->msgCount; + mq->usedCount--; + OSWakeupThread(&mq->queueSend); + OSRestoreInterrupts(enabled); + return 1; +} + +int OSJamMessage(OSMessageQueue* mq, void* msg, s32 flags) { + BOOL enabled = OSDisableInterrupts(); + + while(mq->msgCount <= mq->usedCount) { + if(!(flags & 1)) { + OSRestoreInterrupts(enabled); + return 0; + } + OSSleepThread(&mq->queueSend); + } + mq->firstIndex = (mq->firstIndex + mq->msgCount - 1) % mq->msgCount; + ((u32*)mq->msgArray)[mq->firstIndex] = (u32)msg; + mq->usedCount++; + OSWakeupThread(&mq->queueReceive); + OSRestoreInterrupts(enabled); + return 1; +} diff --git a/src/revolution/os/OSMutex.c b/src/revolution/os/OSMutex.c new file mode 100644 index 0000000000..190c5a98b2 --- /dev/null +++ b/src/revolution/os/OSMutex.c @@ -0,0 +1,256 @@ +#include +#include + +#include "__os.h" + +#define ENQUEUE_MUTEX(mutex, queue, link) \ + do { \ + OSMutex* __prev = (queue)->tail; \ + if (__prev == NULL) { \ + (queue)->head = (mutex); \ + } else { \ + __prev->link.next = (mutex); \ + } \ + (mutex)->link.prev = __prev; \ + (mutex)->link.next = 0; \ + (queue)->tail = (mutex); \ + } while(0); + +#define DEQUEUE_MUTEX(mutex, queue, link) \ + do { \ + OSMutex* __next = (mutex)->link.next; \ + OSMutex* __prev = (mutex)->link.prev; \ + if (__next == NULL) { \ + (queue)->tail = __prev; \ + } else { \ + __next->link.prev = __prev; \ + } \ + if (__prev == NULL) { \ + (queue)->head = __next; \ + } else { \ + __prev->link.next = __next; \ + } \ + } while(0); + +#define DEQUEUE_HEAD(mutex, queue, link) \ + do { \ + OSMutex* __next = mutex->link.next; \ + if (__next == NULL) { \ + (queue)->tail = 0; \ + } else { \ + __next->link.prev = 0; \ + } \ + (queue)->head = __next; \ + } while(0); + +// prototypes +static int IsMember(OSMutexQueue* queue, OSMutex* mutex); +int __OSCheckMutex(OSMutex* mutex); +int __OSCheckDeadLock(OSThread* thread); +int __OSCheckMutexes(OSThread* thread); + +void OSInitMutex(OSMutex* mutex) { + OSInitThreadQueue(&mutex->queue); + mutex->thread = 0; + mutex->count = 0; +} + +void OSLockMutex(OSMutex* mutex) { + BOOL enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(146, currentThread, "OSLockMutex(): current thread does not exist."); + ASSERTMSGLINE(148, currentThread->state == 2, "OSLockMutex(): current thread is not running."); + + while (1) { + OSThread* ownerThread = ((volatile OSMutex*)mutex)->thread; + if (ownerThread == 0) { + mutex->thread = currentThread; + mutex->count++; + ENQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + break; + } else if (ownerThread == currentThread) { + mutex->count++; + break; + } else { + currentThread->mutex = mutex; + __OSPromoteThread(mutex->thread, currentThread->priority); + ASSERTMSG2LINE(170, __OSCheckDeadLock(currentThread) == 0, "OSLockMutex(): detected deadlock: current thread %p, mutex %p.", currentThread, mutex); + OSSleepThread(&mutex->queue); + currentThread->mutex = NULL; + } + } + OSRestoreInterrupts(enabled); +} + +void OSUnlockMutex(OSMutex* mutex) { + BOOL enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(195, currentThread, "OSUnlockMutex(): current thread does not exist."); + ASSERTMSGLINE(197, currentThread->state == 2, "OSUnlockMutex(): current thread is not running."); + ASSERTMSG2LINE(200, mutex->thread == currentThread, "OSUnlockMutex(): current thread %p is not the owner of mutex %p.", currentThread, mutex); + + if (mutex->thread == currentThread) { + if (!--mutex->count) { + DEQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + mutex->thread = 0; + + if (currentThread->priority < currentThread->base) { + currentThread->priority = __OSGetEffectivePriority(currentThread); + } + OSWakeupThread(&mutex->queue); + } + } + OSRestoreInterrupts(enabled); +} + +void __OSUnlockAllMutex(OSThread* thread) { + OSMutex* mutex; + + while (thread->queueMutex.head) { + mutex = thread->queueMutex.head; + DEQUEUE_HEAD(mutex, &thread->queueMutex, link); + ASSERTLINE(235, mutex->thread == thread); + mutex->count = 0; + mutex->thread = 0; + OSWakeupThread(&mutex->queue); + } +} + +BOOL OSTryLockMutex(OSMutex* mutex) { + BOOL enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + BOOL locked; + + ASSERTMSGLINE(261, currentThread, "OSTryLockMutex(): current thread does not exist."); + ASSERTMSGLINE(263, currentThread->state == 2, "OSTryLockMutex(): current thread is not running."); + + if (!mutex->thread) { + mutex->thread = currentThread; + mutex->count++; + ENQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + locked = TRUE; + } else if (mutex->thread == currentThread) { + mutex->count++; + locked = TRUE; + } else { + locked = FALSE; + } + OSRestoreInterrupts(enabled); + return locked; +} + +void OSInitCond(OSCond* cond) { + OSInitThreadQueue(&cond->queue); +} + +void OSWaitCond(OSCond* cond, OSMutex* mutex) { + BOOL enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(319, currentThread, "OSWaitCond(): current thread does not exist."); + ASSERTMSGLINE(321, currentThread->state == 2, "OSWaitCond(): current thread is not running."); + ASSERTMSG2LINE(324, mutex->thread == currentThread, "OSWaitCond(): current thread %p is not the owner of mutex %p.", currentThread, mutex); + + if (mutex->thread == currentThread) { + s32 count = mutex->count; + mutex->count = 0; + DEQUEUE_MUTEX(mutex, ¤tThread->queueMutex, link); + mutex->thread = 0; + if (currentThread->priority < currentThread->base) { + currentThread->priority = __OSGetEffectivePriority(currentThread); + } + OSDisableScheduler(); + OSWakeupThread(&mutex->queue); + OSEnableScheduler(); + OSSleepThread(&cond->queue); + OSLockMutex(mutex); + mutex->count = count; + } + OSRestoreInterrupts(enabled); +} + +void OSSignalCond(OSCond* cond) { + OSWakeupThread(&cond->queue); +} + +static int IsMember(OSMutexQueue* queue, OSMutex* mutex) { + OSMutex* member = queue->head; + + while (member) { + if (mutex == member) { + return 1; + } + member = member->link.next; + } + return 0; +} + +int __OSCheckMutex(OSMutex* mutex) { + OSThread* thread; + OSThreadQueue* queue; + s32 priority; + + priority = 0; + queue = &mutex->queue; + + if (queue->head != NULL && queue->head->link.prev != NULL) { + return 0; + } + if (queue->tail != NULL && queue->tail->link.next != NULL) { + return 0; + } + thread = queue->head; + while (thread) { + if (thread->link.next != NULL && (thread != thread->link.next->link.prev)) { + return 0; + } + if (thread->link.prev != NULL && (thread != thread->link.prev->link.next)) { + return 0; + } + if (thread->state != 4) { + return 0; + } + if (thread->priority < priority) { + return 0; + } + priority = thread->priority; + thread = thread->link.next; + } + if (mutex->thread) { + if (mutex->count <= 0) { + return 0; + } + } else if (mutex->count != 0) { + return 0; + } + return 1; +} + +int __OSCheckDeadLock(OSThread* thread) { + OSMutex* mutex = thread->mutex; + + while (mutex && mutex->thread) { + if (mutex->thread == thread) { + return 1; + } + mutex = mutex->thread->mutex; + } + return 0; +} + +int __OSCheckMutexes(OSThread* thread) { + OSMutex* mutex = thread->queueMutex.head; + + while (mutex) { + if (mutex->thread != thread) { + return 0; + } + if (__OSCheckMutex(mutex) == 0) { + return 0; + } + mutex = mutex->link.next; + } + return 1; +} diff --git a/src/revolution/os/OSNandbootInfo.c b/src/revolution/os/OSNandbootInfo.c new file mode 100644 index 0000000000..7e9912844f --- /dev/null +++ b/src/revolution/os/OSNandbootInfo.c @@ -0,0 +1,67 @@ +#include +#include + +static u32 CheckSum(OSNandbootInfo* info) { + u32* ptr, i, sum; + + ptr = (u32*)&(info->ArgOffset); + sum = 0; + for (i = 0; i < (sizeof(OSNandbootInfo) - 4) / 4; i++) { + sum = sum + *ptr; + ptr++; + } + + return sum; +} + +BOOL __OSCreateNandbootInfo(void) { + NANDStatus status; + s32 result; + + result = NANDPrivateGetStatus("/shared2/sys/NANDBOOTINFO", &status); + if (result == 0 && status.permission == 0x3F) { + return TRUE; + } else if (result == 0 && status.permission != 0x3F) { + result = NANDPrivateDelete("/shared2/sys/NANDBOOTINFO"); + if (result != 0) { + return FALSE; + } + } else if (result == -12) { + + } else { + return FALSE; + } + + result = NANDPrivateCreate("/shared2/sys/NANDBOOTINFO", 63, 0); + if (result != 0) { + return FALSE; + } + + return TRUE; +} + +BOOL __OSWriteNandbootInfo(OSNandbootInfo* info) { + NANDFileInfo fileInfo; + s32 result; + + ASSERTMSGLINE(145, !((u32)info & 0x1F), "OSNandbootInfo needs 32 byte alignment."); + info->CheckSum = CheckSum(info); + result = NANDPrivateOpen("/shared2/sys/NANDBOOTINFO", &fileInfo, 2); + + if (result == 0) { + result = NANDWrite(&fileInfo, info, sizeof(OSNandbootInfo)); + if (result != sizeof(OSNandbootInfo)) { + NANDClose(&fileInfo); + return FALSE; + } + + result = NANDClose(&fileInfo); + if (result != 0) { + return FALSE; + } + } else { + return FALSE; + } + + return TRUE; +} diff --git a/src/revolution/os/OSNet.c b/src/revolution/os/OSNet.c new file mode 100644 index 0000000000..a795b33093 --- /dev/null +++ b/src/revolution/os/OSNet.c @@ -0,0 +1,300 @@ +#include +#include +#include + +static OSShutdownFunctionInfo ShutdownFuncInfo; + +static IOSFd nwc24ShtFd = -1; +static int nwc24ShtRetryRest = 0; +static BOOL NWC24iIsRequestPending = FALSE; + +typedef enum NWC24Err { + NWC24_OK = 0, +} NWC24Err; + +NWC24Err NWC24iPrepareShutdown(void); +NWC24Err NWC24iSynchronizeRtcCounter(BOOL); +NWC24Err NWC24iOpenResourceManager_(const char* callerName, const char* path, IOSFd* fd, u32 flags); +NWC24Err NWC24SuspendScheduler(void); +NWC24Err NWC24iSetRtcCounter_(int rtc, BOOL); +NWC24Err NWC24iIoctlResourceManager_(const char* callerName, IOSFd fd, s32 cmd, void* input, u32 inputLen, void* output, u32 outputLen); +NWC24Err NWC24iCloseResourceManager_(const char* callerName, IOSFd); +NWC24Err NWC24iRequestShutdown(u32 event, s32* result); +NWC24Err NWC24iIoctlResourceManagerAsync_(const char* callerName, IOSFd fd, s32 cmd, void* input, u32 inputLen, void* output, u32 outputLen, void* cbArg); +BOOL NWC24iIsAsyncRequestPending_(void); + +BOOL NWC24Shutdown_(BOOL, u32); + +static void REXInit(void); +static NWC24Err GetRTC(int* rtc); +static s32 CheckCallingStatus(const char* callerName); +static IOSError CallbackAsyncIpc(IOSError, void*); + +void __OSInitNet(void) { + NWC24Err cur_err; + s32 res; + OSIOSRev iosRev; + + REXInit(); + __OSGetIOSRev(&iosRev); + + if (iosRev.major <= 4 || iosRev.major == 9) { + return; + } + + cur_err = NWC24iPrepareShutdown(); + + if (cur_err != NWC24_OK) { + if (cur_err < NWC24_OK) { + OSReport("Failed to register network shutdown function. %d\n", cur_err); + } + + res = NWC24SuspendScheduler(); + if (res < NWC24_OK) { + OSReport("Failed to suspend the WiiConnect24 scheduler. %d\n", res); + } + } + + if (!__OSInIPL) { + cur_err = NWC24iSynchronizeRtcCounter(0); + + if (cur_err != NWC24_OK) { + OSReport("Failed to synchronize time with network resource managers. %d\n", cur_err); + } + } +} + +void REXInit(void) {} + +NWC24Err NWC24iPrepareShutdown(void) { + NWC24Err rt = NWC24_OK; + ShutdownFuncInfo.func = NWC24Shutdown_; + ShutdownFuncInfo.priority = 110; + OSRegisterShutdownFunction(&ShutdownFuncInfo); + + if (nwc24ShtFd < 0) { + rt = NWC24iOpenResourceManager_("NWC24iPrepareShutdown", "/dev/net/kd/request", &nwc24ShtFd, 1); + } + + nwc24ShtRetryRest = 5; + + if (rt == NWC24_OK) { + rt = 1; + } + + return rt; +} + +NWC24Err NWC24iSynchronizeRtcCounter(BOOL param_0) { + NWC24Err rt; + int rtc; + + rt = GetRTC(&rtc); + if (rt != NWC24_OK) { + return rt; + } + + return NWC24iSetRtcCounter_(rtc, param_0 ? TRUE : FALSE); +} + +NWC24Err NWC24SuspendScheduler(void) { + static u8 susResult[0x20] __attribute__ ((aligned(32))); + NWC24Err rt = NWC24_OK; + NWC24Err closeRt = NWC24_OK; + IOSFd fd; + + rt = CheckCallingStatus("NWC24SuspendScheduler"); + if (rt < NWC24_OK) { + return rt; + } + + rt = NWC24iOpenResourceManager_("NWC24SuspendScheduler", "/dev/net/kd/request", &fd, 0); + if (rt >= NWC24_OK) { + rt = NWC24iIoctlResourceManager_("NWC24SuspendScheduler", fd, 1, NULL, 0, &susResult, sizeof(susResult)); + if (rt >= NWC24_OK) { + rt = *(NWC24Err*)susResult; + } + + closeRt = NWC24iCloseResourceManager_("NWC24SuspendScheduler", fd); + if (closeRt < NWC24_OK) { + rt = closeRt; + } + } + + return rt; +} + +void dummyStrings() { + OSReport("NWC24ResumeScheduler"); +} + +NWC24Err NWC24iRequestShutdown(u32 event, s32* result) { + static u32 shtBuffer[8]; + static u32 shtResult[8]; + NWC24Err ret = NWC24_OK; + NWC24Err var_r30 = NWC24_OK; + + shtBuffer[0] = event; + ret = NWC24iIoctlResourceManagerAsync_("NWC24iRequestShutdown", nwc24ShtFd, 0x28, shtBuffer, 0x20, shtResult, 0x20, result); + return ret; +} + +BOOL NWC24Shutdown_(BOOL final, u32 event) { + static BOOL shuttingdown; + static s32 result; + + if (final) { + return TRUE; + } + + if (shuttingdown) { + if (NWC24iIsAsyncRequestPending_()) { + return FALSE; + } + + if (result >= 0) { + return TRUE; + } + + if (nwc24ShtRetryRest > 0) { + shuttingdown = FALSE; + nwc24ShtRetryRest--; + } else { + OSReport("NWC24Shutdown_: Give up!\n"); + return 1; + } + } else { + if (NWC24iRequestShutdown(event, &result) >= NWC24_OK) { + shuttingdown = TRUE; + } + } + + return FALSE; +} + +static u32 nwc24TimeCommonBuffer[8]; +static u32 nwc24TimeCommonResult[8]; + +NWC24Err NWC24iSetRtcCounter_(int rtc, BOOL param_1) { + NWC24Err rt = NWC24_OK; + NWC24Err closeRt = NWC24_OK; + IOSFd fd; + + rt = CheckCallingStatus("NWC24iSetRtcCounter_"); + if (rt < NWC24_OK) { + return rt; + } + + rt = NWC24iOpenResourceManager_("NWC24iSetRtcCounter_", "/dev/net/kd/time", &fd, 0); + if (rt >= NWC24_OK) { + nwc24TimeCommonBuffer[0] = rtc; + nwc24TimeCommonBuffer[1] = param_1; + + rt = NWC24iIoctlResourceManager_("NWC24iSetRtcCounter_", fd, 0x17, &nwc24TimeCommonBuffer, sizeof(nwc24TimeCommonBuffer), &nwc24TimeCommonResult, sizeof(nwc24TimeCommonResult)); + if (rt >= NWC24_OK) { + rt = *(int*)nwc24TimeCommonResult; + } + + closeRt = NWC24iCloseResourceManager_("NWC24iSetRtcCounter_", fd); + if (rt >= NWC24_OK) { + rt = closeRt; + } + } + + return rt; +} + +NWC24Err NWC24iOpenResourceManager_(const char* callerName, const char* path, IOSFd* fd, u32 flags) { + if (fd == 0) { + return -3; + } + + *fd = IOS_Open(path, flags); + if (*fd < IOS_ERROR_OK) { + if (*fd == IOS_ERROR_NOEXISTS) { + OSReport("%s() %s\n", callerName, "Firmware is still in progress."); + return -29; + } else { + OSReport("%s() %s (%d)\n", callerName, "IOS_Open failure.", *fd); + return -42; + } + } + + return NWC24_OK; +} + +NWC24Err NWC24iCloseResourceManager_(const char* callerName, IOSFd fd) { + int rt = IOS_Close(fd); + if (rt < IOS_ERROR_OK) { + OSReport("%s() %s (%d)\n", callerName, "IOS_Close failure.", rt); + return -42; + } + + return NWC24_OK; +} + +// NOTE: function doesn't exist in TP debug, stub for string data +NWC24Err NWC24iCloseResourceManagerAsync_(const char* callerName, IOSFd fd) { + OSReport("IOS_CloseAsync failure."); + return NWC24_OK; +} + +NWC24Err NWC24iIoctlResourceManager_(const char* callerName, IOSFd fd, s32 cmd, void* input, u32 inputLen, void* output, u32 outputLen) { + int rt = IOS_Ioctl(fd, cmd, input, inputLen, output, outputLen); + if (rt < IOS_ERROR_OK) { + OSReport("%s() %s (%d)\n", callerName, "IOS_Ioctl failure.", rt); + return -42; + } + + return NWC24_OK; +} + +NWC24Err NWC24iIoctlResourceManagerAsync_(const char* callerName, IOSFd fd, s32 cmd, void* input, u32 inputLen, void* output, u32 outputLen, void* cbArg) { + int rt = IOS_IoctlAsync(fd, cmd, input, inputLen, output, outputLen, CallbackAsyncIpc, cbArg); + if (rt < IOS_ERROR_OK) { + OSReport("%s() %s (%d)\n", callerName, "IOS_IoctlAsync failure.", rt); + return -42; + } + + NWC24iIsRequestPending = TRUE; + return NWC24_OK; +} + +BOOL NWC24iIsAsyncRequestPending_(void) { + return NWC24iIsRequestPending; +} + +static IOSError CallbackAsyncIpc(IOSError param_0, void* param_1) { + if (param_1 != 0) { + *(IOSError*)param_1 = param_0; + } + + NWC24iIsRequestPending = FALSE; + return 0; +} + +static s32 CheckCallingStatus(const char* callerName) { + if (OSGetCurrentThread() == 0) { + OSReport("%s() %s\n", callerName, "Illegal status. Unavailable from exception handler."); + return -1; + } + + return 0; +} + +static NWC24Err GetRTC(int* rtc) { + OSTime time; + u32 bias; + u32 status; + do { + status = SCCheckStatus(); + if (status == 2) { + return -1; + } + } while (status != 0); + + bias = SCGetCounterBias(); + time = OSGetTime(); + *rtc = (time / OS_TIMER_CLOCK) - bias; + return NWC24_OK; +} diff --git a/src/revolution/os/OSPlayRecord.c b/src/revolution/os/OSPlayRecord.c new file mode 100644 index 0000000000..d530121869 --- /dev/null +++ b/src/revolution/os/OSPlayRecord.c @@ -0,0 +1,259 @@ +#include +#include + +static BOOL PlayRecordGet = FALSE; +static OSPlayRecord PlayRecord __attribute__ ((aligned(32))); +static NANDFileInfo FileInfo; +static NANDCommandBlock Block; +static s32 PlayRecordState = 9; +static OSAlarm PlayRecordAlarm; +static BOOL PlayRecordError = FALSE; +static volatile BOOL PlayRecordTerminate = FALSE; +static volatile BOOL PlayRecordTerminated = FALSE; +static BOOL PlayRecordRetry = FALSE; +static OSTime PlayRecordLastCloseTime; +static s32 PlayRecordLastError = NAND_RESULT_OK; + +static void PlayRecordCallback(s32, NANDCommandBlock *); + +static u32 RecordCheckSum(OSPlayRecord* record) { + u32 *ptr, i, sum; + ptr = (u32*)record->titleName; + sum = 0; + + for (i = 0; i < (sizeof(PlayRecord) - 4) / 4; i++) { + sum = sum + *ptr; + ptr++; + } + + return sum; +} + +void PlayRecordAlarmCallback(OSAlarm* alarm, OSContext* context) { + PlayRecordCallback(NAND_RESULT_OK, NULL); +} + +static void PlayRecordCallback(s32 result, NANDCommandBlock* block) { + s32 ret = 0; + PlayRecordLastError = result; + + if (PlayRecordTerminate) { + PlayRecordTerminated = TRUE; + return; + } + + if (!PlayRecordRetry) { + switch (PlayRecordState) { + case 0: + PlayRecordState = 1; + break; + case 1: + if (result == NAND_RESULT_MAXFD) { + PlayRecordRetry = TRUE; + OSCreateAlarm(&PlayRecordAlarm); + OSSetAlarm(&PlayRecordAlarm, (OSTime)1 * OSSecondsToTicks(1), PlayRecordAlarmCallback); + return; + } + else if (result == NAND_RESULT_OK) { + if (!PlayRecordGet) { + PlayRecordState = 2; + } + else { + PlayRecordState = 4; + } + break; + } + else { + PlayRecordError = TRUE; + PlayRecordState = 7; + return; + } + case 2: + if (result == sizeof(OSPlayRecord)) { + PlayRecordGet = TRUE; + PlayRecordLastCloseTime = PlayRecord.playTime; + PlayRecordState = 3; + } + else { + PlayRecordError = TRUE; + PlayRecordState = 6; + } + break; + case 3: + if (result == 0) { + PlayRecordState = 4; + } + else { + PlayRecordError = TRUE; + PlayRecordState = 6; + } + break; + case 4: + PlayRecordState = 5; + break; + case 5: + if (result == sizeof(OSPlayRecord)) { + if (OSGetTime() - PlayRecordLastCloseTime > (OSTime)300 * OSSecondsToTicks(1)) { + PlayRecordState = 6; + } + else { + PlayRecordState = 3; + } + } + else { + PlayRecordError = TRUE; + PlayRecordState = 6; + } + break; + case 6: + if (PlayRecordError) { + PlayRecordState = 7; + return; + } + else { + if (result == NAND_RESULT_OK) { + PlayRecordLastCloseTime = PlayRecord.playTime; + PlayRecordState = 1; + break; + } + else { + PlayRecordState = 7; + PlayRecordError = TRUE; + return; + } + } + default: + PlayRecordState = 7; + PlayRecordError = TRUE; + return; + } + } + + PlayRecordRetry = FALSE; + + switch (PlayRecordState) { + case 1: + ret = NANDOpenAsync("/title/00000001/00000002/data/play_rec.dat", &FileInfo, 3, PlayRecordCallback, &Block); + break; + case 2: + ret = NANDReadAsync(&FileInfo, &PlayRecord, sizeof(OSPlayRecord), PlayRecordCallback, &Block); + break; + case 3: + ret = NANDSeekAsync(&FileInfo, 0, 0, PlayRecordCallback, &Block); + break; + case 4: + OSCreateAlarm(&PlayRecordAlarm); + OSSetAlarm(&PlayRecordAlarm, (OSTime)60 * OSSecondsToTicks(1), PlayRecordAlarmCallback); + break; + case 5: + PlayRecord.playTime = OSGetTime(); + PlayRecord.checkSum = RecordCheckSum(&PlayRecord); + ret = NANDWriteAsync(&FileInfo, &PlayRecord, sizeof(OSPlayRecord), PlayRecordCallback, &Block); + break; + case 6: + ret = NANDCloseAsync(&FileInfo, PlayRecordCallback, &Block); + break; + } + + if (ret != NAND_RESULT_OK) { + if (ret == NAND_RESULT_BUSY) { + OSCreateAlarm(&PlayRecordAlarm); + OSSetAlarm(&PlayRecordAlarm, (OSTime)1 * OSSecondsToTicks(1), PlayRecordAlarmCallback); + PlayRecordRetry = TRUE; + } + else { + PlayRecordError = TRUE; + switch (PlayRecordState) { + case 2: + case 3: + case 5: + PlayRecordState = 6; + ret = NANDCloseAsync(&FileInfo, PlayRecordCallback, &Block); + + if (ret == NAND_RESULT_BUSY) { + PlayRecordRetry = TRUE; + OSCreateAlarm(&PlayRecordAlarm); + OSSetAlarm(&PlayRecordAlarm, 1 * OSSecondsToTicks(1), PlayRecordAlarmCallback); + } + break; + default: + PlayRecordState = 7; + } + } + } + + PlayRecordLastError = ret; +} + +void __OSStartPlayRecord(void) { + if (NANDInit() == NAND_RESULT_OK) { + PlayRecordGet = FALSE; + PlayRecordState = 0; + PlayRecordError = FALSE; + PlayRecordRetry = FALSE; + PlayRecordTerminate = FALSE; + PlayRecordTerminated = FALSE; + PlayRecordLastError = NAND_RESULT_OK; + PlayRecordCallback(NAND_RESULT_OK, NULL); + } +} + +void __OSStopPlayRecord(void) { + BOOL old; + OSTime start; + + old = OSDisableInterrupts(); + + PlayRecordTerminate = TRUE; + + if (PlayRecordState == 7 || PlayRecordState == 0 || + PlayRecordState == 9 || PlayRecordState == 8) + { + OSRestoreInterrupts(old); + } + else if (PlayRecordState == 4) { + OSCancelAlarm(&PlayRecordAlarm); + OSRestoreInterrupts(old); + PlayRecord.playTime = OSGetTime(); + PlayRecord.checkSum = RecordCheckSum(&PlayRecord); + NANDWrite(&FileInfo, &PlayRecord, sizeof(PlayRecord)); + NANDClose(&FileInfo); + } else { + if (PlayRecordRetry) { + OSCancelAlarm(&PlayRecordAlarm); + OSRestoreInterrupts(old); + } else { + OSRestoreInterrupts(old); + start = OSGetTime(); + while (1) { + if (PlayRecordTerminated) { + break; + } + if ((OSGetTime() - start) > OSMillisecondsToTicks(500)) { + PlayRecordState = 8; + return; + } + } + } + + switch (PlayRecordState) { + case 2: + case 3: + case 5: + NANDClose(&FileInfo); + break; + case 1: + if (PlayRecordLastError == NAND_RESULT_OK && !PlayRecordRetry) { + NANDClose(&FileInfo); + } + break; + case 6: + if (PlayRecordRetry) { + NANDClose(&FileInfo); + } + break; + } + } + + PlayRecordState = 9; +} diff --git a/src/revolution/os/OSPlayTime.c b/src/revolution/os/OSPlayTime.c new file mode 100644 index 0000000000..be0879a96c --- /dev/null +++ b/src/revolution/os/OSPlayTime.c @@ -0,0 +1,350 @@ +#include +#include +#include +#include + +OSAlarm __OSExpireAlarm; +OSTime __OSExpireTime; +OSPlayTimeCallbackFunc __OSExpireCallback; +BOOL __OSExpireSetExpiredFlag; + +static void __OSPlayTimeRebootCallback(OSAlarm *, OSContext *); +static void* __OSPlayTimeRebootThread(void *); + +extern void __OSHotResetForError(void); + +typedef struct { + s16 new_ai_buffer[2][48*2*3]; + s32 idx_ai_buffer; + s16* src_buffer; + u32 frames; + s16 aLeft; + s16 aRight; + AIDCallback gameAIDCallback; +} __OSExpireAIFadeStruct; + +static __OSExpireAIFadeStruct* __OSExpireAIFade = NULL; + +BOOL OSPlayTimeIsLimited() { + return __OSExpireTime != 0; +} + +static void __OSPlayTimeRebootCallback(OSAlarm* alarm, OSContext* context) { + void* arenaHi; + u32 memSize; + OSThread* thread; + void* stack; + + for (thread = __OSActiveThreadQueue.head; thread; thread = thread->linkActive.next) { + OSSuspendThread(thread); + } + + memSize = OSRoundUp32B(sizeof(OSThread)) + 0x1000; + arenaHi = *(void**)OSPhysicalToCached(0x3128); + arenaHi = (void*)((u32)arenaHi - memSize); + + thread = (OSThread*)arenaHi; + arenaHi = (void*)((u32)arenaHi + OSRoundUp32B(sizeof(OSThread))); + stack = arenaHi; + + if (!OSCreateThread(thread, __OSPlayTimeRebootThread, NULL, (void*)((u32)stack + 0x1000), 0x1000, 0, 0)) { + __OSHotResetForError(); + } + + OSResumeThread(thread); +} + +void __OSPlayTimeFadeLastAIDCallback(void) { + if (__OSExpireAIFade->gameAIDCallback) { + __OSExpireAIFade->gameAIDCallback(); + } + + if (__OSExpireAIFade->frames == 0) { + __OSExpireAIFade->src_buffer = (s16*)OSPhysicalToCached(AIGetDMAStartAddr()); + } + + if (__OSExpireAIFade->frames == 1) { + DCInvalidateRange(__OSExpireAIFade->src_buffer, 4); + __OSExpireAIFade->aLeft = (s16)(*__OSExpireAIFade->src_buffer++); + __OSExpireAIFade->aRight = (s16)(*__OSExpireAIFade->src_buffer); + } + + if (__OSExpireAIFade->frames >= 1) { + s16* buffer = __OSExpireAIFade->new_ai_buffer[__OSExpireAIFade->idx_ai_buffer]; + s16* dest = buffer; + u32 bytes = AIGetDMALength(); + u32 i = bytes; + f32 delta = 0.995f; + + while (i) { + *dest++ = __OSExpireAIFade->aLeft; + *dest++ = __OSExpireAIFade->aRight; + + __OSExpireAIFade->aLeft *= delta; + __OSExpireAIFade->aRight *= delta; + + i -= 4; + } + + DCFlushRange(buffer, bytes); + AIInitDMA((u32)buffer, bytes); + __OSExpireAIFade->idx_ai_buffer++; + __OSExpireAIFade->idx_ai_buffer &= 1; + } + + __OSExpireAIFade->frames++; +} + +BOOL __OSWriteExpiredFlag(void) { + s32 rv = 0; + NANDFileInfo nInfo; + BOOL openNInfo = FALSE; + u8 titleId[32] __attribute__ ((aligned(32))); + + rv = NANDPrivateCreate("/shared2/expired", 63, 0); + + if (rv != NAND_RESULT_OK && rv != NAND_RESULT_EXISTS) { + goto out; + } + + rv = NANDPrivateOpen("/shared2/expired", &nInfo, 2); + + if (rv != NAND_RESULT_OK) { + goto out; + } + + openNInfo = TRUE; + + rv = ESP_InitLib(); + if (rv != 0) { + goto out; + } + + memset(titleId, 0, 32); + rv = ESP_GetTitleId((ESTitleId*)titleId); + + if (rv != 0) { + goto out; + } + + rv = NANDWrite(&nInfo, titleId, 32); + if (rv < 0) { + goto out; + } + else if (rv != 32) { + rv = NAND_RESULT_INVALID; + goto out; + } + else { + rv = 0; + } + +out: + if (openNInfo) { + NANDClose(&nInfo); + } + + return rv == 0 ? TRUE : FALSE; +} + +BOOL __OSWriteExpiredFlagIfSet(void) { + if (__OSExpireSetExpiredFlag) { + return __OSWriteExpiredFlag(); + } + + return FALSE; +} + +void* __OSPlayTimeRebootThread(void* args) { + BOOL enabled; + u32 frames, fadeShift = 1; + __OSExpireAIFadeStruct aiFade __attribute__ ((aligned(32))); + + __OSExpireAIFade = &aiFade; + memset(__OSExpireAIFade, 0, sizeof(__OSExpireAIFadeStruct)); + __OSExpireAIFade->gameAIDCallback = AIRegisterDMACallback(__OSPlayTimeFadeLastAIDCallback); + + for (frames = 0; frames < 20; frames++) { + fadeShift = (frames / 5) + 1; + if (fadeShift > 7) { + fadeShift = 7; + } + + VIWaitForRetrace(); + __OSSetVIForceDimming(TRUE, fadeShift, fadeShift); + } + + AIRegisterDMACallback(NULL); + + VISetBlack(TRUE); + VIFlush(); + + enabled = OSDisableInterrupts(); + + __OSWriteExpiredFlagIfSet(); + OSRestoreInterrupts(enabled); + OSReturnToMenu(); + return NULL; +} + +void __OSPlayTimeAlarmExpired(OSAlarm* alarm, OSContext* context) { + if (__OSExpireCallback != 0) { + __OSExpireCallback(); + } else { + __OSPlayTimeRebootCallback(alarm, context); + } +} + +static s32 __OSPlayTimeGetConsumption(ESTicketView *tk, ESLpEntry *lpEntry, u32 *nEntries) { + s32 rv = ESP_GetConsumption(tk->ticketID, NULL, nEntries); + + if (rv > 0) { + goto out; + } else if (rv != 0) { + ASSERTMSGLINE(573, rv != -0x3F9, "Fix by calling ESP_InitLib"); + ASSERTMSG1LINE(574, FALSE, "Failed: %d\n", rv); + rv = rv; + goto out; + } + + if (*nEntries != 0) { + rv = ESP_GetConsumption(tk->ticketID, lpEntry, nEntries); + if (rv != 0) { + ASSERTMSG1LINE(583, FALSE, "Failed: %d\n", rv); + rv = rv; + goto out; + } + } + +out: + return rv; +} + +s32 __OSGetPlayTime(ESTicketView* ticket, __OSPlayTimeType* type, u32* playTime) { + s32 rv; + u32 i; + ESLpEntry lpEntry[8] __attribute__ ((aligned(32))); + u32 numCc = 0, seenOther = 0; + ESTicketView ticketAligned __attribute__ ((aligned(32))); + + ASSERTLINE(601, ticket && type && playTime); + + if ((u32)(ticket) & 31) { + memcpy(&ticketAligned, ticket, sizeof(ESTicketView)); + ticket = &ticketAligned; + } + + rv = __OSPlayTimeGetConsumption(ticket, lpEntry, &numCc); + if (rv != 0) { + goto out; + } + + for (i = 0; i < 8; i++) { + if (ticket->limits[i].code == 1) { + *type = 1; + + if (numCc == 0) { + *playTime = ticket->limits[i].limit; + } else { + ASSERTLINE(630, i < numCc); + + if (lpEntry[i].limit >= ticket->limits[i].limit) { + *playTime = 0; + } else { + *playTime = ticket->limits[i].limit - lpEntry[i].limit; + } + } + goto out; + } else if (ticket->limits[i].code != 0) { + seenOther = i + 1; + } + } + + if (!seenOther) { + *type = 0; + *playTime = 0xFFFFFFFF; + } else { + seenOther--; + + if (ticket->limits[seenOther].code == 4) { + *type = 4; + *playTime = ticket->limits[seenOther].limit; + + if (numCc > 0) { + *playTime -= lpEntry[seenOther].limit; + } + } else { + *type = 9; + } + } + +out: + return rv; +} + +s32 __OSGetPlayTimeCurrent(__OSPlayTimeType* type, u32* playTime) { + s32 rv; + ESTicketView ticket __attribute__ ((aligned(32))); + + ASSERTLINE(676, type && playTime); + + rv = ESP_DiGetTicketView(NULL, &ticket); + + if (rv == -1017) { + goto out; + } + + if (rv != 0) { + ASSERTMSG1LINE(687, FALSE, "Failed: %d\n", rv); + rv = rv; + goto out; + } + + rv = __OSGetPlayTime(&ticket, type, playTime); + +out: + return rv; +} + +void __OSInitPlayTime() { + s32 rv; + u32 limit; + __OSPlayTimeType type; + + __OSExpireTime = 0; + __OSExpireCallback = NULL; + __OSExpireSetExpiredFlag = TRUE; + + rv = ESP_InitLib(); + if (rv != 0) { + ASSERTMSG1LINE(710, FALSE, "Failed: %d\n", rv); + rv = rv; + goto out; + } + + rv = __OSGetPlayTimeCurrent(&type, &limit); + if (rv != 0) { + if (rv != -1017) { + ASSERTMSG1LINE(721, FALSE, "Failed: %d\n", rv); + rv = rv; + } + + goto out; + } + + if (type == OSPLAYTIME_PERMANENT) { + goto out; + } else if (type == OSPLAYTIME_LIMITED) { + if (limit == 0) { + OSPanic(__FILE__, 737, "Expired"); + } + + OSCreateAlarm(&__OSExpireAlarm); + OSSetAlarm(&__OSExpireAlarm, OSSecondsToTicks((OSTime)limit + 20), __OSPlayTimeAlarmExpired); + __OSExpireTime = __OSExpireAlarm.fire; + OSReport("PlayTime: %d seconds left\n", limit); + } + +out: + ESP_CloseLib(); +} diff --git a/src/revolution/os/OSReboot.c b/src/revolution/os/OSReboot.c new file mode 100644 index 0000000000..b8c3f64c3f --- /dev/null +++ b/src/revolution/os/OSReboot.c @@ -0,0 +1,38 @@ +#include +#include + +#include "__os.h" + +static void* SaveEnd; +static void* SaveStart; + +void __OSReboot(u32 resetCode, u32 bootDol) { + OSContext exceptionContext; + char* argvToPass; + + OSDisableInterrupts(); + OSSetArenaLo((void*)0x81280000); + OSSetArenaHi((void*)0x812f0000); + argvToPass = NULL; + __OSNextPartitionType = *(u32*)0x80003194; + __OSBootDol(bootDol, resetCode | 0x80000000, (const char**)&argvToPass); +} + +void OSSetSaveRegion(void* start, void* end) { + ASSERTMSGLINE(134, (u32)start >= 0x80700000 || start == NULL, "OSSetSaveRegion(): start address should be NULL or higher than 0x80700000\n"); + ASSERTMSGLINE(135, 0x81200000 >= (u32)end || end == NULL, "OSSetSaveRegion(): end address should be NULL or lower than 0x81200000\n"); + ASSERTMSGLINE(136, ((start == NULL) ^ (end == NULL)) == 0, "OSSetSaveRegion(): if either start or end is NULL, both should be NULL\n"); + + SaveStart = start; + SaveEnd = end; +} + +void OSGetSaveRegion(void** start, void** end) { + *start = SaveStart; + *end = SaveEnd; +} + +void OSGetSavedRegion(void** start, void** end) { + *start = __OSRebootParams.regionStart; + *end = __OSRebootParams.regionEnd; +} diff --git a/src/revolution/os/OSReset.c b/src/revolution/os/OSReset.c new file mode 100644 index 0000000000..12cd1ae138 --- /dev/null +++ b/src/revolution/os/OSReset.c @@ -0,0 +1,339 @@ +#include +#include +#include + +#include "__os.h" +#include "__dvd.h" + +extern BOOL __OSInNandBoot; + +// These macros are copied from OSThread.c. Or ARE they the same +// macros? They dont seem to be in the SDK headers. +#define ENQUEUE_INFO(info, queue) \ + do { \ + OSShutdownFunctionInfo* __prev = (queue)->tail; \ + if (__prev == 0) { \ + (queue)->head = (info); \ + } else { \ + __prev->next = (info); \ + } \ + (info)->prev = __prev; \ + (info)->next = 0; \ + (queue)->tail = (info); \ + } while(0); + +#define DEQUEUE_INFO(info, queue) \ + do { \ + OSShutdownFunctionInfo* __next = (info)->next; \ + OSShutdownFunctionInfo* __prev = (info)->prev; \ + if (__next == 0) { \ + (queue)->tail = __prev; \ + } else { \ + __next->prev = __prev; \ + } \ + if (__prev == 0) { \ + (queue)->head = __next; \ + } else { \ + __prev->next = __next; \ + } \ + } while(0); + +#define ENQUEUE_INFO_PRIO(info, queue) \ + do { \ + OSShutdownFunctionInfo* __prev; \ + OSShutdownFunctionInfo* __next; \ + for(__next = (queue)->head; __next \ + && (__next->priority <= (info)->priority); \ + __next = __next->next) ; \ + \ + if (__next == 0) { \ + ENQUEUE_INFO(info, queue); \ + } else { \ + (info)->next = __next; \ + __prev = __next->prev; \ + __next->prev = (info); \ + (info)->prev = __prev; \ + if (__prev == 0) { \ + (queue)->head = (info); \ + } else { \ + __prev->next = (info); \ + } \ + } \ + } while(0); + +static OSShutdownFunctionQueue ShutdownFunctionQueue; +static u32 bootThisDol = 0; +volatile BOOL __OSIsReturnToIdle = FALSE; + +// prototypes +static void KillThreads(void); +static int CallResetFunctions(int final); +static void Reset(u32 resetCode); + +void OSRegisterShutdownFunction(OSShutdownFunctionInfo* info) { + ASSERTLINE(373, info->func); + + ENQUEUE_INFO_PRIO(info, &ShutdownFunctionQueue); +} + +void OSUnregisterShutdownFunction(OSShutdownFunctionInfo* info) { + DEQUEUE_INFO(info, &ShutdownFunctionQueue); +} + +int __OSCallShutdownFunctions(BOOL final, u32 event) { + OSShutdownFunctionInfo* info; + int err; + u32 priority; + + priority = 0; + err = 0; + + for (info = ShutdownFunctionQueue.head; info != 0;) { + if (err != 0 && priority != info->priority) + break; + err |= !info->func(final, event); + priority = info->priority; + info = info->next; + } + + err |= !__OSSyncSram(); + return err ? FALSE : TRUE; +} + +void __OSShutdownDevices(u32 event) { + int rc; + BOOL disableRecalibration; + BOOL doRecal; + + switch(event) { + case 0: + case 5: + case 6: + doRecal = FALSE; + break; + case 2: + case 3: + case 4: + case 1: + default: + doRecal = TRUE; + break; + } + + __OSStopAudioSystem(); + + if (!doRecal) { + disableRecalibration = __PADDisableRecalibration(TRUE); + } + + do {} while (!__OSCallShutdownFunctions(FALSE, event)); + do {} while (!__OSSyncSram()); + + OSDisableInterrupts(); + + rc = __OSCallShutdownFunctions(TRUE, event); + ASSERTLINE(491, rc); + + LCDisable(); + if (!doRecal) { + __PADDisableRecalibration(disableRecalibration); + } + + KillThreads(); +} + +u8 __OSGetDiscState(u8 last) { + u32 flags; + + if (__DVDGetCoverStatus() != 2) { + return 3; + } else { + if ((last == 1) && (__OSGetRTCFlags(&flags) && !flags)) { + return 1; + } else { + return 2; + } + } +} + +static void KillThreads(void) { + OSThread* thread; + OSThread* next; + + for (thread = __OSActiveThreadQueue.head; thread; thread = next) { + next = thread->linkActive.next; + switch (thread->state) { + case 1: + case 4: + OSCancelThread(thread); + continue; + default: + continue; + } + } +} + +void OSShutdownSystem(BOOL reset, u32 resetCode, BOOL forceMenu) { + SCIdleModeInfo idleModeInfo; + OSIOSRev iosRev; + OSStateFlags state; + + memset(&idleModeInfo, 0, sizeof(SCIdleModeInfo)); + + SCInit(); + while ( SCCheckStatus() == 1 ) + {} + + SCGetIdleMode(&idleModeInfo); + __OSStopPlayRecord(); + __OSUnRegisterStateEvent(); + __DVDPrepareReset(); + __OSReadStateFlags(&state); + state.lastDiscState = __OSGetDiscState(state.lastDiscState); + + if (idleModeInfo.mode == 1) { + state.lastShutdown = 5; + } else { + state.lastShutdown = 1; + } + + __OSClearRTCFlags(); + __OSWriteStateFlags(&state); + __OSGetIOSRev(&iosRev); + + if (idleModeInfo.mode == 1) { + __OSIsReturnToIdle = TRUE; + + OSDisableScheduler(); + __OSShutdownDevices(5); + OSEnableScheduler(); + __OSLaunchMenu(); + } else { + OSDisableScheduler(); + __OSShutdownDevices(2); + __OSShutdownToSBY(); + } +} + +void OSRestart(u32 resetCode) { + u8 type = OSGetAppType(); + __OSStopPlayRecord(); + __OSUnRegisterStateEvent(); + + if (type == 0x81) { + OSDisableScheduler(); + __OSShutdownDevices(4); + OSEnableScheduler(); + __OSRelaunchTitle(resetCode); + } else if (type == 0x80) { + OSDisableScheduler(); + __OSShutdownDevices(4); + OSEnableScheduler(); + __OSReboot(resetCode, bootThisDol); + } + + OSDisableScheduler(); + __OSShutdownDevices(1); + __OSHotResetForError(); +} + +void __OSReturnToMenu(u8 menuMode) { + OSStateFlags state; + ESTicketView* var_r30 = NULL; + int rc; + + __OSStopPlayRecord(); + __OSUnRegisterStateEvent(); + __DVDPrepareReset(); + __OSReadStateFlags(&state); + + state.lastDiscState = __OSGetDiscState(state.lastDiscState); + state.lastShutdown = 3; + state.menuMode = menuMode; + + __OSClearRTCFlags(); + __OSWriteStateFlags(&state); + + OSSetArenaLo((void*)0x81280000); + OSSetArenaHi((void*)0x812F0000); + + rc = ESP_InitLib(); + if (rc) { + __OSReturnToMenuForError(); + } + + var_r30 = OSAllocFromMEM1ArenaLo(0xE0, 0x20); + if (var_r30 == 0) { + __OSReturnToMenuForError(); + } + + memset(var_r30, 0, 0xE0); + + rc = ESP_DiGetTicketView(NULL, var_r30); + if (!rc && OSPlayTimeIsLimited()) { + __OSPlayTimeType type = OSPLAYTIME_PERMANENT; + u32 playTime = -1; + __OSGetPlayTime(var_r30, &type, &playTime); + if (playTime == 0) { + __OSWriteExpiredFlagIfSet(); + } + } + + OSDisableScheduler(); + __OSShutdownDevices(5); + OSEnableScheduler(); + + __OSLaunchMenu(); + OSDisableScheduler(); + + __VISetRGBModeImm(); + __OSHotResetForError(); +} + +void OSReturnToMenu(void) { + __OSReturnToMenu(0); + OSPanic(__FILE__, 895, "OSReturnToMenu(): Falied to boot system menu.\n"); +} + +void __OSReturnToMenuForError(void) { + OSStateFlags state; + __OSReadStateFlags(&state); + + state.lastDiscState = 2; + state.lastShutdown = 3; + + __OSClearRTCFlags(); + __OSWriteStateFlags(&state); + + __OSLaunchMenu(); + OSDisableScheduler(); + + __VISetRGBModeImm(); + __OSHotResetForError(); + + OSPanic(__FILE__, 1010, "__OSReturnToMenu(): Falied to boot system menu.\n"); +} + +void __OSHotResetForError(void) { + if (__OSInNandBoot || __OSInReboot) { + __OSInitSTM(); + } + + __OSHotReset(); + + OSPanic(__FILE__, 1034, "__OSHotReset(): Falied to reset system.\n"); +} + +u32 OSGetResetCode() { + u32 resetCode; + if (__OSRebootParams.valid) + resetCode = 0x80000000 | __OSRebootParams.restartCode; + else + resetCode = (__PIRegs[9] & 0xFFFFFFF8) / 8; + + return resetCode; +} + +void OSResetSystem(int, u32, int) { + OSPanic(__FILE__, 1185, "OSResetSystem() is obsoleted. It doesn't work any longer.\n"); +} diff --git a/src/revolution/os/OSRtc.c b/src/revolution/os/OSRtc.c new file mode 100644 index 0000000000..67a5d90527 --- /dev/null +++ b/src/revolution/os/OSRtc.c @@ -0,0 +1,564 @@ +#include +#include + +#include "__os.h" + +static SramControl Scb ATTRIBUTE_ALIGN(DOLPHIN_ALIGNMENT); + +// prototypes +static int GetRTC(u32* rtc); +static int ReadSram(void* buffer); +static void WriteSramCallback(s32, OSContext*); +static int WriteSram(void* buffer, u32 offset, u32 size); +static void* LockSram(u32 offset); +static int UnlockSram(int commit, u32 offset); +static void __OSReadROMCallback(s32 chan); + +static int GetRTC(u32* rtc) { + int err; + u32 cmd; + + if (EXILock(0, 1, NULL) == 0) { + return 0; + } + if (EXISelect(0, 1, 3) == 0) { + EXIUnlock(0); + return 0; + } + cmd = 0x20000000; + err = 0; + err |= !EXIImm(0, &cmd, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIImm(0, &cmd, 4, 0, 0); + err |= !EXISync(0); + err |= !EXIDeselect(0); + EXIUnlock(0); + rtc[0] = cmd; + return !err; +} + +int __OSGetRTC(u32* rtc) { + int err; + u32 t0; + u32 t1; + int i; + + for(i = 0; i < 16; i++) { + err = 0; + err |= !GetRTC(&t0); + err |= !GetRTC(&t1); + if (err) { + break; + } + if (t0 == t1) { + rtc[0] = t0; + return 1; + } + } + return 0; +} + +int __OSSetRTC(u32 rtc) { + int err; + u32 cmd; + + if (EXILock(0, 1, NULL) == 0) { + return 0; + } + if (EXISelect(0, 1, 3) == 0) { + EXIUnlock(0); + return 0; + } + cmd = 0xA0000000; + err = 0; + err |= !EXIImm(0, &cmd, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIImm(0, &rtc, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIDeselect(0); + EXIUnlock(0); + return !err; +} + +static int ReadSram(void* buffer) { + int err; + u32 cmd; + + DCInvalidateRange(buffer, SRAM_SIZE); + if (!EXILock(0, 1, NULL) ) { + return 0; + } + if (!EXISelect(0, 1, 3)) { + EXIUnlock(0); + return 0; + } + cmd = 0x20000100; + err = 0; + err |= !EXIImm(0, &cmd, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIDma(0, buffer, SRAM_SIZE, 0, NULL); + err |= !EXISync(0); + err |= !EXIDeselect(0); + EXIUnlock(0); + return !err; +} + +static void WriteSramCallback(s32, OSContext*) { + ASSERTLINE(270, !Scb.locked); + Scb.sync = WriteSram(&Scb.sram[Scb.offset], Scb.offset, SRAM_SIZE - Scb.offset); + if (Scb.sync != 0) { + Scb.offset = SRAM_SIZE; + } + ASSERTLINE(276, Scb.sync); +} + +static int WriteSram(void* buffer, u32 offset, u32 size) { + int err; + u32 cmd; + + if (!EXILock(0, 1, WriteSramCallback)) { + return 0; + } + if (!EXISelect(0, 1, 3)) { + EXIUnlock(0); + return 0; + } + offset <<= 6; + cmd = ((offset + 0x100) | 0xA0000000); + err = 0; + err |= !EXIImm(0, &cmd, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIImmEx(0, buffer, size, 1); + err |= !EXIDeselect(0); + EXIUnlock(0); + return !err; +} + +void __OSInitSram(void) { + Scb.locked = Scb.enabled = FALSE; + Scb.sync = ReadSram(&Scb); + ASSERTLINE(330, Scb.sync); + Scb.offset = SRAM_SIZE; + + OSSetGbsMode(OSGetGbsMode()); +} + +static void* LockSram(u32 offset) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + ASSERTLINE(353, !Scb.locked); + if (Scb.locked) { + OSRestoreInterrupts(enabled); + return NULL; + } + Scb.enabled = enabled; + Scb.locked = TRUE; + return &Scb.sram[offset]; +} + +OSSram* __OSLockSram(void) { + return (OSSram*)LockSram(0); +} + +OSSramEx* __OSLockSramEx(void) { + return (OSSramEx*)LockSram(sizeof(OSSram)); +} + +static int UnlockSram(int commit, u32 offset) { + u16* p; + + ASSERTLINE(387, Scb.locked); + if (commit != 0) { + if (offset == 0) { + OSSram* sram = (OSSram*)Scb.sram; + if (2u < (sram->flags & 3)) { + sram->flags &= ~3; + } + + sram->checkSum = sram->checkSumInv = 0; + for(p = (u16*)&sram->counterBias; p < ((u16*)&Scb.sram[0x14]); p++) { + sram->checkSum += *p; + sram->checkSumInv += ~(*p); + } + } + if (offset < Scb.offset) { + Scb.offset = offset; + } + + if (Scb.offset <= 0x14) { + OSSramEx* sram = (OSSramEx*)(Scb.sram + sizeof(OSSram)); + if (((u32)sram->gbs & 0x7c00) == 0x5000 || ((u32)sram->gbs & 0xc0) == 0xc0) { + sram->gbs = 0; + } + } + + Scb.sync = WriteSram(&Scb.sram[Scb.offset], Scb.offset, SRAM_SIZE - Scb.offset); + if (Scb.sync != 0) { + Scb.offset = SRAM_SIZE; + } + } + Scb.locked = FALSE; + OSRestoreInterrupts(Scb.enabled); + return Scb.sync; +} + +int __OSUnlockSram(int commit) { + UnlockSram(commit, 0); +} + +int __OSUnlockSramEx(int commit) { + UnlockSram(commit, sizeof(OSSram)); +} + +int __OSSyncSram(void) { + return Scb.sync; +} + +int __OSCheckSram(void) { + u16* p; + u16 checkSum; + u16 checkSumInv; + OSSram* sram; + int unused; + + ASSERTLINE(466, Scb.locked); + + checkSum = checkSumInv = 0; + + sram = (OSSram*)Scb.sram; + + for (p = (void*)&sram->counterBias; p < (u16*)&Scb.sram[0x14]; p++) { + checkSum += *p; + checkSumInv += ~(*p); + } + + return (sram->checkSum == checkSum && sram->checkSumInv == checkSumInv); +} + +int __OSReadROM(void * buffer, s32 length, s32 offset) { + int err; + u32 cmd; + + ASSERTLINE(509, length <= 1024); + DCInvalidateRange(buffer, length); + if (EXILock(0, 1, NULL) == 0) { + return 0; + } + if (EXISelect(0, 1, 3) == 0) { + EXIUnlock(0); + return 0; + } + cmd = offset << 6; + err = 0; + err |= !EXIImm(0, &cmd, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIDma(0, buffer, length, 0, NULL); + err |= !EXISync(0); + err |= !EXIDeselect(0); + EXIUnlock(0); + return !err; +} + +static void __OSReadROMCallback(s32 chan) { + void (*callback)(); + + EXIDeselect(chan); + EXIUnlock(chan); + callback = Scb.callback; + if (callback) { + Scb.callback = NULL; + callback(); + } +} + +int __OSReadROMAsync(void* buffer, s32 length, s32 offset, void (*callback)()) { + int err; + u32 cmd; + + ASSERTLINE(556, length <= 1024); + ASSERTLINE(557, callback); + DCInvalidateRange(buffer, length); + Scb.callback = callback; + if (EXILock(0, 1, NULL) == 0) { + return 0; + } + if (EXISelect(0, 1, 3) == 0) { + EXIUnlock(0); + return 0; + } + cmd = offset << 6; + err = 0; + err |= !EXIImm(0, &cmd, 4, 1, 0); + err |= !EXISync(0); + err |= !EXIDma(0, buffer, length, 0, (void*)__OSReadROMCallback); + return !err; +} + +u32 OSGetSoundMode(void) { + OSSram* sram = __OSLockSram(); + u32 mode = (sram->flags & 4) ? 1 : 0; + + __OSUnlockSram(0); + return mode; +} + +void OSSetSoundMode(u32 mode) { + OSSram* sram; + int unused; + + ASSERTLINE(617, mode == OS_SOUND_MODE_MONO || mode == OS_SOUND_MODE_STEREO); + mode *= 4; + mode &= 4; + sram = __OSLockSram(); + if (mode == (sram->flags & 4)) { + __OSUnlockSram(0); + return; + } + sram->flags &= 0xFFFFFFFB; + sram->flags |= mode; + __OSUnlockSram(1); +} + +u32 OSGetProgressiveMode(void) { + OSSram* sram; + u32 on; + + sram = __OSLockSram(); + on = (sram->flags & 0x80) >> 7; + __OSUnlockSram(FALSE); + return on; +} + +void OSSetProgressiveMode(u32 on) { +#ifndef DEBUG + u32 padding[1]; +#endif + OSSram* sram; + + ASSERTLINE(670, on == OS_PROGRESSIVE_MODE_OFF || on == OS_PROGRESSIVE_MODE_ON); + + on <<= 7; + on &= 0x80; + + sram = __OSLockSram(); + if (on == (sram->flags & 0x80)) { + __OSUnlockSram(FALSE); + return; + } + + sram->flags &= ~0x80; + sram->flags |= on; + __OSUnlockSram(TRUE); +} + +u32 OSGetVideoMode(void) { + OSSram* sram = __OSLockSram(); + u32 mode = sram->flags & 3; + + __OSUnlockSram(0); + + if (mode > 2) { + mode = 0; + } + + return mode; +} + +void OSSetVideoMode(u32 mode) { + OSSram* sram; + int unused; + + ASSERTLINE(731, OS_VIDEO_MODE_NTSC <= mode && mode <= OS_VIDEO_MODE_MPAL); + + if (mode > 2) { + mode = 0; + } + + sram = __OSLockSram(); + + if (mode == (sram->flags & 3)) { + __OSUnlockSram(0); + return; + } + sram->flags &= 0xFFFFFFFC; + sram->flags |= mode; + __OSUnlockSram(1); +} + +u8 OSGetLanguage(void) { + OSSram* sram = __OSLockSram(); + u8 language = sram->language; + + __OSUnlockSram(0); + return language; +} + +void OSSetLanguage(u8 language) { + OSSram* sram = __OSLockSram(); + int unused; + + if (language == sram->language) { + __OSUnlockSram(0); + return; + } + sram->language = language; + __OSUnlockSram(1); +} + +u8 __OSGetBootMode(void) { + OSSram* sram = __OSLockSram(); + u8 ntd = sram->ntd; + __OSUnlockSram(0); + return ntd & 0x80; +} + +void __OSSetBootMode(u8 ntd) { + OSSram* sram; + int unused; + + ntd &= 0x80; + sram = __OSLockSram(); + if (ntd == (sram->ntd & 0x80U)) { + __OSUnlockSram(0); + return; + } + sram->ntd &= 0xFFFFFF7F; + sram->ntd |= ntd; + __OSUnlockSram(1); +} + +u32 OSGetEuRgb60Mode(void) { + OSSram* sram; + u32 on; + + sram = __OSLockSram(); + on = (sram->ntd & 0x40) >> 6; + __OSUnlockSram(0); + return on; +} + +void OSSetEuRgb60Mode(u32 on) { +#ifndef DEBUG + u32 padding[1]; +#endif + OSSram* sram; + + ASSERTLINE(895, on == OS_EURGB60_OFF || on == OS_EURGB60_ON); + on <<= 6; + on &= 0x40; + + sram = __OSLockSram(); + if (on == (sram->ntd & 0x40)) { + __OSUnlockSram(0); + } else { + sram->ntd &= ~0x40; + sram->ntd |= on; + __OSUnlockSram(1); + } +} + +u16 OSGetWirelessID(s32 chan) { + OSSramEx* sram; + u16 id; + + sram = __OSLockSramEx(); + id = sram->wirelessPadID[chan]; + __OSUnlockSramEx(FALSE); + return id; +} + +void OSSetWirelessID(s32 chan, u16 id) { + OSSramEx* sram; + + sram = __OSLockSramEx(); + if (sram->wirelessPadID[chan] != id) { + sram->wirelessPadID[chan] = id; + __OSUnlockSramEx(TRUE); + return; + } + + __OSUnlockSramEx(FALSE); +} + +u16 OSGetGbsMode(void) { + OSSramEx* sram; + u16 mode; + + sram = __OSLockSramEx(); + mode = sram->gbs; + __OSUnlockSramEx(FALSE); + return mode; +} + +void OSSetGbsMode(u16 mode) { +#ifndef DEBUG + u32 padding[1]; +#endif + OSSramEx* sram; + + if (((u32)mode & 0x7c00) == 0x5000 || ((u32)mode & 0xc0) == 0xc0) { + mode = 0; + } + + sram = __OSLockSramEx(); + + if (mode == sram->gbs) { + __OSUnlockSramEx(FALSE); + return; + } + sram->gbs = mode; + + __OSUnlockSramEx(TRUE); +} + +BOOL __OSGetRTCFlags(u32* flags) { + BOOL err; + u32 cmd; + + if (!EXILock(0, 1, 0)) { + return FALSE; + } + + if (!EXISelect(0, 1, 3)) { + EXIUnlock(0); + return FALSE; + } + + cmd = 0x21000800; + err = FALSE; + err |= !EXIImm(0, &cmd, 4, 1, NULL); + err |= !EXISync(0); + err |= !EXIImm(0, &cmd, 4, 0, NULL); + err |= !EXISync(0); + err |= !EXIDeselect(0); + EXIUnlock(0); + *flags = cmd; + return !err; +} + +BOOL __OSClearRTCFlags(void) { + BOOL err; + u32 cmd; + u32 data = 0; + + if (!EXILock(0, 1, 0)) { + return FALSE; + } + + if (!EXISelect(0, 1, 3)) { + EXIUnlock(0); + return FALSE; + } + + cmd = 0xA1000800; + err = FALSE; + err |= !EXIImm(0, &cmd, 4, 1, NULL); + err |= !EXISync(0); + err |= !EXIImm(0, &data, 4, 1, NULL); + err |= !EXISync(0); + err |= !EXIDeselect(0); + EXIUnlock(0); + + return !err; +} diff --git a/src/revolution/os/OSStateFlags.c b/src/revolution/os/OSStateFlags.c new file mode 100644 index 0000000000..bf99843907 --- /dev/null +++ b/src/revolution/os/OSStateFlags.c @@ -0,0 +1,74 @@ +#include +#include +#include + +static OSStateFlags StateFlags __attribute__ ((aligned(32))); + +static u32 CheckSum(OSStateFlags* flags) { + u32* ptr, i, sum; + + ptr = (u32*)&flags->lastBootApp; + sum = 0; + + for (i = 0; i < (sizeof(OSStateFlags) - 4) / 4; i++) { + sum = sum + *ptr; + ptr++; + } + + return sum; +} + +BOOL __OSWriteStateFlags(OSStateFlags* flags) { + NANDFileInfo fileInfo; + s32 result; + + memcpy(&StateFlags, flags, sizeof(StateFlags)); + StateFlags.checkSum = CheckSum(&StateFlags); + + result = NANDOpen("/title/00000001/00000002/data/state.dat", &fileInfo, 2); + + if (result == 0) { + result = NANDWrite(&fileInfo, &StateFlags, sizeof(StateFlags)); + if (result != sizeof(StateFlags)) { + NANDClose(&fileInfo); + return FALSE; + } + + result = NANDClose(&fileInfo); + if (result != 0) { + return FALSE; + } + } else { + return FALSE; + } + + return TRUE; +} + +BOOL __OSReadStateFlags(OSStateFlags* flags) { + NANDFileInfo fileInfo; + s32 result; + + result = NANDOpen("/title/00000001/00000002/data/state.dat", &fileInfo, 1); + if (result == 0) { + result = NANDRead(&fileInfo, &StateFlags, sizeof(OSStateFlags)); + NANDClose(&fileInfo); + + if (result != sizeof(OSStateFlags)) { + NANDDelete("/title/00000001/00000002/data/state.dat"); + memset(flags, 0, sizeof(StateFlags)); + return FALSE; + } + } else { + memset(flags, 0, sizeof(OSStateFlags)); + return FALSE; + } + + if (CheckSum(&StateFlags) != StateFlags.checkSum) { + memset(flags, 0, sizeof(OSStateFlags)); + return FALSE; + } + + memcpy(flags, &StateFlags, sizeof(OSStateFlags)); + return TRUE; +} diff --git a/src/revolution/os/OSStateTM.c b/src/revolution/os/OSStateTM.c new file mode 100644 index 0000000000..53d4bdc2d1 --- /dev/null +++ b/src/revolution/os/OSStateTM.c @@ -0,0 +1,307 @@ +#include +#include +#include + +#include + +static u32 StmImInBuf[8] __attribute__((align(32))); +static u32 StmImOutBuf[8] __attribute__((align(32))); + +static u32 StmVdInBuf[8] __attribute__((align(32))); +static u32 StmVdOutBuf[8] __attribute__((align(32))); + +static u32 StmEhInBuf[8]__attribute__((align(32))); +static u32 StmEhOutBuf[8] __attribute__((align(32))); + +static OSResetCallback ResetCallback; +static OSPowerCallback PowerCallback; +static BOOL ResetDown = 0; +static int StmReady = 0; +static int StmImDesc = 0; +static int StmEhDesc = 0; +static int StmEhRegistered = 0; +static int StmVdInUse = 0; + +static BOOL __OSGetResetButtonStateRaw(void); +static s32 __OSStateEventHandler(s32, void *); +static s32 __OSVIDimReplyHandler(s32, void *); +static void __OSDefaultResetCallback(void); +static void __OSDefaultPowerCallback(void); +static void __OSRegisterStateEvent(void); + +static void LockUp(void); + +OSPowerCallback OSSetPowerCallback(OSPowerCallback callback) { + BOOL enabled; + OSPowerCallback prevCallback; + + enabled = OSDisableInterrupts(); + prevCallback = PowerCallback; + + if (callback) { + PowerCallback = callback; + } else { + PowerCallback = __OSDefaultPowerCallback; + } + + if (!StmEhRegistered) { + __OSRegisterStateEvent(); + } + + OSRestoreInterrupts(enabled); + + if (prevCallback == __OSDefaultPowerCallback) { + return NULL; + } else { + return prevCallback; + } +} + +// NONMATCHING - regswap +BOOL OSGetResetButtonState(void) { + BOOL enabled = OSDisableInterrupts(); + int state = ResetDown; + + ResetDown = FALSE; + OSRestoreInterrupts(enabled); + if (!StmEhRegistered) { + __OSRegisterStateEvent(); + } + + return state; +} + +BOOL OSGetResetSwitchState(void) { + return OSGetResetButtonState(); +} + +int __OSInitSTM(void) { + PowerCallback = __OSDefaultPowerCallback; + ResetCallback = __OSDefaultResetCallback; + ResetDown = 0; + + if (StmReady) { + return 1; + } + + StmVdInUse = 0; + + StmImDesc = IOS_Open("/dev/stm/immediate", 0); + if (StmImDesc < 0) { + OSReport("[OS] Note: STM is not included in the firmware.\n"); + StmReady = 0; + return 0; + } + + StmEhDesc = IOS_Open("/dev/stm/eventhook", 0); + if (StmEhDesc < 0) { + OSReport("[OS] Note: STM is not included in the firmware.\n"); + StmReady = 0; + return 0; + } + + __OSRegisterStateEvent(); + StmReady = 1; + return 1; +} + +// unknown function of origin +void dummyStrings() { + OSReport("Error: Failed to close STM immediate control driver. %d\n"); + OSReport("Error: Failed to close STM event hook driver. %d\n"); +} + +void __OSShutdownToSBY(void) { + int res; + __VIRegs[1] = 0; + + if (!StmReady) { + OSPanic(__FILE__, 348, "Error: The firmware doesn\'t support shutdown feature.\n"); + } + + StmImInBuf[0] = 0; + res = IOS_Ioctl(StmImDesc, 0x2003, StmImInBuf, 0x20, StmImOutBuf, 0x20); + LockUp(); +} + +void __OSHotReset(void) { + int result; + __VIRegs[1] = 0; + + if (!StmReady) { + OSPanic(__FILE__, 412, "Error: The firmware doesn't support reboot feature.\n"); + } + + result = IOS_Ioctl(StmImDesc, 0x2001, StmImInBuf, sizeof(StmImInBuf), StmImOutBuf, sizeof(StmImOutBuf)); + LockUp(); +} + +BOOL __OSGetResetButtonStateRaw(void) { + u32 reg = __PIRegs[0]; + if (!(reg & 0x10000)) { + return TRUE; + } else { + return FALSE; + } +} + +int __OSSetVIForceDimming(BOOL isEnabled, u32 yShift, u32 xShift) { + BOOL en; + int var_r31; + + if (!StmReady) { + return -10; + } + + en = OSDisableInterrupts(); + + if (StmVdInUse) { + OSRestoreInterrupts(en); + return 0; + } + + StmVdInUse = 1; + OSRestoreInterrupts(en); + + StmVdInBuf[0] = (xShift | yShift << 3) | isEnabled << 7; + StmVdInBuf[1] = 0; + StmVdInBuf[2] = 0; + StmVdInBuf[3] = 0; + StmVdInBuf[4] = 0; + StmVdInBuf[5] = 0xFFFFFFFF; + StmVdInBuf[6] = 0xFFFF0000; + StmVdInBuf[7] = 0; + + var_r31 = AccessVIDimRegs(); + return var_r31; +} + +s32 __OSSetIdleLEDMode(u32 led_mode) { + s32 ret; + + if (StmReady == 0) { + return -6; + } + + StmImInBuf[0] = led_mode; + ret = IOS_Ioctl(StmImDesc, 0x6002, StmImInBuf, 0x20, StmImOutBuf, 0x20); + return ret; +} + +s32 __OSUnRegisterStateEvent(void) { + s32 ret; + + if (StmEhRegistered == 0) { + return 0; + } + + if (StmReady == 0) { + return -6; + } + + ret = IOS_Ioctl(StmImDesc, 0x3002, StmImInBuf, 0x20, StmImOutBuf, 0x20); + + if (ret == 0) { + StmEhRegistered = 0; + } + + return ret; +} + +void ACRWriteReg(u32 param_0, u32 param_1) { + __IPCRegs[param_0 >> 2] = param_1; +} + +// NONMATCHING - extra branch +static int AccessVIDimRegs(void) { + int res; + res = IOS_IoctlAsync(StmImDesc, 0x5001, StmVdInBuf, 0x20, StmVdOutBuf, 0x20, __OSVIDimReplyHandler, 0); + switch(res) { + default: + return res; + case 0: + return 1; + } +} + +s32 __OSVIDimReplyHandler(s32 ret, void *pUnused) { + StmVdInUse = 0; + return 0; +} + +static void __OSRegisterStateEvent(void) { + int err, enabled; + enabled = OSDisableInterrupts(); + + err = IOS_IoctlAsync(StmEhDesc, 0x1000, StmEhInBuf, 0x20, StmEhOutBuf, 0x20, __OSStateEventHandler, (void*)0); + + if (err == IOS_ERROR_OK) { + StmEhRegistered = 1; + } + else { + StmEhRegistered = 0; + } + + OSRestoreInterrupts(enabled); +} + +void __OSDefaultResetCallback(void) { + +} + +void __OSDefaultPowerCallback(void) { + +} + +// unknown origin function +void dummyStrings2() { + OSReport("Error: The firmware doesn't support hot reset feature.\n"); +} + +// NONMATCHING +static s32 __OSStateEventHandler(s32 ret, void* pUnused) { + int en; + OSResetCallback cb; + + if (ret != 0) { + OSPanic(__FILE__, 820, "Error on STM state event handler\n"); + } + + StmEhRegistered = 0; + + if (StmEhOutBuf[0] == 0x20000) { + if (__OSGetResetButtonStateRaw()) { + en = OSDisableInterrupts(); + ResetDown = TRUE; + cb = ResetCallback; + ResetCallback = __OSDefaultResetCallback; + cb(); + OSRestoreInterrupts(en); + VIResetDimmingCount(); + } + + __OSRegisterStateEvent(); + } + + if (StmEhOutBuf[0] == 0x800) { + en = OSDisableInterrupts(); + cb = PowerCallback; + PowerCallback = __OSDefaultPowerCallback; + cb(); + OSRestoreInterrupts(en); + } + + if (StmEhOutBuf[0] == 0) {} + + return 0; +} + +static void LockUp(void) { + BOOL en = OSDisableInterrupts(); + + ICFlashInvalidate(); + + while (1) { + + } +} diff --git a/src/revolution/os/OSStopwatch.c b/src/revolution/os/OSStopwatch.c new file mode 100644 index 0000000000..a314e2a281 --- /dev/null +++ b/src/revolution/os/OSStopwatch.c @@ -0,0 +1,55 @@ +#include +#include + +void OSInitStopwatch(OSStopwatch* sw, char* name) { + sw->name = name; + sw->total = 0; + sw->hits = 0; + sw->min = 0x00000000FFFFFFFF; + sw->max = 0; +} + +void OSStartStopwatch(OSStopwatch* sw) { + sw->running = TRUE; + sw->last = OSGetTime(); +} + +void OSStopStopwatch(OSStopwatch* sw) { + OSTime interval; + + if (sw->running) { + interval = OSGetTime() - sw->last; + sw->total += interval; + sw->running = FALSE; + sw->hits++; + if (sw->max < interval) { + sw->max = interval; + } + if (interval < sw->min) { + sw->min = interval; + } + } +} + +OSTime OSCheckStopwatch(OSStopwatch* sw) { + OSTime currTotal; + + currTotal = sw->total; + if (sw->running) { + currTotal += OSGetTime() - sw->last; + } + return currTotal; +} + +void OSResetStopwatch(OSStopwatch* sw) { + OSInitStopwatch(sw, sw->name); +} + +void OSDumpStopwatch(OSStopwatch* sw) { + OSReport("Stopwatch [%s] :\n", sw->name); + OSReport("\tTotal= %lld us\n", OSTicksToMicroseconds(sw->total)); + OSReport("\tHits = %d \n", sw->hits); + OSReport("\tMin = %lld us\n", OSTicksToMicroseconds(sw->min)); + OSReport("\tMax = %lld us\n", OSTicksToMicroseconds(sw->max)); + OSReport("\tMean = %lld us\n", OSTicksToMicroseconds(sw->total/sw->hits)); +} diff --git a/src/revolution/os/OSSync.c b/src/revolution/os/OSSync.c new file mode 100644 index 0000000000..7bf90140c2 --- /dev/null +++ b/src/revolution/os/OSSync.c @@ -0,0 +1,33 @@ +#include +#include + +#include "__os.h" + +// prototypes +void __OSSystemCallVectorStart(void); +void __OSSystemCallVectorEnd(void); + +#ifdef __GEKKO__ +static asm void SystemCallVector(void) { +entry __OSSystemCallVectorStart + nofralloc + mfspr r9, HID0 + ori r10, r9, 0x8 + mtspr HID0, r10 + isync + sync + mtspr HID0, r9 + rfi +entry __OSSystemCallVectorEnd + nop +} +#endif + +void __OSInitSystemCall(void) { + void* addr = (void*)OSPhysicalToCached(0xC00); + + memcpy(addr, __OSSystemCallVectorStart, (u32)&__OSSystemCallVectorEnd - (u32)&__OSSystemCallVectorStart); + DCFlushRangeNoSync(addr, 0x100); + __sync(); + ICInvalidateRange(addr, 0x100); +} diff --git a/src/revolution/os/OSThread.c b/src/revolution/os/OSThread.c new file mode 100644 index 0000000000..5635fb8eca --- /dev/null +++ b/src/revolution/os/OSThread.c @@ -0,0 +1,877 @@ +#include +#include + +#include "__os.h" + +#define ENQUEUE_THREAD(thread, queue, link) \ + do { \ + OSThread* __prev = (queue)->tail; \ + if (__prev == NULL) { \ + (queue)->head = (thread); \ + } else { \ + __prev->link.next = (thread); \ + } \ + (thread)->link.prev = __prev; \ + (thread)->link.next = 0; \ + (queue)->tail = (thread); \ + } while(0); + +#define DEQUEUE_THREAD(thread, queue, link) \ + do { \ + OSThread* __next = (thread)->link.next; \ + OSThread* __prev = (thread)->link.prev; \ + if (__next == NULL) { \ + (queue)->tail = __prev; \ + } else { \ + __next->link.prev = __prev; \ + } \ + if (__prev == NULL) { \ + (queue)->head = __next; \ + } else { \ + __prev->link.next = __next; \ + } \ + } while(0); + +#define ENQUEUE_THREAD_PRIO(thread, queue, link) \ + do { \ + OSThread* __prev; \ + OSThread* __next; \ + for(__next = (queue)->head; __next \ + && (__next->priority <= (thread)->priority); \ + __next = __next->link.next) ; \ + \ + if (__next == NULL) { \ + ENQUEUE_THREAD(thread, queue, link); \ + } else { \ + (thread)->link.next = __next; \ + __prev = __next->link.prev; \ + __next->link.prev = (thread); \ + (thread)->link.prev = __prev; \ + if (__prev == NULL) { \ + (queue)->head = (thread); \ + } else { \ + __prev->link.next = (thread); \ + } \ + } \ + } while(0); + +#define DEQUEUE_HEAD(thread, queue, link) \ + do { \ + OSThread* __next = thread->link.next; \ + if (__next == NULL) { \ + (queue)->tail = 0; \ + } else { \ + __next->link.prev = 0; \ + } \ + (queue)->head = __next; \ + } while(0); + +// defined in linkscript +extern u8 _stack_end[]; +extern u8 _stack_addr[]; + +static OSThreadQueue RunQueue[32]; +static OSThread IdleThread; +static OSThread DefaultThread; +static OSContext IdleContext; +static volatile u32 RunQueueBits; +static volatile int RunQueueHint; +static volatile s32 Reschedule; + +#define ALIGN4(val) (((val) + 0x3) & ~0x3) +#define ALIGN8(val) (((val) + 0x7) & ~0x7) + +// prototypes +static void OSInitMutexQueue(OSMutexQueue* queue); +static void __OSSwitchThread(OSThread* nextThread); +static int __OSIsThreadActive(OSThread* thread); +static void SetRun(OSThread* thread); +static void UnsetRun(OSThread* thread); +static OSThread* SetEffectivePriority(OSThread* thread, s32 priority); +static void UpdatePriority(OSThread* thread); +static OSThread* SelectThread(int yield); +static int CheckThreadQueue(OSThreadQueue* queue); +static int IsMember(OSThreadQueue* queue, OSThread* thread); +static void OSSetCurrentThread(OSThread* thread); + +static void DefaultSwitchThreadCallback(OSThread* from, OSThread* to) {} +static OSSwitchThreadCallback SwitchThreadCallback = DefaultSwitchThreadCallback; + +OSSwitchThreadCallback OSSetSwitchThreadCallback(OSSwitchThreadCallback callback) { + OSSwitchThreadCallback prev; + BOOL enabled; + + enabled = OSDisableInterrupts(); + prev = SwitchThreadCallback; + + SwitchThreadCallback = callback ? callback : DefaultSwitchThreadCallback; + OSRestoreInterrupts(enabled); + + return prev == DefaultSwitchThreadCallback ? NULL : prev; +} + +void __OSThreadInit() { + OSThread* thread = &DefaultThread; + OSPriority prio; + + thread->state = OS_THREAD_STATE_RUNNING; + thread->attr = 1; + thread->priority = thread->base = 0x10; + thread->suspend = 0; + thread->val = (void*)-1; // wut + thread->mutex = 0; + + OSInitThreadQueue(&thread->queueJoin); +#ifdef DEBUG + OSInitMutexQueue(&thread->queueMutex); +#else + thread->queueMutex.head = thread->queueMutex.tail = 0; // it got inlined? cant reproduce the inline... +#endif + + ASSERTLINE(372, PPCMfmsr() & MSR_FP); + + __gUnkThread1 = thread; + OSClearContext(&thread->context); + OSSetCurrentContext(&thread->context); + thread->stackBase = (u8*)&_stack_addr; + thread->stackEnd = (u32*)&_stack_end; + *(u32*)thread->stackEnd = OS_THREAD_STACK_MAGIC; + OSSetCurrentThread(thread); + OSClearStack(0); + RunQueueBits = 0; + RunQueueHint = 0; + + for (prio = 0; prio <= 31; prio++) { + OSInitThreadQueue(&RunQueue[prio]); + } + OSInitThreadQueue(&__OSActiveThreadQueue); + + ENQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + + OSClearContext(&IdleContext); + Reschedule = 0; +} + +void OSSetCurrentThread(OSThread* thread) { + SwitchThreadCallback(__OSCurrentThread, thread); + __OSCurrentThread = thread; +} + +#if DEBUG +static void OSInitMutexQueue(OSMutexQueue* queue) { + queue->head = queue->tail = 0; +} +#endif + +void OSInitThreadQueue(OSThreadQueue* queue) { + queue->head = queue->tail = 0; +} + +OSThread* OSGetCurrentThread() { + return __OSCurrentThread; +} + +static void __OSSwitchThread(OSThread* nextThread) { + OSSetCurrentThread(nextThread); + OSSetCurrentContext(&nextThread->context); + OSLoadContext(&nextThread->context); +} + +BOOL OSIsThreadSuspended(OSThread* thread) { + if (thread->suspend > 0) { + return TRUE; + } + return FALSE; +} + +BOOL OSIsThreadTerminated(OSThread* thread) { + return (thread->state == OS_THREAD_STATE_MORIBUND || thread->state == 0) ? TRUE : FALSE; +} + +static BOOL __OSIsThreadActive(OSThread* thread) { + OSThread* active; + + if (thread->state == 0) { + return FALSE; + } + + for (active = __OSActiveThreadQueue.head; active; active = active->linkActive.next) { + if (thread == active) { + return TRUE; + } + } + return FALSE; +} + +s32 OSDisableScheduler(void) { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = Reschedule++; + OSRestoreInterrupts(enabled); + return count; +} + +s32 OSEnableScheduler(void) { + BOOL enabled; + s32 count; + + enabled = OSDisableInterrupts(); + count = Reschedule--; + OSRestoreInterrupts(enabled); + return count; +} + +static void SetRun(OSThread* thread) { + ASSERTLINE(569, !IsSuspended(thread->suspend)); + ASSERTLINE(570, thread->state == OS_THREAD_STATE_READY); + + ASSERTLINE(572, OS_PRIORITY_MIN <= thread->priority && thread->priority <= OS_PRIORITY_MAX); + + thread->queue = &RunQueue[thread->priority]; + + ENQUEUE_THREAD(thread, thread->queue, link); + + RunQueueBits |= 1 << (OS_PRIORITY_MAX - thread->priority); + RunQueueHint = 1; +} + +static void UnsetRun(OSThread* thread) { + OSThreadQueue* queue; + + ASSERTLINE(593, thread->state == OS_THREAD_STATE_READY); + + ASSERTLINE(595, OS_PRIORITY_MIN <= thread->priority && thread->priority <= OS_PRIORITY_MAX); + ASSERTLINE(596, thread->queue == &RunQueue[thread->priority]); + + queue = thread->queue; + + DEQUEUE_THREAD(thread, queue, link); + + if (!queue->head) { + RunQueueBits &= ~(1 << (OS_PRIORITY_MAX - thread->priority)); + } + thread->queue = NULL; +} + +s32 __OSGetEffectivePriority(OSThread* thread) { + s32 priority = thread->base; + OSMutex* mutex; + OSThread* blocked; + + for (mutex = thread->queueMutex.head; mutex; mutex = mutex->link.next) { + blocked = mutex->queue.head; + if (blocked && blocked->priority < priority) { + priority = blocked->priority; + } + } + return priority; +} + +static OSThread* SetEffectivePriority(OSThread* thread, s32 priority) { + ASSERTLINE(647, !IsSuspended(thread->suspend)); + + switch(thread->state) { + case OS_THREAD_STATE_READY: + UnsetRun(thread); + thread->priority = priority; + SetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + DEQUEUE_THREAD(thread, thread->queue, link); + thread->priority = priority; + + ENQUEUE_THREAD_PRIO(thread, thread->queue, link); + + if (thread->mutex) { + ASSERTLINE(662, thread->mutex->thread); + return thread->mutex->thread; + } + break; + case OS_THREAD_STATE_RUNNING: + RunQueueHint = 1; + thread->priority = priority; + break; + } + return 0; +} + +static void UpdatePriority(OSThread* thread) { + s32 priority; + + while (1) { + if(thread->suspend > 0) { + break; + } + priority = __OSGetEffectivePriority(thread); + if (thread->priority == priority) { + break; + } + thread = SetEffectivePriority(thread, priority); + if (thread == 0) { + break; + } + } +} + +void __OSPromoteThread(OSThread* thread, s32 priority) { + while (1) { + if (thread->suspend > 0 || thread->priority <= priority) { + break; + } + thread = SetEffectivePriority(thread, priority); + if (thread == 0) { + break; + } + } +} + +static OSThread* SelectThread(int yield) { + OSContext* currentContext; + OSThread* currentThread; + OSThread* nextThread; + OSPriority priority; + OSThreadQueue* queue; + + if (Reschedule > 0) { + return NULL; + } + + currentContext = OSGetCurrentContext(); + currentThread = OSGetCurrentThread(); + + if (currentContext != ¤tThread->context) { + return NULL; + } + + if (currentThread) { + if (currentThread->state == 2) { + if (yield == 0) { + priority = __cntlzw(RunQueueBits); + if (currentThread->priority <= priority) + return NULL; + } + currentThread->state = OS_THREAD_STATE_READY; + SetRun(currentThread); + } + if (!(currentThread->context.state & 2) && (OSSaveContext(¤tThread->context) != 0)) { + return NULL; + } + } + + if (RunQueueBits == 0) { + OSSetCurrentThread(NULL); + OSSetCurrentContext(&IdleContext); + do { + OSEnableInterrupts(); + while (RunQueueBits == 0) ; + OSDisableInterrupts(); + } while (RunQueueBits == 0); + OSClearContext(&IdleContext); + } + + RunQueueHint = 0; + priority = __cntlzw(RunQueueBits); + + ASSERTLINE(823, OS_PRIORITY_MIN <= priority && priority <= OS_PRIORITY_MAX); + + queue = &RunQueue[priority]; + nextThread = queue->head; + + DEQUEUE_HEAD(nextThread, queue, link); + + ASSERTLINE(826, nextThread->priority == priority); + + if (!queue->head) { + RunQueueBits &= ~(1 << (OS_PRIORITY_MAX - priority)); + } + nextThread->queue = 0; + nextThread->state = OS_THREAD_STATE_RUNNING; + __OSSwitchThread(nextThread); + return nextThread; +} + +void __OSReschedule(void) { + if (RunQueueHint != 0) { + SelectThread(0); + } +} + +void OSYieldThread(void) { + BOOL enabled = OSDisableInterrupts(); + + SelectThread(1); + OSRestoreInterrupts(enabled); +} + +int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param, void* stack, u32 stackSize, OSPriority priority, u16 attr) { + BOOL enabled; + u32 sp; + int i; + + ASSERTMSGLINE(910, ((priority >= OS_PRIORITY_MIN) && (priority <= OS_PRIORITY_MAX)), "OSCreateThread(): priority out of range (0 <= priority <= 31)."); + + // why check this for an assert just to check it again right after? + if ((priority < OS_PRIORITY_MIN) || (priority > OS_PRIORITY_MAX)) { + return 0; + } + + thread->state = OS_THREAD_STATE_READY; + thread->attr = attr & 1U; + thread->base = priority; + thread->priority = priority; + thread->suspend = 1; + thread->val = (void*)-1; + thread->mutex = 0; + OSInitThreadQueue(&thread->queueJoin); +#ifdef DEBUG + OSInitMutexQueue(&thread->queueMutex); +#else + OSInitThreadQueue((void*)&thread->queueMutex); // why +#endif + sp = (u32)stack; + sp &= ~7; + sp -= 8; + ((u32*)sp)[0] = 0; + ((u32*)sp)[1] = 0; + OSInitContext(&thread->context, (u32)func, sp); + thread->context.lr = (u32)&OSExitThread; + thread->context.gpr[3] = (u32)param; + thread->stackBase = stack; + thread->stackEnd = (void*)((unsigned int)stack - stackSize); + *thread->stackEnd = OS_THREAD_STACK_MAGIC; + thread->error = 0; + for (i = 0; i < 2; i++) { + thread->specific[i] = NULL; + } + enabled = OSDisableInterrupts(); + + if (__OSErrorTable[16] != NULL) { + thread->context.srr1 |= 0x900; + thread->context.state |= 1; + thread->context.fpscr = (__OSFpscrEnableBits & 0xf8) | 4; + for (i = 0; i < 32; ++i) { + *(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL; + *(u64*)&thread->context.psf[i] = (u64)0xffffffffffffffffLL; + } + } + + ASSERTMSG1LINE(964, __OSIsThreadActive(thread) == 0L, "OSCreateThread(): thread %p is still active.", thread); + + ENQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + + OSRestoreInterrupts(enabled); + return 1; +} + +void OSExitThread(void* val) { + BOOL enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(989, currentThread, + "OSExitThread(): current thread does not exist."); + ASSERTMSGLINE(991, currentThread->state == OS_THREAD_STATE_RUNNING, + "OSExitThread(): current thread is not running."); + ASSERTMSGLINE(993, __OSIsThreadActive(currentThread) != 0, + "OSExitThread(): current thread is not active."); + + OSClearContext(¤tThread->context); + if (currentThread->attr & 1) { + DEQUEUE_THREAD(currentThread, &__OSActiveThreadQueue, linkActive); + currentThread->state = 0; + } else { + currentThread->state = 8; + currentThread->val = val; + } + __OSUnlockAllMutex(currentThread); + OSWakeupThread(¤tThread->queueJoin); + RunQueueHint = 1; +#ifdef DEBUG + __OSReschedule(); +#else + if (RunQueueHint != 0) { + SelectThread(0); + } +#endif + OSRestoreInterrupts(enabled); +} + +void OSCancelThread(OSThread* thread) { + BOOL enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(1031, __OSIsThreadActive(thread) != 0, + "OSExitThread(): thread %p is not active.", thread); + + __OSCancelInternalAlarms(thread); + + switch(thread->state) { + case OS_THREAD_STATE_READY: + if (thread->suspend <= 0) { + UnsetRun(thread); + } + break; + case OS_THREAD_STATE_RUNNING: + RunQueueHint = 1; + break; + case OS_THREAD_STATE_WAITING: + DEQUEUE_THREAD(thread, thread->queue, link); + thread->queue = 0; + if ((thread->suspend <= 0) && (thread->mutex)) { + ASSERTLINE(1053, thread->mutex->thread); + UpdatePriority(thread->mutex->thread); + } + break; + default: + OSRestoreInterrupts(enabled); + return; + } + OSClearContext(&thread->context); + if (thread->attr & 1) { + DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + thread->state = 0; + } else { + thread->state = 8; + } + __OSUnlockAllMutex(thread); + OSWakeupThread(&thread->queueJoin); + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +int OSJoinThread(OSThread* thread, void* val) { + BOOL enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(LINE(1061, 1092, 1092), __OSIsThreadActive(thread) != 0, "OSJoinThread(): thread %p is not active.", thread); + + if (!(thread->attr & 1) && (thread->state != OS_THREAD_STATE_MORIBUND) && (thread->queueJoin.head == NULL)) { + OSSleepThread(&thread->queueJoin); + if (__OSIsThreadActive(thread) == 0) { + OSRestoreInterrupts(enabled); + return 0; + } + } + if (thread->state == OS_THREAD_STATE_MORIBUND) { + if (val) { + *(s32*)val = (s32)thread->val; + } + DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + thread->state = 0; + OSRestoreInterrupts(enabled); + return 1; + } + OSRestoreInterrupts(enabled); + return 0; +} + +void OSDetachThread(OSThread* thread) { + BOOL enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(1160, __OSIsThreadActive(thread) != 0, "OSDetachThread(): thread %p is not active.", thread); + + thread->attr |= 1; + if (thread->state == OS_THREAD_STATE_MORIBUND) { + DEQUEUE_THREAD(thread, &__OSActiveThreadQueue, linkActive); + thread->state = 0; + } + OSWakeupThread(&thread->queueJoin); + OSRestoreInterrupts(enabled); +} + +s32 OSResumeThread(OSThread* thread) { + BOOL enabled = OSDisableInterrupts(); + s32 suspendCount; + + ASSERTMSG1LINE(1189, __OSIsThreadActive(thread) != 0, "OSResumeThread(): thread %p is not active.", thread); + ASSERTMSG1LINE(1191, thread->state != OS_THREAD_STATE_MORIBUND, "OSResumeThread(): thread %p is terminated.", thread); + + suspendCount = thread->suspend--; + if (thread->suspend < 0) { + thread->suspend = 0; + } else if (thread->suspend == 0) { + switch(thread->state) { + case OS_THREAD_STATE_READY: + thread->priority = __OSGetEffectivePriority(thread); + SetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + ASSERTLINE(1206, thread->queue); + DEQUEUE_THREAD(thread, thread->queue, link); + thread->priority = __OSGetEffectivePriority(thread); + ENQUEUE_THREAD_PRIO(thread, thread->queue, link); + if (thread->mutex) { + UpdatePriority(thread->mutex->thread); + } + } + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} + +s32 OSSuspendThread(OSThread* thread) { + BOOL enabled = OSDisableInterrupts(); + s32 suspendCount; + + ASSERTMSG1LINE(1240, __OSIsThreadActive(thread) != 0, "OSSuspendThread(): thread %p is not active.", thread); + ASSERTMSG1LINE(1242, thread->state != OS_THREAD_STATE_MORIBUND, "OSSuspendThread(): thread %p is terminated.", thread); + + suspendCount = thread->suspend++; + if (suspendCount == 0) { + switch(thread->state) { + case OS_THREAD_STATE_RUNNING: + RunQueueHint = 1; + thread->state = 1; + break; + case OS_THREAD_STATE_READY: + UnsetRun(thread); + break; + case OS_THREAD_STATE_WAITING: + DEQUEUE_THREAD(thread, thread->queue, link); + thread->priority = 0x20; + ENQUEUE_THREAD(thread, thread->queue, link); + if (thread->mutex) { + ASSERTLINE(1263, thread->mutex->thread); + UpdatePriority(thread->mutex->thread); + } + break; + } + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return suspendCount; +} + +void OSSleepThread(OSThreadQueue* queue) { + BOOL enabled = OSDisableInterrupts(); + OSThread* currentThread = OSGetCurrentThread(); + + ASSERTMSGLINE(1296, currentThread, "OSSleepThread(): current thread does not exist."); + ASSERTMSG1LINE(1298, __OSIsThreadActive(currentThread) != 0, "OSSleepThread(): current thread %p is not active.", currentThread); + ASSERTMSG1LINE(1300, currentThread->state == OS_THREAD_STATE_RUNNING, "OSSleepThread(): current thread %p is not running.", currentThread); + ASSERTMSG1LINE(1302, !(currentThread->suspend > 0), "OSSleepThread(): current thread %p is suspended.", currentThread); + + currentThread->state = OS_THREAD_STATE_WAITING; + currentThread->queue = queue; + ENQUEUE_THREAD_PRIO(currentThread, queue, link); + RunQueueHint = 1; + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +void OSWakeupThread(OSThreadQueue* queue) { + BOOL enabled = OSDisableInterrupts(); + + while (queue->head) { + OSThread* thread = queue->head; + + DEQUEUE_HEAD(thread, queue, link); + + ASSERTLINE(1331, __OSIsThreadActive(thread)); + ASSERTLINE(1332, thread->state != OS_THREAD_STATE_MORIBUND); + ASSERTLINE(1333, thread->queue == queue); + thread->state = OS_THREAD_STATE_READY; + if (thread->suspend <= 0) { + SetRun(thread); + } + } + __OSReschedule(); + OSRestoreInterrupts(enabled); +} + +int OSSetThreadPriority(OSThread* thread, s32 priority) { + BOOL enabled; + + ASSERTMSGLINE(1359, (priority >= OS_PRIORITY_MIN) && (priority <= OS_PRIORITY_MAX), "OSSetThreadPriority(): priority out of range (0 <= priority <= 31)."); + + if ((priority < OS_PRIORITY_MIN) || (priority > OS_PRIORITY_MAX)) { + return 0; + } + enabled = OSDisableInterrupts(); + + ASSERTMSG1LINE(1366, __OSIsThreadActive(thread) != 0, "OSSetThreadPriority(): thread %p is not active.", thread); + ASSERTMSG1LINE(1368, thread->state != 8, "OSSetThreadPriority(): thread %p is terminated.", thread); + + if (thread->base != priority) { + thread->base = priority; + UpdatePriority(thread); + __OSReschedule(); + } + OSRestoreInterrupts(enabled); + return 1; +} + +s32 OSGetThreadPriority(OSThread* thread) { + return thread->base; +} + +OSThread* OSSetIdleFunction(OSIdleFunction idleFunction, void* param, void* stack, u32 stackSize) { + if (idleFunction) { + if (IdleThread.state == 0) { + OSCreateThread(&IdleThread, (void*)idleFunction, param, stack, stackSize, OS_PRIORITY_MAX, 1); + OSResumeThread(&IdleThread); + return &IdleThread; + } + } else if (IdleThread.state != 0) { + OSCancelThread(&IdleThread); + } + return NULL; +} + +OSThread* OSGetIdleFunction(void) { + if (IdleThread.state != 0) { + return &IdleThread; + } + return NULL; +} + +static int CheckThreadQueue(OSThreadQueue* queue) { + OSThread* thread; + + if ((queue->head != NULL) && (queue->head->link.prev != NULL)) { + return 0; + } + if ((queue->tail != NULL) && (queue->tail->link.next != NULL)) { + return 0; + } + thread = queue->head; + while (thread) { + if ((thread->link.next != NULL) && (thread != thread->link.next->link.prev)) { + return 0; + } + if ((thread->link.prev != NULL) && (thread != thread->link.prev->link.next)) { + return 0; + } + thread = thread->link.next; + } + return 1; +} + +static BOOL IsMember(OSThreadQueue* queue, OSThread* thread) { + OSThread* member = queue->head; + + while (member) { + if (thread == member) { + return TRUE; + } + member = member->link.next; + } + return FALSE; +} + +// custom macro for OSCheckActiveThreads? +#define ASSERTREPORT(line, cond) \ + if (!(cond)) { \ + OSReport("OSCheckActiveThreads: Failed " #cond " in %d\n", line); \ + OSPanic(__FILE__, line, ""); \ + } + +s32 OSCheckActiveThreads(void) { + OSThread* thread; + s32 prio; + s32 cThread; + BOOL enabled; + + cThread = 0; + enabled = OSDisableInterrupts(); + + for (prio = 0; prio <= OS_PRIORITY_MAX; prio++) { + if (RunQueueBits & (1 << (OS_PRIORITY_MAX - prio))) { + ASSERTREPORT(1522, RunQueue[prio].head != NULL && RunQueue[prio].tail != NULL); + } else { + ASSERTREPORT(1527, RunQueue[prio].head == NULL && RunQueue[prio].tail == NULL); + } + ASSERTREPORT(1529, CheckThreadQueue(&RunQueue[prio])); + } + + ASSERTREPORT(1534, __OSActiveThreadQueue.head == NULL || __OSActiveThreadQueue.head->linkActive.prev == NULL); + ASSERTREPORT(1536, __OSActiveThreadQueue.tail == NULL || __OSActiveThreadQueue.tail->linkActive.next == NULL); + + thread = __OSActiveThreadQueue.head; + while (thread) { + cThread++; + ASSERTREPORT(1544, thread->linkActive.next == NULL || thread == thread->linkActive.next->linkActive.prev); + ASSERTREPORT(1546, thread->linkActive.prev == NULL || thread == thread->linkActive.prev->linkActive.next); + ASSERTREPORT(1549, *(thread->stackEnd) == OS_THREAD_STACK_MAGIC); + ASSERTREPORT(1552, OS_PRIORITY_MIN <= thread->priority && thread->priority <= OS_PRIORITY_MAX+1); + ASSERTREPORT(1553, 0 <= thread->suspend); + ASSERTREPORT(1554, CheckThreadQueue(&thread->queueJoin)); + + switch(thread->state) { + case OS_THREAD_STATE_READY: + if (thread->suspend <= 0) { + ASSERTREPORT(1560, thread->queue == &RunQueue[thread->priority]); + ASSERTREPORT(1561, IsMember(&RunQueue[thread->priority], thread)); + ASSERTREPORT(1562, thread->priority == __OSGetEffectivePriority(thread)); + } + break; + case OS_THREAD_STATE_RUNNING: + ASSERTREPORT(1566, !IsSuspended(thread->suspend)); + ASSERTREPORT(1567, thread->queue == NULL); + ASSERTREPORT(1568, thread->priority == __OSGetEffectivePriority(thread)); + break; + case OS_THREAD_STATE_WAITING: + ASSERTREPORT(1571, thread->queue != NULL); + ASSERTREPORT(1572, CheckThreadQueue(thread->queue)); + ASSERTREPORT(1573, IsMember(thread->queue, thread)); + if (thread->suspend <= 0) { + ASSERTREPORT(1576, thread->priority == __OSGetEffectivePriority(thread)); + } else { + ASSERTREPORT(1580, thread->priority == 32); + } + ASSERTREPORT(1582, !__OSCheckDeadLock(thread)); + break; + case OS_THREAD_STATE_MORIBUND: + ASSERTREPORT(1586, thread->queueMutex.head == NULL && thread->queueMutex.tail == NULL); + break; + default: + OSReport("OSCheckActiveThreads: Failed. unkown thread state (%d) of thread %p\n", thread->state, thread); + OSPanic(__FILE__, 1592, ""); + } + ASSERTREPORT(1597, __OSCheckMutexes(thread)); + thread = thread->linkActive.next; + } + OSRestoreInterrupts(enabled); + return cThread; +} + +void OSClearStack(u8 val) { + register u32 sp; + register u32* p; + register u32 pattern; + + pattern = (val << 24) | (val << 16) | (val << 8) | val; + sp = OSGetStackPointer(); + for (p = __OSCurrentThread->stackEnd + 1; (u32)p < sp; ++p) { + *p = pattern; + } +} + +void OSSetThreadSpecific(s32 index, void* ptr) { + OSThread* thread; + + thread = __OSCurrentThread; + ASSERTLINE(LINE(1573, 1604, 1604), 0 <= index && index < OS_THREAD_SPECIFIC_MAX); + + if (thread != 0 && index >= 0 && index < OS_THREAD_SPECIFIC_MAX) { + thread->specific[index] = ptr; + } +} + +void* OSGetThreadSpecific(s32 index) { + OSThread* thread; + + thread = __OSCurrentThread; + ASSERTLINE(LINE(1584, 1615, 1615), 0 <= index && index < OS_THREAD_SPECIFIC_MAX); + + if (thread != 0 && index >= 0 && index < OS_THREAD_SPECIFIC_MAX) { + return thread->specific[index]; + } + + return NULL; +} + +/* 804516D0-804516D8 000BD0 0008+00 0/0 2/1 0/0 .sbss None */ +#include "global.h" +extern u8 Debug_BBA_804516D0; +u8 Debug_BBA_804516D0 ALIGN_DECL(8); diff --git a/src/revolution/os/OSTime.c b/src/revolution/os/OSTime.c new file mode 100644 index 0000000000..2688a17c5c --- /dev/null +++ b/src/revolution/os/OSTime.c @@ -0,0 +1,201 @@ +#include +#include +#include + +#include "__os.h" + +// End of each month in standard year +static int YearDays[MONTH_MAX] = {0, 31, 59, 90, 120, 151, + 181, 212, 243, 273, 304, 334}; +// End of each month in leap year +static int LeapYearDays[MONTH_MAX] = {0, 31, 60, 91, 121, 152, + 182, 213, 244, 274, 305, 335}; + +#ifdef __GEKKO__ +asm OSTime OSGetTime(void) { +jump: + nofralloc + + mftbu r3 + mftb r4 + + // Check for possible carry from TBL to TBU + mftbu r5 + cmpw r3, r5 + bne jump + + blr +} + +asm OSTick OSGetTick(void){ + nofralloc + + mftb r3 + blr +} + +asm static void __SetTime(OSTime time) { + nofralloc + li r5, 0 + mttbl r5 + mttbu r3 + mttbl r4 + blr +} +#endif + +void __OSSetTime(OSTime time) { + BOOL enabled; + OSTime * timeAdjustAddr; + + timeAdjustAddr = __OSSystemTime; + enabled = OSDisableInterrupts(); + + *timeAdjustAddr += OSGetTime() - time; + __SetTime(time); + EXIProbeReset(); + OSRestoreInterrupts(enabled); +} + +OSTime __OSGetSystemTime() { + BOOL enabled; + OSTime* timeAdjustAddr; + OSTime result; + + timeAdjustAddr = __OSSystemTime; + enabled = OSDisableInterrupts(); + + result = OSGetTime() + *timeAdjustAddr; + OSRestoreInterrupts(enabled); + return result; +} + +OSTime __OSTimeToSystemTime(OSTime time) { + BOOL enabled; + OSTime* timeAdjustAddr = __OSSystemTime; + OSTime result; + + enabled = OSDisableInterrupts(); + result = *timeAdjustAddr + time; + OSRestoreInterrupts(enabled); + return result; +} + +#ifdef __GEKKO__ +asm void __OSSetTick(register OSTick newTicks) { + nofralloc + mttbl newTicks + blr +} +#endif + +static int IsLeapYear(int year) { + return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); +} + +static int GetYearDays(int year, int mon) { + int* md = (IsLeapYear(year)) ? LeapYearDays : YearDays; + + return md[mon]; +} + +static int GetLeapDays(int year) { + ASSERTLINE(292, 0 <= year); + + if (year < 1) { + return 0; + } + return (year + 3) / 4 - (year - 1) / 100 + (year - 1) / 400; +} + +static void GetDates(int days, OSCalendarTime* td) { + int year; + int n; + int month; + int * md; + + ASSERTLINE(317, 0 <= days); + + td->wday = (days + 6) % WEEK_DAY_MAX; + + for (year = days / YEAR_DAY_MAX; + days < (n = year * YEAR_DAY_MAX + GetLeapDays(year)); year--) { + ; + } + + days -= n; + td->year = year; + td->yday = days; + + md = IsLeapYear(year) ? LeapYearDays : YearDays; + for (month = MONTH_MAX; days < md[--month];) { + ; + } + td->mon = month; + td->mday = days - md[month] + 1; +} + +void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* td) { + int days; + int secs; + OSTime d; + + d = ticks % OS_SEC_TO_TICKS(1); + if (d < 0) { + d += OS_SEC_TO_TICKS(1); + ASSERTLINE(362, 0 <= d); + } + + td->usec = OS_TICKS_TO_USEC(d) % USEC_MAX; + td->msec = OS_TICKS_TO_MSEC(d) % MSEC_MAX; + + ASSERTLINE(366, 0 <= td->usec); + ASSERTLINE(367, 0 <= td->msec); + + ticks -= d; + + ASSERTLINE(370, ticks % OSSecondsToTicks(1) == 0); + ASSERTLINE(374, 0 <= OSTicksToSeconds(ticks) / 86400 + BIAS && OSTicksToSeconds(ticks) / 86400 + BIAS <= INT_MAX); + + days = (OS_TICKS_TO_SEC(ticks) / SECS_IN_DAY) + BIAS; + secs = OS_TICKS_TO_SEC(ticks) % SECS_IN_DAY; + if (secs < 0) { + days -= 1; + secs += SECS_IN_DAY; + ASSERTLINE(381, 0 <= secs); + } + + GetDates(days, td); + td->hour = secs / 60 / 60; + td->min = secs / 60 % 60; + td->sec = secs % 60; +} + +OSTime OSCalendarTimeToTicks(OSCalendarTime* td) { + OSTime secs; + int ov_mon; + int mon; + int year; + + ov_mon = td->mon / MONTH_MAX; + mon = td->mon - (ov_mon * MONTH_MAX); + + if (mon < 0) { + mon += MONTH_MAX; + ov_mon--; + } + + ASSERTLINE(412, (ov_mon <= 0 && 0 <= td->year + ov_mon) || (0 < ov_mon && td->year <= INT_MAX - ov_mon)); + + year = td->year + ov_mon; + + secs = (OSTime)SECS_IN_YEAR * year + + (OSTime)SECS_IN_DAY * (GetLeapDays(year) + GetYearDays(year, mon) + td->mday - 1) + + (OSTime)SECS_IN_HOUR * td->hour + + (OSTime)SECS_IN_MIN * td->min + + td->sec - + (OSTime)0xEB1E1BF80ULL; + + return OS_SEC_TO_TICKS(secs) + OS_MSEC_TO_TICKS((OSTime)td->msec) + + OS_USEC_TO_TICKS((OSTime)td->usec); +} diff --git a/src/revolution/os/OSUtf.c b/src/revolution/os/OSUtf.c new file mode 100644 index 0000000000..a4013d9d5f --- /dev/null +++ b/src/revolution/os/OSUtf.c @@ -0,0 +1,6374 @@ +#include +#include + +char* OSUTF8to32(const char* utf8, u32* utf32) { + u32 u = 0; + u8 c; + unsigned int len; + unsigned int i; + + c = *utf8; + if (c != 0) { + utf8++; + } + + if ((c & 0x80) == 0) { + u = c; + len = 0; + } else if ((c & 0xE0) == 0xC0u) { + u = c & 0x1F; + len = 1; + } else if ((c & 0xF0) == 0xE0u) { + u = c & 0xF; + len = 2; + } else if ((c & 0xF8) == 0xF0u) { + u = c & 0x7; + len = 3; + } else { + return NULL; + } + + for (i = 0; i < len; i++) { + u = u << 6; + c = *utf8++; + if ((c & 0xC0) != 0x80u) { + return NULL; + } + + u |= (c & 0x3F); + } + + if (u <= 0x7Fu) { + if (len != 0) { + return NULL; + } + } else if (u <= 0x7FFu) { + if (len != 1) { + return NULL; + } + } else if (u <= 0xFFFFu) { + if (len != 2) { + return NULL; + } + } + + if (u >= 0xD800u && u <= 0xDFFFu) { + return NULL; + } + + *utf32 = u; + return (char*)utf8; +} + +char* OSUTF32to8(u32 utf32, char* utf8) { + int len; + + if (utf32 >= 0xD800u && utf32 <= 0xDFFFu) { + return NULL; + } + + if (utf32 < 0x80u) { + *utf8 = (s8)utf32; + utf8++; + } else if (utf32 < 0x800u) { + *utf8 = (utf32 >> 6) | 0xC0; + utf8++; + len = 1; + } else if (utf32 < 0x10000u) { + *utf8 = (utf32 >> 0xC) | 0xE0; + utf8++; + len = 2; + } else if (utf32 < 0x110000u) { + *utf8 = (utf32 >> 0x12) | 0xF0; + utf8++; + len = 3; + } else { + return NULL; + } + + while (len-- > 0) { + *utf8 = ((utf32 >> (len * 6)) & 0x3F) | 0x80; + utf8++; + } + + return utf8; +} + +u16* OSUTF16to32(const u16* utf16, u32* utf32) { + u16 w1; + u16 w2; + u32 u = 0; + + w1 = *utf16; + if (w1 != 0) { + utf16++; + } + + if (w1 < 0xD800 || w1 > 0xDFFF) { + u = w1; + } else if (w1 <= 0xDBFF) { + w2 = *utf16++; + + if (w2 >= 0xDC00 && w2 <= 0xDFFF) { + u = ((w1 & 0x03FF) << 10) | (w2 & 0x03FF); + u += 0x10000; + } else { + return NULL; + } + } else { + return NULL; + } + + *utf32 = u; + return (u16*)utf16; +} + +u16* OSUTF32to16(u32 utf32, u16* utf16) { + u16 w1; + u16 w2; + + if (utf32 >= 0xD800u && utf32 <= 0xDFFFu) { + return NULL; + } + + if (utf32 < 0x10000u) { + *utf16 = utf32; + utf16++; + } else if (utf32 <= 0x10FFFFu) { + w1 = -0x122800; + w2 = -0x122400; + utf32 -= 0x10000; + ASSERTLINE(0xD1, utf32 <= 0xFFFFF); + + w1 |= utf32 >> 10; + w2 |= utf32 & 0x3FF; + + *utf16++ = w1; + *utf16++ = w2; + } else { + return NULL; + } + + return utf16; +} + +static u16 UcsAnsiTable[32] = { + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, + 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, + 0x0152, 0x0000, 0x017D, 0x0000, 0x0000, 0x2018, + 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, + 0x017E, 0x0178, +}; + +u8 OSUTF32toANSI(u32 utf32) { + int i; + + if (utf32 > 0xFF) { + return 0; + } + + if (utf32 < 0x80 || utf32 > 0x9F) { + return utf32; + } + + if (utf32 >= 0x152 && utf32 <= 0x2122) { + for (i = 0; i <= 31; i++) { + if (utf32 == UcsAnsiTable[i]) { + return i + 0x80; + } + } + } + + return 0; +} + +u32 OSANSItoUTF32(u8 ansi) { + if (ansi >= 0x80 && ansi <= 0x9F) { + return UcsAnsiTable[ansi - 0x80]; + } + + return ansi; +} + +static u16 Ucs00[] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, + 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, + 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, + 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, + 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, + 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, + 0x005A, 0x005B, 0x815F, 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, + 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, + 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, + 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8191, 0x8192, 0x0000, 0x005C, 0x0000, 0x8198, + 0x814E, 0x0000, 0x0000, 0x0000, 0x81CA, 0x0000, + 0x0000, 0x0000, 0x818B, 0x817D, 0x0000, 0x0000, + 0x814C, 0x0000, 0x81F7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x817E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8180, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs03[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x839F, 0x83A0, 0x83A1, 0x83A2, 0x83A3, + 0x83A4, 0x83A5, 0x83A6, 0x83A7, 0x83A8, 0x83A9, + 0x83AA, 0x83AB, 0x83AC, 0x83AD, 0x83AE, 0x83AF, + 0x0000, 0x83B0, 0x83B1, 0x83B2, 0x83B3, 0x83B4, + 0x83B5, 0x83B6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x83BF, 0x83C0, 0x83C1, + 0x83C2, 0x83C3, 0x83C4, 0x83C5, 0x83C6, 0x83C7, + 0x83C8, 0x83C9, 0x83CA, 0x83CB, 0x83CC, 0x83CD, + 0x83CE, 0x83CF, 0x0000, 0x83D0, 0x83D1, 0x83D2, + 0x83D3, 0x83D4, 0x83D5, 0x83D6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs04[256] = { + 0x0000, 0x8446, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8440, 0x8441, + 0x8442, 0x8443, 0x8444, 0x8445, 0x8447, 0x8448, + 0x8449, 0x844A, 0x844B, 0x844C, 0x844D, 0x844E, + 0x844F, 0x8450, 0x8451, 0x8452, 0x8453, 0x8454, + 0x8455, 0x8456, 0x8457, 0x8458, 0x8459, 0x845A, + 0x845B, 0x845C, 0x845D, 0x845E, 0x845F, 0x8460, + 0x8470, 0x8471, 0x8472, 0x8473, 0x8474, 0x8475, + 0x8477, 0x8478, 0x8479, 0x847A, 0x847B, 0x847C, + 0x847D, 0x847E, 0x8480, 0x8481, 0x8482, 0x8483, + 0x8484, 0x8485, 0x8486, 0x8487, 0x8488, 0x8489, + 0x848A, 0x848B, 0x848C, 0x848D, 0x848E, 0x848F, + 0x8490, 0x8491, 0x0000, 0x8476, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs20[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x815D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x815C, 0x8161, 0x0000, + 0x8165, 0x8166, 0x0000, 0x0000, 0x8167, 0x8168, + 0x0000, 0x0000, 0x81F5, 0x81F6, 0x0000, 0x0000, + 0x0000, 0x8164, 0x8163, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x81F1, 0x0000, 0x818C, 0x818D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x81A6, + 0x0000, 0x0000, 0x007E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs21[256] = { + 0x0000, 0x0000, 0x0000, 0x818E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x81F0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x81A9, 0x81AA, 0x81A8, 0x81AB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x81CB, 0x0000, 0x81CC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs22[256] = { + 0x81CD, 0x0000, 0x81DD, 0x81CE, 0x0000, 0x0000, + 0x0000, 0x81DE, 0x81B8, 0x0000, 0x0000, 0x81B9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x817C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x81E3, 0x0000, 0x0000, 0x81E5, + 0x8187, 0x0000, 0x81DA, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x81C8, 0x81C9, 0x81BF, + 0x81BE, 0x81E7, 0x81E8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8188, 0x81E6, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x81E4, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x81E0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8182, 0x81DF, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8185, 0x8186, 0x0000, 0x0000, 0x81E1, 0x81E2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x81BC, 0x81BD, + 0x0000, 0x0000, 0x81BA, 0x81BB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x81DB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs23[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x81DC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs25[256] = { + 0x849F, 0x84AA, 0x84A0, 0x84AB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x84A1, 0x0000, 0x0000, 0x84AC, 0x84A2, 0x0000, + 0x0000, 0x84AD, 0x84A4, 0x0000, 0x0000, 0x84AF, + 0x84A3, 0x0000, 0x0000, 0x84AE, 0x84A5, 0x84BA, + 0x0000, 0x0000, 0x84B5, 0x0000, 0x0000, 0x84B0, + 0x84A7, 0x84BC, 0x0000, 0x0000, 0x84B7, 0x0000, + 0x0000, 0x84B2, 0x84A6, 0x0000, 0x0000, 0x84B6, + 0x84BB, 0x0000, 0x0000, 0x84B1, 0x84A8, 0x0000, + 0x0000, 0x84B8, 0x84BD, 0x0000, 0x0000, 0x84B3, + 0x84A9, 0x0000, 0x0000, 0x84B9, 0x0000, 0x0000, + 0x84BE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x84B4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x81A1, 0x81A0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x81A3, 0x81A2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x81A5, 0x81A4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x819F, 0x819E, 0x0000, 0x0000, 0x0000, 0x819B, + 0x0000, 0x0000, 0x819D, 0x819C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x81FC, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs26[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x819A, + 0x8199, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x818A, 0x0000, + 0x8189, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x81F4, 0x0000, + 0x0000, 0x81F3, 0x0000, 0x81F2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs30[256] = { + 0x8140, 0x8141, 0x8142, 0x8156, 0x0000, 0x8158, + 0x8159, 0x815A, 0x8171, 0x8172, 0x8173, 0x8174, + 0x8175, 0x8176, 0x8177, 0x8178, 0x8179, 0x817A, + 0x81A7, 0x81AC, 0x816B, 0x816C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8160, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x829F, + 0x82A0, 0x82A1, 0x82A2, 0x82A3, 0x82A4, 0x82A5, + 0x82A6, 0x82A7, 0x82A8, 0x82A9, 0x82AA, 0x82AB, + 0x82AC, 0x82AD, 0x82AE, 0x82AF, 0x82B0, 0x82B1, + 0x82B2, 0x82B3, 0x82B4, 0x82B5, 0x82B6, 0x82B7, + 0x82B8, 0x82B9, 0x82BA, 0x82BB, 0x82BC, 0x82BD, + 0x82BE, 0x82BF, 0x82C0, 0x82C1, 0x82C2, 0x82C3, + 0x82C4, 0x82C5, 0x82C6, 0x82C7, 0x82C8, 0x82C9, + 0x82CA, 0x82CB, 0x82CC, 0x82CD, 0x82CE, 0x82CF, + 0x82D0, 0x82D1, 0x82D2, 0x82D3, 0x82D4, 0x82D5, + 0x82D6, 0x82D7, 0x82D8, 0x82D9, 0x82DA, 0x82DB, + 0x82DC, 0x82DD, 0x82DE, 0x82DF, 0x82E0, 0x82E1, + 0x82E2, 0x82E3, 0x82E4, 0x82E5, 0x82E6, 0x82E7, + 0x82E8, 0x82E9, 0x82EA, 0x82EB, 0x82EC, 0x82ED, + 0x82EE, 0x82EF, 0x82F0, 0x82F1, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x814A, + 0x814B, 0x8154, 0x8155, 0x0000, 0x0000, 0x8340, + 0x8341, 0x8342, 0x8343, 0x8344, 0x8345, 0x8346, + 0x8347, 0x8348, 0x8349, 0x834A, 0x834B, 0x834C, + 0x834D, 0x834E, 0x834F, 0x8350, 0x8351, 0x8352, + 0x8353, 0x8354, 0x8355, 0x8356, 0x8357, 0x8358, + 0x8359, 0x835A, 0x835B, 0x835C, 0x835D, 0x835E, + 0x835F, 0x8360, 0x8361, 0x8362, 0x8363, 0x8364, + 0x8365, 0x8366, 0x8367, 0x8368, 0x8369, 0x836A, + 0x836B, 0x836C, 0x836D, 0x836E, 0x836F, 0x8370, + 0x8371, 0x8372, 0x8373, 0x8374, 0x8375, 0x8376, + 0x8377, 0x8378, 0x8379, 0x837A, 0x837B, 0x837C, + 0x837D, 0x837E, 0x8380, 0x8381, 0x8382, 0x8383, + 0x8384, 0x8385, 0x8386, 0x8387, 0x8388, 0x8389, + 0x838A, 0x838B, 0x838C, 0x838D, 0x838E, 0x838F, + 0x8390, 0x8391, 0x8392, 0x8393, 0x8394, 0x8395, + 0x8396, 0x0000, 0x0000, 0x0000, 0x0000, 0x8145, + 0x815B, 0x8152, 0x8153, 0x0000 +}; + +static u16 Ucs4E[256] = { + 0x88EA, 0x929A, 0x0000, 0x8EB5, 0x0000, 0x0000, + 0x0000, 0x969C, 0x8FE4, 0x8E4F, 0x8FE3, 0x89BA, + 0x0000, 0x9573, 0x975E, 0x0000, 0x98A0, 0x894E, + 0x0000, 0x0000, 0x8A8E, 0x98A1, 0x90A2, 0x99C0, + 0x8B75, 0x95B8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8FE5, 0x0000, 0x0000, 0x97BC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x95C0, 0x0000, 0x0000, 0x0000, + 0x98A2, 0x0000, 0x0000, 0x9286, 0x0000, 0x0000, + 0x0000, 0x98A3, 0x8BF8, 0x0000, 0x0000, 0x0000, + 0x98A4, 0x0000, 0x8ADB, 0x924F, 0x0000, 0x8EE5, + 0x98A5, 0x0000, 0x0000, 0x98A6, 0x0000, 0x0000, + 0x98A7, 0x9454, 0x0000, 0x8B76, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9456, 0x0000, 0x93E1, + 0x8CC1, 0x9652, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE568, 0x98A8, 0x8FE6, 0x98A9, 0x89B3, + 0x0000, 0x0000, 0x0000, 0x8BE3, 0x8CEE, 0x96E7, + 0x0000, 0x0000, 0x9BA4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9790, + 0x0000, 0x93FB, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8AA3, 0x0000, 0x8B54, 0x0000, 0x98AA, 0x0000, + 0x0000, 0x98AB, 0x97B9, 0x0000, 0x975C, 0x9188, + 0x98AD, 0x8E96, 0x93F1, 0x0000, 0x98B0, 0x0000, + 0x0000, 0x895D, 0x8CDD, 0x0000, 0x8CDC, 0x88E4, + 0x0000, 0x0000, 0x986A, 0x9869, 0x0000, 0x8DB1, + 0x889F, 0x0000, 0x98B1, 0x98B2, 0x98B3, 0x9653, + 0x98B4, 0x0000, 0x8CF0, 0x88E5, 0x9692, 0x0000, + 0x8B9C, 0x0000, 0x0000, 0x8B9D, 0x8B9E, 0x92E0, + 0x97BA, 0x0000, 0x98B5, 0x0000, 0x0000, 0x98B6, + 0x0000, 0x0000, 0x98B7, 0x0000, 0x0000, 0x0000, + 0x906C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F59, 0x906D, 0x98BC, 0x0000, 0x98BA, 0x0000, + 0x98BB, 0x8B77, 0x0000, 0x0000, 0x8DA1, 0x89EE, + 0x0000, 0x98B9, 0x98B8, 0x95A7, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8E65, 0x8E64, 0x91BC, 0x98BD, + 0x9574, 0x90E5, 0x0000, 0x0000, 0x0000, 0x8157, + 0x98BE, 0x98C0, 0x0000, 0x0000, 0x0000, 0x91E3, + 0x97DF, 0x88C8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x98BF, 0x89BC, 0x0000, + 0x8BC2, 0x0000, 0x9287, 0x0000, 0x0000, 0x0000, + 0x8C8F, 0x98C1, 0x0000, 0x0000, 0x0000, 0x9443, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs4F[256] = { + 0x0000, 0x8AE9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x98C2, 0x88C9, 0x0000, + 0x0000, 0x8CDE, 0x8AEA, 0x959A, 0x94B0, 0x8B78, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x89EF, 0x0000, 0x98E5, 0x9360, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x948C, + 0x98C4, 0x0000, 0x0000, 0x0000, 0x94BA, 0x0000, + 0x97E0, 0x0000, 0x904C, 0x0000, 0x8E66, 0x0000, + 0x8E97, 0x89BE, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x92CF, 0x0000, 0x0000, 0x9241, 0x98C8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x88CA, + 0x92E1, 0x8F5A, 0x8DB2, 0x9743, 0x0000, 0x91CC, + 0x0000, 0x89BD, 0x0000, 0x98C7, 0x0000, 0x975D, + 0x98C3, 0x98C5, 0x8DEC, 0x98C6, 0x9B43, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x98CE, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x98D1, 0x98CF, 0x0000, + 0x0000, 0x89C0, 0x0000, 0x95B9, 0x98C9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x98CD, 0x8CF1, 0x0000, + 0x0000, 0x8E67, 0x0000, 0x0000, 0x0000, 0x8AA4, + 0x0000, 0x0000, 0x98D2, 0x0000, 0x98CA, 0x0000, + 0x0000, 0x97E1, 0x0000, 0x8E98, 0x0000, 0x98CB, + 0x0000, 0x98D0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x98D3, 0x0000, 0x98CC, 0x0000, 0x0000, 0x8B9F, + 0x0000, 0x88CB, 0x0000, 0x0000, 0x8BA0, 0x89BF, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9B44, 0x0000, 0x9699, + 0x958E, 0x8CF2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x904E, 0x97B5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95D6, + 0x0000, 0x0000, 0x8C57, 0x91A3, 0x89E2, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8F72, 0x0000, + 0x0000, 0x0000, 0x98D7, 0x0000, 0x98DC, 0x98DA, + 0x0000, 0x0000, 0x98D5, 0x0000, 0x0000, 0x91AD, + 0x98D8, 0x0000, 0x98DB, 0x98D9, 0x0000, 0x95DB, + 0x0000, 0x98D6, 0x0000, 0x904D, 0x0000, 0x9693, + 0x98DD, 0x98DE, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8F43, 0x98EB, + 0x0000, 0x0000, 0x0000, 0x946F, 0x0000, 0x9555, + 0x98E6, 0x0000, 0x95EE, 0x0000, 0x89B4, 0x0000, + 0x0000, 0x0000, 0x98EA, 0x0000 +}; + +static u16 Ucs50[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x98E4, + 0x98ED, 0x0000, 0x0000, 0x9171, 0x0000, 0x8CC2, + 0x0000, 0x947B, 0x0000, 0xE0C5, 0x0000, 0x98EC, + 0x937C, 0x0000, 0x98E1, 0x0000, 0x8CF4, 0x0000, + 0x0000, 0x8CF3, 0x98DF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8ED8, 0x0000, 0x98E7, 0x0000, 0x95ED, + 0x926C, 0x98E3, 0x8C91, 0x0000, 0x98E0, 0x98E8, + 0x98E2, 0x97CF, 0x98E9, 0x9860, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8BE4, 0x0000, 0x0000, 0x8C90, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x98EE, 0x0000, 0x0000, 0x0000, 0x98EF, + 0x98F3, 0x88CC, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x95CE, 0x98F2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x98F1, 0x98F5, 0x0000, 0x0000, 0x0000, + 0x98F4, 0x0000, 0x92E2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C92, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x98F6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8EC3, 0x0000, 0x91A4, 0x92E3, 0x8BF4, 0x0000, + 0x98F7, 0x0000, 0x0000, 0x0000, 0x0000, 0x8B55, + 0x0000, 0x0000, 0x98F8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x98FA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9654, 0x0000, 0x0000, + 0x0000, 0x8C86, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8E50, 0x94F5, 0x98F9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8DC3, 0x9762, + 0x0000, 0x0000, 0x0000, 0x0000, 0x98FC, 0x9942, + 0x98FB, 0x8DC2, 0x0000, 0x8F9D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8C58, 0x0000, + 0x0000, 0x0000, 0x9943, 0x0000, 0x0000, 0x8BCD, + 0x0000, 0x0000, 0x0000, 0x9940, 0x9941, 0x0000, + 0x0000, 0x93AD, 0x0000, 0x919C, 0x0000, 0x8BA1, + 0x0000, 0x0000, 0x0000, 0x966C, 0x9944, 0x0000, + 0x0000, 0x0000, 0x97BB, 0x0000, 0x0000, 0x0000, + 0x9945, 0x0000, 0x0000, 0x0000, 0x0000, 0x9948, + 0x0000, 0x9946, 0x0000, 0x916D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9947, 0x9949, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x994B, + 0x0000, 0x0000, 0x0000, 0x994A, 0x0000, 0x95C6, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs51[256] = { + 0x8B56, 0x994D, 0x994E, 0x0000, 0x89AD, 0x0000, + 0x0000, 0x0000, 0x0000, 0x994C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8EF2, 0x0000, 0x9951, 0x9950, 0x994F, 0x0000, + 0x98D4, 0x0000, 0x9952, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8F9E, 0x0000, 0x9953, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9744, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x96D7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9955, 0x0000, 0x0000, 0x9954, 0x9957, + 0x9956, 0x0000, 0x0000, 0x9958, 0x9959, 0x88F2, + 0x0000, 0x8CB3, 0x8C5A, 0x8F5B, 0x929B, 0x8BA2, + 0x90E6, 0x8CF5, 0x0000, 0x8D8E, 0x995B, 0x96C6, + 0x9365, 0x0000, 0x8E99, 0x0000, 0x995A, 0x0000, + 0x995C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x937D, 0x0000, 0x8A95, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x995D, 0x0000, 0x0000, 0x93FC, + 0x0000, 0x0000, 0x9153, 0x995F, 0x9960, 0x94AA, + 0x8CF6, 0x985A, 0x9961, 0x0000, 0x0000, 0x8BA4, + 0x0000, 0x0000, 0x0000, 0x95BA, 0x91B4, 0x8BEF, + 0x9354, 0x0000, 0x0000, 0x0000, 0x8C93, 0x0000, + 0x0000, 0x0000, 0x9962, 0x0000, 0x9963, 0x0000, + 0x0000, 0x93E0, 0x897E, 0x0000, 0x0000, 0x9966, + 0x8DFB, 0x0000, 0x9965, 0x8DC4, 0x0000, 0x9967, + 0xE3EC, 0x9968, 0x9660, 0x9969, 0x0000, 0x996A, + 0x996B, 0x8FE7, 0x0000, 0x8ECA, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8AA5, 0x0000, + 0x996E, 0x0000, 0x996C, 0x96BB, 0x996D, 0x0000, + 0x9579, 0x996F, 0x9970, 0x9971, 0x937E, 0x0000, + 0x0000, 0x0000, 0x9975, 0x9973, 0x9974, 0x9972, + 0x8DE1, 0x9976, 0x96E8, 0x97E2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9977, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x90A6, 0x9978, + 0x8F79, 0x0000, 0x0000, 0x9979, 0x0000, 0x929C, + 0x97BD, 0x9380, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x99C3, 0x0000, + 0x0000, 0x0000, 0x0000, 0x997A, 0xEAA3, 0x8BC3, + 0x0000, 0x0000, 0x997B, 0x967D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8F88, 0x91FA, 0x0000, 0x997D, + 0x93E2, 0x0000, 0x0000, 0x997E, 0x0000, 0x0000, + 0x9980, 0x8A4D, 0x0000, 0x0000, 0x0000, 0x9981, + 0x8BA5, 0x0000, 0x93CA, 0x899A, 0x8F6F, 0x0000, + 0x0000, 0x949F, 0x9982, 0x0000 +}; + +static u16 Ucs52[256] = { + 0x9381, 0x0000, 0x0000, 0x906E, 0x9983, 0x0000, + 0x95AA, 0x90D8, 0x8AA0, 0x0000, 0x8AA7, 0x9984, + 0x0000, 0x0000, 0x9986, 0x0000, 0x0000, 0x8C59, + 0x0000, 0x0000, 0x9985, 0x0000, 0x0000, 0x97F1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8F89, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x94BB, 0x95CA, 0x0000, 0x9987, 0x0000, 0x9798, + 0x9988, 0x0000, 0x0000, 0x0000, 0x9989, 0x0000, + 0x939E, 0x0000, 0x0000, 0x998A, 0x0000, 0x0000, + 0x90A7, 0x8DFC, 0x8C94, 0x998B, 0x8E68, 0x8D8F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x92E4, 0x998D, 0x0000, 0x0000, 0x91A5, + 0x0000, 0x0000, 0x8DED, 0x998E, 0x998F, 0x914F, + 0x0000, 0x998C, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9991, 0x0000, 0x9655, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8D84, 0x0000, 0x0000, 0x9990, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C95, 0x8DDC, 0x948D, + 0x0000, 0x0000, 0x0000, 0x9994, 0x9992, 0x0000, + 0x0000, 0x0000, 0x0000, 0x959B, 0x8FE8, 0x999B, + 0x8A84, 0x9995, 0x9993, 0x916E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9997, + 0x0000, 0x9996, 0x0000, 0x0000, 0x0000, 0x8A63, + 0x0000, 0x0000, 0x0000, 0x8C80, 0x999C, 0x97AB, + 0x0000, 0x0000, 0x0000, 0x9998, 0x0000, 0x0000, + 0x0000, 0x999D, 0x999A, 0x0000, 0x9999, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97CD, + 0x0000, 0x0000, 0x0000, 0x8CF7, 0x89C1, 0x0000, + 0x0000, 0x97F2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8F95, 0x9377, 0x8D85, 0x99A0, 0x99A1, + 0x0000, 0x0000, 0x0000, 0x97E3, 0x0000, 0x0000, + 0x984A, 0x99A3, 0x0000, 0x0000, 0x0000, 0x8CF8, + 0x0000, 0x0000, 0x99A2, 0x0000, 0x8A4E, 0x0000, + 0x0000, 0x99A4, 0x0000, 0x9675, 0x0000, 0x92BA, + 0x0000, 0x9745, 0x0000, 0x95D7, 0x0000, 0x0000, + 0x0000, 0x99A5, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE8D3, 0x0000, 0x0000, 0x93AE, 0x0000, 0x99A6, + 0x8AA8, 0x96B1, 0x0000, 0x0000, 0x0000, 0x8F9F, + 0x99A7, 0x95E5, 0x99AB, 0x0000, 0x90A8, 0x99A8, + 0x8BCE, 0x0000, 0x99A9, 0x8AA9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8C4D, 0x99AC, 0x0000, 0x99AD, + 0x0000, 0x0000, 0x99AE, 0x99AF, 0x8ED9, 0x0000, + 0x0000, 0x0000, 0x8CF9, 0x96DC +}; + +static u16 Ucs53[256] = { + 0x0000, 0x96E6, 0x93F5, 0x0000, 0x0000, 0x95EF, + 0x99B0, 0x0000, 0x99B1, 0x0000, 0x0000, 0x0000, + 0x0000, 0x99B3, 0x0000, 0x99B5, 0x99B4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x99B6, 0x89BB, 0x966B, + 0x0000, 0x8DFA, 0x99B7, 0x0000, 0x0000, 0x9178, + 0x0000, 0x0000, 0x8FA0, 0x8BA7, 0x0000, 0x99B8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x94D9, 0x0000, 0x0000, 0x0000, 0x0000, 0x99B9, + 0x0000, 0x99BA, 0x0000, 0x99BB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x99BC, 0x9543, 0x8BE6, 0x88E3, + 0x0000, 0x0000, 0x0000, 0x93BD, 0x99BD, 0x8F5C, + 0x0000, 0x90E7, 0x0000, 0x99BF, 0x99BE, 0x8FA1, + 0x8CDF, 0x99C1, 0x94BC, 0x0000, 0x0000, 0x99C2, + 0x0000, 0x0000, 0x0000, 0x94DA, 0x91B2, 0x91EC, + 0x8BA6, 0x0000, 0x0000, 0x93EC, 0x9250, 0x0000, + 0x948E, 0x0000, 0x966D, 0x0000, 0x99C4, 0x0000, + 0x90E8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C54, 0x0000, 0x0000, 0x99C5, 0x0000, 0x0000, + 0x0000, 0x0000, 0x99C6, 0x894B, 0x88F3, 0x8AEB, + 0x0000, 0x91A6, 0x8B70, 0x9791, 0x0000, 0x99C9, + 0x89B5, 0x0000, 0x0000, 0x99C8, 0x0000, 0x0000, + 0x0000, 0x8BA8, 0x0000, 0x0000, 0x99CA, 0x0000, + 0x96EF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x99CB, 0x0000, 0x97D0, 0x0000, 0x8CFA, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8CB4, 0x99CC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x99CE, 0x99CD, 0x0000, + 0x907E, 0x8958, 0x0000, 0x0000, 0x0000, 0x897D, + 0x99CF, 0x0000, 0x99D0, 0x0000, 0x0000, 0x8CB5, + 0x0000, 0x0000, 0x99D1, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8B8E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8E51, 0x99D2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9694, 0x8DB3, 0x8B79, 0x9746, + 0x916F, 0x94BD, 0x8EFB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8F66, 0x0000, 0x8EE6, 0x8EF3, + 0x0000, 0x8F96, 0x0000, 0x94BE, 0x0000, 0x0000, + 0x0000, 0x99D5, 0x0000, 0x8962, 0x9170, 0x8CFB, + 0x8CC3, 0x8BE5, 0x0000, 0x0000, 0x99D9, 0x9240, + 0x91FC, 0x8BA9, 0x8FA2, 0x99DA, 0x99D8, 0x89C2, + 0x91E4, 0x8EB6, 0x8E6A, 0x8945, 0x0000, 0x0000, + 0x8A90, 0x8D86, 0x8E69, 0x0000, 0x99DB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs54[256] = { + 0x0000, 0x99DC, 0x0000, 0x8B68, 0x8A65, 0x0000, + 0x0000, 0x0000, 0x8D87, 0x8B67, 0x92DD, 0x8944, + 0x93AF, 0x96BC, 0x8D40, 0x9799, 0x9366, 0x8CFC, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C4E, 0x0000, 0x99E5, + 0x0000, 0x8BE1, 0x9669, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x94DB, 0x0000, 0x0000, 0x99E4, + 0x0000, 0x8ADC, 0x99DF, 0x99E0, 0x99E2, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x99E3, 0x0000, 0x8B7A, 0x9081, 0x0000, 0x95AB, + 0x99E1, 0x99DD, 0x8CE1, 0x0000, 0x99DE, 0x0000, + 0x9843, 0x0000, 0x0000, 0x0000, 0x95F0, 0x0000, + 0x92E6, 0x8CE0, 0x8D90, 0x0000, 0x0000, 0x0000, + 0x99E6, 0x0000, 0x0000, 0x93DB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x99EA, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8EFC, 0x0000, 0x8EF4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x99ED, 0x99EB, + 0x0000, 0x96A1, 0x0000, 0x99E8, 0x99F1, 0x99EC, + 0x0000, 0x0000, 0x0000, 0x99EF, 0x8CC4, 0x96BD, + 0x0000, 0x0000, 0x99F0, 0x0000, 0x0000, 0x0000, + 0x99F2, 0x0000, 0x99F4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8DEE, 0x9861, 0x0000, 0x99E9, 0x99E7, + 0x99F3, 0x0000, 0x99EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x99F6, 0x0000, 0x9A42, 0x99F8, 0x0000, 0x0000, + 0x99FC, 0x0000, 0x0000, 0x9A40, 0x99F9, 0x0000, + 0x0000, 0x9A5D, 0x0000, 0x0000, 0x8DE7, 0x8A50, + 0x0000, 0x0000, 0x0000, 0x0000, 0x99F7, 0x0000, + 0x0000, 0x0000, 0x9A44, 0x88F4, 0x9A43, 0x0000, + 0x88A3, 0x9569, 0x9A41, 0x0000, 0x99FA, 0x0000, + 0x0000, 0x99F5, 0x99FB, 0x8DC6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9A45, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x88F5, 0x9A4E, 0x0000, + 0x0000, 0x9A46, 0x9A47, 0x0000, 0x8FA3, 0x9689, + 0x0000, 0x0000, 0x0000, 0x9A4C, 0x9A4B, 0x0000, + 0x0000, 0x0000, 0x934E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A4D, 0x0000, + 0x0000, 0x9A4A, 0x0000, 0x0000 +}; + +static u16 Ucs55[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x8953, 0x0000, + 0x8DB4, 0x904F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9A48, 0x9382, 0x0000, + 0x0000, 0x0000, 0x9A49, 0x0000, 0x88A0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A53, 0x9742, + 0x0000, 0x8FA5, 0x0000, 0x9A59, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A58, 0x9A4F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x91C1, 0x0000, 0x9A50, 0x0000, + 0x0000, 0x0000, 0x91ED, 0x9A55, 0x8FA4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A52, 0x0000, + 0x0000, 0x96E2, 0x0000, 0x0000, 0x0000, 0x8C5B, + 0x0000, 0x0000, 0x9A56, 0x9A57, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A54, 0x9A5A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9A51, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9A60, 0x9A65, 0x0000, + 0x9A61, 0x0000, 0x9A5C, 0x0000, 0x0000, 0x9A66, + 0x9150, 0x0000, 0x0000, 0x9A68, 0x0000, 0x8D41, + 0x9A5E, 0x929D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A62, 0x9A5B, 0x8AAB, 0x0000, + 0x8AEC, 0x8A85, 0x9A63, 0x9A5F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C96, + 0x9A69, 0x9A67, 0x9172, 0x8B69, 0x8BAA, 0x0000, + 0x9A64, 0x0000, 0x8BF2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8963, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A6D, 0x9A6B, + 0x0000, 0x9AA5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A70, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A6A, 0x0000, 0x9A6E, 0x0000, + 0x0000, 0x9A6C, 0x0000, 0x0000, 0x0000, 0x8E6B, + 0x9A6F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9A72, 0x0000, 0x9A77, 0x0000, 0x0000, + 0x0000, 0x9A75, 0x9A74, 0x0000 +}; + +static u16 Ucs56[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9251, 0x0000, 0x0000, 0x89C3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A71, 0x0000, 0x9A73, 0x8FA6, + 0x8952, 0x0000, 0x0000, 0x9A76, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89DC, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9A82, + 0x0000, 0x8FFA, 0x9A7D, 0x0000, 0x9A7B, 0x0000, + 0x9A7C, 0x0000, 0x9A7E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x895C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9158, 0x0000, + 0x9A78, 0x0000, 0x9A79, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8A9A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A81, 0x0000, + 0x0000, 0x0000, 0x8AED, 0x0000, 0x9A84, 0x9A80, + 0x9A83, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x95AC, 0x0000, 0x0000, 0x0000, + 0x93D3, 0x0000, 0x94B6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A86, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A85, 0x8A64, 0x0000, 0x0000, + 0x9A87, 0x0000, 0x0000, 0x0000, 0x0000, 0x9A8A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A89, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A88, 0x0000, + 0x9458, 0x0000, 0x0000, 0x9A8B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9A8C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9A8E, 0x0000, 0x9A8D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A90, 0x0000, 0x0000, 0x0000, + 0x9A93, 0x9A91, 0x9A8F, 0x9A92, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A94, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9A95, 0x0000, 0x0000, 0x9A96, + 0x0000, 0x9A97, 0x0000, 0x0000, 0x0000, 0x9A98, + 0x9964, 0x0000, 0x8EFA, 0x8E6C, 0x0000, 0x0000, + 0x89F1, 0x0000, 0x88F6, 0x0000, 0x0000, 0x9263, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9A99, 0x0000, + 0x8DA2, 0x0000, 0x88CD, 0x907D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9A9A, 0x8CC5, 0x0000, + 0x0000, 0x8D91, 0x0000, 0x9A9C +}; + +static u16 Ucs57[256] = { + 0x9A9B, 0x0000, 0x0000, 0x95DE, 0x9A9D, 0x0000, + 0x0000, 0x0000, 0x9A9F, 0x9A9E, 0x0000, 0x9AA0, + 0x0000, 0x9AA1, 0x0000, 0x8C97, 0x0000, 0x0000, + 0x8980, 0x9AA2, 0x0000, 0x0000, 0x9AA4, 0x0000, + 0x9AA3, 0x0000, 0x0000, 0x0000, 0x9AA6, 0x0000, + 0x0000, 0x9379, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9AA7, 0x88B3, 0x8DDD, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C5C, 0x0000, 0x0000, + 0x926E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9AA8, 0x9AA9, 0x0000, 0x0000, 0x9AAB, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9AAC, 0x0000, + 0x8DE2, 0x0000, 0x0000, 0x0000, 0x0000, 0x8BCF, + 0x0000, 0x0000, 0x9656, 0x0000, 0x0000, 0x0000, + 0x9AAA, 0x9AAD, 0x8DBF, 0x8D42, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9AB1, 0x0000, 0x0000, 0x8DA3, 0x0000, + 0x9252, 0x0000, 0x0000, 0x9AAE, 0x92D8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9AB2, 0x0000, 0x0000, 0x9082, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9AB0, 0x9AB3, + 0x0000, 0x8C5E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9AB4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9AB5, 0x0000, + 0x8D43, 0x8A5F, 0x9AB7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9AB8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9AB9, 0x0000, 0x0000, 0x9AB6, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9AAF, 0x0000, 0x0000, 0x9ABA, 0x0000, 0x0000, + 0x9ABB, 0x0000, 0x0000, 0x0000, 0x0000, 0x9684, + 0x0000, 0x0000, 0x8FE9, 0x0000, 0x0000, 0x0000, + 0x9ABD, 0x9ABE, 0x9ABC, 0x0000, 0x9AC0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9457, 0x0000, + 0x0000, 0x88E6, 0x9575, 0x0000, 0x0000, 0x9AC1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8FFB, 0x0000, + 0x0000, 0x8EB7, 0x0000, 0x947C, 0x8AEE, 0x0000, + 0x8DE9, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs58[256] = { + 0x9678, 0x0000, 0x93B0, 0x0000, 0x0000, 0x8C98, + 0x91CD, 0x0000, 0x0000, 0x0000, 0x9ABF, 0x9AC2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x91C2, 0x0000, 0x0000, + 0x0000, 0x9AC3, 0x0000, 0x0000, 0x0000, 0x9AC4, + 0x0000, 0x0000, 0x0000, 0x9AC6, 0x0000, 0x0000, + 0x92E7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8AAC, 0x0000, 0x0000, 0x0000, 0x0000, 0xEA9F, + 0x8981, 0x95F1, 0x0000, 0x0000, 0x8FEA, 0x9367, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8DE4, 0x0000, + 0x0000, 0x9ACC, 0x0000, 0x0000, 0x95BB, 0x97DB, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x89F2, 0x9AC8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9159, 0x9ACB, 0x0000, + 0x9383, 0x0000, 0x0000, 0x9368, 0x9384, 0x94B7, + 0x92CB, 0x0000, 0x0000, 0x0000, 0x8DC7, 0x0000, + 0x0000, 0x0000, 0x9AC7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8996, 0x0000, 0x9355, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9AC9, 0x0000, + 0x9AC5, 0x0000, 0x0000, 0x906F, 0x0000, 0x0000, + 0x0000, 0x9ACD, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F6D, 0x0000, 0x0000, 0x0000, 0x0000, 0x8BAB, + 0x0000, 0x9ACE, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x95E6, 0x0000, 0x0000, + 0x0000, 0x919D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x92C4, 0x0000, 0x0000, 0x9AD0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x966E, 0x0000, 0x0000, 0x9AD1, 0x0000, 0x0000, + 0x9AD6, 0x0000, 0x0000, 0x0000, 0x0000, 0x95AD, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9AD5, 0x9ACF, + 0x9AD2, 0x9AD4, 0x0000, 0x0000, 0x8DA4, 0x0000, + 0x0000, 0x95C7, 0x0000, 0x0000, 0x0000, 0x9AD7, + 0x0000, 0x9264, 0x0000, 0x0000, 0x89F3, 0x0000, + 0x8FEB, 0x0000, 0x0000, 0x0000, 0x0000, 0x9AD9, + 0x0000, 0x9AD8, 0x0000, 0x8D88, 0x0000, 0x9ADA, + 0x9ADC, 0x9ADB, 0x0000, 0x0000, 0x9ADE, 0x0000, + 0x9AD3, 0x9AE0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9ADF, 0x9ADD, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8E6D, 0x9070, 0x0000, 0x9173, 0x9AE1, + 0x90BA, 0x88EB, 0x9484, 0x0000, 0x0000, 0x0000, + 0x0000, 0x92D9, 0x0000, 0x9AE3, 0x9AE2, 0x9AE4, + 0x9AE5, 0x9AE6, 0x0000, 0x0000 +}; + +static u16 Ucs59[256] = { + 0x0000, 0x0000, 0x9AE7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x95CF, 0x9AE8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x89C4, 0x9AE9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x975B, 0x8A4F, 0x0000, + 0x99C7, 0x8F67, 0x91BD, 0x9AEA, 0x96E9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x96B2, 0x0000, + 0x0000, 0x9AEC, 0x0000, 0x91E5, 0x0000, 0x9356, + 0x91BE, 0x9576, 0x9AED, 0x9AEE, 0x899B, 0x0000, + 0x0000, 0x8EB8, 0x9AEF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x88CE, 0x9AF0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9AF1, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8982, 0x0000, 0x0000, 0x8AEF, + 0x93DE, 0x95F2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9AF5, 0x9174, 0x9AF4, 0x8C5F, 0x0000, 0x0000, + 0x967A, 0x9AF3, 0x0000, 0x9385, 0x9AF7, 0x0000, + 0x9AF6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9AF9, 0x0000, 0x9AF8, 0x0000, 0x0000, 0x899C, + 0x0000, 0x9AFA, 0x8FA7, 0x9AFC, 0x9244, 0x0000, + 0x9AFB, 0x0000, 0x95B1, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8F97, 0x937A, 0x0000, 0x0000, 0x0000, + 0x9B40, 0x0000, 0x0000, 0x0000, 0x0000, 0x8D44, + 0x0000, 0x0000, 0x0000, 0x9B41, 0x9440, 0x94DC, + 0x96CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9444, 0x0000, 0x0000, 0x9B4A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8B57, 0x0000, 0x0000, + 0x9764, 0x0000, 0x0000, 0x96AD, 0x0000, 0x9BAA, + 0x0000, 0x9B42, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9B45, 0x0000, 0x91C3, 0x0000, 0x0000, + 0x9657, 0x0000, 0x0000, 0x0000, 0x9369, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B46, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9685, + 0x0000, 0x8DC8, 0x0000, 0x0000, 0x8FA8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9B47, 0x0000, 0x0000, 0x8E6F, 0x0000, 0x8E6E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x88B7, 0x8CC6, + 0x0000, 0x90A9, 0x88CF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9B4B, 0x9B4C, 0x0000, 0x9B49, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8957, 0x8AAD, 0x0000, 0x9B48, 0x0000, + 0x96C3, 0x9550, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x88A6, 0x0000, 0x0000, 0x0000, 0x0000, 0x88F7, + 0x0000, 0x0000, 0x0000, 0x8E70 +}; + +static u16 Ucs5A[256] = { + 0x0000, 0x88D0, 0x0000, 0x88A1, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9B51, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9B4F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x96BA, 0x0000, 0x9B52, 0x0000, 0x9B50, 0x0000, + 0x0000, 0x9B4E, 0x9050, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9B4D, 0x0000, 0x0000, 0x0000, 0x95D8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8CE2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9B56, + 0x9B57, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8FA9, 0x0000, 0x0000, 0x0000, 0x9B53, 0x984B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x946B, 0x0000, + 0x0000, 0x9B55, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8DA5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9B58, 0x0000, 0x0000, 0x0000, + 0x9577, 0x0000, 0x0000, 0x0000, 0x9B59, 0x0000, + 0x9B54, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x96B9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x947D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B5A, 0x9551, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9B5B, 0x9B5F, 0x9B5C, 0x0000, + 0x0000, 0x89C5, 0x9B5E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8EB9, 0x0000, 0x9B5D, + 0x8C99, 0x0000, 0x0000, 0x0000, 0x9B6B, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B64, 0x9B61, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9284, 0x0000, 0x9B60, + 0x0000, 0x0000, 0x9B62, 0x0000, 0x0000, 0x9B63, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B65, 0x9B66, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs5B[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8AF0, 0x0000, 0x9B68, + 0x9B67, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B69, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8FEC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9B6C, 0x0000, 0x92DA, 0x0000, 0x0000, 0x0000, + 0x8964, 0x0000, 0x9B6A, 0x0000, 0x0000, 0x0000, + 0x9B6D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9B6E, 0x0000, 0x9B71, 0x0000, + 0x0000, 0x9B6F, 0x0000, 0x9B70, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8E71, 0x9B72, 0x0000, 0x0000, + 0x8D45, 0x9B73, 0x0000, 0x8E9A, 0x91B6, 0x0000, + 0x9B74, 0x9B75, 0x8E79, 0x8D46, 0x0000, 0x96D0, + 0x0000, 0x0000, 0x0000, 0x8B47, 0x8CC7, 0x9B76, + 0x8A77, 0x0000, 0x0000, 0x9B77, 0x0000, 0x91B7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B78, 0x9BA1, + 0x0000, 0x9B79, 0x0000, 0x9B7A, 0x0000, 0x0000, + 0x9B7B, 0x0000, 0x9B7D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9B7E, 0x0000, 0x0000, 0x9B80, + 0x0000, 0x91EE, 0x0000, 0x8946, 0x8EE7, 0x88C0, + 0x0000, 0x9176, 0x8AAE, 0x8EB3, 0x0000, 0x8D47, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9386, + 0x0000, 0x8F40, 0x8AAF, 0x9288, 0x92E8, 0x88B6, + 0x8B58, 0x95F3, 0x0000, 0x8EC0, 0x0000, 0x0000, + 0x8B71, 0x90E9, 0x8EBA, 0x9747, 0x9B81, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8B7B, 0x0000, 0x8DC9, 0x0000, 0x0000, 0x8A51, + 0x8983, 0x8FAA, 0x89C6, 0x0000, 0x9B82, 0x9765, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8F68, + 0x0000, 0x0000, 0x8EE2, 0x9B83, 0x8AF1, 0x93D0, + 0x96A7, 0x9B84, 0x0000, 0x9B85, 0x0000, 0x0000, + 0x9578, 0x0000, 0x0000, 0x0000, 0x9B87, 0x0000, + 0x8AA6, 0x8BF5, 0x9B86, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8AB0, 0x0000, 0x9051, + 0x9B8B, 0x8E40, 0x0000, 0x89C7, 0x9B8A, 0x0000, + 0x9B88, 0x9B8C, 0x9B89, 0x944A, 0x9ECB, 0x9052, + 0x0000, 0x9B8D, 0x0000, 0x0000, 0x97BE, 0x0000, + 0x9B8E, 0x0000, 0x0000, 0x9B90, 0x0000, 0x929E, + 0x9B8F, 0x0000, 0x90A1, 0x0000, 0x8E9B, 0x0000, + 0x0000, 0x0000, 0x91CE, 0x8EF5 +}; + +static u16 Ucs5C[256] = { + 0x0000, 0x9595, 0x90EA, 0x0000, 0x8ECB, 0x9B91, + 0x8FAB, 0x9B92, 0x9B93, 0x88D1, 0x91B8, 0x9071, + 0x0000, 0x9B94, 0x93B1, 0x8FAC, 0x0000, 0x8FAD, + 0x0000, 0x9B95, 0x0000, 0x0000, 0x90EB, 0x0000, + 0x0000, 0x0000, 0x8FAE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9B96, 0x0000, 0x9B97, 0x0000, + 0x96DE, 0x0000, 0x0000, 0x0000, 0x9B98, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8BC4, 0x0000, 0x0000, + 0x0000, 0x8F41, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9B99, 0x9B9A, 0x8EDA, 0x904B, + 0x93F2, 0x9073, 0x94F6, 0x9441, 0x8BC7, 0x9B9B, + 0x0000, 0x0000, 0x0000, 0x8B8F, 0x9B9C, 0x0000, + 0x8BFC, 0x0000, 0x93CD, 0x89AE, 0x0000, 0x8E72, + 0x9B9D, 0x9BA0, 0x9B9F, 0x8BFB, 0x0000, 0x9B9E, + 0x0000, 0x9357, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x91AE, 0x0000, + 0x936A, 0x8EC6, 0x0000, 0x0000, 0x9177, 0x979A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9BA2, 0x0000, 0x9BA3, 0x93D4, 0x0000, 0x8E52, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9BA5, 0x0000, + 0x0000, 0x9BA6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9BA7, 0x0000, 0x0000, 0x0000, + 0x8AF2, 0x9BA8, 0x0000, 0x0000, 0x9BA9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89AA, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x915A, 0x8AE2, 0x0000, 0x9BAB, 0x96A6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x91D0, 0x0000, 0x8A78, + 0x0000, 0x0000, 0x9BAD, 0x9BAF, 0x8ADD, 0x0000, + 0x0000, 0x9BAC, 0x9BAE, 0x0000, 0x9BB1, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9BB0, + 0x0000, 0x9BB2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9BB3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x93BB, 0x8BAC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x89E3, 0x9BB4, + 0x9BB9, 0x0000, 0x0000, 0x9BB7, 0x0000, 0x95F5, + 0x95F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9387, 0x0000, 0x0000, 0x0000, 0x9BB6, 0x8F73, + 0x0000, 0x9BB5, 0x0000, 0x0000 +}; + +static u16 Ucs5D[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9092, 0x0000, 0x0000, 0x0000, 0x9BBA, + 0x0000, 0x0000, 0x8DE8, 0x0000, 0x0000, 0x9BC0, + 0x0000, 0x0000, 0x9BC1, 0x9BBB, 0x8A52, 0x9BBC, + 0x9BC5, 0x9BC4, 0x9BC3, 0x9BBF, 0x0000, 0x0000, + 0x0000, 0x9BBE, 0x0000, 0x0000, 0x9BC2, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95F6, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9BC9, 0x9BC6, 0x0000, + 0x9BC8, 0x0000, 0x9792, 0x0000, 0x9BC7, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9BBD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9093, 0x0000, 0x0000, + 0x9BCA, 0x0000, 0x0000, 0x8DB5, 0x0000, 0x0000, + 0x0000, 0x9BCB, 0x0000, 0x0000, 0x9BCC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9BCF, 0x0000, + 0x9BCE, 0x0000, 0x0000, 0x9BCD, 0x0000, 0x0000, + 0x0000, 0x9388, 0x9BB8, 0x0000, 0x0000, 0x0000, + 0x9BD5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9BD1, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9BD0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9BD2, 0x0000, + 0x9BD3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9BD6, 0x0000, 0x0000, + 0x97E4, 0x0000, 0x9BD7, 0x9BD4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9BD8, 0x0000, 0x0000, + 0x8ADE, 0x9BD9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9BDB, 0x9BDA, 0x0000, 0x0000, 0x9BDC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9BDD, 0x0000, 0x90EC, + 0x8F42, 0x0000, 0x0000, 0x8F84, 0x0000, 0x9183, + 0x0000, 0x8D48, 0x8DB6, 0x8D49, 0x8B90, 0x0000, + 0x0000, 0x9BDE, 0x0000, 0x0000, 0x8DB7, 0x0000, + 0x0000, 0x8CC8, 0x9BDF, 0x96A4, 0x9462, 0x9BE0, + 0x0000, 0x8D4A, 0x0000, 0x0000, 0x0000, 0x8AAA, + 0x0000, 0x9246, 0x8BD0, 0x0000 +}; + +static u16 Ucs5E[256] = { + 0x0000, 0x0000, 0x8E73, 0x957A, 0x0000, 0x0000, + 0x94BF, 0x0000, 0x0000, 0x0000, 0x0000, 0x9BE1, + 0x8AF3, 0x0000, 0x0000, 0x0000, 0x0000, 0x9BE4, + 0x0000, 0x0000, 0x0000, 0x0000, 0x929F, 0x0000, + 0x0000, 0x9BE3, 0x9BE2, 0x9BE5, 0x0000, 0x92E9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9083, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8E74, 0x0000, 0x90C8, 0x0000, 0x91D1, + 0x8B41, 0x0000, 0x0000, 0x92A0, 0x0000, 0x0000, + 0x9BE6, 0x9BE7, 0x8FED, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9658, 0x0000, 0x0000, 0x9BEA, 0x0000, + 0x0000, 0x9BE9, 0x9BE8, 0x959D, 0x0000, 0x9BF1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9679, 0x0000, + 0x9BEB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9BED, 0x968B, 0x0000, 0x9BEC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9BEE, + 0x0000, 0x94A6, 0x9BEF, 0x95BC, 0x9BF0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8AB1, 0x95BD, 0x944E, 0x9BF2, 0x9BF3, 0x0000, + 0x8D4B, 0x8AB2, 0x9BF4, 0x8CB6, 0x9763, 0x9748, + 0x8AF4, 0x9BF6, 0x0000, 0x92A1, 0x0000, 0x8D4C, + 0x8FAF, 0x0000, 0x0000, 0x94DD, 0x0000, 0x0000, + 0x8FB0, 0x0000, 0x0000, 0x0000, 0x0000, 0x8F98, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92EA, + 0x95F7, 0x9358, 0x0000, 0x0000, 0x8D4D, 0x0000, + 0x957B, 0x0000, 0x0000, 0x0000, 0x9BF7, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9378, 0x8DC0, + 0x0000, 0x0000, 0x0000, 0x8CC9, 0x0000, 0x92EB, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x88C1, 0x8F8E, 0x8D4E, 0x9766, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9BF8, 0x9BF9, 0x9470, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9BFA, 0x97F5, 0x984C, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9BFC, 0x9BFB, 0x0000, + 0x0000, 0x8A66, 0x0000, 0x0000, 0x9C40, 0x0000, + 0x0000, 0x0000, 0x9C43, 0x9C44, 0x0000, 0x9C42, + 0x0000, 0x955F, 0x8FB1, 0x9C46, 0x9C45, 0x9C41, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9C47, 0x9C48, + 0x0000, 0x0000, 0x9C49, 0x0000, 0x0000, 0x0000, + 0x9C4C, 0x9C4A, 0x0000, 0x9C4B, 0x9C4D, 0x0000, + 0x8984, 0x92EC, 0x9C4E, 0x0000, 0x8C9A, 0x89F4, + 0x9455, 0x0000, 0x9C4F, 0x93F9 +}; + +static u16 Ucs5F[256] = { + 0x0000, 0x95D9, 0x0000, 0x9C50, 0x984D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9C51, 0x95BE, 0x9C54, + 0x989F, 0x98AF, 0x0000, 0x8EAE, 0x93F3, 0x9C55, + 0x0000, 0x8B7C, 0x92A2, 0x88F8, 0x9C56, 0x95A4, + 0x8D4F, 0x0000, 0x0000, 0x926F, 0x0000, 0x0000, + 0x0000, 0x92ED, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x96ED, 0x8CB7, 0x8CCA, 0x0000, 0x9C57, + 0x0000, 0x0000, 0x0000, 0x9C58, 0x0000, 0x9C5E, + 0x0000, 0x8EE3, 0x0000, 0x0000, 0x0000, 0x92A3, + 0x0000, 0x8BAD, 0x9C59, 0x0000, 0x0000, 0x0000, + 0x954A, 0x0000, 0x9265, 0x0000, 0x0000, 0x9C5A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9C5B, 0x0000, 0x8BAE, 0x0000, 0x9C5C, 0x0000, + 0x9C5D, 0x0000, 0x0000, 0x9C5F, 0x0000, 0x9396, + 0x0000, 0x0000, 0x9C60, 0x9C61, 0x0000, 0x9C62, + 0x0000, 0x0000, 0x9C53, 0x9C52, 0x0000, 0x0000, + 0x0000, 0x9C63, 0x8C60, 0x0000, 0x0000, 0x0000, + 0x9546, 0x0000, 0x0000, 0x8DCA, 0x9556, 0x92A4, + 0x956A, 0x9C64, 0x0000, 0x0000, 0x8FB2, 0x8965, + 0x0000, 0x9C65, 0x0000, 0x0000, 0x0000, 0x9C66, + 0x0000, 0x96F0, 0x0000, 0x0000, 0x94DE, 0x0000, + 0x0000, 0x9C69, 0x899D, 0x90AA, 0x9C68, 0x9C67, + 0x8C61, 0x91D2, 0x0000, 0x9C6D, 0x9C6B, 0x0000, + 0x9C6A, 0x97A5, 0x8CE3, 0x0000, 0x0000, 0x0000, + 0x8F99, 0x9C6C, 0x936B, 0x8F5D, 0x0000, 0x0000, + 0x0000, 0x93BE, 0x9C70, 0x9C6F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9C6E, 0x0000, 0x9C71, 0x8CE4, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9C72, 0x959C, 0x8F7A, 0x0000, 0x0000, 0x9C73, + 0x94F7, 0x0000, 0x0000, 0x0000, 0x0000, 0x93BF, + 0x92A5, 0x0000, 0x0000, 0x0000, 0x0000, 0x934F, + 0x0000, 0x0000, 0x9C74, 0x8B4A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9053, 0x0000, 0x954B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8AF5, 0x9445, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9C75, 0x8E75, + 0x9659, 0x965A, 0x0000, 0x0000, 0x899E, 0x9C7A, + 0x0000, 0x0000, 0x9289, 0x0000, 0x0000, 0x0000, + 0x9C77, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x89F5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9CAB, 0x9C79, 0x0000, 0x0000, 0x0000, 0x944F, + 0x0000, 0x0000, 0x9C78, 0x0000, 0x0000, 0x9C76, + 0x0000, 0x8D9A, 0x0000, 0x9C7C +}; + +static u16 Ucs60[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9C83, 0x9C89, 0x9C81, 0x0000, + 0x937B, 0x0000, 0x0000, 0x9C86, 0x957C, 0x0000, + 0x0000, 0x9C80, 0x0000, 0x9C85, 0x97E5, 0x8E76, + 0x0000, 0x0000, 0x91D3, 0x9C7D, 0x0000, 0x0000, + 0x0000, 0x8B7D, 0x9C88, 0x90AB, 0x8985, 0x9C82, + 0x89F6, 0x9C87, 0x0000, 0x0000, 0x0000, 0x8BAF, + 0x0000, 0x9C84, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9C8A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9C8C, + 0x9C96, 0x9C94, 0x0000, 0x0000, 0x9C91, 0x0000, + 0x0000, 0x0000, 0x9C90, 0x97F6, 0x0000, 0x9C92, + 0x0000, 0x0000, 0x8BB0, 0x0000, 0x8D50, 0x0000, + 0x0000, 0x8F9A, 0x0000, 0x0000, 0x0000, 0x9C99, + 0x9C8B, 0x0000, 0x0000, 0x0000, 0x0000, 0x9C8F, + 0x9C7E, 0x0000, 0x89F8, 0x9C93, 0x9C95, 0x9270, + 0x0000, 0x0000, 0x8DA6, 0x89B6, 0x9C8D, 0x9C98, + 0x9C97, 0x8BB1, 0x0000, 0x91A7, 0x8A86, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C62, 0x0000, 0x9C8E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9C9A, 0x0000, 0x9C9D, + 0x9C9F, 0x0000, 0x0000, 0x0000, 0x0000, 0x8EBB, + 0x0000, 0x9CA5, 0x92EE, 0x9C9B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9CA3, 0x0000, 0x89F7, 0x0000, + 0x9CA1, 0x9CA2, 0x0000, 0x0000, 0x9C9E, 0x9CA0, + 0x0000, 0x0000, 0x0000, 0x8CE5, 0x9749, 0x0000, + 0x0000, 0x8AB3, 0x0000, 0x0000, 0x8978, 0x9CA4, + 0x0000, 0x9459, 0x88AB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x94DF, 0x9C7B, + 0x9CAA, 0x9CAE, 0x96E3, 0x0000, 0x9CA7, 0x0000, + 0x0000, 0x0000, 0x9389, 0x9CAC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8FEE, + 0x9CAD, 0x93D5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9866, + 0x0000, 0x9CA9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9CAF, 0x0000, 0x8D9B, 0x0000, 0x90C9, 0x0000, + 0x0000, 0x88D2, 0x9CA8, 0x9CA6, 0x0000, 0x9179, + 0x0000, 0x0000, 0x0000, 0x9C9C, 0x8E53, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x91C4, 0x9CBB, 0x0000, 0x917A, 0x9CB6, 0x0000, + 0x9CB3, 0x9CB4, 0x0000, 0x8EE4, 0x9CB7, 0x9CBA, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs61[256] = { + 0x9CB5, 0x8F44, 0x0000, 0x9CB8, 0x0000, 0x0000, + 0x9CB2, 0x0000, 0x96FA, 0x96F9, 0x0000, 0x0000, + 0x0000, 0x9CBC, 0x9CBD, 0x88D3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9CB1, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8BF0, 0x88A4, 0x0000, 0x0000, + 0x0000, 0x8AB4, 0x0000, 0x9CB9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9CC1, 0x9CC0, 0x0000, + 0x0000, 0x0000, 0x9CC5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9CC6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9CC4, 0x9CC7, 0x9CBF, 0x9CC3, 0x0000, 0x0000, + 0x9CC8, 0x0000, 0x9CC9, 0x0000, 0x0000, 0x9CBE, + 0x8E9C, 0x0000, 0x9CC2, 0x91D4, 0x8D51, 0x9CB0, + 0x9054, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CD6, + 0x0000, 0x95E7, 0x0000, 0x0000, 0x9CCC, 0x9CCD, + 0x9CCE, 0x0000, 0x0000, 0x9CD5, 0x0000, 0x9CD4, + 0x0000, 0x0000, 0x969D, 0x8AB5, 0x0000, 0x9CD2, + 0x0000, 0x8C64, 0x8A53, 0x0000, 0x0000, 0x9CCF, + 0x0000, 0x0000, 0x97B6, 0x9CD1, 0x88D4, 0x9CD3, + 0x0000, 0x9CCA, 0x9CD0, 0x9CD7, 0x8C63, 0x9CCB, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x977C, 0x0000, 0x0000, 0x0000, 0x974A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9CDA, 0x0000, 0x0000, + 0x9CDE, 0x0000, 0x0000, 0x0000, 0x919E, 0x0000, + 0x97F7, 0x9CDF, 0x0000, 0x0000, 0x9CDC, 0x0000, + 0x9CD9, 0x0000, 0x0000, 0x9CD8, 0x9CDD, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x95AE, 0x0000, 0x0000, 0x93B2, + 0x0000, 0x8C65, 0x0000, 0x9CE0, 0x9CDB, 0x0000, + 0x9CE1, 0x0000, 0x0000, 0x0000, 0x8C9B, 0x0000, + 0x0000, 0x0000, 0x89AF, 0x0000, 0x0000, 0x0000, + 0x9CE9, 0x0000, 0x0000, 0x0000, 0x8AB6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9CE7, 0x0000, 0x0000, + 0x9CE8, 0x8DA7, 0x9CE6, 0x9CE4, 0x9CE3, 0x9CEA, + 0x9CE2, 0x9CEC, 0x0000, 0x0000, 0x89F9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9CEE, + 0x0000, 0x0000, 0x9CED, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x92A6, 0x0000, 0x9CF1, 0x0000, + 0x9CEF, 0x9CE5, 0x8C9C, 0x0000, 0x9CF0, 0x0000, + 0x9CF4, 0x9CF3, 0x9CF5, 0x9CF2 +}; + +static u16 Ucs62[256] = { + 0x9CF6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9CF7, 0x9CF8, 0x95E8, 0x0000, + 0x9CFA, 0x9CF9, 0x8F5E, 0x0000, 0x90AC, 0x89E4, + 0x89FA, 0x0000, 0x9CFB, 0x0000, 0x88BD, 0x0000, + 0x0000, 0x0000, 0x90CA, 0x9CFC, 0x0000, 0xE6C1, + 0x9D40, 0x8C81, 0x0000, 0x9D41, 0x0000, 0x0000, + 0x0000, 0x0000, 0x90ED, 0x0000, 0x0000, 0x0000, + 0x9D42, 0x0000, 0x0000, 0x0000, 0x9D43, 0x8B59, + 0x9D44, 0x0000, 0x9D45, 0x9D46, 0x91D5, 0x0000, + 0x0000, 0x0000, 0x8CCB, 0x0000, 0x0000, 0x96DF, + 0x0000, 0x0000, 0x0000, 0x965B, 0x8F8A, 0x9D47, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90EE, + 0xE7BB, 0x94E0, 0x0000, 0x8EE8, 0x0000, 0x8DCB, + 0x9D48, 0x0000, 0x0000, 0x0000, 0x0000, 0x91C5, + 0x0000, 0x95A5, 0x0000, 0x0000, 0x91EF, 0x0000, + 0x0000, 0x9D4B, 0x0000, 0x0000, 0x9D49, 0x0000, + 0x9D4C, 0x0000, 0x0000, 0x9D4A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9D4D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x95AF, 0x0000, 0x0000, 0x88B5, + 0x0000, 0x0000, 0x0000, 0x0000, 0x957D, 0x0000, + 0x0000, 0x94E1, 0x0000, 0x0000, 0x9D4E, 0x0000, + 0x9D51, 0x8FB3, 0x8B5A, 0x0000, 0x9D4F, 0x9D56, + 0x8FB4, 0x0000, 0x0000, 0x0000, 0x0000, 0x9D50, + 0x9463, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x977D, 0x9D52, 0x9D53, 0x9D57, 0x938A, + 0x9D54, 0x8D52, 0x90DC, 0x0000, 0x0000, 0x9D65, + 0x94B2, 0x0000, 0x91F0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x94E2, 0x9DAB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x95F8, 0x0000, 0x0000, + 0x0000, 0x92EF, 0x0000, 0x0000, 0x0000, 0x9695, + 0x0000, 0x9D5A, 0x899F, 0x928A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9D63, 0x0000, 0x0000, 0x9253, + 0x9D5D, 0x9D64, 0x9D5F, 0x9D66, 0x9D62, 0x0000, + 0x9D61, 0x948F, 0x0000, 0x9D5B, 0x89FB, 0x9D59, + 0x8B91, 0x91F1, 0x9D55, 0x0000, 0x0000, 0x9D58, + 0x8D53, 0x90D9, 0x0000, 0x8FB5, 0x9D60, 0x9471, + 0x0000, 0x0000, 0x8B92, 0x8A67, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8A87, 0x9040, 0x9D68, 0x9D6D, + 0x0000, 0x9D69, 0x0000, 0x8C9D, 0x0000, 0x9D6E, + 0x8E41, 0x8D89, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8F45, 0x9D5C +}; + +static u16 Ucs63[256] = { + 0x0000, 0x8E9D, 0x9D6B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8E77, 0x9D6C, 0x88C2, 0x0000, 0x0000, + 0x9D67, 0x0000, 0x0000, 0x0000, 0x0000, 0x92A7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8B93, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8BB2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9D6A, 0x88A5, 0x0000, + 0x0000, 0x8DC1, 0x0000, 0x0000, 0x0000, 0x9055, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x92F0, 0x0000, + 0x0000, 0x94D2, 0x9D70, 0x917D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x91A8, 0x0000, 0x0000, 0x8E4A, 0x9D71, + 0x0000, 0x9D73, 0x9D6F, 0x0000, 0x0000, 0x0000, + 0x0000, 0x95DF, 0x0000, 0x92BB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x917B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x95F9, 0x8ECC, 0x9D80, 0x0000, 0x9D7E, + 0x0000, 0x0000, 0x9098, 0x0000, 0x0000, 0x0000, + 0x8C9E, 0x0000, 0x0000, 0x0000, 0x9D78, 0x8FB7, + 0x0000, 0x0000, 0x93E6, 0x9450, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9D76, 0x0000, 0x0000, 0x917C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8EF6, 0x9D7B, + 0x0000, 0x0000, 0x8FB6, 0x0000, 0x9D75, 0x9D7A, + 0x0000, 0x0000, 0x9472, 0x0000, 0x0000, 0x0000, + 0x9D74, 0x0000, 0x8C40, 0x0000, 0x0000, 0x8A7C, + 0x0000, 0x0000, 0x0000, 0x9D7C, 0x97A9, 0x8DCC, + 0x9254, 0x9D79, 0x0000, 0x90DA, 0x0000, 0x8D54, + 0x9084, 0x8986, 0x915B, 0x9D77, 0x8B64, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8C66, 0x0000, + 0x92CD, 0x9D7D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x917E, 0x0000, 0x0000, 0x9D81, 0x0000, + 0x9D83, 0x0000, 0x0000, 0x91B5, 0x9D89, 0x0000, + 0x9D84, 0x0000, 0x0000, 0x9D86, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9560, 0x92F1, 0x0000, + 0x9D87, 0x0000, 0x0000, 0x0000, 0x974B, 0x0000, + 0x0000, 0x0000, 0x9767, 0x8AB7, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x88AC, 0x0000, 0x9D85, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9D82, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8AF6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8987, 0x0000, + 0x9D88, 0x0000, 0x0000, 0x0000, 0x9768, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs64[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9D8C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x91B9, 0x0000, 0x9D93, 0x0000, 0x0000, + 0x0000, 0x9D8D, 0x0000, 0x0000, 0x9D8A, 0x9D91, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9D72, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9D8E, 0x0000, 0x9D92, 0x0000, + 0x0000, 0x0000, 0x94C0, 0x938B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9D8B, 0x0000, + 0x9D8F, 0x0000, 0x0000, 0x0000, 0x8C67, 0x0000, + 0x0000, 0x0000, 0x8DEF, 0x0000, 0x0000, 0x0000, + 0x90DB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9D97, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9345, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9D94, 0x0000, 0x9680, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9D95, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9D96, 0x0000, + 0x96CC, 0x0000, 0x90A0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C82, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9D9D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8E54, 0x9D9A, 0x0000, 0x9D99, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9451, 0x0000, + 0x0000, 0x0000, 0x93B3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9350, 0x9D9B, 0x0000, 0x0000, + 0x0000, 0x9D9C, 0x0000, 0x958F, 0x0000, 0x9464, + 0x8E42, 0x0000, 0x90EF, 0x0000, 0x966F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8A68, + 0x0000, 0x9DA3, 0x9D9E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9769, 0x9DA5, 0x0000, 0x0000, 0x9DA1, + 0x0000, 0x9DA2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9180, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9DA0, 0x0000, 0x9D5E, 0x0000, 0x0000, 0x0000, + 0x9DA4, 0x0000, 0x9D9F, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9DA9, 0x9DAA, 0x9346, 0x9DAC, + 0x0000, 0x0000, 0x8E43, 0x9DA7, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8B5B, 0x0000, 0x0000, 0x9DAD, + 0x0000, 0x9DA6, 0x9DB1, 0x0000, 0x9DB0, 0x0000, + 0x9DAF, 0x0000, 0x0000, 0x0000, 0x9DB2, 0x0000, + 0x0000, 0x9DB4, 0x8FEF, 0x0000 +}; + +static u16 Ucs65[256] = { + 0x9DB3, 0x0000, 0x0000, 0x0000, 0x0000, 0x9DB7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9DB5, 0x0000, 0x0000, 0x0000, 0x9DB6, 0x9D90, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9DB9, + 0x9DB8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9D98, 0x9DBA, 0x9DAE, 0x0000, 0x0000, 0x8E78, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9DBB, 0x9DBC, + 0x9DBE, 0x9DBD, 0x9DBF, 0x89FC, 0x0000, 0x8D55, + 0x0000, 0x0000, 0x95FA, 0x90AD, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8CCC, 0x0000, 0x0000, + 0x9DC1, 0x0000, 0x0000, 0x0000, 0x0000, 0x9DC4, + 0x0000, 0x9571, 0x0000, 0x8B7E, 0x0000, 0x0000, + 0x0000, 0x9DC3, 0x9DC2, 0x9473, 0x9DC5, 0x8BB3, + 0x0000, 0x0000, 0x0000, 0x9DC7, 0x9DC6, 0x0000, + 0x0000, 0x0000, 0x8AB8, 0x8E55, 0x0000, 0x0000, + 0x93D6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C68, 0x0000, 0x0000, 0x0000, 0x9094, 0x0000, + 0x9DC8, 0x0000, 0x90AE, 0x9347, 0x0000, 0x957E, + 0x9DC9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9DCA, 0x9DCB, + 0x0000, 0x0000, 0x0000, 0x95B6, 0x9B7C, 0x90C4, + 0x0000, 0x0000, 0x956B, 0x0000, 0x8DD6, 0x0000, + 0x94E3, 0x94C1, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x936C, 0x0000, 0x97BF, 0x0000, 0x9DCD, + 0x8ECE, 0x0000, 0x0000, 0x9DCE, 0x0000, 0x88B4, + 0x0000, 0x0000, 0x8BD2, 0x90CB, 0x0000, 0x9580, + 0x0000, 0x0000, 0x0000, 0x9DCF, 0x8E61, 0x9266, + 0x0000, 0x8E7A, 0x9056, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9DD0, 0x0000, 0x95FB, + 0x0000, 0x0000, 0x8997, 0x8E7B, 0x0000, 0x0000, + 0x0000, 0x9DD3, 0x0000, 0x9DD1, 0x9DD4, 0x97B7, + 0x9DD2, 0x0000, 0x0000, 0x0000, 0x0000, 0x90F9, + 0x9DD5, 0x0000, 0x0000, 0x91B0, 0x0000, 0x0000, + 0x9DD6, 0x0000, 0x0000, 0x0000, 0x0000, 0x8AF8, + 0x0000, 0x9DD8, 0x0000, 0x9DD7, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9DD9, 0x9DDA, 0x8AF9, 0x0000, + 0x0000, 0x93FA, 0x9255, 0x8B8C, 0x8E7C, 0x9181, + 0x0000, 0x0000, 0x8F7B, 0x88AE, 0x0000, 0x0000, + 0x0000, 0x9DDB, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x89A0, 0x9DDF, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs66[256] = { + 0x0000, 0x0000, 0x8D56, 0x9DDE, 0x0000, 0x0000, + 0x8DA9, 0x8FB8, 0x0000, 0x0000, 0x9DDD, 0x0000, + 0x8FB9, 0x0000, 0x96BE, 0x8DA8, 0x0000, 0x0000, + 0x0000, 0x88D5, 0x90CC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9DE4, 0x0000, + 0x0000, 0x90AF, 0x8966, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8F74, 0x0000, 0x9686, 0x8DF0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8FBA, 0x0000, 0x90A5, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9DE3, 0x9DE1, + 0x9DE2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x928B, 0x0000, 0x0000, 0x9E45, 0x0000, 0x9DE8, + 0x8E9E, 0x8D57, 0x9DE6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9DE7, 0x0000, 0x9057, 0x0000, 0x0000, + 0x0000, 0x9DE5, 0x0000, 0x0000, 0x8E4E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9DEA, 0x9DE9, 0x9DEE, + 0x0000, 0x0000, 0x9DEF, 0x0000, 0x9DEB, 0x0000, + 0x8A41, 0x9DEC, 0x9DED, 0x94D3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9581, 0x8C69, 0x9DF0, 0x0000, + 0x0000, 0x0000, 0x90B0, 0x0000, 0x8FBB, 0x0000, + 0x0000, 0x0000, 0x9271, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8BC5, 0x0000, 0x9DF1, + 0x9DF5, 0x0000, 0x0000, 0x89C9, 0x9DF2, 0x9DF4, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9DF3, 0x0000, + 0x0000, 0x8F8B, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9267, 0x88C3, 0x9DF6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9DF7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x92A8, 0x0000, 0x0000, 0x0000, 0x97EF, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8E62, 0x0000, 0x0000, + 0x95E9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x965C, 0x0000, 0x0000, 0x0000, 0x9E41, 0x9DF9, + 0x0000, 0x0000, 0x9DFC, 0x0000, 0x9DFB, 0x0000, + 0x0000, 0x9DF8, 0x0000, 0x0000, 0x9E40, 0x0000, + 0x0000, 0x93DC, 0x0000, 0x9DFA, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9E42, 0x0000, + 0x0000, 0x8F8C, 0x9E43, 0x0000, 0x976A, 0x9498, + 0x0000, 0x0000, 0x9E44, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9E46, 0x0000, 0x0000, 0x9E47, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9E48, 0x0000, 0x8BC8, 0x8967, 0x8D58, 0x9E49, + 0x0000, 0x9E4A, 0x8F91, 0x9182, 0x0000, 0x0000, + 0x99D6, 0x915D, 0x915C, 0x91D6 +}; + +static u16 Ucs67[256] = { + 0x8DC5, 0x0000, 0x0000, 0x98F0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8C8E, 0x974C, 0x0000, 0x95FC, + 0x0000, 0x959E, 0x0000, 0x9E4B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8DF1, 0x92BD, 0x9E4C, 0x984E, + 0x0000, 0x0000, 0x0000, 0x965D, 0x0000, 0x92A9, + 0x9E4D, 0x8AFA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9E4E, 0x9E4F, 0x96D8, 0x0000, + 0x96A2, 0x9696, 0x967B, 0x8E44, 0x9E51, 0x0000, + 0x0000, 0x8EE9, 0x0000, 0x0000, 0x9670, 0x0000, + 0x9E53, 0x9E56, 0x9E55, 0x0000, 0x8AF7, 0x0000, + 0x0000, 0x8B80, 0x0000, 0x9E52, 0x0000, 0x9E54, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9E57, 0x0000, + 0x0000, 0x9099, 0x0000, 0x0000, 0x0000, 0x0000, + 0x979B, 0x88C7, 0x8DDE, 0x91BA, 0x0000, 0x8EDB, + 0x0000, 0x0000, 0x8FF1, 0x0000, 0x0000, 0x9E5A, + 0x0000, 0x0000, 0x936D, 0x0000, 0x9E58, 0x91A9, + 0x9E59, 0x8FF0, 0x96DB, 0x9E5B, 0x9E5C, 0x9788, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9E61, 0x0000, + 0x0000, 0x8D59, 0x0000, 0x9474, 0x9E5E, 0x938C, + 0x9DDC, 0x9DE0, 0x0000, 0x8B6E, 0x0000, 0x9466, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9E60, 0x0000, + 0x8FBC, 0x94C2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9E66, 0x0000, 0x94F8, 0x0000, 0x9E5D, + 0x0000, 0x9E63, 0x9E62, 0x0000, 0x0000, 0x0000, + 0x90CD, 0x0000, 0x0000, 0x0000, 0x0000, 0x968D, + 0x0000, 0x97D1, 0x0000, 0x0000, 0x9687, 0x0000, + 0x89CA, 0x8E7D, 0x0000, 0x0000, 0x9867, 0x9E65, + 0x9095, 0x0000, 0x0000, 0x0000, 0x9E64, 0x0000, + 0x0000, 0x9E5F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8CCD, 0x0000, 0x0000, 0x0000, 0x9E6B, + 0x9E69, 0x0000, 0x89CB, 0x9E67, 0x9E6D, 0x9E73, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x91C6, 0x0000, 0x0000, 0x95BF, 0x0000, + 0x9E75, 0x0000, 0x0000, 0x0000, 0x9541, 0x0000, + 0x0000, 0x0000, 0x9E74, 0x9490, 0x965E, 0x8AB9, + 0x0000, 0x90F5, 0x8F5F, 0x0000, 0x0000, 0x0000, + 0x92D1, 0x0000, 0x974D, 0x0000, 0x0000, 0x9E70, + 0x9E6F, 0x0000, 0x0000, 0x0000, 0x9E71, 0x0000, + 0x9E6E, 0x0000, 0x0000, 0x9E76, 0x0000, 0x9E6C, + 0x0000, 0x0000, 0x9E6A, 0x0000, 0x9E72, 0x9E68, + 0x0000, 0x928C, 0x0000, 0x96F6, 0x8EC4, 0x8DF2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8DB8, + 0x0000, 0x0000, 0x968F, 0x8A60 +}; + +static u16 Ucs68[256] = { + 0x0000, 0x0000, 0x92CC, 0x93C8, 0x8968, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x90F0, 0x0000, 0x0000, 0x90B2, 0x8C49, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9E78, 0x0000, 0x0000, 0x8D5A, 0x8A9C, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9E7A, + 0x8A94, 0x9E81, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9E7D, 0x0000, 0x90F1, 0x0000, + 0x0000, 0x0000, 0x8A6A, 0x8DAA, 0x0000, 0x0000, + 0x8A69, 0x8DCD, 0x0000, 0x0000, 0x9E7B, 0x8C85, + 0x8C6A, 0x938D, 0x0000, 0x0000, 0x9E79, 0x0000, + 0x88C4, 0x0000, 0x0000, 0x0000, 0x0000, 0x9E7C, + 0x9E7E, 0x0000, 0x8BCB, 0x8C4B, 0x0000, 0x8ABA, + 0x8B6A, 0x0000, 0x0000, 0x0000, 0x0000, 0x9E82, + 0x0000, 0x0000, 0x8DF7, 0x9691, 0x0000, 0x8E56, + 0x0000, 0x0000, 0x0000, 0x9E83, 0x0000, 0x0000, + 0x0000, 0x954F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9E8F, 0x0000, 0x89B1, 0x9E84, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9E95, 0x9E85, 0x0000, 0x97C0, 0x0000, 0x9E8C, + 0x0000, 0x947E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9E94, 0x0000, 0x9E87, + 0x0000, 0x0000, 0x0000, 0x88B2, 0x9E89, 0x0000, + 0x0000, 0x8D5B, 0x0000, 0x0000, 0x0000, 0x9E8B, + 0x0000, 0x9E8A, 0x0000, 0x9E86, 0x9E91, 0x0000, + 0x8FBD, 0x0000, 0x0000, 0x0000, 0x9AEB, 0x8CE6, + 0x979C, 0x0000, 0x0000, 0x0000, 0x0000, 0x9E88, + 0x0000, 0x92F2, 0x8A42, 0x8DAB, 0x0000, 0x9E80, + 0x0000, 0x9E90, 0x8A81, 0x0000, 0x0000, 0x9E8E, + 0x9E92, 0x0000, 0x938E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8AFC, 0x0000, + 0x9EB0, 0x0000, 0x0000, 0x96C7, 0x9E97, 0x8AFB, + 0x0000, 0x9E9E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x965F, 0x0000, 0x9E9F, 0x9EA1, 0x0000, 0x9EA5, + 0x9E99, 0x0000, 0x9249, 0x0000, 0x0000, 0x0000, + 0x0000, 0x938F, 0x9EA9, 0x9E9C, 0x0000, 0x9EA6, + 0x0000, 0x0000, 0x0000, 0x9EA0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9058, 0x9EAA, + 0x0000, 0x0000, 0x90B1, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9EA8, 0x8ABB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs69[256] = { + 0x986F, 0x9E96, 0x0000, 0x0000, 0x9EA4, 0x88D6, + 0x0000, 0x0000, 0x9E98, 0x0000, 0x0000, 0x96B8, + 0x9E9D, 0x9041, 0x92C5, 0x9E93, 0x0000, 0x0000, + 0x9EA3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x909A, 0x9EAD, 0x8A91, 0x8C9F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9EAF, 0x9E9A, 0x9EAE, + 0x0000, 0x9EA7, 0x9E9B, 0x0000, 0x9EAB, 0x0000, + 0x9EAC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9EBD, 0x0000, 0x0000, 0x0000, 0x93CC, 0x0000, + 0x9EA2, 0x0000, 0x0000, 0x9EB9, 0x0000, 0x0000, + 0x0000, 0x9EBB, 0x0000, 0x92D6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x976B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9596, + 0x9EB6, 0x91C8, 0x0000, 0x0000, 0x0000, 0x9EBC, + 0x915E, 0x0000, 0x9EB3, 0x9EC0, 0x9EBF, 0x0000, + 0x93ED, 0x9EBE, 0x93E8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9EC2, 0x9EB5, + 0x0000, 0x8BC6, 0x9EB8, 0x8F7C, 0x0000, 0x0000, + 0x0000, 0x9480, 0x9EBA, 0x8BC9, 0x0000, 0x9EB2, + 0x9EB4, 0x9EB1, 0x0000, 0x0000, 0x984F, 0x8A79, + 0x9EB7, 0x0000, 0x0000, 0x9EC1, 0x8A54, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8DE5, 0x0000, 0x0000, 0x0000, 0x897C, 0x0000, + 0x0000, 0x9ED2, 0x0000, 0x0000, 0x9850, 0x9ED5, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9059, + 0x9ED4, 0x0000, 0x0000, 0x0000, 0x9ED3, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9ED0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9EC4, 0x0000, 0x0000, 0x9EE1, 0x9EC3, 0x0000, + 0x9ED6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9ECE, 0x0000, 0x0000, 0x9EC9, 0x9EC6, + 0x0000, 0x9EC7, 0x0000, 0x9ECF, 0x0000, 0x0000, + 0x0000, 0xEAA0, 0x0000, 0x0000, 0x9ECC, 0x8D5C, + 0x92C6, 0x9184, 0x9ECA, 0x0000, 0x9EC5, 0x0000, + 0x0000, 0x9EC8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x976C, 0x968A, 0x0000, 0x0000, 0x0000, 0x9ECD, + 0x9ED7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9EDF, 0x9ED8, 0x0000, + 0x0000, 0x9EE5, 0x0000, 0x9EE3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9EDE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9EDD, 0x0000, 0x92CE, + 0x0000, 0x9185, 0x0000, 0x9EDB +}; + +static u16 Ucs6A[256] = { + 0x0000, 0x0000, 0x9ED9, 0x0000, 0x0000, 0x9EE0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9EE6, 0x94F3, + 0x9EEC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9EE7, 0x9EEA, 0x9EE4, 0x0000, 0x0000, 0x9294, + 0x0000, 0x9557, 0x0000, 0x9EDA, 0x0000, 0x0000, + 0x9EE2, 0x8FBE, 0x0000, 0x96CD, 0x9EF6, 0x9EE9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8CA0, + 0x89A1, 0x8A7E, 0x0000, 0x0000, 0x9ED1, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8FBF, + 0x9EEE, 0x0000, 0x9EF5, 0x8EF7, 0x8A92, 0x0000, + 0x0000, 0x924D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9EEB, 0x0000, 0x0000, 0x9EF0, + 0x9EF4, 0x0000, 0x0000, 0x8BB4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8B6B, 0x9EF2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8B40, + 0x0000, 0x93C9, 0x9EF1, 0x0000, 0x0000, 0x0000, + 0x9EF3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9EED, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9EEF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8A80, 0x9268, 0x0000, 0x0000, 0x0000, + 0x9EFA, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9EF8, 0x8CE7, 0x0000, + 0x9EF7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9F40, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9E77, 0x0000, 0x0000, 0x0000, 0x9EF9, 0x0000, + 0x9EFB, 0x9EFC, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F4B, 0x0000, 0x9F47, 0x0000, + 0x9E8D, 0x0000, 0x0000, 0x0000, 0x0000, 0x9F46, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9F45, 0x0000, + 0x0000, 0x9F42, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9EE8, 0x9F44, 0x9F43, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9F49, + 0x0000, 0x9845, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F4C, 0x8BF9, 0x0000, 0x0000, + 0x9F48, 0x9F4A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x94A5, 0x0000, + 0x9F4D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9F51, 0x9F4E, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs6B[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x9793, 0x9F4F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9EDC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9F52, 0x0000, 0x0000, 0x0000, 0x9F53, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8954, + 0x0000, 0x9F55, 0x8C87, 0x8E9F, 0x0000, 0x8BD3, + 0x0000, 0x0000, 0x0000, 0x89A2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x977E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9F57, 0x9F56, 0x9F59, 0x8B5C, 0x0000, + 0x0000, 0x8BD4, 0x8ABC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9F5C, 0x0000, 0x0000, 0x0000, 0x9F5B, + 0x0000, 0x9F5D, 0x0000, 0x0000, 0x89CC, 0x0000, + 0x9256, 0x0000, 0x9F5E, 0x0000, 0x0000, 0x8ABD, + 0x9F60, 0x0000, 0x0000, 0x0000, 0x0000, 0x9F5F, + 0x0000, 0x9F61, 0x0000, 0x0000, 0x0000, 0x9F62, + 0x0000, 0x9F63, 0x8E7E, 0x90B3, 0x8D9F, 0x0000, + 0x9590, 0x0000, 0x0000, 0x95E0, 0x9863, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8E95, 0x0000, 0x0000, + 0x0000, 0x8DCE, 0x97F0, 0x0000, 0x0000, 0x0000, + 0x9F64, 0x9F65, 0x0000, 0x8E80, 0x0000, 0x0000, + 0x0000, 0x9F66, 0x9F67, 0x0000, 0x0000, 0x9F69, + 0x9F68, 0x0000, 0x9677, 0x0000, 0x0000, 0x8F7D, + 0x8EEA, 0x8E63, 0x0000, 0x9F6A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9F6C, + 0x9042, 0x0000, 0x9F6B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F6D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F6E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F6F, 0x9F70, 0x0000, 0x0000, + 0x0000, 0x9F71, 0x0000, 0x9F73, 0x9F72, 0x9F74, + 0x89A3, 0x9269, 0x0000, 0x9F75, 0x0000, 0x0000, + 0x8E45, 0x8A6B, 0x9F76, 0x0000, 0x0000, 0x9361, + 0x9ACA, 0x0000, 0x0000, 0x0000, 0x0000, 0x8B42, + 0x9F77, 0x0000, 0x0000, 0x0000, 0x0000, 0x9F78, + 0x0000, 0x95EA, 0x9688, 0x0000, 0x0000, 0x0000, + 0x93C5, 0x9F79, 0x94E4, 0x0000, 0x0000, 0x0000, + 0x94F9, 0x0000, 0x0000, 0x96D1, 0x0000, 0x0000, + 0x0000, 0x9F7A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9F7C, 0x9F7B, 0x0000, 0x0000, 0x9F7E, + 0x0000, 0x0000, 0x0000, 0x9F7D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs6C[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F81, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8E81, 0x0000, 0x96AF, + 0x0000, 0x9F82, 0x9F83, 0x0000, 0x0000, 0x8B43, + 0x0000, 0x0000, 0x0000, 0x9F84, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9F86, + 0x9F85, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9085, 0x0000, + 0x0000, 0x9558, 0x8969, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x94C3, 0x0000, 0x92F3, 0x8F60, + 0x8B81, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x94C4, 0x0000, 0x8EAC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9F88, 0x0000, 0x8ABE, 0x0000, 0x0000, + 0x8998, 0x0000, 0x0000, 0x93F0, 0x9F87, 0x8D5D, + 0x9272, 0x0000, 0x9F89, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9F91, 0x0000, 0x9F8A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x91BF, 0x0000, + 0x8B82, 0x9F92, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8C88, 0x0000, 0x0000, 0x8B44, + 0x9F90, 0x0000, 0x0000, 0x9F8E, 0x9F8B, 0x9780, + 0x0000, 0x0000, 0x0000, 0x0000, 0x92BE, 0x0000, + 0x0000, 0x0000, 0x93D7, 0x9F8C, 0x0000, 0x0000, + 0x9F94, 0x0000, 0x9F93, 0x8C42, 0x0000, 0x0000, + 0x89AB, 0x0000, 0x0000, 0x8DB9, 0x9F8D, 0x9F8F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9676, + 0x91F2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9697, 0x0000, 0x0000, + 0x9F9C, 0x0000, 0x0000, 0x9F9D, 0x0000, 0x89CD, + 0x0000, 0x0000, 0x0000, 0x0000, 0x95A6, 0x96FB, + 0x9F9F, 0x8EA1, 0x8FC0, 0x9F98, 0x9F9E, 0x8988, + 0x0000, 0x8BB5, 0x0000, 0x0000, 0x9F95, 0x9F9A, + 0x0000, 0x0000, 0x0000, 0x90F2, 0x9491, 0x0000, + 0x94E5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9F97, 0x0000, 0x9640, 0x0000, 0x9F99, + 0x0000, 0x9FA2, 0x0000, 0x9FA0, 0x0000, 0x9F9B, + 0x0000, 0x0000, 0x0000, 0x9641, 0x9467, 0x8B83, + 0x0000, 0x9344, 0x0000, 0x0000, 0x928D, 0x0000, + 0x9FA3, 0x0000, 0x0000, 0x0000, 0x0000, 0x9FA1, + 0x91D7, 0x9F96, 0x0000, 0x896A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs6D[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x976D, + 0x9FAE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9FAD, 0x0000, 0x0000, 0x0000, 0x0000, 0x90F4, + 0x0000, 0x9FAA, 0x0000, 0x978C, 0x0000, 0x0000, + 0x93B4, 0x9FA4, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x92C3, 0x0000, 0x0000, 0x0000, 0x896B, + 0x8D5E, 0x9FA7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8F46, 0x9FAC, 0x0000, 0x9FAB, + 0x9FA6, 0x0000, 0x9FA9, 0x0000, 0x0000, 0x8A88, + 0x0000, 0x9FA8, 0x9468, 0x0000, 0x0000, 0x97AC, + 0x0000, 0x0000, 0x8FF2, 0x90F3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9FB4, + 0x9FB2, 0x0000, 0x956C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9FAF, 0x9FB1, 0x0000, + 0x8959, 0x0000, 0x0000, 0x8D5F, 0x9851, 0x0000, + 0x8A5C, 0x0000, 0x9582, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9781, 0x0000, 0x0000, 0x8A43, + 0x905A, 0x9FB3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9FB8, 0x0000, 0x0000, 0x8FC1, 0x0000, + 0x0000, 0x0000, 0x974F, 0x0000, 0x9FB5, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9FB0, 0x0000, 0x9FB6, + 0x0000, 0x0000, 0x0000, 0x97DC, 0x0000, 0x9393, + 0x93C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8A55, 0x0000, 0x0000, 0x8974, 0x0000, + 0x0000, 0x9FBC, 0x0000, 0x0000, 0x9FBF, 0x0000, + 0x0000, 0x0000, 0x97C1, 0x0000, 0x0000, 0x0000, + 0x9784, 0x0000, 0x0000, 0x0000, 0x0000, 0x9FC6, + 0x9FC0, 0x9FBD, 0x0000, 0x0000, 0x0000, 0x97D2, + 0x9FC3, 0x0000, 0x0000, 0x0000, 0x0000, 0x8F69, + 0x9FC5, 0x0000, 0x0000, 0x9FCA, 0x0000, 0x0000, + 0x9391, 0x9FC8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9FC2, 0x0000, 0x0000, 0x9257, 0x0000, 0x0000, + 0x9FC9, 0x0000, 0x9FBE, 0x0000, 0x9FC4, 0x0000, + 0x9FCB, 0x88FA, 0x9FC1, 0x0000, 0x9FCC, 0x0000, + 0x0000, 0x905B, 0x0000, 0x8F7E, 0x0000, 0x95A3, + 0x0000, 0x8DAC, 0x0000, 0x9FB9, 0x9FC7, 0x9359, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs6E[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90B4, + 0x0000, 0x8A89, 0x8DCF, 0x8FC2, 0x9FBB, 0x8F61, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8C6B, 0x0000, 0x9FBA, 0x0000, 0x0000, + 0x0000, 0x9FD0, 0x8F8D, 0x8CB8, 0x0000, 0x9FDF, + 0x0000, 0x9FD9, 0x8B94, 0x936E, 0x0000, 0x9FD4, + 0x9FDD, 0x88AD, 0x8951, 0x0000, 0x0000, 0x89B7, + 0x0000, 0x9FD6, 0x91AA, 0x9FCD, 0x9FCF, 0x8D60, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9FE0, 0x0000, 0x9FDB, 0x0000, + 0x0000, 0x0000, 0x9FD3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9FDA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x96A9, 0x0000, 0x0000, 0x9FD8, + 0x9FDC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8CCE, 0x0000, 0x8FC3, 0x0000, + 0x0000, 0x9258, 0x0000, 0x0000, 0x0000, 0x9FD2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x974E, 0x0000, 0x0000, 0x0000, 0x9FD5, + 0x0000, 0x0000, 0x9FCE, 0x9392, 0x0000, 0x0000, + 0x9FD1, 0x0000, 0x0000, 0x0000, 0x9FD7, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9870, 0x8EBC, 0x969E, 0x0000, 0x9FE1, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x94AC, 0x0000, 0x0000, 0x9FED, + 0x8CB9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F80, 0x0000, 0x9FE3, 0x0000, 0x0000, 0x0000, + 0x97AD, 0x8D61, 0x0000, 0x9FF0, 0x0000, 0x0000, + 0x88EC, 0x0000, 0x0000, 0x9FEE, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9FE2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9FE8, 0x0000, 0x0000, 0x9FEA, 0x0000, + 0x0000, 0x0000, 0x976E, 0x9FE5, 0x0000, 0x0000, + 0x934D, 0x0000, 0x0000, 0x9FE7, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9FEF, 0x0000, 0x9FE9, 0x96C5, + 0x0000, 0x0000, 0x0000, 0x9FE4, 0x0000, 0x8EA0, + 0x9FFC, 0x0000, 0x0000, 0x0000, 0x0000, 0x8A8A, + 0x0000, 0x9FE6, 0x9FEB, 0x9FEC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91EA, + 0x91D8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9FF4, 0x0000, 0x0000, 0x9FFA, + 0x0000, 0x0000, 0x9FF8, 0x0000, 0x9348, 0x0000, + 0x0000, 0xE042, 0x9FF5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9FF6, 0x9FDE +}; + +static u16 Ucs6F[256] = { + 0x0000, 0x8B99, 0x9559, 0x0000, 0x0000, 0x0000, + 0x8EBD, 0x0000, 0x0000, 0x8D97, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9852, 0x0000, 0x9FF2, + 0x0000, 0xE041, 0x8989, 0x9186, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9499, 0x0000, 0x8ABF, 0x97F8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x969F, 0x92D0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9FF9, 0x9FFB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9151, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE040, 0x9FF7, 0x0000, 0x9FF1, + 0x0000, 0x0000, 0x0000, 0x8AC1, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C89, 0x0000, 0x0000, 0x0000, 0xE04E, 0x0000, + 0x0000, 0xE049, 0x90F6, 0x0000, 0x0000, 0x8A83, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8F81, 0x0000, + 0xE052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE04B, 0x92AA, 0xE048, 0x92D7, 0x0000, + 0x0000, 0x0000, 0xE06B, 0x0000, 0x0000, 0x0000, + 0xE045, 0x0000, 0xE044, 0x0000, 0xE04D, 0x0000, + 0x0000, 0x0000, 0xE047, 0xE046, 0xE04C, 0x0000, + 0x909F, 0x0000, 0xE043, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE04F, 0x0000, + 0x0000, 0xE050, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8AC0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE055, + 0x0000, 0xE054, 0xE056, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE059, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9362, 0x0000, 0xE053, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE057, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C83, 0x91F7, 0xE051, 0x945A, 0x0000, 0x0000, + 0xE058, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE05D, 0xE05B, 0x0000, 0x0000, + 0xE05E, 0x0000, 0x0000, 0xE061, 0x0000, 0x0000, + 0x0000, 0xE05A, 0x8D8A, 0x9447, 0x0000, 0x0000, + 0x9FB7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9794, 0xE05C, 0x0000, 0xE060, 0x91F3, + 0x0000, 0xE05F, 0x0000, 0xE04A, 0x0000, 0x0000, + 0xE889, 0x0000, 0x0000, 0x0000, 0xE064, 0x0000, + 0x0000, 0x0000, 0xE068, 0x0000 +}; + +static u16 Ucs70[256] = { + 0x0000, 0xE066, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE062, 0x0000, 0xE063, + 0x0000, 0x0000, 0x0000, 0xE067, 0x0000, 0xE065, + 0x0000, 0x0000, 0x0000, 0x956D, 0x0000, 0x0000, + 0xE06D, 0x0000, 0xE06A, 0xE069, 0x0000, 0xE06C, + 0x93D2, 0xE06E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9295, 0x91EB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x90A3, 0x0000, 0x0000, 0x0000, + 0xE06F, 0x0000, 0xE071, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE070, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9FF3, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE072, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x93E5, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE073, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89CE, + 0x0000, 0x0000, 0x0000, 0x9394, 0x8A44, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8B84, 0x0000, 0x0000, 0x0000, 0x8EDC, 0x8DD0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9846, + 0x9086, 0x0000, 0x0000, 0x0000, 0x898A, 0x0000, + 0x0000, 0x0000, 0xE075, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE074, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE078, 0x9259, + 0xE07B, 0xE076, 0x0000, 0x0000, 0x0000, 0xE07A, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE079, 0x935F, + 0x88D7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x97F3, 0x0000, 0x0000, 0xE07D, + 0x0000, 0x0000, 0x0000, 0x8947, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE080, 0x0000, 0x0000, 0x0000, 0xE07E, + 0x0000, 0xE07C, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE077, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9642, 0x0000, 0x0000, + 0x0000, 0xE082, 0x0000, 0x0000 +}; + +static u16 Ucs71[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE081, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x898B, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE084, 0x95B0, 0x0000, 0xE083, 0x0000, + 0x0000, 0x0000, 0x0000, 0x96B3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8FC5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9152, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8FC4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x97F9, 0x0000, 0x0000, 0xE08A, 0x0000, + 0x90F7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE086, 0xE08B, 0x0000, 0x0000, 0x898C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE089, 0x0000, 0x9481, 0xE085, + 0xE088, 0x8FC6, 0x0000, 0x94CF, 0x0000, 0x0000, + 0xE08C, 0x0000, 0x8ECF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90F8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE08F, 0x0000, 0x0000, 0x0000, 0xE087, 0x0000, + 0x8C46, 0x0000, 0x0000, 0x0000, 0x0000, 0xE08D, + 0x0000, 0x0000, 0x0000, 0x0000, 0x976F, 0xE090, + 0x0000, 0x0000, 0x0000, 0xEAA4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8F6E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE091, 0x0000, 0x0000, 0x0000, 0xE092, 0x0000, + 0x0000, 0x0000, 0x0000, 0x944D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE094, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE095, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9452, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9395, 0xE097, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE099, 0x0000, 0x97D3, 0x0000, + 0xE096, 0x0000, 0xE098, 0x898D, 0x0000, 0xE093, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9A7A, 0xE09A, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9187, 0x8E57, 0xE09C, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE09B, 0x9043, 0x99D7, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE09D, + 0x0000, 0x0000, 0x0000, 0xE09F, 0x0000, 0xE08E, + 0xE09E, 0x0000, 0x0000, 0xE0A0 +}; + +static u16 Ucs72[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x949A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0A1, 0x0000, 0x0000, 0xE0A2, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0A3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0A4, 0x0000, + 0x92DC, 0x0000, 0xE0A6, 0xE0A5, 0x0000, 0x0000, + 0xE0A7, 0x0000, 0xE0A8, 0x0000, 0x0000, 0x8EDD, + 0x9583, 0x0000, 0x0000, 0x0000, 0x96EA, 0xE0A9, + 0xE0AA, 0x9175, 0x8EA2, 0xE0AB, 0xE0AC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0AD, 0x95D0, + 0x94C5, 0x0000, 0x0000, 0xE0AE, 0x9476, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x92AB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0AF, 0x89E5, + 0x0000, 0x8B8D, 0x0000, 0x96C4, 0x0000, 0x96B4, + 0x0000, 0x89B2, 0x9853, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9671, 0x0000, 0x95A8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x90B5, 0x0000, 0xE0B0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x93C1, 0x0000, 0x0000, 0x0000, 0x8CA1, + 0xE0B1, 0x0000, 0x8DD2, 0xE0B3, 0xE0B2, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0B4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0B5, 0x0000, 0x0000, 0x0000, + 0xE0B6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8B5D, 0x0000, + 0xE0B7, 0x0000, 0x0000, 0x0000, 0x0000, 0xE0B8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8CA2, 0x0000, + 0x0000, 0x94C6, 0x0000, 0x0000, 0xE0BA, 0x0000, + 0x0000, 0x0000, 0x8FF3, 0x0000, 0x0000, 0xE0B9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8BB6, 0xE0BB, 0xE0BD, 0x0000, + 0xE0BC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0BE, 0x0000, 0x8CCF, 0x0000, + 0xE0BF, 0x0000, 0x0000, 0x0000, 0x0000, 0x8BE7, + 0x0000, 0x915F, 0x0000, 0x8D9D, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0C1, 0xE0C2, 0xE0C0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8EEB, + 0x0000, 0x0000, 0x93C6, 0x8BB7, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0C4, 0x924B, 0xE0C3, 0x0000, 0x0000, + 0x9854, 0x9482, 0x0000, 0x0000 +}; + +static u16 Ucs73[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0C7, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0C9, 0xE0C6, + 0x0000, 0x0000, 0x0000, 0x96D2, 0xE0C8, 0xE0CA, + 0x0000, 0x97C2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0CE, 0x0000, 0x0000, 0x0000, 0xE0CD, + 0x9296, 0x944C, 0x0000, 0x0000, 0x8CA3, 0xE0CC, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0CB, 0x0000, + 0x9750, 0x9751, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0CF, 0x898E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8D96, 0x8E82, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE0D0, 0xE0D1, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0D3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8F62, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0D5, 0x0000, 0xE0D4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0D6, 0x0000, + 0x8A6C, 0x0000, 0x0000, 0xE0D8, 0x0000, 0x0000, + 0xE0D7, 0x0000, 0xE0DA, 0xE0D9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8CBA, 0x0000, 0x0000, 0x97A6, 0x0000, 0x8BCA, + 0x0000, 0x89A4, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8BE8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8ADF, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x97E6, 0xE0DC, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0DE, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE0DF, 0x0000, 0x89CF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0DB, 0x0000, 0x8E58, 0x0000, + 0x0000, 0x92BF, 0xE0DD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE0E2, 0x0000, 0x8EEC, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0E0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C5D, 0x0000, 0x0000, 0x94C7, 0xE0E1, 0x0000, + 0x0000, 0xE0FC, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0E7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8CBB, 0x0000 +}; + +static u16 Ucs74[256] = { + 0x0000, 0x0000, 0x0000, 0x8B85, 0x0000, 0xE0E4, + 0x979D, 0x0000, 0x0000, 0x97AE, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x91F4, 0x0000, + 0x0000, 0xE0E6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0E8, 0x97D4, 0x8BD5, 0x94FA, + 0x9469, 0x0000, 0x0000, 0x0000, 0xE0E9, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0EB, 0x0000, 0xE0EE, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0EA, 0x0000, 0x0000, 0x0000, 0xE0ED, + 0x8CE8, 0x896C, 0xE0EF, 0x0000, 0x9090, 0xE0EC, + 0x97DA, 0x0000, 0x0000, 0xE0F2, 0xEAA2, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0F0, 0xE0F3, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0E5, 0xE0F1, 0x0000, + 0x0000, 0x8DBA, 0x0000, 0x0000, 0xE0F4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE0F5, 0x0000, 0x0000, 0x0000, 0x0000, 0x979E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE0F6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0F7, 0x0000, 0x0000, 0x0000, + 0xE0E3, 0x0000, 0x0000, 0x0000, 0x0000, 0xE0F8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8AC2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8EA3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE0F9, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE0FA, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE0FB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x895A, 0x0000, + 0x0000, 0x0000, 0xE140, 0x0000, 0x955A, 0xE141, + 0x0000, 0x0000, 0x8AA2, 0xE142, 0x0000, 0xE143, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE144, 0x0000, + 0xE146, 0xE147, 0xE145, 0x0000, 0x0000, 0x0000, + 0x9572, 0xE149, 0xE148, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs75[256] = { + 0x0000, 0x0000, 0x0000, 0xE14B, 0xE14A, 0xE14C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE14D, 0xE14F, 0xE14E, 0x0000, 0x0000, 0x8D99, + 0x0000, 0xE151, 0x0000, 0xE150, 0x0000, 0x0000, + 0x8AC3, 0x0000, 0x9072, 0x0000, 0x935B, 0x0000, + 0xE152, 0x90B6, 0x0000, 0x0000, 0x0000, 0x8E59, + 0x0000, 0x8999, 0xE153, 0x0000, 0x9770, 0x0000, + 0x0000, 0x95E1, 0xE154, 0x0000, 0x0000, 0x0000, + 0x9363, 0x9752, 0x8D62, 0x905C, 0x0000, 0x0000, + 0x0000, 0x926A, 0x99B2, 0x0000, 0x92AC, 0x89E6, + 0xE155, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE156, 0x0000, 0xE15B, 0x0000, + 0x0000, 0xE159, 0xE158, 0x9DC0, 0x8A45, 0xE157, + 0x0000, 0x88D8, 0x0000, 0x94A8, 0x0000, 0x0000, + 0x94C8, 0x0000, 0x0000, 0x0000, 0x0000, 0x97AF, + 0xE15C, 0xE15A, 0x927B, 0x90A4, 0x0000, 0x0000, + 0x94A9, 0x0000, 0x954C, 0x0000, 0xE15E, 0x97AA, + 0x8C6C, 0xE15F, 0x0000, 0xE15D, 0x94D4, 0xE160, + 0x0000, 0xE161, 0x0000, 0x0000, 0x88D9, 0x0000, + 0x0000, 0x8FF4, 0xE166, 0x0000, 0xE163, 0x93EB, + 0xE162, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8B45, 0x0000, 0x0000, 0xE169, 0x0000, + 0x0000, 0x0000, 0xE164, 0xE165, 0x0000, 0xE168, + 0xE167, 0x9544, 0x0000, 0x0000, 0x9161, 0x9160, + 0x0000, 0x8B5E, 0x0000, 0x0000, 0xE16A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE16B, 0x0000, + 0x0000, 0xE16C, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE16E, 0x0000, 0xE16D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8975, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE176, 0x94E6, 0xE170, + 0x0000, 0xE172, 0x0000, 0x0000, 0xE174, 0x905D, + 0x0000, 0x0000, 0xE175, 0xE173, 0x8EBE, 0x0000, + 0x0000, 0x0000, 0xE16F, 0xE171, 0x0000, 0x9561, + 0x0000, 0x8FC7, 0x0000, 0x0000, 0xE178, 0x0000, + 0x0000, 0xE177, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE179, 0x0000, 0x8EA4, 0x8DAD, 0x0000, 0x0000, + 0x9397, 0xE17A, 0x0000, 0x92C9, 0x0000, 0x0000, + 0xE17C, 0x0000, 0x0000, 0x0000, 0x979F, 0xE17B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9189, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE182, 0x0000, 0xE184, 0xE185, 0x9273, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE183, 0x0000, + 0xE180, 0x0000, 0xE17D, 0xE17E +}; + +static u16 Ucs76[256] = { + 0x0000, 0xE181, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE188, 0x0000, 0xE186, + 0x0000, 0xE187, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE189, 0xE18B, 0xE18C, 0xE18D, 0x0000, + 0xE18E, 0x0000, 0x0000, 0xE18A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE190, 0x0000, 0x0000, 0x0000, 0xE18F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE191, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x97C3, 0x0000, 0x0000, 0x0000, 0xE194, 0xE192, + 0xE193, 0x0000, 0x0000, 0x0000, 0x8AE0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x96FC, 0x0000, + 0x0000, 0x0000, 0x95C8, 0x0000, 0xE196, 0x0000, + 0x0000, 0x0000, 0xE195, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE197, 0xE198, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE19C, 0xE199, 0xE19A, 0xE19B, 0x0000, + 0xE19D, 0x0000, 0x0000, 0x0000, 0xE19E, 0x0000, + 0xE19F, 0x0000, 0x0000, 0x0000, 0xE1A0, 0x0000, + 0xE1A1, 0x0000, 0x94AD, 0x936F, 0xE1A2, 0x9492, + 0x9553, 0x0000, 0xE1A3, 0x0000, 0x0000, 0xE1A4, + 0x9349, 0x0000, 0x8A46, 0x8D63, 0xE1A5, 0x0000, + 0x0000, 0xE1A6, 0x0000, 0x0000, 0xE1A7, 0x0000, + 0x8E48, 0x0000, 0x0000, 0xE1A9, 0x0000, 0x0000, + 0xE1A8, 0x0000, 0x0000, 0xE1AA, 0xE1AB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x94E7, 0x0000, 0xE1AC, 0x0000, 0x0000, 0x0000, + 0xE1AD, 0x0000, 0x0000, 0xEA89, 0xE1AE, 0xE1AF, + 0xE1B0, 0x0000, 0x0000, 0x0000, 0x0000, 0x8E4D, + 0x0000, 0x0000, 0xE1B1, 0x9475, 0x0000, 0x0000, + 0x967E, 0x0000, 0x896D, 0x0000, 0x8976, 0x0000, + 0x0000, 0xE1B2, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE1B4, 0x0000, 0x0000, 0x0000, 0xE1B3, 0x9390, + 0x0000, 0x0000, 0x0000, 0x90B7, 0x9F58, 0x0000, + 0xE1B5, 0x96BF, 0x0000, 0xE1B6, 0x0000, 0x8AC4, + 0x94D5, 0xE1B7, 0x0000, 0xE1B8, 0x0000, 0x0000, + 0xE1B9, 0x0000, 0x0000, 0x0000, 0x96DA, 0x0000, + 0x0000, 0x0000, 0x96D3, 0x0000, 0x92BC, 0x0000, + 0x0000, 0x0000, 0x918A, 0x0000, 0x0000, 0xE1BB, + 0x0000, 0x0000, 0x8F82, 0x0000 +}; + +static u16 Ucs77[256] = { + 0x0000, 0x8FC8, 0x0000, 0x0000, 0xE1BE, 0x0000, + 0x0000, 0xE1BD, 0xE1BC, 0x94FB, 0x0000, 0x8AC5, + 0x8CA7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE1C4, 0x0000, 0x0000, + 0xE1C1, 0x905E, 0x96B0, 0x0000, 0x0000, 0x0000, + 0xE1C0, 0xE1C2, 0xE1C3, 0x0000, 0x0000, 0xE1BF, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1C5, 0xE1C6, 0x0000, 0x92AD, 0x0000, + 0x8AE1, 0x0000, 0x0000, 0x0000, 0x9285, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE1C7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE1C8, 0xE1CB, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9087, 0x0000, 0x93C2, 0x0000, 0xE1CC, + 0x9672, 0x0000, 0xE1C9, 0x0000, 0x0000, 0xE1CA, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1CF, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE1CE, 0xE1CD, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1D1, 0x0000, 0x0000, 0xE1D0, 0x0000, + 0x0000, 0xE1D2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE1D4, 0x0000, 0xE1D3, 0x0000, + 0x0000, 0x0000, 0x0000, 0x95CB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8F75, 0x97C4, + 0x0000, 0x0000, 0xE1D5, 0x0000, 0x0000, 0x93B5, + 0x0000, 0x0000, 0xE1D6, 0x0000, 0x0000, 0xE1D7, + 0x0000, 0xE1DB, 0xE1D9, 0xE1DA, 0x0000, 0xE1D8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1DC, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1DD, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE1DE, + 0x0000, 0x0000, 0xE1DF, 0x96B5, 0xE1E0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x96EE, 0xE1E1, + 0x0000, 0x926D, 0x0000, 0x948A, 0x0000, 0x8BE9, + 0x0000, 0x0000, 0x0000, 0x925A, 0xE1E2, 0x8BB8, + 0x0000, 0x0000, 0x0000, 0x90CE, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE1E3, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs78[256] = { + 0x0000, 0x0000, 0x8DBB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE1E4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE1E5, 0x0000, 0x8CA4, 0x8DD3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE1E7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9375, 0x8DD4, 0x8B6D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9643, 0x0000, 0x946A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9376, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8D7B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE1E9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8FC9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x97B0, + 0x8D64, 0x0000, 0x0000, 0x8CA5, 0x0000, 0x0000, + 0x94A1, 0x0000, 0xE1EB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE1ED, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8CE9, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE1EC, 0x92F4, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE1EF, 0x8A56, 0xE1EA, 0x0000, + 0x0000, 0x94E8, 0x0000, 0x894F, 0x0000, 0x8DEA, + 0x0000, 0x9871, 0x0000, 0x0000, 0xE1EE, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1F0, 0x0000, 0x0000, 0x0000, 0x95C9, + 0x0000, 0x90D7, 0xE1F2, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1F3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE1F1, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8A6D, 0x0000, 0xE1F9, 0x0000, 0xE1F8, 0x0000, + 0x0000, 0x8EA5, 0x0000, 0x0000, 0x0000, 0xE1FA, + 0xE1F5, 0x0000, 0x0000, 0x0000, 0xE1FB, 0xE1F6, + 0x0000, 0x0000, 0x0000, 0x0000, 0x94D6, 0xE1F4, + 0x0000, 0x0000, 0xE1F7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE241, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE240, 0x9681, 0x0000, + 0x0000, 0x0000, 0xE1FC, 0x0000, 0x0000, 0x88E9, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE243, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE242, 0x0000, 0x0000 +}; + +static u16 Ucs79[256] = { + 0x0000, 0x8FCA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE244, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9162, 0x0000, 0x0000, 0xE246, + 0xE245, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE247, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE1E6, 0x0000, 0x0000, 0x0000, + 0xE1E8, 0xE249, 0xE248, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8EA6, 0x0000, + 0x97E7, 0x0000, 0x8ED0, 0x0000, 0xE24A, 0x8C56, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8B5F, + 0x8B46, 0x8E83, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9753, 0x0000, 0x0000, 0xE250, + 0x0000, 0xE24F, 0x9163, 0xE24C, 0x0000, 0x0000, + 0xE24E, 0x0000, 0x0000, 0x8F6A, 0x905F, 0xE24D, + 0xE24B, 0x0000, 0x9449, 0x0000, 0x0000, 0x8FCB, + 0x0000, 0x0000, 0x955B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8DD5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9398, + 0x0000, 0x0000, 0xE251, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE252, 0xE268, 0x8BD6, 0x0000, 0x0000, + 0x985C, 0x9154, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE253, 0x0000, 0x0000, 0x89D0, 0x92F5, 0x959F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE254, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8B9A, 0xE255, + 0x0000, 0x0000, 0xE257, 0x0000, 0x0000, 0x0000, + 0xE258, 0x0000, 0x9448, 0x0000, 0x0000, 0xE259, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE25A, + 0xE25B, 0x0000, 0x0000, 0x8BD7, 0x89D1, 0x93C3, + 0x8F47, 0x8E84, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE25C, 0x0000, 0x8F48, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89C8, + 0x9562, 0x0000, 0x0000, 0xE25D, 0x0000, 0x0000, + 0x94E9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9164, 0x0000, 0xE260, 0x0000, 0xE261, + 0x9489, 0x0000, 0x9060, 0xE25E, 0x0000, 0x9281, + 0x0000, 0x0000, 0xE25F, 0x0000, 0x0000, 0x0000, + 0x8FCC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x88DA, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs7A[256] = { + 0x8B48, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE262, 0x0000, 0x0000, 0x92F6, + 0x0000, 0xE263, 0x90C5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x96AB, 0x0000, 0x0000, 0x9542, + 0xE264, 0xE265, 0x9274, 0x0000, 0x97C5, 0x0000, + 0x0000, 0xE267, 0xE266, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8EED, 0x0000, + 0x0000, 0xE269, 0x88EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE26C, 0x0000, 0x0000, 0x0000, 0xE26A, + 0x89D2, 0x8C6D, 0xE26B, 0x8D65, 0x8D92, 0x0000, + 0x95E4, 0xE26D, 0x0000, 0x0000, 0x9673, 0x0000, + 0x0000, 0xE26F, 0x0000, 0x0000, 0x0000, 0x90CF, + 0x896E, 0x89B8, 0x88AA, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE26E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE270, 0xE271, 0x8FF5, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE272, 0x0000, 0x8A6E, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE274, 0x0000, + 0x0000, 0x0000, 0x8C8A, 0x0000, 0x8B86, 0x0000, + 0x0000, 0xE275, 0x8BF3, 0x0000, 0x0000, 0xE276, + 0x0000, 0x90FA, 0x0000, 0x93CB, 0x0000, 0x90DE, + 0x8DF3, 0x0000, 0x0000, 0x0000, 0xE277, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9282, 0x918B, 0x0000, 0xE279, + 0xE27B, 0xE278, 0xE27A, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C41, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE27C, 0x8C45, 0x0000, 0x0000, 0x0000, + 0x8B87, 0x9771, 0xE27E, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE280, 0x0000, 0x0000, 0x0000, + 0x894D, 0x0000, 0x0000, 0x0000, 0x0000, 0xE283, + 0x0000, 0x0000, 0x0000, 0x8A96, 0xE282, 0xE281, + 0x0000, 0xE285, 0xE27D, 0x0000, 0xE286, 0x97A7, + 0x0000, 0xE287, 0x0000, 0xE288, 0x0000, 0x0000, + 0x9AF2, 0xE28A, 0x0000, 0xE289, 0x0000, 0x0000, + 0x0000, 0xE28B, 0xE28C, 0x0000, 0x97B3, 0xE28D, + 0x0000, 0xE8ED, 0x8FCD, 0xE28E, 0xE28F, 0x8F76, + 0x0000, 0x93B6, 0xE290, 0x0000, 0x0000, 0x0000, + 0x9247, 0x0000, 0x0000, 0xE291, 0x0000, 0x925B, + 0xE292, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8BA3, 0x0000, 0x995E, 0x927C, 0x8EB1, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8AC6 +}; + +static u16 Ucs7B[256] = { + 0x0000, 0x0000, 0xE293, 0x0000, 0xE2A0, 0x0000, + 0xE296, 0x0000, 0x8B88, 0x0000, 0xE295, 0xE2A2, + 0x0000, 0x0000, 0x0000, 0xE294, 0x0000, 0x8FCE, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE298, 0xE299, 0x0000, 0x934A, 0x0000, 0x0000, + 0xE29A, 0x0000, 0x8A7D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9079, 0x9584, 0x0000, 0xE29C, 0x0000, + 0x0000, 0x0000, 0x91E6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE297, 0x0000, 0xE29B, + 0xE29D, 0x0000, 0x0000, 0x8DF9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE2A4, 0x954D, 0x0000, + 0x94A4, 0x9399, 0x0000, 0x8BD8, 0xE2A3, 0xE2A1, + 0x0000, 0x94B3, 0xE29E, 0x927D, 0x939B, 0x0000, + 0x939A, 0x0000, 0x8DF4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE2B6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE2A6, + 0x0000, 0xE2A8, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE2AB, 0x0000, 0xE2AC, 0x0000, 0xE2A9, 0xE2AA, + 0x0000, 0x0000, 0xE2A7, 0xE2A5, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE29F, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x95CD, 0x89D3, 0x0000, 0x0000, + 0x0000, 0xE2B3, 0x0000, 0xE2B0, 0x0000, 0xE2B5, + 0x0000, 0x0000, 0xE2B4, 0x0000, 0x9493, 0x96A5, + 0x0000, 0x8E5A, 0xE2AE, 0xE2B7, 0xE2B2, 0x0000, + 0xE2B1, 0xE2AD, 0x0000, 0xE2AF, 0x0000, 0x8AC7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x925C, 0x0000, 0x0000, 0x90FB, + 0x0000, 0x0000, 0x0000, 0x94A0, 0x0000, 0x0000, + 0xE2BC, 0x0000, 0x0000, 0x0000, 0x94A2, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x90DF, 0xE2B9, 0x0000, 0x0000, 0x94CD, 0x0000, + 0xE2BD, 0x95D1, 0x0000, 0x927A, 0x0000, 0xE2B8, + 0xE2BA, 0x0000, 0x0000, 0xE2BB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE2BE, + 0x0000, 0x0000, 0x8EC2, 0x0000, 0x0000, 0x0000, + 0x93C4, 0xE2C3, 0xE2C2, 0x0000, 0x0000, 0xE2BF, + 0x0000, 0x0000, 0x0000, 0x9855, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE2C8, 0x0000, 0x0000, + 0xE2CC, 0xE2C9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs7C[256] = { + 0xE2C5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE2C6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE2CB, 0x0000, 0x0000, 0x0000, 0xE2C0, + 0x99D3, 0xE2C7, 0xE2C1, 0x0000, 0x0000, 0xE2CA, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE2D0, 0x0000, 0x8AC8, 0x0000, 0xE2CD, + 0x0000, 0x0000, 0x0000, 0xE2CE, 0x0000, 0x0000, + 0xE2CF, 0xE2D2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE2D1, 0x94F4, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE2D3, 0x97FA, 0x95EB, 0xE2D8, 0x0000, + 0x0000, 0xE2D5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE2D4, 0x90D0, + 0x0000, 0xE2D7, 0xE2D9, 0x0000, 0x0000, 0x0000, + 0xE2D6, 0x0000, 0xE2DD, 0x0000, 0xE2DA, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE2DB, + 0xE2C4, 0x0000, 0x0000, 0x0000, 0xE2DC, 0xE2DE, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE2DF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x95C4, 0x0000, 0xE2E0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x96E0, 0x0000, 0x0000, 0x8BCC, 0x8C48, 0xE2E1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95B2, + 0x0000, 0x9088, 0x0000, 0x96AE, 0x0000, 0x0000, + 0xE2E2, 0x0000, 0x97B1, 0x0000, 0x0000, 0x9494, + 0x0000, 0x9165, 0x9453, 0x0000, 0x0000, 0x8F6C, + 0x0000, 0x0000, 0x0000, 0x88BE, 0x0000, 0xE2E7, + 0xE2E5, 0x0000, 0xE2E3, 0x8A9F, 0x0000, 0x8FCF, + 0xE2E8, 0x0000, 0x0000, 0xE2E6, 0x0000, 0xE2E4, + 0xE2EC, 0x0000, 0x0000, 0xE2EB, 0xE2EA, 0xE2E9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE2ED, + 0x0000, 0x0000, 0x0000, 0xE2EE, 0x90B8, 0x0000, + 0xE2EF, 0x0000, 0xE2F1, 0x0000, 0x0000, 0xE2F0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8CD0, 0x0000, + 0x0000, 0x0000, 0x9157, 0x0000, 0x0000, 0x0000, + 0xE2F3, 0x0000, 0x0000, 0x0000, 0x939C, 0x0000, + 0xE2F2, 0x0000, 0x0000, 0x0000, 0xE2F4, 0x0000, + 0x95B3, 0x918C, 0x8D66, 0x0000, 0xE2F5, 0x0000, + 0x0000, 0x0000, 0x0000, 0x97C6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE2F7, + 0x0000, 0x0000, 0xE2F8, 0x0000, 0xE2F9, 0x0000, + 0xE2FA, 0x0000, 0x8E85, 0x0000, 0xE2FB, 0x8C6E, + 0x0000, 0x0000, 0x8B8A, 0x0000 +}; + +static u16 Ucs7D[256] = { + 0x8B49, 0x0000, 0xE340, 0x0000, 0x96F1, 0x8D67, + 0xE2FC, 0x0000, 0x0000, 0x0000, 0xE343, 0x96E4, + 0x0000, 0x945B, 0x0000, 0x0000, 0x9552, 0x0000, + 0x0000, 0x0000, 0x8F83, 0xE342, 0x0000, 0x8ED1, + 0x8D68, 0x8E86, 0x8B89, 0x95B4, 0xE341, 0x0000, + 0x0000, 0x0000, 0x9166, 0x9661, 0x8DF5, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8E87, 0x92DB, 0x0000, 0xE346, 0x97DD, + 0x8DD7, 0x0000, 0xE347, 0x9061, 0x0000, 0xE349, + 0x0000, 0x0000, 0x0000, 0x8FD0, 0x8DAE, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE348, 0x0000, 0x0000, + 0x8F49, 0x8CBC, 0x9167, 0xE344, 0xE34A, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE345, 0x8C6F, 0x0000, + 0xE34D, 0xE351, 0x8C8B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE34C, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE355, 0x0000, 0x0000, 0x8D69, 0x0000, + 0x0000, 0x978D, 0x88BA, 0xE352, 0x0000, 0x0000, + 0x8B8B, 0x0000, 0xE34F, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE350, 0x0000, 0x0000, 0x939D, + 0xE34E, 0xE34B, 0x0000, 0x8A47, 0x90E2, 0x0000, + 0x0000, 0x8CA6, 0x0000, 0x0000, 0x0000, 0xE357, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE354, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE356, + 0x0000, 0x0000, 0x0000, 0xE353, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C70, 0x91B1, 0xE358, + 0x918E, 0x0000, 0x0000, 0xE365, 0x0000, 0x0000, + 0xE361, 0xE35B, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE35F, 0x8EF8, 0x88DB, + 0xE35A, 0xE362, 0xE366, 0x8D6A, 0x96D4, 0x0000, + 0x92D4, 0xE35C, 0x0000, 0x0000, 0xE364, 0x0000, + 0xE359, 0x925D, 0x0000, 0xE35E, 0x88BB, 0x96C8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE35D, 0x0000, 0x0000, 0x8BD9, 0x94EA, + 0x0000, 0x0000, 0x0000, 0x918D, 0x0000, 0x97CE, + 0x8F8F, 0x0000, 0x0000, 0xE38E, 0x0000, 0x0000, + 0xE367, 0x0000, 0x90FC, 0x0000, 0xE363, 0xE368, + 0xE36A, 0x0000, 0x92F7, 0xE36D, 0x0000, 0x0000, + 0xE369, 0x0000, 0x0000, 0x0000, 0x95D2, 0x8AC9, + 0x0000, 0x0000, 0x96C9, 0x0000, 0x0000, 0x88DC, + 0x0000, 0x0000, 0xE36C, 0x0000, 0x97FB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE36B, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs7E[256] = { + 0x0000, 0x898F, 0x0000, 0x0000, 0x93EA, 0xE36E, + 0x0000, 0x0000, 0x0000, 0xE375, 0xE36F, 0xE376, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE372, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x949B, 0x0000, 0x0000, + 0x8EC8, 0xE374, 0x0000, 0xE371, 0xE377, 0xE370, + 0x0000, 0x0000, 0x8F63, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9644, 0x0000, 0x0000, 0x8F6B, 0x0000, + 0x0000, 0xE373, 0xE380, 0x0000, 0x0000, 0xE37B, + 0x0000, 0xE37E, 0x0000, 0xE37C, 0xE381, 0xE37A, + 0x0000, 0xE360, 0x90D1, 0x0000, 0x0000, 0x94C9, + 0x0000, 0xE37D, 0x0000, 0x0000, 0xE378, 0x0000, + 0x0000, 0x0000, 0x9140, 0x8C71, 0x0000, 0x8F4A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9044, 0x9155, 0xE384, 0x0000, 0x0000, 0xE386, + 0xE387, 0x0000, 0x0000, 0xE383, 0xE385, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE379, 0xE382, 0x0000, 0xE38A, 0xE389, 0x0000, + 0x0000, 0x969A, 0x0000, 0x0000, 0x8C4A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE388, 0x0000, 0xE38C, 0xE38B, 0xE38F, + 0x0000, 0xE391, 0x0000, 0x0000, 0x8E5B, 0xE38D, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE392, 0xE393, + 0x0000, 0x0000, 0xE394, 0x0000, 0xE39A, 0x935A, + 0xE396, 0x0000, 0xE395, 0xE397, 0xE398, 0x0000, + 0xE399, 0x0000, 0x0000, 0x0000, 0x0000, 0xE39B, + 0xE39C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs7F[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8ACA, 0x0000, 0xE39D, 0x0000, 0xE39E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE39F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3A0, 0xE3A1, + 0xE3A2, 0x0000, 0xE3A3, 0xE3A4, 0x0000, 0x0000, + 0xE3A6, 0xE3A5, 0x0000, 0x0000, 0xE3A7, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3A8, + 0xE3A9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE3AC, 0xE3AA, 0xE3AB, 0x8DDF, 0x8C72, + 0x0000, 0x0000, 0x9275, 0x0000, 0x94B1, 0x0000, + 0x8F90, 0x0000, 0x0000, 0x946C, 0x0000, 0x94EB, + 0xE3AD, 0x9CEB, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3AE, 0xE3B0, + 0x0000, 0x9785, 0xE3AF, 0xE3B2, 0xE3B1, 0x0000, + 0x9772, 0x0000, 0xE3B3, 0x0000, 0x94FC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3B4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3B7, 0x0000, + 0x0000, 0xE3B6, 0xE3B5, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE3B8, 0x8C51, 0x0000, 0x0000, 0x0000, + 0x9141, 0x8B60, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE3BC, 0xE3B9, 0x0000, 0x0000, 0xE3BA, 0x0000, + 0x0000, 0x0000, 0xE3BD, 0x0000, 0xE3BE, 0xE3BB, + 0x0000, 0x0000, 0x0000, 0x8948, 0x0000, 0x0000, + 0x0000, 0x89A5, 0x0000, 0x0000, 0x0000, 0xE3C0, + 0xE3C1, 0x0000, 0x0000, 0x0000, 0xE3C2, 0x0000, + 0x9782, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F4B, 0x0000, 0xE3C4, 0xE3C3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9089, 0xE3C5, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE3C6, 0x0000, 0x0000, 0xE3C7, + 0x0000, 0x8AE3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8ACB, 0x0000, 0x0000, 0xE3C8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE3C9, 0x0000, 0x967C, + 0x9783, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs80[256] = { + 0x9773, 0x9856, 0x0000, 0x8D6C, 0xE3CC, 0x8ED2, + 0xE3CB, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3CD, + 0x8EA7, 0x0000, 0x0000, 0x0000, 0x91CF, 0x0000, + 0xE3CE, 0x0000, 0x0000, 0x8D6B, 0x0000, 0x96D5, + 0xE3CF, 0xE3D0, 0x0000, 0x0000, 0xE3D1, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE3D2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3D3, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8EA8, 0x0000, 0x0000, + 0x96EB, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3D5, + 0x0000, 0x925E, 0x0000, 0xE3D4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3D7, 0x0000, + 0x0000, 0x0000, 0xE3D6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3D8, 0x0000, + 0x0000, 0x0000, 0x90B9, 0x0000, 0xE3D9, 0x0000, + 0xE3DA, 0x0000, 0x0000, 0x0000, 0x95B7, 0xE3DB, + 0x0000, 0x918F, 0xE3DC, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE3DD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x97FC, 0xE3E0, 0x0000, + 0xE3DF, 0xE3DE, 0x92AE, 0x0000, 0xE3E1, 0x9045, + 0x0000, 0xE3E2, 0x0000, 0x0000, 0x0000, 0xE3E3, + 0x9857, 0xE3E4, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE3E5, 0xE3E7, 0xE3E6, 0x94A3, 0x0000, 0x93F7, + 0x0000, 0x985D, 0x94A7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE3E9, 0x0000, 0x0000, + 0x8FD1, 0x0000, 0x9549, 0x0000, 0xE3EA, 0xE3E8, + 0x0000, 0x8ACC, 0x0000, 0x0000, 0x0000, 0x8CD2, + 0x8E88, 0x0000, 0x0000, 0x94EC, 0x0000, 0x0000, + 0x0000, 0x8CA8, 0x9662, 0x0000, 0xE3ED, 0xE3EB, + 0x0000, 0x8D6D, 0x0000, 0x8D6E, 0x88E7, 0x0000, + 0x8DE6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9478, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x88DD, 0xE3F2, 0x0000, + 0x925F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9477, 0x0000, 0x91D9, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE3F4, 0x0000, + 0x0000, 0xE3F0, 0xE3F3, 0xE3EE, 0x0000, 0xE3F1, + 0x9645, 0x0000, 0x0000, 0x8CD3, 0x0000, 0x0000, + 0x88FB, 0xE3EF, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3F6, + 0x0000, 0xE3F7, 0x0000, 0x0000, 0x93B7, 0x0000, + 0x0000, 0x0000, 0x8BB9, 0x0000, 0x0000, 0x0000, + 0xE445, 0x945C, 0x0000, 0x0000 +}; + +static u16 Ucs81[256] = { + 0x0000, 0x0000, 0x8E89, 0x0000, 0x0000, 0x8BBA, + 0x90C6, 0x9865, 0x96AC, 0xE3F5, 0x90D2, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8B72, 0xE3F8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3FA, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3F9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE3FB, + 0x0000, 0x9245, 0x0000, 0x945D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x92AF, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE442, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE441, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE3FC, 0x0000, 0x0000, + 0x9074, 0x0000, 0x9585, 0xE444, 0x0000, 0xE443, + 0x8D6F, 0x9872, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE454, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE448, + 0xE449, 0x0000, 0x0000, 0x0000, 0x0000, 0x8EEE, + 0x0000, 0x0000, 0xE447, 0x0000, 0x8D98, 0xE446, + 0x0000, 0x0000, 0xE44A, 0x0000, 0x0000, 0x0000, + 0x92B0, 0x95A0, 0x9142, 0x0000, 0x0000, 0x0000, + 0x0000, 0x91DA, 0xE44E, 0x0000, 0xE44F, 0xE44B, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE44C, 0x0000, + 0xE44D, 0x0000, 0x0000, 0x0000, 0x0000, 0x8D70, + 0x0000, 0x0000, 0x0000, 0xE455, 0x0000, 0xE451, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9586, 0x0000, + 0x968C, 0x9547, 0x0000, 0x0000, 0xE450, 0x0000, + 0x0000, 0xE453, 0xE452, 0x0000, 0x0000, 0x0000, + 0x9663, 0xE456, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE457, 0x0000, 0x0000, 0x9156, + 0x0000, 0xE458, 0x0000, 0x0000, 0xE45A, 0x0000, + 0xE45E, 0x0000, 0x0000, 0xE45B, 0xE459, 0x945E, + 0xE45C, 0x0000, 0xE45D, 0x0000, 0x0000, 0x0000, + 0x89B0, 0x0000, 0xE464, 0xE45F, 0x0000, 0x0000, + 0x0000, 0xE460, 0x0000, 0x0000, 0x0000, 0xE461, + 0x0000, 0x919F, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE463, 0xE462, 0xE465, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE466, 0xE467, 0x0000, 0x0000, 0x9062, + 0x0000, 0x89E7, 0x0000, 0xE468, 0x97D5, 0x0000, + 0x8EA9, 0x0000, 0x0000, 0x8F4C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8E8A, 0x9276, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE469, 0xE46A, + 0x8950, 0x0000, 0xE46B, 0x0000 +}; + +static u16 Ucs82[256] = { + 0x0000, 0xE46C, 0xE46D, 0x0000, 0x0000, 0xE46E, + 0x0000, 0xE46F, 0x8BBB, 0x9DA8, 0xE470, 0x0000, + 0x90E3, 0xE471, 0x8EC9, 0x0000, 0xE472, 0x0000, + 0x98AE, 0x0000, 0x0000, 0x0000, 0xE473, 0x95DC, + 0x8ADA, 0x0000, 0x0000, 0x9143, 0x8F77, 0x0000, + 0x9591, 0x8F4D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE474, + 0x8D71, 0xE475, 0x94CA, 0x0000, 0xE484, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE477, 0x0000, 0x91C7, + 0x9495, 0x8CBD, 0xE476, 0x9144, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE478, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92F8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE47A, 0xE479, + 0xE47C, 0x0000, 0x0000, 0xE47B, 0x0000, 0xE47D, + 0x0000, 0x0000, 0xE480, 0x0000, 0xE47E, 0x0000, + 0x8ACD, 0x0000, 0xE481, 0x0000, 0xE482, 0xE483, + 0x0000, 0x0000, 0x8DAF, 0x97C7, 0x0000, 0xE485, + 0x9046, 0x0000, 0x0000, 0x0000, 0x8990, 0xE486, + 0xE487, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE488, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x88F0, 0x0000, 0xE489, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE48A, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9587, 0x0000, 0x0000, + 0x0000, 0x8EC5, 0x0000, 0xE48C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8A48, 0x88B0, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE48B, 0xE48E, 0x946D, + 0x0000, 0x9063, 0x0000, 0x89D4, 0x0000, 0x9646, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8C7C, 0x8BDA, + 0x0000, 0xE48D, 0x0000, 0x89E8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8AA1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8991, + 0xE492, 0x97E8, 0x91DB, 0x0000, 0x0000, 0x9563, + 0x0000, 0xE49E, 0x0000, 0x89D5, 0xE49C, 0x0000, + 0xE49A, 0xE491, 0x0000, 0xE48F, 0x0000, 0xE490, + 0x0000, 0x8EE1, 0x8BEA, 0x9297, 0x0000, 0x0000, + 0x0000, 0x93CF, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8970, 0x0000, 0xE494, 0xE493, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE499, 0xE495, 0xE498, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs83[256] = { + 0x0000, 0x0000, 0x96CE, 0xE497, 0x89D6, 0x8A9D, + 0xE49B, 0x0000, 0x0000, 0xE49D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8C73, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE4A1, 0xE4AA, + 0xE4AB, 0x0000, 0x0000, 0x0000, 0x88A9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE4B2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x88EF, 0x0000, + 0x0000, 0xE4A9, 0x0000, 0x0000, 0x0000, 0xE4A8, + 0x0000, 0xE4A3, 0xE4A2, 0x0000, 0xE4A0, 0xE49F, + 0x9283, 0x0000, 0x91F9, 0xE4A5, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE4A4, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE4A7, 0x0000, 0x0000, + 0x0000, 0x9190, 0x8C74, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8960, 0xE4A6, 0x0000, 0x8D72, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9191, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE4B8, 0x0000, 0xE4B9, 0x0000, 0x89D7, + 0x0000, 0x0000, 0x0000, 0x89AC, 0xE4B6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE4AC, 0x0000, 0xE4B4, 0x0000, 0xE4BB, + 0xE4B5, 0x0000, 0x0000, 0x0000, 0xE4B3, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE496, 0x0000, 0x0000, + 0xE4B1, 0x0000, 0x0000, 0x0000, 0xE4AD, 0x0000, + 0x0000, 0x0000, 0x8ACE, 0xE4AF, 0xE4BA, 0x0000, + 0xE4B0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE4BC, 0x0000, 0xE4AE, 0x949C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9789, 0x0000, 0x0000, + 0x0000, 0xE4B7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE4CD, 0x0000, 0x0000, + 0x0000, 0xE4C5, 0x0000, 0x0000, 0x0000, 0x909B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8B65, 0x0000, + 0x8BDB, 0x0000, 0xE4C0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x89D9, 0x0000, 0x0000, 0x8FD2, 0x0000, + 0xE4C3, 0x0000, 0x0000, 0x0000, 0x8DD8, 0x0000, + 0x0000, 0x9370, 0xE4C8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95EC, + 0x0000, 0xE4BF, 0x0000, 0x0000, 0x0000, 0x89D8, + 0x8CD4, 0x9548, 0xE4C9, 0x0000, 0xE4BD, 0x0000, + 0x0000, 0xE4C6, 0x0000, 0x0000, 0x0000, 0xE4D0, + 0x0000, 0xE4C1, 0x0000, 0x0000 +}; + +static u16 Ucs84[256] = { + 0x0000, 0x0000, 0x0000, 0xE4C2, 0x93B8, 0x0000, + 0x0000, 0xE4C7, 0x0000, 0x0000, 0x0000, 0xE4C4, + 0x9647, 0xE4CA, 0x88DE, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE4BE, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE4CC, 0x0000, 0xE4CB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x948B, + 0xE4D2, 0x0000, 0xE4DD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8A9E, 0x0000, 0x0000, 0x0000, 0xE4E0, + 0x0000, 0x0000, 0xE4CE, 0x0000, 0x0000, 0x0000, + 0xE4D3, 0x978E, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE4DC, 0x0000, + 0x0000, 0x9774, 0x0000, 0x0000, 0x0000, 0x0000, + 0x97A8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9298, 0x0000, 0x0000, + 0x0000, 0x8A8B, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9592, 0xE4E2, 0x939F, 0x0000, 0x0000, + 0x88AF, 0x0000, 0x0000, 0xE4DB, 0x0000, 0xE4D7, + 0x9192, 0xE4D1, 0xE4D9, 0xE4DE, 0x0000, 0x944B, + 0x0000, 0x0000, 0x0000, 0x88A8, 0x0000, 0xE4D6, + 0x0000, 0xE4DF, 0x9598, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE4DA, 0x0000, + 0xE4D5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8FD3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F4E, 0x0000, 0x0000, 0x0000, 0x8EAA, 0x0000, + 0x0000, 0x0000, 0x0000, 0x96D6, 0x0000, 0x0000, + 0x9566, 0x0000, 0x0000, 0xE4E5, 0x0000, 0xE4EE, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE4D8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8A97, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8FF6, 0xE4E3, + 0x0000, 0xE4E8, 0x9193, 0x0000, 0x0000, 0xE4E4, + 0x0000, 0xE4EB, 0x0000, 0x0000, 0x927E, 0x0000, + 0xE4EC, 0x0000, 0x0000, 0x9775, 0xE4E1, 0x8A57, + 0x0000, 0xE4E7, 0x0000, 0x0000, 0xE4EA, 0x96AA, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE4ED, 0x0000, + 0x0000, 0xE4E6, 0xE4E9, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9648, 0x0000, 0x9840, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE4F1, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE4F8, 0x0000, 0x0000, 0xE4F0 +}; + +static u16 Ucs85[256] = { + 0x8EC1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE4CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x95CC, + 0x0000, 0x96A0, 0xE4F7, 0xE4F6, 0x0000, 0xE4F2, + 0xE4F3, 0x0000, 0x8955, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE4F5, 0x0000, 0xE4EF, 0x0000, 0x0000, + 0x0000, 0x0000, 0x92D3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE4F4, 0x88FC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91A0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x95C1, 0x0000, 0x0000, 0xE4F9, 0xE540, + 0x0000, 0x94D7, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE4FC, 0x8FD4, 0x8EC7, 0xE542, 0x0000, 0x0000, + 0x8BBC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE543, 0x0000, 0x9599, 0xE4FB, 0x0000, + 0xE4D4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE4FA, 0x0000, 0x0000, + 0x0000, 0x0000, 0x986E, 0x93A0, 0x9593, 0x0000, + 0x0000, 0xE54A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE550, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE551, 0x0000, 0xE544, 0x0000, 0x0000, 0x0000, + 0x9496, 0x0000, 0x0000, 0xE54E, 0xE546, 0x0000, + 0xE548, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE552, 0xE547, 0x0000, 0x0000, 0xE54B, 0x0000, + 0x0000, 0x8992, 0x0000, 0x93E3, 0x0000, 0xE54C, + 0xE54F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE545, 0x0000, 0x9145, 0x0000, + 0xE549, 0x8E46, 0x9064, 0x8C4F, 0x96F2, 0x0000, + 0x96F7, 0x8F92, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE556, + 0xE554, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x986D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE553, 0x0000, 0x0000, + 0x0000, 0x9795, 0x0000, 0xE555, 0xE557, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE558, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE55B, 0xE559, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x93A1, 0xE55A, 0x0000, 0x0000, 0x0000, 0x94CB, + 0xE54D, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8F93, 0x0000, 0xE55C, 0xE561, 0x9194, + 0x0000, 0x0000, 0xE560, 0x0000 +}; + +static u16 Ucs86[256] = { + 0x0000, 0x0000, 0xE541, 0x0000, 0x0000, 0x0000, + 0xE562, 0x9168, 0x0000, 0x0000, 0xE55D, 0xE55F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE55E, 0x0000, 0x0000, 0x9F50, 0x9F41, + 0x0000, 0x0000, 0xE564, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE563, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9796, 0x0000, 0xE1BA, + 0xE565, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE566, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE567, + 0x8CD5, 0x0000, 0x8B73, 0x0000, 0x0000, 0x0000, + 0xE569, 0x997C, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8B95, 0x0000, 0x97B8, 0x0000, 0x8BF1, 0xE56A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE56B, 0x0000, 0x0000, 0x0000, 0x928E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE56C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x93F8, 0x0000, 0x88B8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x89E1, 0xE571, 0xE572, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE56D, 0x0000, 0x8E5C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE56E, 0x9461, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE56F, 0xE570, 0xE57A, 0x0000, 0x0000, + 0x0000, 0xE574, 0xE577, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE573, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE575, 0x0000, + 0xE576, 0x8ED6, 0x0000, 0xE578, 0x0000, 0x9260, + 0x0000, 0x8C75, 0x8A61, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE57B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8A5E, 0x0000, 0xE581, 0x0000, 0x0000, + 0xE57C, 0xE580, 0x0000, 0x0000, 0x0000, 0x0000, + 0x94B8, 0x0000, 0x0000, 0x0000, 0x0000, 0xE57D, + 0x0000, 0x0000, 0xE57E, 0x9567, 0x94D8, 0xE582, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x91FB, 0xE58C, 0x0000, 0xE588, + 0x0000, 0x0000, 0x89E9, 0x0000 +}; + +static u16 Ucs87[256] = { + 0xE586, 0x0000, 0x9649, 0xE587, 0x0000, 0x0000, + 0xE584, 0x0000, 0xE585, 0xE58A, 0xE58D, 0x0000, + 0x0000, 0xE58B, 0x0000, 0x0000, 0x0000, 0xE589, + 0xE583, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9277, 0x0000, 0xE594, 0x0000, 0x96A8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE592, 0x0000, 0x0000, 0x0000, 0xE593, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE58E, 0x0000, + 0x0000, 0xE590, 0x0000, 0x0000, 0x0000, 0xE591, + 0x0000, 0x0000, 0x0000, 0xE58F, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x90E4, 0x0000, 0x9858, 0xE598, 0x0000, + 0xE599, 0x0000, 0x0000, 0x0000, 0x0000, 0xE59F, + 0x0000, 0x9049, 0x0000, 0xE59B, 0x0000, 0xE59E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE596, + 0xE595, 0x0000, 0x0000, 0xE5A0, 0x0000, 0x0000, + 0x89DA, 0x0000, 0xE59C, 0x0000, 0xE5A1, 0x0000, + 0x0000, 0x0000, 0xE59D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE59A, 0x0000, 0x92B1, 0x0000, + 0xE597, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9488, 0x0000, 0x0000, 0xE5A5, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x975A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE5A4, 0x0000, 0x0000, + 0xE5A3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE5AC, 0x0000, 0x0000, + 0x0000, 0xE5A6, 0x0000, 0x0000, 0x0000, 0xE5AE, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9786, 0xE5B1, 0x0000, 0xE5A8, 0x0000, 0x0000, + 0xE5A9, 0x0000, 0x0000, 0x0000, 0xE5AD, 0x0000, + 0xE5B0, 0xE5AF, 0x0000, 0x0000, 0x0000, 0xE5A7, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE5AA, 0x0000, + 0xE5BB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE5B4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE5B2, + 0x0000, 0x0000, 0xE5B3, 0x0000, 0x0000, 0x0000, + 0xE5B8, 0xE5B9, 0x0000, 0x8A49, 0x0000, 0x8B61, + 0x0000, 0x0000, 0xE5B7, 0x0000 +}; + +static u16 Ucs88[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE5A2, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE5B6, 0xE5BA, 0xE5B5, 0x0000, 0xE5BC, + 0x0000, 0x0000, 0x0000, 0xE5BE, 0xE5BD, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE5C0, 0xE5BF, 0xE579, + 0x0000, 0x0000, 0x0000, 0xE5C4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE5C1, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE5C2, 0x0000, 0x0000, 0xE5C3, 0x0000, 0xE5C5, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8C8C, 0x0000, + 0xE5C7, 0x0000, 0xE5C6, 0x0000, 0x8F4F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8D73, 0x9FA5, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE5C8, 0x8F70, + 0x0000, 0x0000, 0x0000, 0x8A58, 0x0000, 0xE5C9, + 0x0000, 0x8971, 0x0000, 0x8FD5, 0xE5CA, 0x0000, + 0x0000, 0x8D74, 0xE5CB, 0x88DF, 0x0000, 0x0000, + 0x0000, 0x0000, 0x955C, 0x0000, 0x0000, 0xE5CC, + 0x0000, 0x0000, 0x0000, 0x0000, 0x908A, 0x0000, + 0xE5D3, 0x0000, 0x0000, 0xE5D0, 0x0000, 0x928F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE5D1, + 0xE5CE, 0x8BDC, 0x0000, 0xE5CD, 0xE5D4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8C55, 0x0000, + 0x0000, 0x91DC, 0x0000, 0xE5DA, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE5D6, 0x0000, 0x0000, 0x0000, + 0x91B3, 0xE5D5, 0x0000, 0xE5D8, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE5CF, 0x0000, 0x0000, 0x0000, + 0xE5D9, 0x0000, 0xE5DB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x94ED, 0x0000, 0x0000, + 0xE5D7, 0x0000, 0xE5DC, 0xE5DE, 0x0000, 0x0000, + 0x8CD1, 0xE5D2, 0x0000, 0x88BF, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE5DD, + 0x0000, 0x8DD9, 0x97F4, 0xE5DF, 0xE5E0, 0x9195, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x97A0, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE5E1, 0x9754, 0x0000, 0x0000, + 0xE5E2, 0xE5E3, 0x0000, 0x0000, 0x95E2, 0xE5E4, + 0x0000, 0x8DBE, 0x0000, 0x97A1, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE5E9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE5EA, 0x8FD6, 0xE5E8, 0x0000, + 0x0000, 0x0000, 0x9787, 0xE5E5, 0x0000, 0x0000, + 0xE5E7, 0x90BB, 0x909E, 0x0000 +}; + +static u16 Ucs89[256] = { + 0x0000, 0x0000, 0xE5E6, 0x0000, 0xE5EB, 0x0000, + 0x0000, 0x95A1, 0x0000, 0x0000, 0xE5ED, 0x0000, + 0xE5EC, 0x0000, 0x0000, 0x0000, 0x8A8C, 0x0000, + 0x964A, 0xE5EE, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE5FA, + 0xE5F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE5F1, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE5F2, 0xE5F3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE5F7, 0x0000, 0xE5F8, 0x0000, 0x0000, 0xE5F6, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE5F4, + 0x0000, 0xE5EF, 0xE5F5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE5F9, 0xE8B5, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x89A6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE5FC, 0x8BDD, + 0xE5FB, 0x0000, 0x0000, 0x0000, 0xE641, 0x0000, + 0xE640, 0x0000, 0x0000, 0x0000, 0xE643, 0x0000, + 0x0000, 0xE642, 0x0000, 0xE644, 0x0000, 0x0000, + 0x8F50, 0x0000, 0xE645, 0x0000, 0x0000, 0xE646, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE647, 0x90BC, 0x0000, 0x9776, 0x0000, 0xE648, + 0x0000, 0x0000, 0x95A2, 0x9465, 0xE649, 0x0000, + 0xE64A, 0x8CA9, 0x0000, 0x0000, 0x0000, 0x8B4B, + 0x0000, 0x0000, 0x0000, 0xE64B, 0x0000, 0x0000, + 0x8E8B, 0x9460, 0xE64C, 0x0000, 0x8A6F, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE64D, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE64F, 0x9797, + 0x0000, 0xE64E, 0x9065, 0x0000, 0xE650, 0x0000, + 0x0000, 0xE651, 0x0000, 0x0000, 0xE652, 0x8ACF, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE653, 0x0000, 0x0000, 0xE654, 0x0000, 0xE655, + 0xE656, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8A70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE657, 0x0000, 0xE658, 0xE659, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x89F0, + 0x0000, 0x0000, 0x9047, 0xE65A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE65B, 0x0000, + 0x0000, 0x0000, 0xE65C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs8A[256] = { + 0x8CBE, 0x0000, 0x92F9, 0xE65D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8C76, 0x0000, 0x9075, 0x0000, + 0xE660, 0x0000, 0x93A2, 0x0000, 0xE65F, 0x0000, + 0x0000, 0x8C50, 0x0000, 0x0000, 0xE65E, 0x91F5, + 0x8B4C, 0x0000, 0x0000, 0xE661, 0x0000, 0xE662, + 0x0000, 0x8FD7, 0x0000, 0x0000, 0x0000, 0x8C8D, + 0x0000, 0xE663, 0x0000, 0x0000, 0x0000, 0x0000, + 0x964B, 0x0000, 0x0000, 0x90DD, 0x0000, 0x0000, + 0x0000, 0x8B96, 0x0000, 0x96F3, 0x9169, 0x0000, + 0xE664, 0x0000, 0x0000, 0x0000, 0x9066, 0x9290, + 0x8FD8, 0x0000, 0x0000, 0x0000, 0x0000, 0xE665, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE668, 0x0000, + 0xE669, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8DBC, 0x91C0, 0xE667, 0x0000, + 0x8FD9, 0x955D, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE666, 0x0000, 0x0000, 0x8E8C, 0x0000, + 0x8972, 0x0000, 0xE66D, 0x8C77, 0x0000, 0x0000, + 0x8E8E, 0x0000, 0x0000, 0x8E8D, 0x0000, 0x986C, + 0xE66C, 0xE66B, 0x9146, 0x0000, 0x8B6C, 0x9862, + 0x8A59, 0x8FDA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE66A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE66F, 0x0000, + 0xE670, 0xE66E, 0x0000, 0x8CD6, 0x0000, 0x975F, + 0x0000, 0x0000, 0x8E8F, 0x9446, 0x0000, 0x0000, + 0x0000, 0xE673, 0x0000, 0x90BE, 0x0000, 0x9261, + 0x0000, 0x0000, 0x9755, 0x0000, 0xE676, 0x0000, + 0x0000, 0x0000, 0x8CEA, 0x0000, 0x90BD, 0xE672, + 0x0000, 0xE677, 0x8CEB, 0xE674, 0xE675, 0x0000, + 0xE671, 0x0000, 0x0000, 0x0000, 0x90E0, 0x93C7, + 0x0000, 0x0000, 0x924E, 0x0000, 0x89DB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x94EE, + 0x0000, 0x0000, 0x8B62, 0x0000, 0x0000, 0x92B2, + 0x0000, 0x0000, 0xE67A, 0x0000, 0xE678, 0x0000, + 0x0000, 0x926B, 0x0000, 0x0000, 0x0000, 0x90BF, + 0x8AD0, 0xE679, 0x0000, 0x907A, 0x0000, 0x0000, + 0x97C8, 0x0000, 0x0000, 0x0000, 0x985F, 0x0000, + 0x0000, 0x0000, 0xE67B, 0xE687, 0x92B3, 0x0000, + 0xE686, 0x0000, 0xE683, 0xE68B, 0xE684, 0x0000, + 0xE680, 0x0000, 0x92FA, 0xE67E, 0x0000, 0x0000, + 0x0000, 0xE67C, 0x0000, 0x9740, 0x8E90, 0x0000, + 0x0000, 0xE681, 0x0000, 0xE67D, 0x0000, 0x0000, + 0x0000, 0xE685, 0x8F94, 0x0000, 0x8CBF, 0x0000, + 0x0000, 0x0000, 0x91F8, 0x0000 +}; + +static u16 Ucs8B[256] = { + 0x9664, 0x8979, 0x88E0, 0x0000, 0x93A3, 0x0000, + 0x0000, 0xE689, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE688, 0x0000, 0x93E4, 0x0000, 0xE68D, 0x0000, + 0x0000, 0x0000, 0xE682, 0x0000, 0xE68C, 0xE68E, + 0x0000, 0x8CAA, 0xE68A, 0x8D75, 0x0000, 0x8ED3, + 0x0000, 0x0000, 0xE68F, 0x9777, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE692, 0x0000, 0xE695, 0x0000, + 0x0000, 0xE693, 0x9554, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE690, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8BDE, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE694, 0x0000, 0x0000, 0xE696, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE69A, 0x0000, 0x0000, 0xE697, 0x0000, + 0xE699, 0xE698, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE69B, 0x0000, 0x8EAF, 0x0000, + 0xE69D, 0xE69C, 0x9588, 0x0000, 0x0000, 0xE69F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C78, 0x0000, 0x0000, 0x0000, 0x0000, 0xE69E, + 0xE6A0, 0x0000, 0x0000, 0xE6A1, 0x8B63, 0xE3BF, + 0x8FF7, 0x0000, 0xE6A2, 0x0000, 0x0000, 0x8CEC, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE6A3, + 0x0000, 0x0000, 0xE6A4, 0x0000, 0x0000, 0x8E5D, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9DCC, 0x0000, 0xE6A5, 0x0000, 0xE6A6, 0x0000, + 0x8F51, 0x0000, 0xE6A7, 0xE6A8, 0x0000, 0x0000, + 0xE6A9, 0x0000, 0x0000, 0xE6AA, 0xE6AB, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs8C[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x924A, 0x0000, 0x0000, 0xE6AC, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE6AE, 0x0000, 0xE6AD, + 0x0000, 0x0000, 0x0000, 0x0000, 0x93A4, 0x0000, + 0xE6AF, 0x0000, 0x964C, 0x0000, 0xE6B0, 0x0000, + 0xE6B1, 0x0000, 0xE6B2, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE6B3, 0x0000, 0x0000, 0x0000, 0x0000, + 0x93D8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8FDB, 0xE6B4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8D8B, 0x98AC, + 0xE6B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE6B6, 0x955E, 0xE6B7, 0x0000, 0xE6BF, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE6B8, 0x0000, + 0x0000, 0xE6BA, 0x0000, 0x0000, 0x0000, 0xE6B9, + 0xE6BB, 0x0000, 0x9665, 0xE6BC, 0xE6BD, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE6BE, 0x0000, + 0x0000, 0x0000, 0xE6C0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8A4C, 0x92E5, 0x0000, 0x9589, 0x8DE0, + 0x8D76, 0x0000, 0x0000, 0x0000, 0x0000, 0x956E, + 0x89DD, 0x94CC, 0xE6C3, 0x8AD1, 0x90D3, 0xE6C2, + 0xE6C7, 0x9299, 0x96E1, 0x0000, 0xE6C5, 0xE6C6, + 0x8B4D, 0x0000, 0xE6C8, 0x9483, 0x91DD, 0x0000, + 0x0000, 0x94EF, 0x935C, 0xE6C4, 0x0000, 0x9666, + 0x89EA, 0xE6CA, 0x9847, 0x92C0, 0x9864, 0x0000, + 0x0000, 0x8E91, 0xE6C9, 0x0000, 0x91AF, 0x0000, + 0x0000, 0xE6DA, 0x9147, 0x0000, 0x0000, 0x93F6, + 0x0000, 0x956F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE6CD, 0x8E5E, 0x8E92, 0x0000, + 0x8FDC, 0x0000, 0x9485, 0x0000, 0x8CAB, 0xE6CC, + 0xE6CB, 0x0000, 0x958A, 0x0000, 0x0000, 0x0000, + 0x8EBF, 0x0000, 0x0000, 0x9371, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE6CF, 0xE6D0, + 0x8D77, 0xE6CE, 0x0000, 0x0000 +}; + +static u16 Ucs8D[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0xE6D1, 0xE6D2, + 0x0000, 0xE6D4, 0x91A1, 0x0000, 0xE6D3, 0x8AE4, + 0x0000, 0xE6D6, 0x0000, 0xE6D5, 0xE6D7, 0x0000, + 0x0000, 0xE6D9, 0xE6DB, 0x0000, 0xE6DC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x90D4, 0x0000, + 0x8ECD, 0xE6DD, 0x0000, 0x0000, 0x0000, 0x8A71, + 0x0000, 0xE6DE, 0x0000, 0x0000, 0x9196, 0xE6DF, + 0x0000, 0xE6E0, 0x958B, 0x0000, 0x0000, 0x8B4E, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE6E1, 0x0000, 0x0000, + 0x0000, 0x92B4, 0x0000, 0x0000, 0x0000, 0x0000, + 0x897A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE6E2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8EEF, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9096, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x91AB, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE6E5, 0x0000, 0x0000, 0x0000, 0xE6E4, 0x0000, + 0x0000, 0x0000, 0xE6E3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE6EB, + 0xE6E9, 0x0000, 0x0000, 0xE6E6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE6E8, 0x0000, + 0x0000, 0x0000, 0xE6E7, 0xE6EA, 0x0000, 0x8B97, + 0x0000, 0xE6EE, 0x0000, 0x90D5, 0x0000, 0xE6EF, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8CD7, 0x0000, + 0xE6EC, 0xE6ED, 0x0000, 0x0000, 0x0000, 0x9848, + 0x0000, 0x0000, 0x0000, 0x92B5, 0x0000, 0x9148, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE6F0, 0x0000, 0x0000, 0xE6F3 +}; + +static u16 Ucs8E[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE6F1, 0xE6F2, 0x9778, 0x0000, + 0x0000, 0x0000, 0x0000, 0x93A5, 0xE6F6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE6F4, + 0xE6F5, 0xE6F7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE748, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE6FA, 0x0000, 0x0000, 0x0000, 0xE6FB, 0xE6F9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE6F8, 0x0000, 0x92FB, 0x0000, 0x0000, 0xE740, + 0xE744, 0xE741, 0xE6FC, 0x0000, 0xE742, 0x0000, + 0x0000, 0x0000, 0xE743, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE74A, 0x0000, 0x0000, 0x0000, 0xE745, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x90D6, + 0xE747, 0x0000, 0x0000, 0xE749, 0xE746, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE74C, 0x0000, 0x8F52, 0x0000, 0xE74B, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE74D, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE74E, 0x0000, 0x0000, + 0xE751, 0xE750, 0x0000, 0xE74F, 0x0000, 0x0000, + 0xE753, 0xE752, 0x0000, 0x96F4, 0x0000, 0x0000, + 0x0000, 0xE755, 0x0000, 0xE754, 0xE756, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE757, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE759, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE758, 0x9067, 0xE75A, 0x0000, + 0x0000, 0x8BEB, 0xE75B, 0xE75D, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE75E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE75F, + 0xE75C, 0x0000, 0xE760, 0x0000, 0x8ED4, 0xE761, + 0x8B4F, 0x8C52, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8CAC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE762, 0x0000, 0x0000, + 0x0000, 0x93EE, 0x0000, 0x0000, 0x935D, 0xE763, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE766, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8EB2, 0x0000, 0x0000, 0xE765, + 0xE764, 0x8C79, 0xE767, 0x0000 +}; + +static u16 Ucs8F[256] = { + 0x0000, 0x0000, 0x0000, 0x8A72, 0x0000, 0xE769, + 0x0000, 0x0000, 0x0000, 0x8DDA, 0xE768, 0x0000, + 0xE771, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE76B, 0xE76D, 0x95E3, 0xE76A, 0x0000, 0x0000, + 0x0000, 0xE76C, 0x0000, 0xE770, 0xE76E, 0x8B50, + 0x0000, 0xE76F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE772, 0x0000, 0x0000, 0x9479, + 0x97D6, 0x0000, 0x0000, 0x0000, 0x0000, 0x8F53, + 0x0000, 0x0000, 0x0000, 0xE773, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9741, 0xE775, 0x0000, 0xE774, + 0x0000, 0x0000, 0xE778, 0x9760, 0x0000, 0x0000, + 0xE777, 0x0000, 0x8A8D, 0xE776, 0xE77B, 0x0000, + 0x0000, 0xE77A, 0x0000, 0x0000, 0xE779, 0x9351, + 0xE77C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE77D, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE77E, 0x0000, 0x0000, 0x8D8C, + 0x0000, 0x8C44, 0xE780, 0xE781, 0xE782, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9068, + 0xE783, 0x0000, 0x8EAB, 0xE784, 0x0000, 0x0000, + 0x0000, 0xE785, 0x0000, 0x0000, 0x0000, 0x999F, + 0x999E, 0x0000, 0x0000, 0x0000, 0x0000, 0xE786, + 0xE390, 0xE787, 0x9243, 0x904A, 0x945F, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE788, 0x0000, 0x0000, + 0x95D3, 0x92D2, 0x8D9E, 0x0000, 0x0000, 0x9248, + 0x0000, 0x0000, 0x8949, 0x0000, 0x9698, 0x9076, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8C7D, 0x0000, 0x0000, 0x8BDF, + 0x0000, 0x0000, 0x95D4, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE789, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE78B, 0x0000, + 0x0000, 0xE78A, 0x89DE, 0x0000, 0x0000, 0x93F4, + 0xE78C, 0x9497, 0x0000, 0x9352, 0x0000, 0xE78D, + 0x8F71, 0x0000, 0x0000, 0x0000, 0xE78F, 0x0000, + 0x0000, 0x96C0, 0xE79E, 0xE791, 0xE792, 0x0000, + 0x0000, 0x92C7, 0x0000, 0x0000 +}; + +static u16 Ucs90[256] = { + 0x91DE, 0x9197, 0x0000, 0x93A6, 0x0000, 0xE790, + 0x8B74, 0x0000, 0x0000, 0x0000, 0x0000, 0xE799, + 0x0000, 0xE796, 0xE7A3, 0x93A7, 0x9280, 0xE793, + 0x0000, 0x92FC, 0x9372, 0xE794, 0xE798, 0x9080, + 0x0000, 0x9487, 0x92CA, 0x0000, 0x0000, 0x90C0, + 0xE797, 0x91AC, 0x91A2, 0xE795, 0x88A7, 0x9841, + 0x0000, 0x0000, 0x0000, 0xE79A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x91DF, 0x0000, + 0x0000, 0x8F54, 0x9069, 0x0000, 0x0000, 0xE79C, + 0xE79B, 0x0000, 0x88ED, 0xE79D, 0x0000, 0x0000, + 0x954E, 0x0000, 0xE7A5, 0x0000, 0x0000, 0x93D9, + 0x908B, 0x0000, 0x0000, 0x9278, 0x0000, 0x8BF6, + 0x0000, 0xE7A4, 0x9756, 0x895E, 0x0000, 0x95D5, + 0x89DF, 0xE79F, 0xE7A0, 0xE7A1, 0xE7A2, 0x93B9, + 0x9242, 0x88E1, 0xE7A6, 0x0000, 0xE7A7, 0xEAA1, + 0x0000, 0x0000, 0x91BB, 0x0000, 0xE7A8, 0x0000, + 0x8993, 0x916B, 0x0000, 0x8CAD, 0x0000, 0x9779, + 0x0000, 0x0000, 0xE7A9, 0x934B, 0x0000, 0x0000, + 0x0000, 0x9198, 0x8ED5, 0xE7AA, 0x0000, 0x0000, + 0xE7AD, 0x0000, 0x0000, 0x8F85, 0xE7AB, 0x914A, + 0x9149, 0x0000, 0x88E2, 0x0000, 0x97C9, 0xE7AF, + 0x0000, 0x94F0, 0xE7B1, 0xE7B0, 0xE7AE, 0xE284, + 0x8AD2, 0x0000, 0x0000, 0xE78E, 0x0000, 0xE7B3, + 0xE7B2, 0x0000, 0x0000, 0x0000, 0x0000, 0xE7B4, + 0x0000, 0x9757, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x93DF, 0x0000, 0x0000, 0x964D, 0x0000, + 0xE7B5, 0x0000, 0x8ED7, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE7B6, 0x0000, 0xE7B7, 0x0000, 0x0000, + 0x0000, 0xE7B8, 0x0000, 0x0000, 0x9340, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x88E8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8D78, 0x0000, + 0x0000, 0x0000, 0x9859, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE7BC, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8C53, 0xE7B9, 0x0000, + 0xE7BA, 0x0000, 0x0000, 0x0000, 0x9594, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8A73, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9758, + 0x0000, 0x8BBD, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9373, 0x0000, 0x0000 +}; + +static u16 Ucs91[256] = { + 0x0000, 0x0000, 0xE7BD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7BE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE7BF, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9341, 0x0000, 0x0000, + 0xE7C1, 0x0000, 0xE7C0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x93D1, 0xE7C2, 0x8F55, 0x8EDE, 0x947A, + 0x9291, 0x0000, 0x0000, 0x0000, 0x8EF0, 0x0000, + 0x908C, 0x0000, 0xE7C3, 0x0000, 0xE7C4, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x907C, 0xE7C5, 0x0000, 0xE7C6, + 0x0000, 0x0000, 0x0000, 0xE7C7, 0x978F, 0x0000, + 0x8F56, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7C9, 0xE7C8, 0x0000, 0x8D79, 0x0000, 0x8D93, + 0x8E5F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE7CC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8F86, 0x0000, 0xE7CB, + 0x0000, 0xE7CA, 0x0000, 0x91E7, 0x0000, 0x0000, + 0x8CED, 0x0000, 0x90C1, 0x0000, 0x0000, 0x0000, + 0x0000, 0x94AE, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F58, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7CD, 0x0000, 0x8FDD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE7D0, 0xE7CE, 0x0000, 0x0000, + 0x0000, 0xE7CF, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7D2, 0xE7D1, 0x0000, 0x0000, 0x8FF8, 0x0000, + 0xE7D3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7D4, 0xE7D5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x94CE, 0x8DD1, 0x8EDF, 0xE7D6, 0x0000, 0xE7D7, + 0x97A2, 0x8F64, 0x96EC, 0x97CA, 0xE7D8, 0x8BE0, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE7D9, 0x0000, + 0x9342, 0x0000, 0x0000, 0xE7DC, 0x8A98, 0x906A, + 0x0000, 0xE7DA, 0x0000, 0xE7DB, 0x0000, 0x92DE, + 0x0000, 0x0000, 0x9674, 0x8BFA, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE7DE, + 0xE7DF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7DD, 0x0000, 0x0000, 0xE7E1 +}; + +static u16 Ucs92[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x93DD, 0x8A62, 0x0000, 0x0000, 0xE7E5, + 0x0000, 0x0000, 0xE7E2, 0xE7E4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE7E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE86E, + 0x0000, 0x0000, 0xE7E3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x97E9, 0x0000, + 0x0000, 0x8CD8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE7ED, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9353, 0xE7E8, 0x0000, 0x0000, + 0xE7EB, 0xE7E9, 0x0000, 0xE7EE, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE7EF, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE7E7, 0x0000, 0x0000, + 0xE7F4, 0x8994, 0x0000, 0x0000, 0xE7E6, 0x0000, + 0x0000, 0x0000, 0x94AB, 0x0000, 0xE7EA, 0x0000, + 0x8FDE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8D7A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9667, 0x0000, 0x8BE2, 0x0000, 0x0000, 0x8F65, + 0x0000, 0x93BA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x914C, 0x0000, 0xE7F2, 0x0000, 0xE7EC, + 0xE7F1, 0x0000, 0x96C1, 0x0000, 0x92B6, 0xE7F3, + 0xE7F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x914B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE7F7, 0x0000, 0xE7F6, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE7F5, 0x0000, 0x0000, + 0x964E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8F9B, 0x0000, 0x0000, 0x0000, 0x0000, 0xE7F8, + 0x95DD, 0x0000, 0x0000, 0x8973, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9565, 0x9292, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8B98, 0x0000, 0xE7FA, 0x0000, + 0x8D7C, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs93[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8E4B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE7F9, 0x908D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x908E, 0xE840, 0xE842, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8FF9, 0x0000, 0xE841, 0xE843, + 0x0000, 0x0000, 0x8BD1, 0x0000, 0x9564, 0x0000, + 0x0000, 0x8EE0, 0x9842, 0x0000, 0xE7FC, 0x8DF6, + 0x0000, 0x0000, 0x985E, 0x0000, 0x0000, 0xE845, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE844, 0xE846, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE7FB, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x93E7, 0x0000, 0x9374, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x92D5, 0x0000, 0xE84B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9262, 0xE847, 0x0000, 0x0000, 0x0000, + 0xE848, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8C4C, 0x0000, 0xE84A, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8CAE, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE849, 0x0000, + 0x8FDF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8A99, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE84F, 0x0000, + 0x8DBD, 0x9199, 0x0000, 0x0000, 0x92C8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8A5A, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE84D, 0xE84E, + 0x92C1, 0x0000, 0xE84C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE850, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE856, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE859, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE858, 0x934C, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE851, 0xE852, + 0xE855, 0x0000, 0x0000, 0x0000, 0x0000, 0xE857, + 0x0000, 0x0000, 0x0000, 0x8BBE, 0x0000, 0x0000, + 0xE85A, 0xE854, 0x0000, 0x0000, 0xE853, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs94[256] = { + 0x0000, 0x0000, 0x0000, 0xE85E, 0x0000, 0x0000, + 0x0000, 0xE85F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE860, 0x0000, + 0x0000, 0xE85D, 0xE85C, 0x0000, 0x0000, 0x0000, + 0x8FE0, 0x93A8, 0xE85B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE864, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE862, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE863, + 0xE861, 0x0000, 0x91F6, 0x0000, 0xE865, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE866, + 0x0000, 0x0000, 0xE868, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8AD3, 0xE867, 0x96F8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE873, 0xE869, 0x0000, 0x0000, 0xE86C, 0x0000, + 0xE86A, 0x0000, 0xE86B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE86D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE86F, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE870, 0x0000, 0xE871, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE874, 0xE872, + 0xE875, 0xE877, 0x0000, 0xE876, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs95[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x92B7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x96E5, 0x0000, 0xE878, 0x914D, + 0x0000, 0x0000, 0x0000, 0xE879, 0x0000, 0x95C2, + 0xE87A, 0x8A4A, 0x0000, 0x0000, 0x0000, 0x895B, + 0x0000, 0x8AD5, 0x0000, 0x8AD4, 0xE87B, 0x0000, + 0xE87C, 0x0000, 0xE87D, 0xE87E, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE880, 0x0000, + 0x8AD6, 0x8A74, 0x8D7D, 0x94B4, 0x0000, 0xE882, + 0xE881, 0x0000, 0x0000, 0x0000, 0x0000, 0xE883, + 0x0000, 0x0000, 0x0000, 0x0000, 0x897B, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE886, + 0x0000, 0xE885, 0xE884, 0x0000, 0xE887, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE88A, 0x0000, 0x0000, + 0x0000, 0x88C5, 0x0000, 0x0000, 0xE888, 0x0000, + 0xE88C, 0xE88B, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE88E, 0xE88D, 0xE88F, 0x0000, + 0x93AC, 0x0000, 0x0000, 0x0000, 0xE890, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE891, 0xE893, 0x0000, + 0x0000, 0xE892, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs96[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x958C, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE894, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE895, 0x0000, + 0x8DE3, 0x0000, 0x0000, 0x0000, 0xE896, 0xE897, + 0x0000, 0x0000, 0x9668, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x916A, + 0x0000, 0x0000, 0x0000, 0x88A2, 0x91C9, 0x0000, + 0xE898, 0x0000, 0x958D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE89B, 0xE899, 0x8D7E, + 0x0000, 0xE89A, 0x8CC0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x95C3, 0xE89D, 0xE89F, 0xE89E, 0xE8A0, + 0x0000, 0x0000, 0x8940, 0x9077, 0x8F9C, 0x8AD7, + 0xE8A1, 0x0000, 0x0000, 0x0000, 0x9486, 0x0000, + 0xE8A3, 0x0000, 0x0000, 0x0000, 0x8941, 0x0000, + 0xE8A2, 0x92C2, 0x0000, 0x97CB, 0x93A9, 0xE89C, + 0x97A4, 0x0000, 0x8CAF, 0x0000, 0x0000, 0x977A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8BF7, 0x97B2, 0x0000, 0x8C47, 0x0000, + 0x91E0, 0xE440, 0x0000, 0xE8A4, 0x8A4B, 0x908F, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8A75, 0xE8A6, + 0x0000, 0xE8A7, 0xE8A5, 0x8C84, 0x0000, 0x8DDB, + 0x8FE1, 0x0000, 0x0000, 0x0000, 0x8942, 0x0000, + 0x0000, 0x97D7, 0x0000, 0x0000, 0x0000, 0xE8A9, + 0xE7AC, 0x0000, 0xE8A8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE8AC, 0xE8AA, 0xE8AB, 0x0000, + 0xE8AD, 0x0000, 0xE8AE, 0x97EA, 0xE8AF, 0xE8B0, + 0x0000, 0x90C7, 0x94B9, 0x0000, 0x0000, 0x0000, + 0x909D, 0x8AE5, 0x0000, 0x0000, 0x9759, 0x89EB, + 0x8F57, 0x8CD9, 0x0000, 0xE8B3, 0x0000, 0xE8B2, + 0x8E93, 0xE8B4, 0xE8B1, 0x0000, 0x0000, 0x8E47, + 0x0000, 0x0000, 0x0000, 0xE8B8, 0xE5AB, 0x0000, + 0x0000, 0x99D4, 0x0000, 0x9097, 0xE8B6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x97A3, 0x93EF, + 0x0000, 0x0000, 0x0000, 0x0000, 0x894A, 0x0000, + 0x90E1, 0x8EB4, 0x0000, 0x0000, 0x0000, 0x0000, + 0x95B5, 0x0000, 0x895F, 0x0000, 0x0000, 0x0000, + 0x97EB, 0x978B, 0x0000, 0xE8B9, 0x0000, 0x9364, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs97[256] = { + 0x8EF9, 0x0000, 0x0000, 0x0000, 0xE8BA, 0x0000, + 0xE8BB, 0x906B, 0xE8BC, 0x0000, 0x97EC, 0x0000, + 0x0000, 0xE8B7, 0xE8BE, 0xE8C0, 0x0000, 0xE8BF, + 0x0000, 0xE8BD, 0x0000, 0x0000, 0xE8C1, 0x0000, + 0x0000, 0xE8C2, 0x0000, 0x0000, 0x919A, 0x0000, + 0x89E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE8C3, 0x0000, 0x0000, 0x96B6, 0x0000, 0x0000, + 0xE8C4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE8C5, 0x0000, 0x9849, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9E50, 0xE8C6, 0x0000, 0x0000, + 0x0000, 0xE8C7, 0xE8C8, 0x0000, 0x0000, 0x0000, + 0xE8CC, 0x0000, 0xE8C9, 0x0000, 0xE8CA, 0x0000, + 0xE8CB, 0xE8CD, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x90C2, 0x0000, + 0x0000, 0x0000, 0x96F5, 0x0000, 0x0000, 0x90C3, + 0x0000, 0x0000, 0xE8CE, 0x0000, 0x94F1, 0x0000, + 0xE8CF, 0xEA72, 0x96CA, 0x0000, 0xE8D0, 0x0000, + 0xE8D1, 0x0000, 0xE8D2, 0x8A76, 0x0000, 0xE8D4, + 0x0000, 0x9078, 0x0000, 0x0000, 0x0000, 0xE8D5, + 0x0000, 0x0000, 0x8C43, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE8D6, 0xE8DA, 0x0000, 0xE8D8, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE8D9, 0x0000, 0x0000, + 0x8A93, 0xE8D7, 0xE8DB, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE8DC, 0x0000, 0x88C6, 0x0000, 0xE8DD, + 0xE8DE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8FE2, 0x0000, 0x0000, 0x0000, + 0xE8DF, 0x0000, 0x0000, 0x0000, 0x8B66, 0x0000, + 0x0000, 0xE8E2, 0x0000, 0x0000, 0xE8E1, 0x0000, + 0xE8E0, 0x0000, 0x0000, 0xE691, 0x0000, 0x95DA, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE8E3, + 0xE8E4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE8E5, 0x0000, 0x0000, + 0xE8E6, 0x0000, 0xE8E7, 0x0000, 0x0000, 0xE8E8, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8AD8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE8E9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE8EA, 0x9442, 0x0000, + 0x0000, 0x0000, 0xE8EC, 0x89B9, 0x0000, 0xE8EF, + 0xE8EE, 0x0000, 0x0000, 0x0000, 0x0000, 0x8943, + 0x0000, 0x0000, 0x0000, 0x8BBF +}; + +static u16 Ucs98[256] = { + 0x0000, 0x95C5, 0x92B8, 0x8DA0, 0x0000, 0x8D80, + 0x8F87, 0x0000, 0x907B, 0x0000, 0x0000, 0x0000, + 0xE8F1, 0x0000, 0x0000, 0xE8F0, 0x9761, 0x8AE6, + 0x94D0, 0x93DA, 0x0000, 0x0000, 0x0000, 0x909C, + 0x97CC, 0x0000, 0x8C7A, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE8F4, 0x0000, 0x0000, + 0xE8F3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x966A, 0x93AA, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x896F, 0x0000, + 0x0000, 0xE8F5, 0xE8F2, 0x0000, 0x0000, 0x9570, + 0x978A, 0xE8F6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE8F7, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE8F9, 0x91E8, 0x8A7A, + 0x8A7B, 0xE8F8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8AE7, 0x8CB0, 0x0000, 0x0000, 0x8AE8, 0x0000, + 0x0000, 0x935E, 0x0000, 0x0000, 0x97DE, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8CDA, 0x0000, 0x0000, 0x0000, 0xE8FA, + 0x0000, 0x0000, 0x0000, 0xE8FB, 0xE8FC, 0xE940, + 0x0000, 0xE942, 0xE941, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9597, 0x0000, 0xE943, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE944, 0x0000, 0xE945, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE946, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE948, 0xE947, 0x0000, + 0xE949, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x94F2, 0xE3CA, 0x0000, + 0x0000, 0x9048, 0x0000, 0x0000, 0x8B51, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE94A, + 0x0000, 0xE94B, 0x0000, 0x99AA, 0x9F5A, 0x94D1, + 0x0000, 0x0000, 0x88F9, 0x0000, 0x88B9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8E94, 0x964F, 0x8FFC, 0x0000 +}; + +static u16 Ucs99[256] = { + 0x0000, 0x0000, 0x0000, 0xE94C, 0x0000, 0x96DD, + 0x0000, 0x0000, 0x0000, 0xE94D, 0x977B, 0x0000, + 0x8961, 0x0000, 0x0000, 0x0000, 0x8E60, 0x0000, + 0xE94E, 0x89EC, 0xE94F, 0x0000, 0x0000, 0x0000, + 0xE950, 0x0000, 0x0000, 0x0000, 0x0000, 0xE952, + 0xE953, 0x0000, 0xE955, 0xE951, 0x0000, 0x0000, + 0xE954, 0x0000, 0x0000, 0x0000, 0x8AD9, 0x0000, + 0x0000, 0x0000, 0xE956, 0x0000, 0xE957, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE958, 0xE959, 0x0000, 0x0000, 0x0000, + 0xE95A, 0x0000, 0x0000, 0xE95C, 0x0000, 0x0000, + 0x0000, 0xE95B, 0x0000, 0xE95E, 0xE961, 0x0000, + 0x0000, 0x0000, 0xE95D, 0xE95F, 0xE960, 0x0000, + 0x0000, 0xE962, 0x0000, 0x8BC0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8EF1, 0xE963, 0xE964, 0x8D81, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE965, 0x0000, 0x0000, + 0x8A5D, 0x0000, 0x0000, 0x0000, 0x946E, 0xE966, + 0xE967, 0x0000, 0x0000, 0x0000, 0x0000, 0x9279, + 0x93E9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE968, 0x0000, 0x0000, 0x0000, + 0x0000, 0x949D, 0x0000, 0x0000, 0x91CA, 0x8977, + 0x8BEC, 0x0000, 0x8BED, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9293, 0xE96D, + 0x8BEE, 0x0000, 0x0000, 0x89ED, 0x0000, 0x0000, + 0xE96C, 0x0000, 0x0000, 0xE96A, 0x0000, 0xE96B, + 0x0000, 0xE969, 0x0000, 0x0000, 0xE977, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE96E, 0xE96F, 0x0000, + 0x0000, 0xE970, 0xE971, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE973, 0x0000, 0x0000, 0xE972, + 0x0000, 0x0000, 0x0000, 0x8F78 +}; + +static u16 Ucs9A[256] = { + 0x0000, 0xE974, 0x0000, 0x0000, 0x0000, 0xE976, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8B52, 0xE975, 0x0000, 0x0000, + 0x919B, 0x8CB1, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE978, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x91CB, 0x0000, + 0x0000, 0xE979, 0x0000, 0x0000, 0x0000, 0x0000, + 0x93AB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE97A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE980, 0x0000, 0xE97D, 0x0000, + 0xE97C, 0xE97E, 0x0000, 0xE97B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE982, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE981, 0x0000, 0xE984, 0x0000, 0x0000, + 0x8BC1, 0xE983, 0x0000, 0x0000, 0x0000, 0xE985, + 0x0000, 0x0000, 0xE986, 0x0000, 0xE988, 0xE987, + 0x0000, 0x0000, 0x0000, 0xE989, 0xE98B, 0xE98A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x8D9C, 0x0000, 0x0000, 0x0000, 0x0000, 0xE98C, + 0x0000, 0x0000, 0xE98D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8A5B, 0x0000, + 0x0000, 0x0000, 0xE98E, 0x0000, 0x0000, 0x0000, + 0xE98F, 0x0000, 0x0000, 0x0000, 0x9091, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE990, 0x0000, 0xE991, + 0x0000, 0xE992, 0xE993, 0x0000, 0x0000, 0x0000, + 0x8D82, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE994, 0xE995, 0x0000, 0x0000, 0xE996, 0xE997, + 0x0000, 0x0000, 0xE998, 0x0000, 0x0000, 0x0000, + 0x94AF, 0xE99A, 0x0000, 0x9545, 0xE99B, 0xE999, + 0x0000, 0xE99D, 0x0000, 0x0000, 0xE99C, 0x0000, + 0x0000, 0xE99E, 0x0000, 0x0000, 0x0000, 0xE99F, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs9B[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9A0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9A1, 0x0000, 0xE9A2, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE9A3, 0x0000, 0x0000, 0xE9A4, 0xE9A5, + 0x0000, 0xE9A6, 0x0000, 0xE9A7, 0xE9A8, 0xE9A9, + 0xE9AA, 0x0000, 0x0000, 0x0000, 0xE9AB, 0xE9AC, + 0x0000, 0x9F54, 0xE9AD, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE2F6, + 0x8B53, 0x0000, 0x0000, 0x0000, 0x0000, 0x8A40, + 0x8DB0, 0xE9AF, 0xE9AE, 0x96A3, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE9B1, + 0xE9B2, 0xE9B0, 0x0000, 0xE9B3, 0x0000, 0x0000, + 0x9682, 0x0000, 0x0000, 0x0000, 0xE9B4, 0x0000, + 0x8B9B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9844, 0x0000, 0x0000, + 0x0000, 0x0000, 0xE9B5, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE9B7, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x88BC, 0x0000, + 0x0000, 0xE9B8, 0x95A9, 0xE9B6, 0x0000, 0x0000, + 0xE9B9, 0xE9BA, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE9BB, 0xE9BC, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9BD, 0x0000, 0x968E, 0x8E4C, 0x0000, 0x8DF8, + 0x914E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9BE, 0x0000, 0x0000, 0x0000, 0x0000, 0xE9C1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9BF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9C2, 0x0000, 0x0000, 0x8CEF, 0xE9C0, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE9C3, 0x0000, 0xE9C4, + 0xE9C5, 0x0000, 0xE9C9, 0x0000, 0x8E49, 0x0000, + 0x0000, 0x0000, 0x0000, 0x91E2, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE9CA, 0xE9C7, 0xE9C6, + 0xE9C8, 0x0000, 0x0000, 0x0000, 0x8C7E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9CE, 0xE9CD, 0xE9CC, 0x0000, 0x0000, 0x88B1, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs9C[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0xE9D8, 0x0000, + 0xE9D4, 0x0000, 0xE9D5, 0xE9D1, 0xE9D7, 0x0000, + 0xE9D3, 0x8A82, 0x0000, 0x0000, 0x986B, 0x0000, + 0xE9D6, 0xE9D2, 0xE9D0, 0xE9CF, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE9DA, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xE9DD, 0x0000, 0x0000, + 0xE9DC, 0xE9DB, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x9568, 0xE9D9, 0x88F1, + 0xE9DE, 0x0000, 0xE9E0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8A8F, 0xE9CB, 0x8956, + 0x0000, 0x0000, 0xE9E2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE9E1, 0xE9DF, + 0x924C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9690, 0x0000, + 0x0000, 0x0000, 0x0000, 0x97D8, 0x0000, 0x0000, + 0xE9E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xE9E4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xE9E5, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xE9E6, 0x0000, + 0xE9E7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x92B9, 0x0000, 0xE9E8, 0x0000, 0x94B5, + 0x0000, 0xE9ED, 0xE9E9, 0x0000, 0x0000, 0x0000, + 0xE9EA, 0x0000, 0x0000, 0x9650, 0x96C2, 0x0000, + 0x93CE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Ucs9D[256] = { + 0x0000, 0x0000, 0x0000, 0xE9EE, 0x0000, 0x0000, + 0xE9EF, 0x93BC, 0xE9EC, 0xE9EB, 0x0000, 0x0000, + 0x0000, 0x0000, 0x89A8, 0x0000, 0x0000, 0x0000, + 0xE9F7, 0x0000, 0x0000, 0xE9F6, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x8995, 0x0000, 0x0000, + 0x0000, 0xE9F4, 0x0000, 0x0000, 0x0000, 0xE9F3, + 0x0000, 0x0000, 0xE9F1, 0x0000, 0x8A9B, 0x0000, + 0xE9F0, 0x8EB0, 0x89A7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8D83, + 0x0000, 0x0000, 0xE9FA, 0xE9F9, 0x0000, 0xE9F8, + 0x0000, 0x0000, 0xE9F5, 0x0000, 0xE9FB, 0x0000, + 0xE9FC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA44, 0xEA43, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xEA45, + 0x0000, 0x0000, 0x894C, 0xEA40, 0xEA41, 0x0000, + 0x8D94, 0x96B7, 0x0000, 0x0000, 0xEA42, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9651, 0x0000, 0x0000, 0xEA4A, 0x0000, 0x0000, + 0xEA46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA4B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xEA48, 0x0000, 0xEA47, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8C7B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xEA4C, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA4D, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA4E, 0x0000, 0xEA49, 0x0000, 0x0000, + 0x0000, 0xE9F2, 0x0000, 0x0000, 0xEA4F, 0x0000, + 0x92DF, 0x0000, 0x0000, 0x0000, 0xEA53, 0x0000, + 0xEA54, 0xEA52, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA51, 0xEA57, 0x0000, 0xEA50, 0x0000, + 0xEA55, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xEA56, 0x0000, 0x0000, + 0x0000, 0xEA59, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA58, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA5B, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xEA5C, 0x0000, 0xEA5D, + 0x0000, 0x0000, 0x9868, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA5A, 0x91E9, 0x8DEB, 0x0000, + 0x0000, 0xEA5E, 0x0000, 0x0000 +}; + +static u16 Ucs9E[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA5F, 0xEA60, 0x0000, 0x0000, + 0xEA61, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xEA62, 0x0000, 0x0000, + 0x8CB2, 0xEA63, 0x0000, 0x0000, 0x0000, 0xEA64, + 0x0000, 0x8EAD, 0x0000, 0xEA65, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xEA66, 0x0000, + 0x0000, 0xEA67, 0xEA68, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA6B, 0xEA69, 0x985B, 0x0000, 0xEA6A, + 0x0000, 0x97ED, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA6C, 0x0000, 0x97D9, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xEA6D, 0x949E, 0x0000, + 0x0000, 0xEA6E, 0xEA70, 0x0000, 0x0000, 0xEA71, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xEA6F, 0x8D8D, + 0x96CB, 0x9683, 0x9BF5, 0x0000, 0x9F80, 0x969B, + 0x0000, 0x0000, 0x0000, 0x0000, 0x89A9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xEA73, 0x8B6F, 0xEA74, 0xEA75, 0xEA76, 0x0000, + 0x8D95, 0x0000, 0xEA77, 0x0000, 0x0000, 0x0000, + 0xE0D2, 0x96D9, 0x0000, 0x91E1, 0xEA78, 0xEA7A, + 0xEA79, 0x0000, 0xEA7B, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA7C, 0x0000, 0x0000, 0xEA7D, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xEA7E, + 0x0000, 0x0000, 0x0000, 0x0000, 0xEA80, 0x0000, + 0xEA81, 0xEA82, 0x0000, 0xEA83, 0x0000, 0xEA84, + 0xEA85, 0xEA86, 0x0000, 0x0000 +}; + +static u16 Ucs9F[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xEA87, 0xEA88, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x9343, 0x0000, 0x0000, 0x0000, + 0x0000, 0x8CDB, 0x0000, 0xEA8A, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x916C, 0xEA8B, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA8C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9540, + 0x0000, 0x0000, 0xEA8D, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xEA8E, 0xE256, 0x0000, 0x0000, + 0xE6D8, 0xE8EB, 0x0000, 0x0000, 0xEA8F, 0x0000, + 0xEA90, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xEA92, + 0xEA93, 0xEA94, 0x97EE, 0xEA91, 0x0000, 0x0000, + 0xEA95, 0xEA96, 0x0000, 0x0000, 0xEA98, 0x0000, + 0xEA97, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xEA9A, 0x0000, 0x0000, 0x0000, 0xEA9B, 0xEA99, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x97B4, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xEA9C, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xEA9D, 0xE273, 0x0000, 0x0000, 0xEA9E, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 UcsFF[256] = { + 0x0000, 0x8149, 0x0000, 0x8194, 0x8190, 0x8193, + 0x8195, 0x0000, 0x8169, 0x816A, 0x8196, 0x817B, + 0x8143, 0x0000, 0x8144, 0x815E, 0x824F, 0x8250, + 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256, + 0x8257, 0x8258, 0x8146, 0x8147, 0x8183, 0x8181, + 0x8184, 0x8148, 0x8197, 0x8260, 0x8261, 0x8262, + 0x8263, 0x8264, 0x8265, 0x8266, 0x8267, 0x8268, + 0x8269, 0x826A, 0x826B, 0x826C, 0x826D, 0x826E, + 0x826F, 0x8270, 0x8271, 0x8272, 0x8273, 0x8274, + 0x8275, 0x8276, 0x8277, 0x8278, 0x8279, 0x816D, + 0x0000, 0x816E, 0x814F, 0x8151, 0x814D, 0x8281, + 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287, + 0x8288, 0x8289, 0x828A, 0x828B, 0x828C, 0x828D, + 0x828E, 0x828F, 0x8290, 0x8291, 0x8292, 0x8293, + 0x8294, 0x8295, 0x8296, 0x8297, 0x8298, 0x8299, + 0x829A, 0x816F, 0x8162, 0x8170, 0x0000, 0x0000, + 0x0000, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, + 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, + 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, + 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, + 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, + 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, + 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, + 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, + 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8150, + 0x0000, 0x818F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16* UcsSjisTable[] = +{ + Ucs00, NULL, NULL, Ucs03, Ucs04, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + Ucs20, Ucs21, Ucs22, Ucs23, NULL, Ucs25, Ucs26, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + Ucs30, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, Ucs4E, Ucs4F, + Ucs50, Ucs51, Ucs52, Ucs53, Ucs54, Ucs55, Ucs56, Ucs57, + Ucs58, Ucs59, Ucs5A, Ucs5B, Ucs5C, Ucs5D, Ucs5E, Ucs5F, + Ucs60, Ucs61, Ucs62, Ucs63, Ucs64, Ucs65, Ucs66, Ucs67, + Ucs68, Ucs69, Ucs6A, Ucs6B, Ucs6C, Ucs6D, Ucs6E, Ucs6F, + Ucs70, Ucs71, Ucs72, Ucs73, Ucs74, Ucs75, Ucs76, Ucs77, + Ucs78, Ucs79, Ucs7A, Ucs7B, Ucs7C, Ucs7D, Ucs7E, Ucs7F, + Ucs80, Ucs81, Ucs82, Ucs83, Ucs84, Ucs85, Ucs86, Ucs87, + Ucs88, Ucs89, Ucs8A, Ucs8B, Ucs8C, Ucs8D, Ucs8E, Ucs8F, + Ucs90, Ucs91, Ucs92, Ucs93, Ucs94, Ucs95, Ucs96, Ucs97, + Ucs98, Ucs99, Ucs9A, Ucs9B, Ucs9C, Ucs9D, Ucs9E, Ucs9F, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, UcsFF +}; + +u16 OSUTF32toSJIS(u32 utf32) { + u16* table; + + if (0x10000 <= utf32) { + return 0; + } + + table = UcsSjisTable[(utf32 >> 8) & 0xFF]; + if (table != 0) { + return table[utf32 & 0xFF]; + } + + return 0; +} + +static u16 Sjis00[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, + 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, + 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, + 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, + 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, + 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, + 0x005A, 0x005B, 0x00A5, 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, + 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, + 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, + 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, + 0x203E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFF61, + 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, + 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, + 0xFF6E, 0xFF6F, 0xFF70, 0xFF71, 0xFF72, 0xFF73, + 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, + 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, + 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, + 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0xFF91, + 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, + 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, + 0xFF9E, 0xFF9F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis81[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3001, + 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A, 0xFF1B, + 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, + 0x00A8, 0xFF3E, 0xFFE3, 0xFF3F, 0x30FD, 0x30FE, + 0x309D, 0x309E, 0x3003, 0x4EDD, 0x3005, 0x3006, + 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, 0x005C, + 0x301C, 0x2016, 0xFF5C, 0x2026, 0x2025, 0x2018, + 0x2019, 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, + 0x3015, 0xFF3B, 0xFF3D, 0xFF5B, 0xFF5D, 0x3008, + 0x3009, 0x300A, 0x300B, 0x300C, 0x300D, 0x300E, + 0x300F, 0x3010, 0x3011, 0xFF0B, 0x2212, 0x00B1, + 0x00D7, 0x0000, 0x00F7, 0xFF1D, 0x2260, 0xFF1C, + 0xFF1E, 0x2266, 0x2267, 0x221E, 0x2234, 0x2642, + 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0xFFE5, + 0xFF04, 0x00A2, 0x00A3, 0xFF05, 0xFF03, 0xFF06, + 0xFF0A, 0xFF20, 0x00A7, 0x2606, 0x2605, 0x25CB, + 0x25CF, 0x25CE, 0x25C7, 0x25C6, 0x25A1, 0x25A0, + 0x25B3, 0x25B2, 0x25BD, 0x25BC, 0x203B, 0x3012, + 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x2208, 0x220B, + 0x2286, 0x2287, 0x2282, 0x2283, 0x222A, 0x2229, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x2227, 0x2228, 0x00AC, 0x21D2, + 0x21D4, 0x2200, 0x2203, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x2220, 0x22A5, 0x2312, 0x2202, + 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, + 0x223D, 0x221D, 0x2235, 0x222B, 0x222C, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, + 0x2021, 0x00B6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x25EF, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis82[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, + 0xFF15, 0xFF16, 0xFF17, 0xFF18, 0xFF19, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, + 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, + 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, + 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, + 0xFF39, 0xFF3A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xFF41, 0xFF42, 0xFF43, + 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, + 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, + 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0x0000, + 0x0000, 0x0000, 0x0000, 0x3041, 0x3042, 0x3043, + 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, + 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, + 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, + 0x3056, 0x3057, 0x3058, 0x3059, 0x305A, 0x305B, + 0x305C, 0x305D, 0x305E, 0x305F, 0x3060, 0x3061, + 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, + 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, + 0x306E, 0x306F, 0x3070, 0x3071, 0x3072, 0x3073, + 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, + 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F, + 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, + 0x3086, 0x3087, 0x3088, 0x3089, 0x308A, 0x308B, + 0x308C, 0x308D, 0x308E, 0x308F, 0x3090, 0x3091, + 0x3092, 0x3093, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis83[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x30A1, 0x30A2, + 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, 0x30A8, + 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, + 0x30AF, 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, + 0x30B5, 0x30B6, 0x30B7, 0x30B8, 0x30B9, 0x30BA, + 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF, 0x30C0, + 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, + 0x30C7, 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, + 0x30CD, 0x30CE, 0x30CF, 0x30D0, 0x30D1, 0x30D2, + 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7, 0x30D8, + 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, + 0x30DF, 0x0000, 0x30E0, 0x30E1, 0x30E2, 0x30E3, + 0x30E4, 0x30E5, 0x30E6, 0x30E7, 0x30E8, 0x30E9, + 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, + 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, + 0x30F6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0391, 0x0392, 0x0393, + 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, + 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, + 0x03A7, 0x03A8, 0x03A9, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03B1, + 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, + 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C4, + 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis84[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0410, 0x0411, + 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416, + 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, + 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, + 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, + 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, + 0x042F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0430, 0x0431, + 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, + 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, + 0x043D, 0x0000, 0x043E, 0x043F, 0x0440, 0x0441, + 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, + 0x044E, 0x044F, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x2500, 0x2502, 0x250C, + 0x2510, 0x2518, 0x2514, 0x251C, 0x252C, 0x2524, + 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513, + 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, + 0x254B, 0x2520, 0x252F, 0x2528, 0x2537, 0x253F, + 0x251D, 0x2530, 0x2525, 0x2538, 0x2542, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis88[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x4E9C, 0x5516, 0x5A03, + 0x963F, 0x54C0, 0x611B, 0x6328, 0x59F6, 0x9022, + 0x8475, 0x831C, 0x7A50, 0x60AA, 0x63E1, 0x6E25, + 0x65ED, 0x8466, 0x82A6, 0x9BF5, 0x6893, 0x5727, + 0x65A1, 0x6271, 0x5B9B, 0x59D0, 0x867B, 0x98F4, + 0x7D62, 0x7DBE, 0x9B8E, 0x6216, 0x7C9F, 0x88B7, + 0x5B89, 0x5EB5, 0x6309, 0x6697, 0x6848, 0x95C7, + 0x978D, 0x674F, 0x4EE5, 0x4F0A, 0x4F4D, 0x4F9D, + 0x5049, 0x56F2, 0x5937, 0x59D4, 0x5A01, 0x5C09, + 0x60DF, 0x610F, 0x6170, 0x6613, 0x6905, 0x70BA, + 0x754F, 0x7570, 0x79FB, 0x7DAD, 0x7DEF, 0x80C3, + 0x840E, 0x8863, 0x8B02, 0x9055, 0x907A, 0x533B, + 0x4E95, 0x4EA5, 0x57DF, 0x80B2, 0x90C1, 0x78EF, + 0x4E00, 0x58F1, 0x6EA2, 0x9038, 0x7A32, 0x8328, + 0x828B, 0x9C2F, 0x5141, 0x5370, 0x54BD, 0x54E1, + 0x56E0, 0x59FB, 0x5F15, 0x98F2, 0x6DEB, 0x80E4, + 0x852D, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis89[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9662, 0x9670, + 0x96A0, 0x97FB, 0x540B, 0x53F3, 0x5B87, 0x70CF, + 0x7FBD, 0x8FC2, 0x96E8, 0x536F, 0x9D5C, 0x7ABA, + 0x4E11, 0x7893, 0x81FC, 0x6E26, 0x5618, 0x5504, + 0x6B1D, 0x851A, 0x9C3B, 0x59E5, 0x53A9, 0x6D66, + 0x74DC, 0x958F, 0x5642, 0x4E91, 0x904B, 0x96F2, + 0x834F, 0x990C, 0x53E1, 0x55B6, 0x5B30, 0x5F71, + 0x6620, 0x66F3, 0x6804, 0x6C38, 0x6CF3, 0x6D29, + 0x745B, 0x76C8, 0x7A4E, 0x9834, 0x82F1, 0x885B, + 0x8A60, 0x92ED, 0x6DB2, 0x75AB, 0x76CA, 0x99C5, + 0x60A6, 0x8B01, 0x8D8A, 0x95B2, 0x698E, 0x53AD, + 0x5186, 0x0000, 0x5712, 0x5830, 0x5944, 0x5BB4, + 0x5EF6, 0x6028, 0x63A9, 0x63F4, 0x6CBF, 0x6F14, + 0x708E, 0x7114, 0x7159, 0x71D5, 0x733F, 0x7E01, + 0x8276, 0x82D1, 0x8597, 0x9060, 0x925B, 0x9D1B, + 0x5869, 0x65BC, 0x6C5A, 0x7525, 0x51F9, 0x592E, + 0x5965, 0x5F80, 0x5FDC, 0x62BC, 0x65FA, 0x6A2A, + 0x6B27, 0x6BB4, 0x738B, 0x7FC1, 0x8956, 0x9D2C, + 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, + 0x5C4B, 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, + 0x4FFA, 0x5378, 0x6069, 0x6E29, 0x7A4F, 0x97F3, + 0x4E0B, 0x5316, 0x4EEE, 0x4F55, 0x4F3D, 0x4FA1, + 0x4F73, 0x52A0, 0x53EF, 0x5609, 0x590F, 0x5AC1, + 0x5BB6, 0x5BE1, 0x79D1, 0x6687, 0x679C, 0x67B6, + 0x6B4C, 0x6CB3, 0x706B, 0x73C2, 0x798D, 0x79BE, + 0x7A3C, 0x7B87, 0x82B1, 0x82DB, 0x8304, 0x8377, + 0x83EF, 0x83D3, 0x8766, 0x8AB2, 0x5629, 0x8CA8, + 0x8FE6, 0x904E, 0x971E, 0x868A, 0x4FC4, 0x5CE8, + 0x6211, 0x7259, 0x753B, 0x81E5, 0x82BD, 0x86FE, + 0x8CC0, 0x96C5, 0x9913, 0x99D5, 0x4ECB, 0x4F1A, + 0x89E3, 0x56DE, 0x584A, 0x58CA, 0x5EFB, 0x5FEB, + 0x602A, 0x6094, 0x6062, 0x61D0, 0x6212, 0x62D0, + 0x6539, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis8A[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9B41, 0x6666, + 0x68B0, 0x6D77, 0x7070, 0x754C, 0x7686, 0x7D75, + 0x82A5, 0x87F9, 0x958B, 0x968E, 0x8C9D, 0x51F1, + 0x52BE, 0x5916, 0x54B3, 0x5BB3, 0x5D16, 0x6168, + 0x6982, 0x6DAF, 0x788D, 0x84CB, 0x8857, 0x8A72, + 0x93A7, 0x9AB8, 0x6D6C, 0x99A8, 0x86D9, 0x57A3, + 0x67FF, 0x86CE, 0x920E, 0x5283, 0x5687, 0x5404, + 0x5ED3, 0x62E1, 0x64B9, 0x683C, 0x6838, 0x6BBB, + 0x7372, 0x78BA, 0x7A6B, 0x899A, 0x89D2, 0x8D6B, + 0x8F03, 0x90ED, 0x95A3, 0x9694, 0x9769, 0x5B66, + 0x5CB3, 0x697D, 0x984D, 0x984E, 0x639B, 0x7B20, + 0x6A2B, 0x0000, 0x6A7F, 0x68B6, 0x9C0D, 0x6F5F, + 0x5272, 0x559D, 0x6070, 0x62EC, 0x6D3B, 0x6E07, + 0x6ED1, 0x845B, 0x8910, 0x8F44, 0x4E14, 0x9C39, + 0x53F6, 0x691B, 0x6A3A, 0x9784, 0x682A, 0x515C, + 0x7AC3, 0x84B2, 0x91DC, 0x938C, 0x565B, 0x9D28, + 0x6822, 0x8305, 0x8431, 0x7CA5, 0x5208, 0x82C5, + 0x74E6, 0x4E7E, 0x4F83, 0x51A0, 0x5BD2, 0x520A, + 0x52D8, 0x52E7, 0x5DFB, 0x559A, 0x582A, 0x59E6, + 0x5B8C, 0x5B98, 0x5BDB, 0x5E72, 0x5E79, 0x60A3, + 0x611F, 0x6163, 0x61BE, 0x63DB, 0x6562, 0x67D1, + 0x6853, 0x68FA, 0x6B3E, 0x6B53, 0x6C57, 0x6F22, + 0x6F97, 0x6F45, 0x74B0, 0x7518, 0x76E3, 0x770B, + 0x7AFF, 0x7BA1, 0x7C21, 0x7DE9, 0x7F36, 0x7FF0, + 0x809D, 0x8266, 0x839E, 0x89B3, 0x8ACC, 0x8CAB, + 0x9084, 0x9451, 0x9593, 0x9591, 0x95A2, 0x9665, + 0x97D3, 0x9928, 0x8218, 0x4E38, 0x542B, 0x5CB8, + 0x5DCC, 0x73A9, 0x764C, 0x773C, 0x5CA9, 0x7FEB, + 0x8D0B, 0x96C1, 0x9811, 0x9854, 0x9858, 0x4F01, + 0x4F0E, 0x5371, 0x559C, 0x5668, 0x57FA, 0x5947, + 0x5B09, 0x5BC4, 0x5C90, 0x5E0C, 0x5E7E, 0x5FCC, + 0x63EE, 0x673A, 0x65D7, 0x65E2, 0x671F, 0x68CB, + 0x68C4, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis8B[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x6A5F, 0x5E30, + 0x6BC5, 0x6C17, 0x6C7D, 0x757F, 0x7948, 0x5B63, + 0x7A00, 0x7D00, 0x5FBD, 0x898F, 0x8A18, 0x8CB4, + 0x8D77, 0x8ECC, 0x8F1D, 0x98E2, 0x9A0E, 0x9B3C, + 0x4E80, 0x507D, 0x5100, 0x5993, 0x5B9C, 0x622F, + 0x6280, 0x64EC, 0x6B3A, 0x72A0, 0x7591, 0x7947, + 0x7FA9, 0x87FB, 0x8ABC, 0x8B70, 0x63AC, 0x83CA, + 0x97A0, 0x5409, 0x5403, 0x55AB, 0x6854, 0x6A58, + 0x8A70, 0x7827, 0x6775, 0x9ECD, 0x5374, 0x5BA2, + 0x811A, 0x8650, 0x9006, 0x4E18, 0x4E45, 0x4EC7, + 0x4F11, 0x53CA, 0x5438, 0x5BAE, 0x5F13, 0x6025, + 0x6551, 0x0000, 0x673D, 0x6C42, 0x6C72, 0x6CE3, + 0x7078, 0x7403, 0x7A76, 0x7AAE, 0x7B08, 0x7D1A, + 0x7CFE, 0x7D66, 0x65E7, 0x725B, 0x53BB, 0x5C45, + 0x5DE8, 0x62D2, 0x62E0, 0x6319, 0x6E20, 0x865A, + 0x8A31, 0x8DDD, 0x92F8, 0x6F01, 0x79A6, 0x9B5A, + 0x4EA8, 0x4EAB, 0x4EAC, 0x4F9B, 0x4FA0, 0x50D1, + 0x5147, 0x7AF6, 0x5171, 0x51F6, 0x5354, 0x5321, + 0x537F, 0x53EB, 0x55AC, 0x5883, 0x5CE1, 0x5F37, + 0x5F4A, 0x602F, 0x6050, 0x606D, 0x631F, 0x6559, + 0x6A4B, 0x6CC1, 0x72C2, 0x72ED, 0x77EF, 0x80F8, + 0x8105, 0x8208, 0x854E, 0x90F7, 0x93E1, 0x97FF, + 0x9957, 0x9A5A, 0x4EF0, 0x51DD, 0x5C2D, 0x6681, + 0x696D, 0x5C40, 0x66F2, 0x6975, 0x7389, 0x6850, + 0x7C81, 0x50C5, 0x52E4, 0x5747, 0x5DFE, 0x9326, + 0x65A4, 0x6B23, 0x6B3D, 0x7434, 0x7981, 0x79BD, + 0x7B4B, 0x7DCA, 0x82B9, 0x83CC, 0x887F, 0x895F, + 0x8B39, 0x8FD1, 0x91D1, 0x541F, 0x9280, 0x4E5D, + 0x5036, 0x53E5, 0x533A, 0x72D7, 0x7396, 0x77E9, + 0x82E6, 0x8EAF, 0x99C6, 0x99C8, 0x99D2, 0x5177, + 0x611A, 0x865E, 0x55B0, 0x7A7A, 0x5076, 0x5BD3, + 0x9047, 0x9685, 0x4E32, 0x6ADB, 0x91E7, 0x5C51, + 0x5C48, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis8C[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x6398, 0x7A9F, + 0x6C93, 0x9774, 0x8F61, 0x7AAA, 0x718A, 0x9688, + 0x7C82, 0x6817, 0x7E70, 0x6851, 0x936C, 0x52F2, + 0x541B, 0x85AB, 0x8A13, 0x7FA4, 0x8ECD, 0x90E1, + 0x5366, 0x8888, 0x7941, 0x4FC2, 0x50BE, 0x5211, + 0x5144, 0x5553, 0x572D, 0x73EA, 0x578B, 0x5951, + 0x5F62, 0x5F84, 0x6075, 0x6176, 0x6167, 0x61A9, + 0x63B2, 0x643A, 0x656C, 0x666F, 0x6842, 0x6E13, + 0x7566, 0x7A3D, 0x7CFB, 0x7D4C, 0x7D99, 0x7E4B, + 0x7F6B, 0x830E, 0x834A, 0x86CD, 0x8A08, 0x8A63, + 0x8B66, 0x8EFD, 0x981A, 0x9D8F, 0x82B8, 0x8FCE, + 0x9BE8, 0x0000, 0x5287, 0x621F, 0x6483, 0x6FC0, + 0x9699, 0x6841, 0x5091, 0x6B20, 0x6C7A, 0x6F54, + 0x7A74, 0x7D50, 0x8840, 0x8A23, 0x6708, 0x4EF6, + 0x5039, 0x5026, 0x5065, 0x517C, 0x5238, 0x5263, + 0x55A7, 0x570F, 0x5805, 0x5ACC, 0x5EFA, 0x61B2, + 0x61F8, 0x62F3, 0x6372, 0x691C, 0x6A29, 0x727D, + 0x72AC, 0x732E, 0x7814, 0x786F, 0x7D79, 0x770C, + 0x80A9, 0x898B, 0x8B19, 0x8CE2, 0x8ED2, 0x9063, + 0x9375, 0x967A, 0x9855, 0x9A13, 0x9E78, 0x5143, + 0x539F, 0x53B3, 0x5E7B, 0x5F26, 0x6E1B, 0x6E90, + 0x7384, 0x73FE, 0x7D43, 0x8237, 0x8A00, 0x8AFA, + 0x9650, 0x4E4E, 0x500B, 0x53E4, 0x547C, 0x56FA, + 0x59D1, 0x5B64, 0x5DF1, 0x5EAB, 0x5F27, 0x6238, + 0x6545, 0x67AF, 0x6E56, 0x72D0, 0x7CCA, 0x88B4, + 0x80A1, 0x80E1, 0x83F0, 0x864E, 0x8A87, 0x8DE8, + 0x9237, 0x96C7, 0x9867, 0x9F13, 0x4E94, 0x4E92, + 0x4F0D, 0x5348, 0x5449, 0x543E, 0x5A2F, 0x5F8C, + 0x5FA1, 0x609F, 0x68A7, 0x6A8E, 0x745A, 0x7881, + 0x8A9E, 0x8AA4, 0x8B77, 0x9190, 0x4E5E, 0x9BC9, + 0x4EA4, 0x4F7C, 0x4FAF, 0x5019, 0x5016, 0x5149, + 0x516C, 0x529F, 0x52B9, 0x52FE, 0x539A, 0x53E3, + 0x5411, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis8D[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x540E, 0x5589, + 0x5751, 0x57A2, 0x597D, 0x5B54, 0x5B5D, 0x5B8F, + 0x5DE5, 0x5DE7, 0x5DF7, 0x5E78, 0x5E83, 0x5E9A, + 0x5EB7, 0x5F18, 0x6052, 0x614C, 0x6297, 0x62D8, + 0x63A7, 0x653B, 0x6602, 0x6643, 0x66F4, 0x676D, + 0x6821, 0x6897, 0x69CB, 0x6C5F, 0x6D2A, 0x6D69, + 0x6E2F, 0x6E9D, 0x7532, 0x7687, 0x786C, 0x7A3F, + 0x7CE0, 0x7D05, 0x7D18, 0x7D5E, 0x7DB1, 0x8015, + 0x8003, 0x80AF, 0x80B1, 0x8154, 0x818F, 0x822A, + 0x8352, 0x884C, 0x8861, 0x8B1B, 0x8CA2, 0x8CFC, + 0x90CA, 0x9175, 0x9271, 0x783F, 0x92FC, 0x95A4, + 0x964D, 0x0000, 0x9805, 0x9999, 0x9AD8, 0x9D3B, + 0x525B, 0x52AB, 0x53F7, 0x5408, 0x58D5, 0x62F7, + 0x6FE0, 0x8C6A, 0x8F5F, 0x9EB9, 0x514B, 0x523B, + 0x544A, 0x56FD, 0x7A40, 0x9177, 0x9D60, 0x9ED2, + 0x7344, 0x6F09, 0x8170, 0x7511, 0x5FFD, 0x60DA, + 0x9AA8, 0x72DB, 0x8FBC, 0x6B64, 0x9803, 0x4ECA, + 0x56F0, 0x5764, 0x58BE, 0x5A5A, 0x6068, 0x61C7, + 0x660F, 0x6606, 0x6839, 0x68B1, 0x6DF7, 0x75D5, + 0x7D3A, 0x826E, 0x9B42, 0x4E9B, 0x4F50, 0x53C9, + 0x5506, 0x5D6F, 0x5DE6, 0x5DEE, 0x67FB, 0x6C99, + 0x7473, 0x7802, 0x8A50, 0x9396, 0x88DF, 0x5750, + 0x5EA7, 0x632B, 0x50B5, 0x50AC, 0x518D, 0x6700, + 0x54C9, 0x585E, 0x59BB, 0x5BB0, 0x5F69, 0x624D, + 0x63A1, 0x683D, 0x6B73, 0x6E08, 0x707D, 0x91C7, + 0x7280, 0x7815, 0x7826, 0x796D, 0x658E, 0x7D30, + 0x83DC, 0x88C1, 0x8F09, 0x969B, 0x5264, 0x5728, + 0x6750, 0x7F6A, 0x8CA1, 0x51B4, 0x5742, 0x962A, + 0x583A, 0x698A, 0x80B4, 0x54B2, 0x5D0E, 0x57FC, + 0x7895, 0x9DFA, 0x4F5C, 0x524A, 0x548B, 0x643E, + 0x6628, 0x6714, 0x67F5, 0x7A84, 0x7B56, 0x7D22, + 0x932F, 0x685C, 0x9BAD, 0x7B39, 0x5319, 0x518A, + 0x5237, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis8E[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x5BDF, 0x62F6, + 0x64AE, 0x64E6, 0x672D, 0x6BBA, 0x85A9, 0x96D1, + 0x7690, 0x9BD6, 0x634C, 0x9306, 0x9BAB, 0x76BF, + 0x6652, 0x4E09, 0x5098, 0x53C2, 0x5C71, 0x60E8, + 0x6492, 0x6563, 0x685F, 0x71E6, 0x73CA, 0x7523, + 0x7B97, 0x7E82, 0x8695, 0x8B83, 0x8CDB, 0x9178, + 0x9910, 0x65AC, 0x66AB, 0x6B8B, 0x4ED5, 0x4ED4, + 0x4F3A, 0x4F7F, 0x523A, 0x53F8, 0x53F2, 0x55E3, + 0x56DB, 0x58EB, 0x59CB, 0x59C9, 0x59FF, 0x5B50, + 0x5C4D, 0x5E02, 0x5E2B, 0x5FD7, 0x601D, 0x6307, + 0x652F, 0x5B5C, 0x65AF, 0x65BD, 0x65E8, 0x679D, + 0x6B62, 0x0000, 0x6B7B, 0x6C0F, 0x7345, 0x7949, + 0x79C1, 0x7CF8, 0x7D19, 0x7D2B, 0x80A2, 0x8102, + 0x81F3, 0x8996, 0x8A5E, 0x8A69, 0x8A66, 0x8A8C, + 0x8AEE, 0x8CC7, 0x8CDC, 0x96CC, 0x98FC, 0x6B6F, + 0x4E8B, 0x4F3C, 0x4F8D, 0x5150, 0x5B57, 0x5BFA, + 0x6148, 0x6301, 0x6642, 0x6B21, 0x6ECB, 0x6CBB, + 0x723E, 0x74BD, 0x75D4, 0x78C1, 0x793A, 0x800C, + 0x8033, 0x81EA, 0x8494, 0x8F9E, 0x6C50, 0x9E7F, + 0x5F0F, 0x8B58, 0x9D2B, 0x7AFA, 0x8EF8, 0x5B8D, + 0x96EB, 0x4E03, 0x53F1, 0x57F7, 0x5931, 0x5AC9, + 0x5BA4, 0x6089, 0x6E7F, 0x6F06, 0x75BE, 0x8CEA, + 0x5B9F, 0x8500, 0x7BE0, 0x5072, 0x67F4, 0x829D, + 0x5C61, 0x854A, 0x7E1E, 0x820E, 0x5199, 0x5C04, + 0x6368, 0x8D66, 0x659C, 0x716E, 0x793E, 0x7D17, + 0x8005, 0x8B1D, 0x8ECA, 0x906E, 0x86C7, 0x90AA, + 0x501F, 0x52FA, 0x5C3A, 0x6753, 0x707C, 0x7235, + 0x914C, 0x91C8, 0x932B, 0x82E5, 0x5BC2, 0x5F31, + 0x60F9, 0x4E3B, 0x53D6, 0x5B88, 0x624B, 0x6731, + 0x6B8A, 0x72E9, 0x73E0, 0x7A2E, 0x816B, 0x8DA3, + 0x9152, 0x9996, 0x5112, 0x53D7, 0x546A, 0x5BFF, + 0x6388, 0x6A39, 0x7DAC, 0x9700, 0x56DA, 0x53CE, + 0x5468, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis8F[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x5B97, 0x5C31, + 0x5DDE, 0x4FEE, 0x6101, 0x62FE, 0x6D32, 0x79C0, + 0x79CB, 0x7D42, 0x7E4D, 0x7FD2, 0x81ED, 0x821F, + 0x8490, 0x8846, 0x8972, 0x8B90, 0x8E74, 0x8F2F, + 0x9031, 0x914B, 0x916C, 0x96C6, 0x919C, 0x4EC0, + 0x4F4F, 0x5145, 0x5341, 0x5F93, 0x620E, 0x67D4, + 0x6C41, 0x6E0B, 0x7363, 0x7E26, 0x91CD, 0x9283, + 0x53D4, 0x5919, 0x5BBF, 0x6DD1, 0x795D, 0x7E2E, + 0x7C9B, 0x587E, 0x719F, 0x51FA, 0x8853, 0x8FF0, + 0x4FCA, 0x5CFB, 0x6625, 0x77AC, 0x7AE3, 0x821C, + 0x99FF, 0x51C6, 0x5FAA, 0x65EC, 0x696F, 0x6B89, + 0x6DF3, 0x0000, 0x6E96, 0x6F64, 0x76FE, 0x7D14, + 0x5DE1, 0x9075, 0x9187, 0x9806, 0x51E6, 0x521D, + 0x6240, 0x6691, 0x66D9, 0x6E1A, 0x5EB6, 0x7DD2, + 0x7F72, 0x66F8, 0x85AF, 0x85F7, 0x8AF8, 0x52A9, + 0x53D9, 0x5973, 0x5E8F, 0x5F90, 0x6055, 0x92E4, + 0x9664, 0x50B7, 0x511F, 0x52DD, 0x5320, 0x5347, + 0x53EC, 0x54E8, 0x5546, 0x5531, 0x5617, 0x5968, + 0x59BE, 0x5A3C, 0x5BB5, 0x5C06, 0x5C0F, 0x5C11, + 0x5C1A, 0x5E84, 0x5E8A, 0x5EE0, 0x5F70, 0x627F, + 0x6284, 0x62DB, 0x638C, 0x6377, 0x6607, 0x660C, + 0x662D, 0x6676, 0x677E, 0x68A2, 0x6A1F, 0x6A35, + 0x6CBC, 0x6D88, 0x6E09, 0x6E58, 0x713C, 0x7126, + 0x7167, 0x75C7, 0x7701, 0x785D, 0x7901, 0x7965, + 0x79F0, 0x7AE0, 0x7B11, 0x7CA7, 0x7D39, 0x8096, + 0x83D6, 0x848B, 0x8549, 0x885D, 0x88F3, 0x8A1F, + 0x8A3C, 0x8A54, 0x8A73, 0x8C61, 0x8CDE, 0x91A4, + 0x9266, 0x937E, 0x9418, 0x969C, 0x9798, 0x4E0A, + 0x4E08, 0x4E1E, 0x4E57, 0x5197, 0x5270, 0x57CE, + 0x5834, 0x58CC, 0x5B22, 0x5E38, 0x60C5, 0x64FE, + 0x6761, 0x6756, 0x6D44, 0x72B6, 0x7573, 0x7A63, + 0x84B8, 0x8B72, 0x91B8, 0x9320, 0x5631, 0x57F4, + 0x98FE, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis90[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x62ED, 0x690D, + 0x6B96, 0x71ED, 0x7E54, 0x8077, 0x8272, 0x89E6, + 0x98DF, 0x8755, 0x8FB1, 0x5C3B, 0x4F38, 0x4FE1, + 0x4FB5, 0x5507, 0x5A20, 0x5BDD, 0x5BE9, 0x5FC3, + 0x614E, 0x632F, 0x65B0, 0x664B, 0x68EE, 0x699B, + 0x6D78, 0x6DF1, 0x7533, 0x75B9, 0x771F, 0x795E, + 0x79E6, 0x7D33, 0x81E3, 0x82AF, 0x85AA, 0x89AA, + 0x8A3A, 0x8EAB, 0x8F9B, 0x9032, 0x91DD, 0x9707, + 0x4EBA, 0x4EC1, 0x5203, 0x5875, 0x58EC, 0x5C0B, + 0x751A, 0x5C3D, 0x814E, 0x8A0A, 0x8FC5, 0x9663, + 0x976D, 0x7B25, 0x8ACF, 0x9808, 0x9162, 0x56F3, + 0x53A8, 0x0000, 0x9017, 0x5439, 0x5782, 0x5E25, + 0x63A8, 0x6C34, 0x708A, 0x7761, 0x7C8B, 0x7FE0, + 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968F, + 0x745E, 0x9AC4, 0x5D07, 0x5D69, 0x6570, 0x67A2, + 0x8DA8, 0x96DB, 0x636E, 0x6749, 0x6919, 0x83C5, + 0x9817, 0x96C0, 0x88FE, 0x6F84, 0x647A, 0x5BF8, + 0x4E16, 0x702C, 0x755D, 0x662F, 0x51C4, 0x5236, + 0x52E2, 0x59D3, 0x5F81, 0x6027, 0x6210, 0x653F, + 0x6574, 0x661F, 0x6674, 0x68F2, 0x6816, 0x6B63, + 0x6E05, 0x7272, 0x751F, 0x76DB, 0x7CBE, 0x8056, + 0x58F0, 0x88FD, 0x897F, 0x8AA0, 0x8A93, 0x8ACB, + 0x901D, 0x9192, 0x9752, 0x9759, 0x6589, 0x7A0E, + 0x8106, 0x96BB, 0x5E2D, 0x60DC, 0x621A, 0x65A5, + 0x6614, 0x6790, 0x77F3, 0x7A4D, 0x7C4D, 0x7E3E, + 0x810A, 0x8CAC, 0x8D64, 0x8DE1, 0x8E5F, 0x78A9, + 0x5207, 0x62D9, 0x63A5, 0x6442, 0x6298, 0x8A2D, + 0x7A83, 0x7BC0, 0x8AAC, 0x96EA, 0x7D76, 0x820C, + 0x8749, 0x4ED9, 0x5148, 0x5343, 0x5360, 0x5BA3, + 0x5C02, 0x5C16, 0x5DDD, 0x6226, 0x6247, 0x64B0, + 0x6813, 0x6834, 0x6CC9, 0x6D45, 0x6D17, 0x67D3, + 0x6F5C, 0x714E, 0x717D, 0x65CB, 0x7A7F, 0x7BAD, + 0x7DDA, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis91[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x7E4A, 0x7FA8, + 0x817A, 0x821B, 0x8239, 0x85A6, 0x8A6E, 0x8CCE, + 0x8DF5, 0x9078, 0x9077, 0x92AD, 0x9291, 0x9583, + 0x9BAE, 0x524D, 0x5584, 0x6F38, 0x7136, 0x5168, + 0x7985, 0x7E55, 0x81B3, 0x7CCE, 0x564C, 0x5851, + 0x5CA8, 0x63AA, 0x66FE, 0x66FD, 0x695A, 0x72D9, + 0x758F, 0x758E, 0x790E, 0x7956, 0x79DF, 0x7C97, + 0x7D20, 0x7D44, 0x8607, 0x8A34, 0x963B, 0x9061, + 0x9F20, 0x50E7, 0x5275, 0x53CC, 0x53E2, 0x5009, + 0x55AA, 0x58EE, 0x594F, 0x723D, 0x5B8B, 0x5C64, + 0x531D, 0x60E3, 0x60F3, 0x635C, 0x6383, 0x633F, + 0x63BB, 0x0000, 0x64CD, 0x65E9, 0x66F9, 0x5DE3, + 0x69CD, 0x69FD, 0x6F15, 0x71E5, 0x4E89, 0x75E9, + 0x76F8, 0x7A93, 0x7CDF, 0x7DCF, 0x7D9C, 0x8061, + 0x8349, 0x8358, 0x846C, 0x84BC, 0x85FB, 0x88C5, + 0x8D70, 0x9001, 0x906D, 0x9397, 0x971C, 0x9A12, + 0x50CF, 0x5897, 0x618E, 0x81D3, 0x8535, 0x8D08, + 0x9020, 0x4FC3, 0x5074, 0x5247, 0x5373, 0x606F, + 0x6349, 0x675F, 0x6E2C, 0x8DB3, 0x901F, 0x4FD7, + 0x5C5E, 0x8CCA, 0x65CF, 0x7D9A, 0x5352, 0x8896, + 0x5176, 0x63C3, 0x5B58, 0x5B6B, 0x5C0A, 0x640D, + 0x6751, 0x905C, 0x4ED6, 0x591A, 0x592A, 0x6C70, + 0x8A51, 0x553E, 0x5815, 0x59A5, 0x60F0, 0x6253, + 0x67C1, 0x8235, 0x6955, 0x9640, 0x99C4, 0x9A28, + 0x4F53, 0x5806, 0x5BFE, 0x8010, 0x5CB1, 0x5E2F, + 0x5F85, 0x6020, 0x614B, 0x6234, 0x66FF, 0x6CF0, + 0x6EDE, 0x80CE, 0x817F, 0x82D4, 0x888B, 0x8CB8, + 0x9000, 0x902E, 0x968A, 0x9EDB, 0x9BDB, 0x4EE3, + 0x53F0, 0x5927, 0x7B2C, 0x918D, 0x984C, 0x9DF9, + 0x6EDD, 0x7027, 0x5353, 0x5544, 0x5B85, 0x6258, + 0x629E, 0x62D3, 0x6CA2, 0x6FEF, 0x7422, 0x8A17, + 0x9438, 0x6FC1, 0x8AFE, 0x8338, 0x51E7, 0x86F8, + 0x53EA, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis92[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x53E9, 0x4F46, + 0x9054, 0x8FB0, 0x596A, 0x8131, 0x5DFD, 0x7AEA, + 0x8FBF, 0x68DA, 0x8C37, 0x72F8, 0x9C48, 0x6A3D, + 0x8AB0, 0x4E39, 0x5358, 0x5606, 0x5766, 0x62C5, + 0x63A2, 0x65E6, 0x6B4E, 0x6DE1, 0x6E5B, 0x70AD, + 0x77ED, 0x7AEF, 0x7BAA, 0x7DBB, 0x803D, 0x80C6, + 0x86CB, 0x8A95, 0x935B, 0x56E3, 0x58C7, 0x5F3E, + 0x65AD, 0x6696, 0x6A80, 0x6BB5, 0x7537, 0x8AC7, + 0x5024, 0x77E5, 0x5730, 0x5F1B, 0x6065, 0x667A, + 0x6C60, 0x75F4, 0x7A1A, 0x7F6E, 0x81F4, 0x8718, + 0x9045, 0x99B3, 0x7BC9, 0x755C, 0x7AF9, 0x7B51, + 0x84C4, 0x0000, 0x9010, 0x79E9, 0x7A92, 0x8336, + 0x5AE1, 0x7740, 0x4E2D, 0x4EF2, 0x5B99, 0x5FE0, + 0x62BD, 0x663C, 0x67F1, 0x6CE8, 0x866B, 0x8877, + 0x8A3B, 0x914E, 0x92F3, 0x99D0, 0x6A17, 0x7026, + 0x732A, 0x82E7, 0x8457, 0x8CAF, 0x4E01, 0x5146, + 0x51CB, 0x558B, 0x5BF5, 0x5E16, 0x5E33, 0x5E81, + 0x5F14, 0x5F35, 0x5F6B, 0x5FB4, 0x61F2, 0x6311, + 0x66A2, 0x671D, 0x6F6E, 0x7252, 0x753A, 0x773A, + 0x8074, 0x8139, 0x8178, 0x8776, 0x8ABF, 0x8ADC, + 0x8D85, 0x8DF3, 0x929A, 0x9577, 0x9802, 0x9CE5, + 0x52C5, 0x6357, 0x76F4, 0x6715, 0x6C88, 0x73CD, + 0x8CC3, 0x93AE, 0x9673, 0x6D25, 0x589C, 0x690E, + 0x69CC, 0x8FFD, 0x939A, 0x75DB, 0x901A, 0x585A, + 0x6802, 0x63B4, 0x69FB, 0x4F43, 0x6F2C, 0x67D8, + 0x8FBB, 0x8526, 0x7DB4, 0x9354, 0x693F, 0x6F70, + 0x576A, 0x58F7, 0x5B2C, 0x7D2C, 0x722A, 0x540A, + 0x91E3, 0x9DB4, 0x4EAD, 0x4F4E, 0x505C, 0x5075, + 0x5243, 0x8C9E, 0x5448, 0x5824, 0x5B9A, 0x5E1D, + 0x5E95, 0x5EAD, 0x5EF7, 0x5F1F, 0x608C, 0x62B5, + 0x633A, 0x63D0, 0x68AF, 0x6C40, 0x7887, 0x798E, + 0x7A0B, 0x7DE0, 0x8247, 0x8A02, 0x8AE6, 0x8E44, + 0x9013, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis93[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x90B8, 0x912D, + 0x91D8, 0x9F0E, 0x6CE5, 0x6458, 0x64E2, 0x6575, + 0x6EF4, 0x7684, 0x7B1B, 0x9069, 0x93D1, 0x6EBA, + 0x54F2, 0x5FB9, 0x64A4, 0x8F4D, 0x8FED, 0x9244, + 0x5178, 0x586B, 0x5929, 0x5C55, 0x5E97, 0x6DFB, + 0x7E8F, 0x751C, 0x8CBC, 0x8EE2, 0x985B, 0x70B9, + 0x4F1D, 0x6BBF, 0x6FB1, 0x7530, 0x96FB, 0x514E, + 0x5410, 0x5835, 0x5857, 0x59AC, 0x5C60, 0x5F92, + 0x6597, 0x675C, 0x6E21, 0x767B, 0x83DF, 0x8CED, + 0x9014, 0x90FD, 0x934D, 0x7825, 0x783A, 0x52AA, + 0x5EA6, 0x571F, 0x5974, 0x6012, 0x5012, 0x515A, + 0x51AC, 0x0000, 0x51CD, 0x5200, 0x5510, 0x5854, + 0x5858, 0x5957, 0x5B95, 0x5CF6, 0x5D8B, 0x60BC, + 0x6295, 0x642D, 0x6771, 0x6843, 0x68BC, 0x68DF, + 0x76D7, 0x6DD8, 0x6E6F, 0x6D9B, 0x706F, 0x71C8, + 0x5F53, 0x75D8, 0x7977, 0x7B49, 0x7B54, 0x7B52, + 0x7CD6, 0x7D71, 0x5230, 0x8463, 0x8569, 0x85E4, + 0x8A0E, 0x8B04, 0x8C46, 0x8E0F, 0x9003, 0x900F, + 0x9419, 0x9676, 0x982D, 0x9A30, 0x95D8, 0x50CD, + 0x52D5, 0x540C, 0x5802, 0x5C0E, 0x61A7, 0x649E, + 0x6D1E, 0x77B3, 0x7AE5, 0x80F4, 0x8404, 0x9053, + 0x9285, 0x5CE0, 0x9D07, 0x533F, 0x5F97, 0x5FB3, + 0x6D9C, 0x7279, 0x7763, 0x79BF, 0x7BE4, 0x6BD2, + 0x72EC, 0x8AAD, 0x6803, 0x6A61, 0x51F8, 0x7A81, + 0x6934, 0x5C4A, 0x9CF6, 0x82EB, 0x5BC5, 0x9149, + 0x701E, 0x5678, 0x5C6F, 0x60C7, 0x6566, 0x6C8C, + 0x8C5A, 0x9041, 0x9813, 0x5451, 0x66C7, 0x920D, + 0x5948, 0x90A3, 0x5185, 0x4E4D, 0x51EA, 0x8599, + 0x8B0E, 0x7058, 0x637A, 0x934B, 0x6962, 0x99B4, + 0x7E04, 0x7577, 0x5357, 0x6960, 0x8EDF, 0x96E3, + 0x6C5D, 0x4E8C, 0x5C3C, 0x5F10, 0x8FE9, 0x5302, + 0x8CD1, 0x8089, 0x8679, 0x5EFF, 0x65E5, 0x4E73, + 0x5165, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis94[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x5982, 0x5C3F, + 0x97EE, 0x4EFB, 0x598A, 0x5FCD, 0x8A8D, 0x6FE1, + 0x79B0, 0x7962, 0x5BE7, 0x8471, 0x732B, 0x71B1, + 0x5E74, 0x5FF5, 0x637B, 0x649A, 0x71C3, 0x7C98, + 0x4E43, 0x5EFC, 0x4E4B, 0x57DC, 0x56A2, 0x60A9, + 0x6FC3, 0x7D0D, 0x80FD, 0x8133, 0x81BF, 0x8FB2, + 0x8997, 0x86A4, 0x5DF4, 0x628A, 0x64AD, 0x8987, + 0x6777, 0x6CE2, 0x6D3E, 0x7436, 0x7834, 0x5A46, + 0x7F75, 0x82AD, 0x99AC, 0x4FF3, 0x5EC3, 0x62DD, + 0x6392, 0x6557, 0x676F, 0x76C3, 0x724C, 0x80CC, + 0x80BA, 0x8F29, 0x914D, 0x500D, 0x57F9, 0x5A92, + 0x6885, 0x0000, 0x6973, 0x7164, 0x72FD, 0x8CB7, + 0x58F2, 0x8CE0, 0x966A, 0x9019, 0x877F, 0x79E4, + 0x77E7, 0x8429, 0x4F2F, 0x5265, 0x535A, 0x62CD, + 0x67CF, 0x6CCA, 0x767D, 0x7B94, 0x7C95, 0x8236, + 0x8584, 0x8FEB, 0x66DD, 0x6F20, 0x7206, 0x7E1B, + 0x83AB, 0x99C1, 0x9EA6, 0x51FD, 0x7BB1, 0x7872, + 0x7BB8, 0x8087, 0x7B48, 0x6AE8, 0x5E61, 0x808C, + 0x7551, 0x7560, 0x516B, 0x9262, 0x6E8C, 0x767A, + 0x9197, 0x9AEA, 0x4F10, 0x7F70, 0x629C, 0x7B4F, + 0x95A5, 0x9CE9, 0x567A, 0x5859, 0x86E4, 0x96BC, + 0x4F34, 0x5224, 0x534A, 0x53CD, 0x53DB, 0x5E06, + 0x642C, 0x6591, 0x677F, 0x6C3E, 0x6C4E, 0x7248, + 0x72AF, 0x73ED, 0x7554, 0x7E41, 0x822C, 0x85E9, + 0x8CA9, 0x7BC4, 0x91C6, 0x7169, 0x9812, 0x98EF, + 0x633D, 0x6669, 0x756A, 0x76E4, 0x78D0, 0x8543, + 0x86EE, 0x532A, 0x5351, 0x5426, 0x5983, 0x5E87, + 0x5F7C, 0x60B2, 0x6249, 0x6279, 0x62AB, 0x6590, + 0x6BD4, 0x6CCC, 0x75B2, 0x76AE, 0x7891, 0x79D8, + 0x7DCB, 0x7F77, 0x80A5, 0x88AB, 0x8AB9, 0x8CBB, + 0x907F, 0x975E, 0x98DB, 0x6A0B, 0x7C38, 0x5099, + 0x5C3E, 0x5FAE, 0x6787, 0x6BD8, 0x7435, 0x7709, + 0x7F8E, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis95[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9F3B, 0x67CA, + 0x7A17, 0x5339, 0x758B, 0x9AED, 0x5F66, 0x819D, + 0x83F1, 0x8098, 0x5F3C, 0x5FC5, 0x7562, 0x7B46, + 0x903C, 0x6867, 0x59EB, 0x5A9B, 0x7D10, 0x767E, + 0x8B2C, 0x4FF5, 0x5F6A, 0x6A19, 0x6C37, 0x6F02, + 0x74E2, 0x7968, 0x8868, 0x8A55, 0x8C79, 0x5EDF, + 0x63CF, 0x75C5, 0x79D2, 0x82D7, 0x9328, 0x92F2, + 0x849C, 0x86ED, 0x9C2D, 0x54C1, 0x5F6C, 0x658C, + 0x6D5C, 0x7015, 0x8CA7, 0x8CD3, 0x983B, 0x654F, + 0x74F6, 0x4E0D, 0x4ED8, 0x57E0, 0x592B, 0x5A66, + 0x5BCC, 0x51A8, 0x5E03, 0x5E9C, 0x6016, 0x6276, + 0x6577, 0x0000, 0x65A7, 0x666E, 0x6D6E, 0x7236, + 0x7B26, 0x8150, 0x819A, 0x8299, 0x8B5C, 0x8CA0, + 0x8CE6, 0x8D74, 0x961C, 0x9644, 0x4FAE, 0x64AB, + 0x6B66, 0x821E, 0x8461, 0x856A, 0x90E8, 0x5C01, + 0x6953, 0x98A8, 0x847A, 0x8557, 0x4F0F, 0x526F, + 0x5FA9, 0x5E45, 0x670D, 0x798F, 0x8179, 0x8907, + 0x8986, 0x6DF5, 0x5F17, 0x6255, 0x6CB8, 0x4ECF, + 0x7269, 0x9B92, 0x5206, 0x543B, 0x5674, 0x58B3, + 0x61A4, 0x626E, 0x711A, 0x596E, 0x7C89, 0x7CDE, + 0x7D1B, 0x96F0, 0x6587, 0x805E, 0x4E19, 0x4F75, + 0x5175, 0x5840, 0x5E63, 0x5E73, 0x5F0A, 0x67C4, + 0x4E26, 0x853D, 0x9589, 0x965B, 0x7C73, 0x9801, + 0x50FB, 0x58C1, 0x7656, 0x78A7, 0x5225, 0x77A5, + 0x8511, 0x7B86, 0x504F, 0x5909, 0x7247, 0x7BC7, + 0x7DE8, 0x8FBA, 0x8FD4, 0x904D, 0x4FBF, 0x52C9, + 0x5A29, 0x5F01, 0x97AD, 0x4FDD, 0x8217, 0x92EA, + 0x5703, 0x6355, 0x6B69, 0x752B, 0x88DC, 0x8F14, + 0x7A42, 0x52DF, 0x5893, 0x6155, 0x620A, 0x66AE, + 0x6BCD, 0x7C3F, 0x83E9, 0x5023, 0x4FF8, 0x5305, + 0x5446, 0x5831, 0x5949, 0x5B9D, 0x5CF0, 0x5CEF, + 0x5D29, 0x5E96, 0x62B1, 0x6367, 0x653E, 0x65B9, + 0x670B, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis96[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x6CD5, 0x6CE1, + 0x70F9, 0x7832, 0x7E2B, 0x80DE, 0x82B3, 0x840C, + 0x84EC, 0x8702, 0x8912, 0x8A2A, 0x8C4A, 0x90A6, + 0x92D2, 0x98FD, 0x9CF3, 0x9D6C, 0x4E4F, 0x4EA1, + 0x508D, 0x5256, 0x574A, 0x59A8, 0x5E3D, 0x5FD8, + 0x5FD9, 0x623F, 0x66B4, 0x671B, 0x67D0, 0x68D2, + 0x5192, 0x7D21, 0x80AA, 0x81A8, 0x8B00, 0x8C8C, + 0x8CBF, 0x927E, 0x9632, 0x5420, 0x982C, 0x5317, + 0x50D5, 0x535C, 0x58A8, 0x64B2, 0x6734, 0x7267, + 0x7766, 0x7A46, 0x91E6, 0x52C3, 0x6CA1, 0x6B86, + 0x5800, 0x5E4C, 0x5954, 0x672C, 0x7FFB, 0x51E1, + 0x76C6, 0x0000, 0x6469, 0x78E8, 0x9B54, 0x9EBB, + 0x57CB, 0x59B9, 0x6627, 0x679A, 0x6BCE, 0x54E9, + 0x69D9, 0x5E55, 0x819C, 0x6795, 0x9BAA, 0x67FE, + 0x9C52, 0x685D, 0x4EA6, 0x4FE3, 0x53C8, 0x62B9, + 0x672B, 0x6CAB, 0x8FC4, 0x4FAD, 0x7E6D, 0x9EBF, + 0x4E07, 0x6162, 0x6E80, 0x6F2B, 0x8513, 0x5473, + 0x672A, 0x9B45, 0x5DF3, 0x7B95, 0x5CAC, 0x5BC6, + 0x871C, 0x6E4A, 0x84D1, 0x7A14, 0x8108, 0x5999, + 0x7C8D, 0x6C11, 0x7720, 0x52D9, 0x5922, 0x7121, + 0x725F, 0x77DB, 0x9727, 0x9D61, 0x690B, 0x5A7F, + 0x5A18, 0x51A5, 0x540D, 0x547D, 0x660E, 0x76DF, + 0x8FF7, 0x9298, 0x9CF4, 0x59EA, 0x725D, 0x6EC5, + 0x514D, 0x68C9, 0x7DBF, 0x7DEC, 0x9762, 0x9EBA, + 0x6478, 0x6A21, 0x8302, 0x5984, 0x5B5F, 0x6BDB, + 0x731B, 0x76F2, 0x7DB2, 0x8017, 0x8499, 0x5132, + 0x6728, 0x9ED9, 0x76EE, 0x6762, 0x52FF, 0x9905, + 0x5C24, 0x623B, 0x7C7E, 0x8CB0, 0x554F, 0x60B6, + 0x7D0B, 0x9580, 0x5301, 0x4E5F, 0x51B6, 0x591C, + 0x723A, 0x8036, 0x91CE, 0x5F25, 0x77E2, 0x5384, + 0x5F79, 0x7D04, 0x85AC, 0x8A33, 0x8E8D, 0x9756, + 0x67F3, 0x85AE, 0x9453, 0x6109, 0x6108, 0x6CB9, + 0x7652, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis97[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8AED, 0x8F38, + 0x552F, 0x4F51, 0x512A, 0x52C7, 0x53CB, 0x5BA5, + 0x5E7D, 0x60A0, 0x6182, 0x63D6, 0x6709, 0x67DA, + 0x6E67, 0x6D8C, 0x7336, 0x7337, 0x7531, 0x7950, + 0x88D5, 0x8A98, 0x904A, 0x9091, 0x90F5, 0x96C4, + 0x878D, 0x5915, 0x4E88, 0x4F59, 0x4E0E, 0x8A89, + 0x8F3F, 0x9810, 0x50AD, 0x5E7C, 0x5996, 0x5BB9, + 0x5EB8, 0x63DA, 0x63FA, 0x64C1, 0x66DC, 0x694A, + 0x69D8, 0x6D0B, 0x6EB6, 0x7194, 0x7528, 0x7AAF, + 0x7F8A, 0x8000, 0x8449, 0x84C9, 0x8981, 0x8B21, + 0x8E0A, 0x9065, 0x967D, 0x990A, 0x617E, 0x6291, + 0x6B32, 0x0000, 0x6C83, 0x6D74, 0x7FCC, 0x7FFC, + 0x6DC0, 0x7F85, 0x87BA, 0x88F8, 0x6765, 0x83B1, + 0x983C, 0x96F7, 0x6D1B, 0x7D61, 0x843D, 0x916A, + 0x4E71, 0x5375, 0x5D50, 0x6B04, 0x6FEB, 0x85CD, + 0x862D, 0x89A7, 0x5229, 0x540F, 0x5C65, 0x674E, + 0x68A8, 0x7406, 0x7483, 0x75E2, 0x88CF, 0x88E1, + 0x91CC, 0x96E2, 0x9678, 0x5F8B, 0x7387, 0x7ACB, + 0x844E, 0x63A0, 0x7565, 0x5289, 0x6D41, 0x6E9C, + 0x7409, 0x7559, 0x786B, 0x7C92, 0x9686, 0x7ADC, + 0x9F8D, 0x4FB6, 0x616E, 0x65C5, 0x865C, 0x4E86, + 0x4EAE, 0x50DA, 0x4E21, 0x51CC, 0x5BEE, 0x6599, + 0x6881, 0x6DBC, 0x731F, 0x7642, 0x77AD, 0x7A1C, + 0x7CE7, 0x826F, 0x8AD2, 0x907C, 0x91CF, 0x9675, + 0x9818, 0x529B, 0x7DD1, 0x502B, 0x5398, 0x6797, + 0x6DCB, 0x71D0, 0x7433, 0x81E8, 0x8F2A, 0x96A3, + 0x9C57, 0x9E9F, 0x7460, 0x5841, 0x6D99, 0x7D2F, + 0x985E, 0x4EE4, 0x4F36, 0x4F8B, 0x51B7, 0x52B1, + 0x5DBA, 0x601C, 0x73B2, 0x793C, 0x82D3, 0x9234, + 0x96B7, 0x96F6, 0x970A, 0x9E97, 0x9F62, 0x66A6, + 0x6B74, 0x5217, 0x52A3, 0x70C8, 0x88C2, 0x5EC9, + 0x604B, 0x6190, 0x6F23, 0x7149, 0x7C3E, 0x7DF4, + 0x806F, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis98[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x84EE, 0x9023, + 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089, 0x8CC2, + 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, + 0x6717, 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, + 0x72FC, 0x7BED, 0x8001, 0x807E, 0x874B, 0x90CE, + 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332, 0x8AD6, + 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, + 0x60D1, 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, + 0x8A6B, 0x85C1, 0x8568, 0x6900, 0x6E7E, 0x7897, + 0x8155, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x5F0C, 0x4E10, 0x4E15, + 0x4E2A, 0x4E31, 0x4E36, 0x4E3C, 0x4E3F, 0x4E42, + 0x4E56, 0x4E58, 0x4E82, 0x4E85, 0x8C6B, 0x4E8A, + 0x8212, 0x5F0D, 0x4E8E, 0x4E9E, 0x4E9F, 0x4EA0, + 0x4EA2, 0x4EB0, 0x4EB3, 0x4EB6, 0x4ECE, 0x4ECD, + 0x4EC4, 0x4EC6, 0x4EC2, 0x4ED7, 0x4EDE, 0x4EED, + 0x4EDF, 0x4EF7, 0x4F09, 0x4F5A, 0x4F30, 0x4F5B, + 0x4F5D, 0x4F57, 0x4F47, 0x4F76, 0x4F88, 0x4F8F, + 0x4F98, 0x4F7B, 0x4F69, 0x4F70, 0x4F91, 0x4F6F, + 0x4F86, 0x4F96, 0x5118, 0x4FD4, 0x4FDF, 0x4FCE, + 0x4FD8, 0x4FDB, 0x4FD1, 0x4FDA, 0x4FD0, 0x4FE4, + 0x4FE5, 0x501A, 0x5028, 0x5014, 0x502A, 0x5025, + 0x5005, 0x4F1C, 0x4FF6, 0x5021, 0x5029, 0x502C, + 0x4FFE, 0x4FEF, 0x5011, 0x5006, 0x5043, 0x5047, + 0x6703, 0x5055, 0x5050, 0x5048, 0x505A, 0x5056, + 0x506C, 0x5078, 0x5080, 0x509A, 0x5085, 0x50B4, + 0x50B2, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis99[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x50C9, 0x50CA, + 0x50B3, 0x50C2, 0x50D6, 0x50DE, 0x50E5, 0x50ED, + 0x50E3, 0x50EE, 0x50F9, 0x50F5, 0x5109, 0x5101, + 0x5102, 0x5116, 0x5115, 0x5114, 0x511A, 0x5121, + 0x513A, 0x5137, 0x513C, 0x513B, 0x513F, 0x5140, + 0x5152, 0x514C, 0x5154, 0x5162, 0x7AF8, 0x5169, + 0x516A, 0x516E, 0x5180, 0x5182, 0x56D8, 0x518C, + 0x5189, 0x518F, 0x5191, 0x5193, 0x5195, 0x5196, + 0x51A4, 0x51A6, 0x51A2, 0x51A9, 0x51AA, 0x51AB, + 0x51B3, 0x51B1, 0x51B2, 0x51B0, 0x51B5, 0x51BD, + 0x51C5, 0x51C9, 0x51DB, 0x51E0, 0x8655, 0x51E9, + 0x51ED, 0x0000, 0x51F0, 0x51F5, 0x51FE, 0x5204, + 0x520B, 0x5214, 0x520E, 0x5227, 0x522A, 0x522E, + 0x5233, 0x5239, 0x524F, 0x5244, 0x524B, 0x524C, + 0x525E, 0x5254, 0x526A, 0x5274, 0x5269, 0x5273, + 0x527F, 0x527D, 0x528D, 0x5294, 0x5292, 0x5271, + 0x5288, 0x5291, 0x8FA8, 0x8FA7, 0x52AC, 0x52AD, + 0x52BC, 0x52B5, 0x52C1, 0x52CD, 0x52D7, 0x52DE, + 0x52E3, 0x52E6, 0x98ED, 0x52E0, 0x52F3, 0x52F5, + 0x52F8, 0x52F9, 0x5306, 0x5308, 0x7538, 0x530D, + 0x5310, 0x530F, 0x5315, 0x531A, 0x5323, 0x532F, + 0x5331, 0x5333, 0x5338, 0x5340, 0x5346, 0x5345, + 0x4E17, 0x5349, 0x534D, 0x51D6, 0x535E, 0x5369, + 0x536E, 0x5918, 0x537B, 0x5377, 0x5382, 0x5396, + 0x53A0, 0x53A6, 0x53A5, 0x53AE, 0x53B0, 0x53B6, + 0x53C3, 0x7C12, 0x96D9, 0x53DF, 0x66FC, 0x71EE, + 0x53EE, 0x53E8, 0x53ED, 0x53FA, 0x5401, 0x543D, + 0x5440, 0x542C, 0x542D, 0x543C, 0x542E, 0x5436, + 0x5429, 0x541D, 0x544E, 0x548F, 0x5475, 0x548E, + 0x545F, 0x5471, 0x5477, 0x5470, 0x5492, 0x547B, + 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54C7, + 0x54A2, 0x54B8, 0x54A5, 0x54AC, 0x54C4, 0x54C8, + 0x54A8, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis9A[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x54AB, 0x54C2, + 0x54A4, 0x54BE, 0x54BC, 0x54D8, 0x54E5, 0x54E6, + 0x550F, 0x5514, 0x54FD, 0x54EE, 0x54ED, 0x54FA, + 0x54E2, 0x5539, 0x5540, 0x5563, 0x554C, 0x552E, + 0x555C, 0x5545, 0x5556, 0x5557, 0x5538, 0x5533, + 0x555D, 0x5599, 0x5580, 0x54AF, 0x558A, 0x559F, + 0x557B, 0x557E, 0x5598, 0x559E, 0x55AE, 0x557C, + 0x5583, 0x55A9, 0x5587, 0x55A8, 0x55DA, 0x55C5, + 0x55DF, 0x55C4, 0x55DC, 0x55E4, 0x55D4, 0x5614, + 0x55F7, 0x5616, 0x55FE, 0x55FD, 0x561B, 0x55F9, + 0x564E, 0x5650, 0x71DF, 0x5634, 0x5636, 0x5632, + 0x5638, 0x0000, 0x566B, 0x5664, 0x562F, 0x566C, + 0x566A, 0x5686, 0x5680, 0x568A, 0x56A0, 0x5694, + 0x568F, 0x56A5, 0x56AE, 0x56B6, 0x56B4, 0x56C2, + 0x56BC, 0x56C1, 0x56C3, 0x56C0, 0x56C8, 0x56CE, + 0x56D1, 0x56D3, 0x56D7, 0x56EE, 0x56F9, 0x5700, + 0x56FF, 0x5704, 0x5709, 0x5708, 0x570B, 0x570D, + 0x5713, 0x5718, 0x5716, 0x55C7, 0x571C, 0x5726, + 0x5737, 0x5738, 0x574E, 0x573B, 0x5740, 0x574F, + 0x5769, 0x57C0, 0x5788, 0x5761, 0x577F, 0x5789, + 0x5793, 0x57A0, 0x57B3, 0x57A4, 0x57AA, 0x57B0, + 0x57C3, 0x57C6, 0x57D4, 0x57D2, 0x57D3, 0x580A, + 0x57D6, 0x57E3, 0x580B, 0x5819, 0x581D, 0x5872, + 0x5821, 0x5862, 0x584B, 0x5870, 0x6BC0, 0x5852, + 0x583D, 0x5879, 0x5885, 0x58B9, 0x589F, 0x58AB, + 0x58BA, 0x58DE, 0x58BB, 0x58B8, 0x58AE, 0x58C5, + 0x58D3, 0x58D1, 0x58D7, 0x58D9, 0x58D8, 0x58E5, + 0x58DC, 0x58E4, 0x58DF, 0x58EF, 0x58FA, 0x58F9, + 0x58FB, 0x58FC, 0x58FD, 0x5902, 0x590A, 0x5910, + 0x591B, 0x68A6, 0x5925, 0x592C, 0x592D, 0x5932, + 0x5938, 0x593E, 0x7AD2, 0x5955, 0x5950, 0x594E, + 0x595A, 0x5958, 0x5962, 0x5960, 0x5967, 0x596C, + 0x5969, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis9B[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x5978, 0x5981, + 0x599D, 0x4F5E, 0x4FAB, 0x59A3, 0x59B2, 0x59C6, + 0x59E8, 0x59DC, 0x598D, 0x59D9, 0x59DA, 0x5A25, + 0x5A1F, 0x5A11, 0x5A1C, 0x5A09, 0x5A1A, 0x5A40, + 0x5A6C, 0x5A49, 0x5A35, 0x5A36, 0x5A62, 0x5A6A, + 0x5A9A, 0x5ABC, 0x5ABE, 0x5ACB, 0x5AC2, 0x5ABD, + 0x5AE3, 0x5AD7, 0x5AE6, 0x5AE9, 0x5AD6, 0x5AFA, + 0x5AFB, 0x5B0C, 0x5B0B, 0x5B16, 0x5B32, 0x5AD0, + 0x5B2A, 0x5B36, 0x5B3E, 0x5B43, 0x5B45, 0x5B40, + 0x5B51, 0x5B55, 0x5B5A, 0x5B5B, 0x5B65, 0x5B69, + 0x5B70, 0x5B73, 0x5B75, 0x5B78, 0x6588, 0x5B7A, + 0x5B80, 0x0000, 0x5B83, 0x5BA6, 0x5BB8, 0x5BC3, + 0x5BC7, 0x5BC9, 0x5BD4, 0x5BD0, 0x5BE4, 0x5BE6, + 0x5BE2, 0x5BDE, 0x5BE5, 0x5BEB, 0x5BF0, 0x5BF6, + 0x5BF3, 0x5C05, 0x5C07, 0x5C08, 0x5C0D, 0x5C13, + 0x5C20, 0x5C22, 0x5C28, 0x5C38, 0x5C39, 0x5C41, + 0x5C46, 0x5C4E, 0x5C53, 0x5C50, 0x5C4F, 0x5B71, + 0x5C6C, 0x5C6E, 0x4E62, 0x5C76, 0x5C79, 0x5C8C, + 0x5C91, 0x5C94, 0x599B, 0x5CAB, 0x5CBB, 0x5CB6, + 0x5CBC, 0x5CB7, 0x5CC5, 0x5CBE, 0x5CC7, 0x5CD9, + 0x5CE9, 0x5CFD, 0x5CFA, 0x5CED, 0x5D8C, 0x5CEA, + 0x5D0B, 0x5D15, 0x5D17, 0x5D5C, 0x5D1F, 0x5D1B, + 0x5D11, 0x5D14, 0x5D22, 0x5D1A, 0x5D19, 0x5D18, + 0x5D4C, 0x5D52, 0x5D4E, 0x5D4B, 0x5D6C, 0x5D73, + 0x5D76, 0x5D87, 0x5D84, 0x5D82, 0x5DA2, 0x5D9D, + 0x5DAC, 0x5DAE, 0x5DBD, 0x5D90, 0x5DB7, 0x5DBC, + 0x5DC9, 0x5DCD, 0x5DD3, 0x5DD2, 0x5DD6, 0x5DDB, + 0x5DEB, 0x5DF2, 0x5DF5, 0x5E0B, 0x5E1A, 0x5E19, + 0x5E11, 0x5E1B, 0x5E36, 0x5E37, 0x5E44, 0x5E43, + 0x5E40, 0x5E4E, 0x5E57, 0x5E54, 0x5E5F, 0x5E62, + 0x5E64, 0x5E47, 0x5E75, 0x5E76, 0x5E7A, 0x9EBC, + 0x5E7F, 0x5EA0, 0x5EC1, 0x5EC2, 0x5EC8, 0x5ED0, + 0x5ECF, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis9C[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x5ED6, 0x5EE3, + 0x5EDD, 0x5EDA, 0x5EDB, 0x5EE2, 0x5EE1, 0x5EE8, + 0x5EE9, 0x5EEC, 0x5EF1, 0x5EF3, 0x5EF0, 0x5EF4, + 0x5EF8, 0x5EFE, 0x5F03, 0x5F09, 0x5F5D, 0x5F5C, + 0x5F0B, 0x5F11, 0x5F16, 0x5F29, 0x5F2D, 0x5F38, + 0x5F41, 0x5F48, 0x5F4C, 0x5F4E, 0x5F2F, 0x5F51, + 0x5F56, 0x5F57, 0x5F59, 0x5F61, 0x5F6D, 0x5F73, + 0x5F77, 0x5F83, 0x5F82, 0x5F7F, 0x5F8A, 0x5F88, + 0x5F91, 0x5F87, 0x5F9E, 0x5F99, 0x5F98, 0x5FA0, + 0x5FA8, 0x5FAD, 0x5FBC, 0x5FD6, 0x5FFB, 0x5FE4, + 0x5FF8, 0x5FF1, 0x5FDD, 0x60B3, 0x5FFF, 0x6021, + 0x6060, 0x0000, 0x6019, 0x6010, 0x6029, 0x600E, + 0x6031, 0x601B, 0x6015, 0x602B, 0x6026, 0x600F, + 0x603A, 0x605A, 0x6041, 0x606A, 0x6077, 0x605F, + 0x604A, 0x6046, 0x604D, 0x6063, 0x6043, 0x6064, + 0x6042, 0x606C, 0x606B, 0x6059, 0x6081, 0x608D, + 0x60E7, 0x6083, 0x609A, 0x6084, 0x609B, 0x6096, + 0x6097, 0x6092, 0x60A7, 0x608B, 0x60E1, 0x60B8, + 0x60E0, 0x60D3, 0x60B4, 0x5FF0, 0x60BD, 0x60C6, + 0x60B5, 0x60D8, 0x614D, 0x6115, 0x6106, 0x60F6, + 0x60F7, 0x6100, 0x60F4, 0x60FA, 0x6103, 0x6121, + 0x60FB, 0x60F1, 0x610D, 0x610E, 0x6147, 0x613E, + 0x6128, 0x6127, 0x614A, 0x613F, 0x613C, 0x612C, + 0x6134, 0x613D, 0x6142, 0x6144, 0x6173, 0x6177, + 0x6158, 0x6159, 0x615A, 0x616B, 0x6174, 0x616F, + 0x6165, 0x6171, 0x615F, 0x615D, 0x6153, 0x6175, + 0x6199, 0x6196, 0x6187, 0x61AC, 0x6194, 0x619A, + 0x618A, 0x6191, 0x61AB, 0x61AE, 0x61CC, 0x61CA, + 0x61C9, 0x61F7, 0x61C8, 0x61C3, 0x61C6, 0x61BA, + 0x61CB, 0x7F79, 0x61CD, 0x61E6, 0x61E3, 0x61F6, + 0x61FA, 0x61F4, 0x61FF, 0x61FD, 0x61FC, 0x61FE, + 0x6200, 0x6208, 0x6209, 0x620D, 0x620C, 0x6214, + 0x621B, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis9D[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x621E, 0x6221, + 0x622A, 0x622E, 0x6230, 0x6232, 0x6233, 0x6241, + 0x624E, 0x625E, 0x6263, 0x625B, 0x6260, 0x6268, + 0x627C, 0x6282, 0x6289, 0x627E, 0x6292, 0x6293, + 0x6296, 0x62D4, 0x6283, 0x6294, 0x62D7, 0x62D1, + 0x62BB, 0x62CF, 0x62FF, 0x62C6, 0x64D4, 0x62C8, + 0x62DC, 0x62CC, 0x62CA, 0x62C2, 0x62C7, 0x629B, + 0x62C9, 0x630C, 0x62EE, 0x62F1, 0x6327, 0x6302, + 0x6308, 0x62EF, 0x62F5, 0x6350, 0x633E, 0x634D, + 0x641C, 0x634F, 0x6396, 0x638E, 0x6380, 0x63AB, + 0x6376, 0x63A3, 0x638F, 0x6389, 0x639F, 0x63B5, + 0x636B, 0x0000, 0x6369, 0x63BE, 0x63E9, 0x63C0, + 0x63C6, 0x63E3, 0x63C9, 0x63D2, 0x63F6, 0x63C4, + 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436, + 0x651D, 0x6417, 0x6428, 0x640F, 0x6467, 0x646F, + 0x6476, 0x644E, 0x652A, 0x6495, 0x6493, 0x64A5, + 0x64A9, 0x6488, 0x64BC, 0x64DA, 0x64D2, 0x64C5, + 0x64C7, 0x64BB, 0x64D8, 0x64C2, 0x64F1, 0x64E7, + 0x8209, 0x64E0, 0x64E1, 0x62AC, 0x64E3, 0x64EF, + 0x652C, 0x64F6, 0x64F4, 0x64F2, 0x64FA, 0x6500, + 0x64FD, 0x6518, 0x651C, 0x6505, 0x6524, 0x6523, + 0x652B, 0x6534, 0x6535, 0x6537, 0x6536, 0x6538, + 0x754B, 0x6548, 0x6556, 0x6555, 0x654D, 0x6558, + 0x655E, 0x655D, 0x6572, 0x6578, 0x6582, 0x6583, + 0x8B8A, 0x659B, 0x659F, 0x65AB, 0x65B7, 0x65C3, + 0x65C6, 0x65C1, 0x65C4, 0x65CC, 0x65D2, 0x65DB, + 0x65D9, 0x65E0, 0x65E1, 0x65F1, 0x6772, 0x660A, + 0x6603, 0x65FB, 0x6773, 0x6635, 0x6636, 0x6634, + 0x661C, 0x664F, 0x6644, 0x6649, 0x6641, 0x665E, + 0x665D, 0x6664, 0x6667, 0x6668, 0x665F, 0x6662, + 0x6670, 0x6683, 0x6688, 0x668E, 0x6689, 0x6684, + 0x6698, 0x669D, 0x66C1, 0x66B9, 0x66C9, 0x66BE, + 0x66BC, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis9E[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x66C4, 0x66B8, + 0x66D6, 0x66DA, 0x66E0, 0x663F, 0x66E6, 0x66E9, + 0x66F0, 0x66F5, 0x66F7, 0x670F, 0x6716, 0x671E, + 0x6726, 0x6727, 0x9738, 0x672E, 0x673F, 0x6736, + 0x6741, 0x6738, 0x6737, 0x6746, 0x675E, 0x6760, + 0x6759, 0x6763, 0x6764, 0x6789, 0x6770, 0x67A9, + 0x677C, 0x676A, 0x678C, 0x678B, 0x67A6, 0x67A1, + 0x6785, 0x67B7, 0x67EF, 0x67B4, 0x67EC, 0x67B3, + 0x67E9, 0x67B8, 0x67E4, 0x67DE, 0x67DD, 0x67E2, + 0x67EE, 0x67B9, 0x67CE, 0x67C6, 0x67E7, 0x6A9C, + 0x681E, 0x6846, 0x6829, 0x6840, 0x684D, 0x6832, + 0x684E, 0x0000, 0x68B3, 0x682B, 0x6859, 0x6863, + 0x6877, 0x687F, 0x689F, 0x688F, 0x68AD, 0x6894, + 0x689D, 0x689B, 0x6883, 0x6AAE, 0x68B9, 0x6874, + 0x68B5, 0x68A0, 0x68BA, 0x690F, 0x688D, 0x687E, + 0x6901, 0x68CA, 0x6908, 0x68D8, 0x6922, 0x6926, + 0x68E1, 0x690C, 0x68CD, 0x68D4, 0x68E7, 0x68D5, + 0x6936, 0x6912, 0x6904, 0x68D7, 0x68E3, 0x6925, + 0x68F9, 0x68E0, 0x68EF, 0x6928, 0x692A, 0x691A, + 0x6923, 0x6921, 0x68C6, 0x6979, 0x6977, 0x695C, + 0x6978, 0x696B, 0x6954, 0x697E, 0x696E, 0x6939, + 0x6974, 0x693D, 0x6959, 0x6930, 0x6961, 0x695E, + 0x695D, 0x6981, 0x696A, 0x69B2, 0x69AE, 0x69D0, + 0x69BF, 0x69C1, 0x69D3, 0x69BE, 0x69CE, 0x5BE8, + 0x69CA, 0x69DD, 0x69BB, 0x69C3, 0x69A7, 0x6A2E, + 0x6991, 0x69A0, 0x699C, 0x6995, 0x69B4, 0x69DE, + 0x69E8, 0x6A02, 0x6A1B, 0x69FF, 0x6B0A, 0x69F9, + 0x69F2, 0x69E7, 0x6A05, 0x69B1, 0x6A1E, 0x69ED, + 0x6A14, 0x69EB, 0x6A0A, 0x6A12, 0x6AC1, 0x6A23, + 0x6A13, 0x6A44, 0x6A0C, 0x6A72, 0x6A36, 0x6A78, + 0x6A47, 0x6A62, 0x6A59, 0x6A66, 0x6A48, 0x6A38, + 0x6A22, 0x6A90, 0x6A8D, 0x6AA0, 0x6A84, 0x6AA2, + 0x6AA3, 0x0000, 0x0000, 0x0000 +}; + +static u16 Sjis9F[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x6A97, 0x8617, + 0x6ABB, 0x6AC3, 0x6AC2, 0x6AB8, 0x6AB3, 0x6AAC, + 0x6ADE, 0x6AD1, 0x6ADF, 0x6AAA, 0x6ADA, 0x6AEA, + 0x6AFB, 0x6B05, 0x8616, 0x6AFA, 0x6B12, 0x6B16, + 0x9B31, 0x6B1F, 0x6B38, 0x6B37, 0x76DC, 0x6B39, + 0x98EE, 0x6B47, 0x6B43, 0x6B49, 0x6B50, 0x6B59, + 0x6B54, 0x6B5B, 0x6B5F, 0x6B61, 0x6B78, 0x6B79, + 0x6B7F, 0x6B80, 0x6B84, 0x6B83, 0x6B8D, 0x6B98, + 0x6B95, 0x6B9E, 0x6BA4, 0x6BAA, 0x6BAB, 0x6BAF, + 0x6BB2, 0x6BB1, 0x6BB3, 0x6BB7, 0x6BBC, 0x6BC6, + 0x6BCB, 0x6BD3, 0x6BDF, 0x6BEC, 0x6BEB, 0x6BF3, + 0x6BEF, 0x0000, 0x9EBE, 0x6C08, 0x6C13, 0x6C14, + 0x6C1B, 0x6C24, 0x6C23, 0x6C5E, 0x6C55, 0x6C62, + 0x6C6A, 0x6C82, 0x6C8D, 0x6C9A, 0x6C81, 0x6C9B, + 0x6C7E, 0x6C68, 0x6C73, 0x6C92, 0x6C90, 0x6CC4, + 0x6CF1, 0x6CD3, 0x6CBD, 0x6CD7, 0x6CC5, 0x6CDD, + 0x6CAE, 0x6CB1, 0x6CBE, 0x6CBA, 0x6CDB, 0x6CEF, + 0x6CD9, 0x6CEA, 0x6D1F, 0x884D, 0x6D36, 0x6D2B, + 0x6D3D, 0x6D38, 0x6D19, 0x6D35, 0x6D33, 0x6D12, + 0x6D0C, 0x6D63, 0x6D93, 0x6D64, 0x6D5A, 0x6D79, + 0x6D59, 0x6D8E, 0x6D95, 0x6FE4, 0x6D85, 0x6DF9, + 0x6E15, 0x6E0A, 0x6DB5, 0x6DC7, 0x6DE6, 0x6DB8, + 0x6DC6, 0x6DEC, 0x6DDE, 0x6DCC, 0x6DE8, 0x6DD2, + 0x6DC5, 0x6DFA, 0x6DD9, 0x6DE4, 0x6DD5, 0x6DEA, + 0x6DEE, 0x6E2D, 0x6E6E, 0x6E2E, 0x6E19, 0x6E72, + 0x6E5F, 0x6E3E, 0x6E23, 0x6E6B, 0x6E2B, 0x6E76, + 0x6E4D, 0x6E1F, 0x6E43, 0x6E3A, 0x6E4E, 0x6E24, + 0x6EFF, 0x6E1D, 0x6E38, 0x6E82, 0x6EAA, 0x6E98, + 0x6EC9, 0x6EB7, 0x6ED3, 0x6EBD, 0x6EAF, 0x6EC4, + 0x6EB2, 0x6ED4, 0x6ED5, 0x6E8F, 0x6EA5, 0x6EC2, + 0x6E9F, 0x6F41, 0x6F11, 0x704C, 0x6EEC, 0x6EF8, + 0x6EFE, 0x6F3F, 0x6EF2, 0x6F31, 0x6EEF, 0x6F32, + 0x6ECC, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE0[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x6F3E, 0x6F13, + 0x6EF7, 0x6F86, 0x6F7A, 0x6F78, 0x6F81, 0x6F80, + 0x6F6F, 0x6F5B, 0x6FF3, 0x6F6D, 0x6F82, 0x6F7C, + 0x6F58, 0x6F8E, 0x6F91, 0x6FC2, 0x6F66, 0x6FB3, + 0x6FA3, 0x6FA1, 0x6FA4, 0x6FB9, 0x6FC6, 0x6FAA, + 0x6FDF, 0x6FD5, 0x6FEC, 0x6FD4, 0x6FD8, 0x6FF1, + 0x6FEE, 0x6FDB, 0x7009, 0x700B, 0x6FFA, 0x7011, + 0x7001, 0x700F, 0x6FFE, 0x701B, 0x701A, 0x6F74, + 0x701D, 0x7018, 0x701F, 0x7030, 0x703E, 0x7032, + 0x7051, 0x7063, 0x7099, 0x7092, 0x70AF, 0x70F1, + 0x70AC, 0x70B8, 0x70B3, 0x70AE, 0x70DF, 0x70CB, + 0x70DD, 0x0000, 0x70D9, 0x7109, 0x70FD, 0x711C, + 0x7119, 0x7165, 0x7155, 0x7188, 0x7166, 0x7162, + 0x714C, 0x7156, 0x716C, 0x718F, 0x71FB, 0x7184, + 0x7195, 0x71A8, 0x71AC, 0x71D7, 0x71B9, 0x71BE, + 0x71D2, 0x71C9, 0x71D4, 0x71CE, 0x71E0, 0x71EC, + 0x71E7, 0x71F5, 0x71FC, 0x71F9, 0x71FF, 0x720D, + 0x7210, 0x721B, 0x7228, 0x722D, 0x722C, 0x7230, + 0x7232, 0x723B, 0x723C, 0x723F, 0x7240, 0x7246, + 0x724B, 0x7258, 0x7274, 0x727E, 0x7282, 0x7281, + 0x7287, 0x7292, 0x7296, 0x72A2, 0x72A7, 0x72B9, + 0x72B2, 0x72C3, 0x72C6, 0x72C4, 0x72CE, 0x72D2, + 0x72E2, 0x72E0, 0x72E1, 0x72F9, 0x72F7, 0x500F, + 0x7317, 0x730A, 0x731C, 0x7316, 0x731D, 0x7334, + 0x732F, 0x7329, 0x7325, 0x733E, 0x734E, 0x734F, + 0x9ED8, 0x7357, 0x736A, 0x7368, 0x7370, 0x7378, + 0x7375, 0x737B, 0x737A, 0x73C8, 0x73B3, 0x73CE, + 0x73BB, 0x73C0, 0x73E5, 0x73EE, 0x73DE, 0x74A2, + 0x7405, 0x746F, 0x7425, 0x73F8, 0x7432, 0x743A, + 0x7455, 0x743F, 0x745F, 0x7459, 0x7441, 0x745C, + 0x7469, 0x7470, 0x7463, 0x746A, 0x7476, 0x747E, + 0x748B, 0x749E, 0x74A7, 0x74CA, 0x74CF, 0x74D4, + 0x73F1, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE1[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x74E0, 0x74E3, + 0x74E7, 0x74E9, 0x74EE, 0x74F2, 0x74F0, 0x74F1, + 0x74F8, 0x74F7, 0x7504, 0x7503, 0x7505, 0x750C, + 0x750E, 0x750D, 0x7515, 0x7513, 0x751E, 0x7526, + 0x752C, 0x753C, 0x7544, 0x754D, 0x754A, 0x7549, + 0x755B, 0x7546, 0x755A, 0x7569, 0x7564, 0x7567, + 0x756B, 0x756D, 0x7578, 0x7576, 0x7586, 0x7587, + 0x7574, 0x758A, 0x7589, 0x7582, 0x7594, 0x759A, + 0x759D, 0x75A5, 0x75A3, 0x75C2, 0x75B3, 0x75C3, + 0x75B5, 0x75BD, 0x75B8, 0x75BC, 0x75B1, 0x75CD, + 0x75CA, 0x75D2, 0x75D9, 0x75E3, 0x75DE, 0x75FE, + 0x75FF, 0x0000, 0x75FC, 0x7601, 0x75F0, 0x75FA, + 0x75F2, 0x75F3, 0x760B, 0x760D, 0x7609, 0x761F, + 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634, + 0x7630, 0x763B, 0x7647, 0x7648, 0x7646, 0x765C, + 0x7658, 0x7661, 0x7662, 0x7668, 0x7669, 0x766A, + 0x7667, 0x766C, 0x7670, 0x7672, 0x7676, 0x7678, + 0x767C, 0x7680, 0x7683, 0x7688, 0x768B, 0x768E, + 0x7696, 0x7693, 0x7699, 0x769A, 0x76B0, 0x76B4, + 0x76B8, 0x76B9, 0x76BA, 0x76C2, 0x76CD, 0x76D6, + 0x76D2, 0x76DE, 0x76E1, 0x76E5, 0x76E7, 0x76EA, + 0x862F, 0x76FB, 0x7708, 0x7707, 0x7704, 0x7729, + 0x7724, 0x771E, 0x7725, 0x7726, 0x771B, 0x7737, + 0x7738, 0x7747, 0x775A, 0x7768, 0x776B, 0x775B, + 0x7765, 0x777F, 0x777E, 0x7779, 0x778E, 0x778B, + 0x7791, 0x77A0, 0x779E, 0x77B0, 0x77B6, 0x77B9, + 0x77BF, 0x77BC, 0x77BD, 0x77BB, 0x77C7, 0x77CD, + 0x77D7, 0x77DA, 0x77DC, 0x77E3, 0x77EE, 0x77FC, + 0x780C, 0x7812, 0x7926, 0x7820, 0x792A, 0x7845, + 0x788E, 0x7874, 0x7886, 0x787C, 0x789A, 0x788C, + 0x78A3, 0x78B5, 0x78AA, 0x78AF, 0x78D1, 0x78C6, + 0x78CB, 0x78D4, 0x78BE, 0x78BC, 0x78C5, 0x78CA, + 0x78EC, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE2[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x78E7, 0x78DA, + 0x78FD, 0x78F4, 0x7907, 0x7912, 0x7911, 0x7919, + 0x792C, 0x792B, 0x7940, 0x7960, 0x7957, 0x795F, + 0x795A, 0x7955, 0x7953, 0x797A, 0x797F, 0x798A, + 0x799D, 0x79A7, 0x9F4B, 0x79AA, 0x79AE, 0x79B3, + 0x79B9, 0x79BA, 0x79C9, 0x79D5, 0x79E7, 0x79EC, + 0x79E1, 0x79E3, 0x7A08, 0x7A0D, 0x7A18, 0x7A19, + 0x7A20, 0x7A1F, 0x7980, 0x7A31, 0x7A3B, 0x7A3E, + 0x7A37, 0x7A43, 0x7A57, 0x7A49, 0x7A61, 0x7A62, + 0x7A69, 0x9F9D, 0x7A70, 0x7A79, 0x7A7D, 0x7A88, + 0x7A97, 0x7A95, 0x7A98, 0x7A96, 0x7AA9, 0x7AC8, + 0x7AB0, 0x0000, 0x7AB6, 0x7AC5, 0x7AC4, 0x7ABF, + 0x9083, 0x7AC7, 0x7ACA, 0x7ACD, 0x7ACF, 0x7AD5, + 0x7AD3, 0x7AD9, 0x7ADA, 0x7ADD, 0x7AE1, 0x7AE2, + 0x7AE6, 0x7AED, 0x7AF0, 0x7B02, 0x7B0F, 0x7B0A, + 0x7B06, 0x7B33, 0x7B18, 0x7B19, 0x7B1E, 0x7B35, + 0x7B28, 0x7B36, 0x7B50, 0x7B7A, 0x7B04, 0x7B4D, + 0x7B0B, 0x7B4C, 0x7B45, 0x7B75, 0x7B65, 0x7B74, + 0x7B67, 0x7B70, 0x7B71, 0x7B6C, 0x7B6E, 0x7B9D, + 0x7B98, 0x7B9F, 0x7B8D, 0x7B9C, 0x7B9A, 0x7B8B, + 0x7B92, 0x7B8F, 0x7B5D, 0x7B99, 0x7BCB, 0x7BC1, + 0x7BCC, 0x7BCF, 0x7BB4, 0x7BC6, 0x7BDD, 0x7BE9, + 0x7C11, 0x7C14, 0x7BE6, 0x7BE5, 0x7C60, 0x7C00, + 0x7C07, 0x7C13, 0x7BF3, 0x7BF7, 0x7C17, 0x7C0D, + 0x7BF6, 0x7C23, 0x7C27, 0x7C2A, 0x7C1F, 0x7C37, + 0x7C2B, 0x7C3D, 0x7C4C, 0x7C43, 0x7C54, 0x7C4F, + 0x7C40, 0x7C50, 0x7C58, 0x7C5F, 0x7C64, 0x7C56, + 0x7C65, 0x7C6C, 0x7C75, 0x7C83, 0x7C90, 0x7CA4, + 0x7CAD, 0x7CA2, 0x7CAB, 0x7CA1, 0x7CA8, 0x7CB3, + 0x7CB2, 0x7CB1, 0x7CAE, 0x7CB9, 0x7CBD, 0x7CC0, + 0x7CC5, 0x7CC2, 0x7CD8, 0x7CD2, 0x7CDC, 0x7CE2, + 0x9B3B, 0x7CEF, 0x7CF2, 0x7CF4, 0x7CF6, 0x7CFA, + 0x7D06, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE3[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x7D02, 0x7D1C, + 0x7D15, 0x7D0A, 0x7D45, 0x7D4B, 0x7D2E, 0x7D32, + 0x7D3F, 0x7D35, 0x7D46, 0x7D73, 0x7D56, 0x7D4E, + 0x7D72, 0x7D68, 0x7D6E, 0x7D4F, 0x7D63, 0x7D93, + 0x7D89, 0x7D5B, 0x7D8F, 0x7D7D, 0x7D9B, 0x7DBA, + 0x7DAE, 0x7DA3, 0x7DB5, 0x7DC7, 0x7DBD, 0x7DAB, + 0x7E3D, 0x7DA2, 0x7DAF, 0x7DDC, 0x7DB8, 0x7D9F, + 0x7DB0, 0x7DD8, 0x7DDD, 0x7DE4, 0x7DDE, 0x7DFB, + 0x7DF2, 0x7DE1, 0x7E05, 0x7E0A, 0x7E23, 0x7E21, + 0x7E12, 0x7E31, 0x7E1F, 0x7E09, 0x7E0B, 0x7E22, + 0x7E46, 0x7E66, 0x7E3B, 0x7E35, 0x7E39, 0x7E43, + 0x7E37, 0x0000, 0x7E32, 0x7E3A, 0x7E67, 0x7E5D, + 0x7E56, 0x7E5E, 0x7E59, 0x7E5A, 0x7E79, 0x7E6A, + 0x7E69, 0x7E7C, 0x7E7B, 0x7E83, 0x7DD5, 0x7E7D, + 0x8FAE, 0x7E7F, 0x7E88, 0x7E89, 0x7E8C, 0x7E92, + 0x7E90, 0x7E93, 0x7E94, 0x7E96, 0x7E8E, 0x7E9B, + 0x7E9C, 0x7F38, 0x7F3A, 0x7F45, 0x7F4C, 0x7F4D, + 0x7F4E, 0x7F50, 0x7F51, 0x7F55, 0x7F54, 0x7F58, + 0x7F5F, 0x7F60, 0x7F68, 0x7F69, 0x7F67, 0x7F78, + 0x7F82, 0x7F86, 0x7F83, 0x7F88, 0x7F87, 0x7F8C, + 0x7F94, 0x7F9E, 0x7F9D, 0x7F9A, 0x7FA3, 0x7FAF, + 0x7FB2, 0x7FB9, 0x7FAE, 0x7FB6, 0x7FB8, 0x8B71, + 0x7FC5, 0x7FC6, 0x7FCA, 0x7FD5, 0x7FD4, 0x7FE1, + 0x7FE6, 0x7FE9, 0x7FF3, 0x7FF9, 0x98DC, 0x8006, + 0x8004, 0x800B, 0x8012, 0x8018, 0x8019, 0x801C, + 0x8021, 0x8028, 0x803F, 0x803B, 0x804A, 0x8046, + 0x8052, 0x8058, 0x805A, 0x805F, 0x8062, 0x8068, + 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807D, + 0x807F, 0x8084, 0x8086, 0x8085, 0x809B, 0x8093, + 0x809A, 0x80AD, 0x5190, 0x80AC, 0x80DB, 0x80E5, + 0x80D9, 0x80DD, 0x80C4, 0x80DA, 0x80D6, 0x8109, + 0x80EF, 0x80F1, 0x811B, 0x8129, 0x8123, 0x812F, + 0x814B, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE4[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x968B, 0x8146, + 0x813E, 0x8153, 0x8151, 0x80FC, 0x8171, 0x816E, + 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818A, + 0x8180, 0x8182, 0x81A0, 0x8195, 0x81A4, 0x81A3, + 0x815F, 0x8193, 0x81A9, 0x81B0, 0x81B5, 0x81BE, + 0x81B8, 0x81BD, 0x81C0, 0x81C2, 0x81BA, 0x81C9, + 0x81CD, 0x81D1, 0x81D9, 0x81D8, 0x81C8, 0x81DA, + 0x81DF, 0x81E0, 0x81E7, 0x81FA, 0x81FB, 0x81FE, + 0x8201, 0x8202, 0x8205, 0x8207, 0x820A, 0x820D, + 0x8210, 0x8216, 0x8229, 0x822B, 0x8238, 0x8233, + 0x8240, 0x8259, 0x8258, 0x825D, 0x825A, 0x825F, + 0x8264, 0x0000, 0x8262, 0x8268, 0x826A, 0x826B, + 0x822E, 0x8271, 0x8277, 0x8278, 0x827E, 0x828D, + 0x8292, 0x82AB, 0x829F, 0x82BB, 0x82AC, 0x82E1, + 0x82E3, 0x82DF, 0x82D2, 0x82F4, 0x82F3, 0x82FA, + 0x8393, 0x8303, 0x82FB, 0x82F9, 0x82DE, 0x8306, + 0x82DC, 0x8309, 0x82D9, 0x8335, 0x8334, 0x8316, + 0x8332, 0x8331, 0x8340, 0x8339, 0x8350, 0x8345, + 0x832F, 0x832B, 0x8317, 0x8318, 0x8385, 0x839A, + 0x83AA, 0x839F, 0x83A2, 0x8396, 0x8323, 0x838E, + 0x8387, 0x838A, 0x837C, 0x83B5, 0x8373, 0x8375, + 0x83A0, 0x8389, 0x83A8, 0x83F4, 0x8413, 0x83EB, + 0x83CE, 0x83FD, 0x8403, 0x83D8, 0x840B, 0x83C1, + 0x83F7, 0x8407, 0x83E0, 0x83F2, 0x840D, 0x8422, + 0x8420, 0x83BD, 0x8438, 0x8506, 0x83FB, 0x846D, + 0x842A, 0x843C, 0x855A, 0x8484, 0x8477, 0x846B, + 0x84AD, 0x846E, 0x8482, 0x8469, 0x8446, 0x842C, + 0x846F, 0x8479, 0x8435, 0x84CA, 0x8462, 0x84B9, + 0x84BF, 0x849F, 0x84D9, 0x84CD, 0x84BB, 0x84DA, + 0x84D0, 0x84C1, 0x84C6, 0x84D6, 0x84A1, 0x8521, + 0x84FF, 0x84F4, 0x8517, 0x8518, 0x852C, 0x851F, + 0x8515, 0x8514, 0x84FC, 0x8540, 0x8563, 0x8558, + 0x8548, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE5[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8541, 0x8602, + 0x854B, 0x8555, 0x8580, 0x85A4, 0x8588, 0x8591, + 0x858A, 0x85A8, 0x856D, 0x8594, 0x859B, 0x85EA, + 0x8587, 0x859C, 0x8577, 0x857E, 0x8590, 0x85C9, + 0x85BA, 0x85CF, 0x85B9, 0x85D0, 0x85D5, 0x85DD, + 0x85E5, 0x85DC, 0x85F9, 0x860A, 0x8613, 0x860B, + 0x85FE, 0x85FA, 0x8606, 0x8622, 0x861A, 0x8630, + 0x863F, 0x864D, 0x4E55, 0x8654, 0x865F, 0x8667, + 0x8671, 0x8693, 0x86A3, 0x86A9, 0x86AA, 0x868B, + 0x868C, 0x86B6, 0x86AF, 0x86C4, 0x86C6, 0x86B0, + 0x86C9, 0x8823, 0x86AB, 0x86D4, 0x86DE, 0x86E9, + 0x86EC, 0x0000, 0x86DF, 0x86DB, 0x86EF, 0x8712, + 0x8706, 0x8708, 0x8700, 0x8703, 0x86FB, 0x8711, + 0x8709, 0x870D, 0x86F9, 0x870A, 0x8734, 0x873F, + 0x8737, 0x873B, 0x8725, 0x8729, 0x871A, 0x8760, + 0x875F, 0x8778, 0x874C, 0x874E, 0x8774, 0x8757, + 0x8768, 0x876E, 0x8759, 0x8753, 0x8763, 0x876A, + 0x8805, 0x87A2, 0x879F, 0x8782, 0x87AF, 0x87CB, + 0x87BD, 0x87C0, 0x87D0, 0x96D6, 0x87AB, 0x87C4, + 0x87B3, 0x87C7, 0x87C6, 0x87BB, 0x87EF, 0x87F2, + 0x87E0, 0x880F, 0x880D, 0x87FE, 0x87F6, 0x87F7, + 0x880E, 0x87D2, 0x8811, 0x8816, 0x8815, 0x8822, + 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883B, + 0x8844, 0x8842, 0x8852, 0x8859, 0x885E, 0x8862, + 0x886B, 0x8881, 0x887E, 0x889E, 0x8875, 0x887D, + 0x88B5, 0x8872, 0x8882, 0x8897, 0x8892, 0x88AE, + 0x8899, 0x88A2, 0x888D, 0x88A4, 0x88B0, 0x88BF, + 0x88B1, 0x88C3, 0x88C4, 0x88D4, 0x88D8, 0x88D9, + 0x88DD, 0x88F9, 0x8902, 0x88FC, 0x88F4, 0x88E8, + 0x88F2, 0x8904, 0x890C, 0x890A, 0x8913, 0x8943, + 0x891E, 0x8925, 0x892A, 0x892B, 0x8941, 0x8944, + 0x893B, 0x8936, 0x8938, 0x894C, 0x891D, 0x8960, + 0x895E, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE6[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8966, 0x8964, + 0x896D, 0x896A, 0x896F, 0x8974, 0x8977, 0x897E, + 0x8983, 0x8988, 0x898A, 0x8993, 0x8998, 0x89A1, + 0x89A9, 0x89A6, 0x89AC, 0x89AF, 0x89B2, 0x89BA, + 0x89BD, 0x89BF, 0x89C0, 0x89DA, 0x89DC, 0x89DD, + 0x89E7, 0x89F4, 0x89F8, 0x8A03, 0x8A16, 0x8A10, + 0x8A0C, 0x8A1B, 0x8A1D, 0x8A25, 0x8A36, 0x8A41, + 0x8A5B, 0x8A52, 0x8A46, 0x8A48, 0x8A7C, 0x8A6D, + 0x8A6C, 0x8A62, 0x8A85, 0x8A82, 0x8A84, 0x8AA8, + 0x8AA1, 0x8A91, 0x8AA5, 0x8AA6, 0x8A9A, 0x8AA3, + 0x8AC4, 0x8ACD, 0x8AC2, 0x8ADA, 0x8AEB, 0x8AF3, + 0x8AE7, 0x0000, 0x8AE4, 0x8AF1, 0x8B14, 0x8AE0, + 0x8AE2, 0x8AF7, 0x8ADE, 0x8ADB, 0x8B0C, 0x8B07, + 0x8B1A, 0x8AE1, 0x8B16, 0x8B10, 0x8B17, 0x8B20, + 0x8B33, 0x97AB, 0x8B26, 0x8B2B, 0x8B3E, 0x8B28, + 0x8B41, 0x8B4C, 0x8B4F, 0x8B4E, 0x8B49, 0x8B56, + 0x8B5B, 0x8B5A, 0x8B6B, 0x8B5F, 0x8B6C, 0x8B6F, + 0x8B74, 0x8B7D, 0x8B80, 0x8B8C, 0x8B8E, 0x8B92, + 0x8B93, 0x8B96, 0x8B99, 0x8B9A, 0x8C3A, 0x8C41, + 0x8C3F, 0x8C48, 0x8C4C, 0x8C4E, 0x8C50, 0x8C55, + 0x8C62, 0x8C6C, 0x8C78, 0x8C7A, 0x8C82, 0x8C89, + 0x8C85, 0x8C8A, 0x8C8D, 0x8C8E, 0x8C94, 0x8C7C, + 0x8C98, 0x621D, 0x8CAD, 0x8CAA, 0x8CBD, 0x8CB2, + 0x8CB3, 0x8CAE, 0x8CB6, 0x8CC8, 0x8CC1, 0x8CE4, + 0x8CE3, 0x8CDA, 0x8CFD, 0x8CFA, 0x8CFB, 0x8D04, + 0x8D05, 0x8D0A, 0x8D07, 0x8D0F, 0x8D0D, 0x8D10, + 0x9F4E, 0x8D13, 0x8CCD, 0x8D14, 0x8D16, 0x8D67, + 0x8D6D, 0x8D71, 0x8D73, 0x8D81, 0x8D99, 0x8DC2, + 0x8DBE, 0x8DBA, 0x8DCF, 0x8DDA, 0x8DD6, 0x8DCC, + 0x8DDB, 0x8DCB, 0x8DEA, 0x8DEB, 0x8DDF, 0x8DE3, + 0x8DFC, 0x8E08, 0x8E09, 0x8DFF, 0x8E1D, 0x8E1E, + 0x8E10, 0x8E1F, 0x8E42, 0x8E35, 0x8E30, 0x8E34, + 0x8E4A, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE7[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8E47, 0x8E49, + 0x8E4C, 0x8E50, 0x8E48, 0x8E59, 0x8E64, 0x8E60, + 0x8E2A, 0x8E63, 0x8E55, 0x8E76, 0x8E72, 0x8E7C, + 0x8E81, 0x8E87, 0x8E85, 0x8E84, 0x8E8B, 0x8E8A, + 0x8E93, 0x8E91, 0x8E94, 0x8E99, 0x8EAA, 0x8EA1, + 0x8EAC, 0x8EB0, 0x8EC6, 0x8EB1, 0x8EBE, 0x8EC5, + 0x8EC8, 0x8ECB, 0x8EDB, 0x8EE3, 0x8EFC, 0x8EFB, + 0x8EEB, 0x8EFE, 0x8F0A, 0x8F05, 0x8F15, 0x8F12, + 0x8F19, 0x8F13, 0x8F1C, 0x8F1F, 0x8F1B, 0x8F0C, + 0x8F26, 0x8F33, 0x8F3B, 0x8F39, 0x8F45, 0x8F42, + 0x8F3E, 0x8F4C, 0x8F49, 0x8F46, 0x8F4E, 0x8F57, + 0x8F5C, 0x0000, 0x8F62, 0x8F63, 0x8F64, 0x8F9C, + 0x8F9F, 0x8FA3, 0x8FAD, 0x8FAF, 0x8FB7, 0x8FDA, + 0x8FE5, 0x8FE2, 0x8FEA, 0x8FEF, 0x9087, 0x8FF4, + 0x9005, 0x8FF9, 0x8FFA, 0x9011, 0x9015, 0x9021, + 0x900D, 0x901E, 0x9016, 0x900B, 0x9027, 0x9036, + 0x9035, 0x9039, 0x8FF8, 0x904F, 0x9050, 0x9051, + 0x9052, 0x900E, 0x9049, 0x903E, 0x9056, 0x9058, + 0x905E, 0x9068, 0x906F, 0x9076, 0x96A8, 0x9072, + 0x9082, 0x907D, 0x9081, 0x9080, 0x908A, 0x9089, + 0x908F, 0x90A8, 0x90AF, 0x90B1, 0x90B5, 0x90E2, + 0x90E4, 0x6248, 0x90DB, 0x9102, 0x9112, 0x9119, + 0x9132, 0x9130, 0x914A, 0x9156, 0x9158, 0x9163, + 0x9165, 0x9169, 0x9173, 0x9172, 0x918B, 0x9189, + 0x9182, 0x91A2, 0x91AB, 0x91AF, 0x91AA, 0x91B5, + 0x91B4, 0x91BA, 0x91C0, 0x91C1, 0x91C9, 0x91CB, + 0x91D0, 0x91D6, 0x91DF, 0x91E1, 0x91DB, 0x91FC, + 0x91F5, 0x91F6, 0x921E, 0x91FF, 0x9214, 0x922C, + 0x9215, 0x9211, 0x925E, 0x9257, 0x9245, 0x9249, + 0x9264, 0x9248, 0x9295, 0x923F, 0x924B, 0x9250, + 0x929C, 0x9296, 0x9293, 0x929B, 0x925A, 0x92CF, + 0x92B9, 0x92B7, 0x92E9, 0x930F, 0x92FA, 0x9344, + 0x932E, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE8[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9319, 0x9322, + 0x931A, 0x9323, 0x933A, 0x9335, 0x933B, 0x935C, + 0x9360, 0x937C, 0x936E, 0x9356, 0x93B0, 0x93AC, + 0x93AD, 0x9394, 0x93B9, 0x93D6, 0x93D7, 0x93E8, + 0x93E5, 0x93D8, 0x93C3, 0x93DD, 0x93D0, 0x93C8, + 0x93E4, 0x941A, 0x9414, 0x9413, 0x9403, 0x9407, + 0x9410, 0x9436, 0x942B, 0x9435, 0x9421, 0x943A, + 0x9441, 0x9452, 0x9444, 0x945B, 0x9460, 0x9462, + 0x945E, 0x946A, 0x9229, 0x9470, 0x9475, 0x9477, + 0x947D, 0x945A, 0x947C, 0x947E, 0x9481, 0x947F, + 0x9582, 0x9587, 0x958A, 0x9594, 0x9596, 0x9598, + 0x9599, 0x0000, 0x95A0, 0x95A8, 0x95A7, 0x95AD, + 0x95BC, 0x95BB, 0x95B9, 0x95BE, 0x95CA, 0x6FF6, + 0x95C3, 0x95CD, 0x95CC, 0x95D5, 0x95D4, 0x95D6, + 0x95DC, 0x95E1, 0x95E5, 0x95E2, 0x9621, 0x9628, + 0x962E, 0x962F, 0x9642, 0x964C, 0x964F, 0x964B, + 0x9677, 0x965C, 0x965E, 0x965D, 0x965F, 0x9666, + 0x9672, 0x966C, 0x968D, 0x9698, 0x9695, 0x9697, + 0x96AA, 0x96A7, 0x96B1, 0x96B2, 0x96B0, 0x96B4, + 0x96B6, 0x96B8, 0x96B9, 0x96CE, 0x96CB, 0x96C9, + 0x96CD, 0x894D, 0x96DC, 0x970D, 0x96D5, 0x96F9, + 0x9704, 0x9706, 0x9708, 0x9713, 0x970E, 0x9711, + 0x970F, 0x9716, 0x9719, 0x9724, 0x972A, 0x9730, + 0x9739, 0x973D, 0x973E, 0x9744, 0x9746, 0x9748, + 0x9742, 0x9749, 0x975C, 0x9760, 0x9764, 0x9766, + 0x9768, 0x52D2, 0x976B, 0x9771, 0x9779, 0x9785, + 0x977C, 0x9781, 0x977A, 0x9786, 0x978B, 0x978F, + 0x9790, 0x979C, 0x97A8, 0x97A6, 0x97A3, 0x97B3, + 0x97B4, 0x97C3, 0x97C6, 0x97C8, 0x97CB, 0x97DC, + 0x97ED, 0x9F4F, 0x97F2, 0x7ADF, 0x97F6, 0x97F5, + 0x980F, 0x980C, 0x9838, 0x9824, 0x9821, 0x9837, + 0x983D, 0x9846, 0x984F, 0x984B, 0x986B, 0x986F, + 0x9870, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisE9[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9871, 0x9874, + 0x9873, 0x98AA, 0x98AF, 0x98B1, 0x98B6, 0x98C4, + 0x98C3, 0x98C6, 0x98E9, 0x98EB, 0x9903, 0x9909, + 0x9912, 0x9914, 0x9918, 0x9921, 0x991D, 0x991E, + 0x9924, 0x9920, 0x992C, 0x992E, 0x993D, 0x993E, + 0x9942, 0x9949, 0x9945, 0x9950, 0x994B, 0x9951, + 0x9952, 0x994C, 0x9955, 0x9997, 0x9998, 0x99A5, + 0x99AD, 0x99AE, 0x99BC, 0x99DF, 0x99DB, 0x99DD, + 0x99D8, 0x99D1, 0x99ED, 0x99EE, 0x99F1, 0x99F2, + 0x99FB, 0x99F8, 0x9A01, 0x9A0F, 0x9A05, 0x99E2, + 0x9A19, 0x9A2B, 0x9A37, 0x9A45, 0x9A42, 0x9A40, + 0x9A43, 0x0000, 0x9A3E, 0x9A55, 0x9A4D, 0x9A5B, + 0x9A57, 0x9A5F, 0x9A62, 0x9A65, 0x9A64, 0x9A69, + 0x9A6B, 0x9A6A, 0x9AAD, 0x9AB0, 0x9ABC, 0x9AC0, + 0x9ACF, 0x9AD1, 0x9AD3, 0x9AD4, 0x9ADE, 0x9ADF, + 0x9AE2, 0x9AE3, 0x9AE6, 0x9AEF, 0x9AEB, 0x9AEE, + 0x9AF4, 0x9AF1, 0x9AF7, 0x9AFB, 0x9B06, 0x9B18, + 0x9B1A, 0x9B1F, 0x9B22, 0x9B23, 0x9B25, 0x9B27, + 0x9B28, 0x9B29, 0x9B2A, 0x9B2E, 0x9B2F, 0x9B32, + 0x9B44, 0x9B43, 0x9B4F, 0x9B4D, 0x9B4E, 0x9B51, + 0x9B58, 0x9B74, 0x9B93, 0x9B83, 0x9B91, 0x9B96, + 0x9B97, 0x9B9F, 0x9BA0, 0x9BA8, 0x9BB4, 0x9BC0, + 0x9BCA, 0x9BB9, 0x9BC6, 0x9BCF, 0x9BD1, 0x9BD2, + 0x9BE3, 0x9BE2, 0x9BE4, 0x9BD4, 0x9BE1, 0x9C3A, + 0x9BF2, 0x9BF1, 0x9BF0, 0x9C15, 0x9C14, 0x9C09, + 0x9C13, 0x9C0C, 0x9C06, 0x9C08, 0x9C12, 0x9C0A, + 0x9C04, 0x9C2E, 0x9C1B, 0x9C25, 0x9C24, 0x9C21, + 0x9C30, 0x9C47, 0x9C32, 0x9C46, 0x9C3E, 0x9C5A, + 0x9C60, 0x9C67, 0x9C76, 0x9C78, 0x9CE7, 0x9CEC, + 0x9CF0, 0x9D09, 0x9D08, 0x9CEB, 0x9D03, 0x9D06, + 0x9D2A, 0x9D26, 0x9DAF, 0x9D23, 0x9D1F, 0x9D44, + 0x9D15, 0x9D12, 0x9D41, 0x9D3F, 0x9D3E, 0x9D46, + 0x9D48, 0x0000, 0x0000, 0x0000 +}; + +static u16 SjisEA[256] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9D5D, 0x9D5E, + 0x9D64, 0x9D51, 0x9D50, 0x9D59, 0x9D72, 0x9D89, + 0x9D87, 0x9DAB, 0x9D6F, 0x9D7A, 0x9D9A, 0x9DA4, + 0x9DA9, 0x9DB2, 0x9DC4, 0x9DC1, 0x9DBB, 0x9DB8, + 0x9DBA, 0x9DC6, 0x9DCF, 0x9DC2, 0x9DD9, 0x9DD3, + 0x9DF8, 0x9DE6, 0x9DED, 0x9DEF, 0x9DFD, 0x9E1A, + 0x9E1B, 0x9E1E, 0x9E75, 0x9E79, 0x9E7D, 0x9E81, + 0x9E88, 0x9E8B, 0x9E8C, 0x9E92, 0x9E95, 0x9E91, + 0x9E9D, 0x9EA5, 0x9EA9, 0x9EB8, 0x9EAA, 0x9EAD, + 0x9761, 0x9ECC, 0x9ECE, 0x9ECF, 0x9ED0, 0x9ED4, + 0x9EDC, 0x9EDE, 0x9EDD, 0x9EE0, 0x9EE5, 0x9EE8, + 0x9EEF, 0x0000, 0x9EF4, 0x9EF6, 0x9EF7, 0x9EF9, + 0x9EFB, 0x9EFC, 0x9EFD, 0x9F07, 0x9F08, 0x76B7, + 0x9F15, 0x9F21, 0x9F2C, 0x9F3E, 0x9F4A, 0x9F52, + 0x9F54, 0x9F63, 0x9F5F, 0x9F60, 0x9F61, 0x9F66, + 0x9F67, 0x9F6C, 0x9F6A, 0x9F77, 0x9F72, 0x9F76, + 0x9F95, 0x9F9C, 0x9FA0, 0x582F, 0x69C7, 0x9059, + 0x7464, 0x51DC, 0x7199, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static u16* SjisUcsTable[256] = {0}; + +u32 OSSJIStoUTF32(u16 sjis) { + u16* table; + + table = SjisUcsTable[(sjis >> 8) & 0xFF]; + if (table != 0) { + return table[sjis & 0xFF]; + } + + return 0; +} diff --git a/src/revolution/os/__os.h b/src/revolution/os/__os.h new file mode 100644 index 0000000000..2b4c354c59 --- /dev/null +++ b/src/revolution/os/__os.h @@ -0,0 +1,150 @@ +#ifndef _REVOLUTION_OS_INTERNAL_H_ +#define _REVOLUTION_OS_INTERNAL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// OS +extern char* __OSExceptionNames[17]; // D ONLY + +u32 __OSIsDebuggerPresent(void); +void __OSPSInit(void); +void __OSInitIPCBuffer(void); +void __OSInitSTM(void); +void __OSInitNet(void); +void __OSInitPlayTime(void); +void __OSStartPlayRecord(void); + +// OSAlarm +void __OSInitAlarm(void); +void __OSCancelInternalAlarms(void* userdata); + +// OSAlloc +extern volatile int __OSCurrHeap; + +// OSAudioSystem +void __OSInitAudioSystem(void); +void __OSStopAudioSystem(void); + +// OSCache +void __OSCacheInit(void); + +// OSContext +void __OSContextInit(void); + +// OSError +void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar); + +// OSExec +void __OSGetExecParams(OSExecParams* params); +void __OSSetExecParams(const OSExecParams* params, OSExecParams* addr); +void __OSBootDolSimple(u32 doloffset, u32 restartCode, void* regionStart, void* regionEnd, BOOL argsUseDefault, s32 argc, char** argv); +void __OSBootDol(u32 doloffset, u32 restartCode, const char** argv); +extern u32 __OSNextPartitionType; + +// OSInterrupt +extern void __RAS_OSDisableInterrupts_begin(void); +extern void __RAS_OSDisableInterrupts_end(void); + +extern u64 __OSSpuriousInterrupts; // D ONLY +extern char* __OSInterruptNames[33]; // D ONLY +extern char* __OSPIErrors[8]; // D ONLY + +__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler); +__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt); +void __OSInterruptInit(void); +OSInterruptMask __OSMaskInterrupts(OSInterruptMask global); +OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global); +void __OSDispatchInterrupt(__OSException exception, OSContext* context); +void __OSModuleInit(void); + +// OSMemory +void __OSInitMemoryProtection(void); + +// OSMutex +void __OSUnlockAllMutex(OSThread* thread); +int __OSCheckDeadLock(OSThread* thread); +int __OSCheckMutexes(OSThread* thread); + +// OSPlayTime +void __OSGetPlayTime(ESTicketView* ticket, __OSPlayTimeType* type, u32* playTime); + +// OSReset +void __OSDoHotReset(u32 resetCode); +void __OSShutdownDevices(u32 event); +int __OSCallShutdownFunctions(BOOL final, u32 event); + +// OSResetSW +void __OSResetSWInterruptHandler(s16 exception, OSContext* context); +void __OSSetResetButtonTimer(u8 min); + +// OSRtc +int __OSGetRTC(u32* rtc); +int __OSSetRTC(u32 rtc); +void __OSInitSram(void); +OSSram* __OSLockSram(void); +OSSramEx* __OSLockSramEx(void); +int __OSUnlockSram(BOOL commit); +int __OSUnlockSramEx(BOOL commit); +int __OSSyncSram(void); +int __OSCheckSram(void); +int __OSReadROM(void* buffer, s32 length, s32 offset); +int __OSReadROMAsync(void* buffer, s32 length, s32 offset, void (*callback)()); +u8 __OSGetBootMode(void); +void __OSSetBootMode(u8 ntd); + +// OSSync +extern void __OSSystemCallVectorStart(); +extern void __OSSystemCallVectorEnd(); + +void __OSInitSystemCall(void); + +// OSThread +void __OSThreadInit(void); +s32 __OSGetEffectivePriority(OSThread* thread); +void __OSPromoteThread(OSThread* thread, s32 priority); +void __OSReschedule(void); + +// OSTime +void __OSSetTime(OSTime time); +OSTime __OSGetSystemTime(); +void __OSSetTick(register OSTick newTicks); +OSTime __OSTimeToSystemTime(OSTime time); + +// ppc_eabi_init +__declspec(section ".init") asm void __init_hardware(void); +__declspec(section ".init") asm void __flush_cache(void* address, unsigned int size); +void __init_user(void); +void _ExitProcess(void); + +// start +__declspec(weak) void InitMetroTRK_BBA(); + +__declspec(section ".init") void __start(void); + +__declspec(section ".init") extern void __start(void); +__declspec(section ".init") void __copy_rom_section(void* dst, const void* src, u32 size); +__declspec(section ".init") void __init_bss_section(void* dst, u32 size); +__declspec(section ".init") extern void __init_registers(void); +__declspec(section ".init") extern void __init_data(void); + +// time.dolphin +OSTime __get_clock(void); +u32 __get_time(void); +int __to_gm_time(void); + + +// unsorted +void __OSWriteExpiredFlag(void); +void __OSReturnToMenuForError(void); +void __OSHotResetForError(void); + +#ifdef __cplusplus +} +#endif + +#endif // _REVOLUTION_OS_INTERNAL_H_ diff --git a/src/revolution/os/__ppc_eabi_init.cpp b/src/revolution/os/__ppc_eabi_init.cpp new file mode 100644 index 0000000000..8d33b13202 --- /dev/null +++ b/src/revolution/os/__ppc_eabi_init.cpp @@ -0,0 +1,47 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __init_cpp(void); +void _ExitProcess(void); + +typedef void (*voidfunctionptr)(); +extern voidfunctionptr _ctors[]; +extern voidfunctionptr _dtors[]; + +void __init_user(void) { + __init_cpp(); +} + +void __init_cpp(void) { + /** + * call static initializers + */ + voidfunctionptr* constructor; + for (constructor = _ctors; *constructor; constructor++) { + (*constructor)(); + } +} + +static void __fini_cpp(void) { + voidfunctionptr* dtor; + + for (dtor = _dtors; *dtor; dtor++) { + (*dtor)(); + } +} + +void exit(int status) { + __fini_cpp(); + _ExitProcess(); +} + +void _ExitProcess(void) { + PPCHalt(); +} + +#ifdef __cplusplus +} +#endif