ユーザ用ツール

サイト用ツール


ハイハイスクールアドベンチャー_palmos版

ハイハイスクールアドベンチャー PalmOS版

あらすじ

2019年神奈山県立ハイ高等学校は 地盤が弱く校舎の老朽化も進んだため、 とうとう廃校にする以外方法がなく なってしまった。

ところで大変な情報を手に入れた。 それは、

「ハイ高校にATOMIC BOMBが仕掛けられている。」

と、いうものだ。 どうやらハイ高が廃校になった時、 気が狂った理科の先生がATOMIC BOMBを 学校のどこかに仕掛けてしまったらしい。

お願いだ。我が母校のコナゴナになった 姿を見たくはない。 早くATOMIC BOMBを取り除いてくれ……!!

行動は英語で、“<動詞>” 或いは、“<動詞>”+“<目的語>“のように入れていただきたい。 例えば、”look room”と入れれば部屋の様子を見ることが出来るという訳だ。

それでは Good Luck!!!…………

概要

PalmOS版のハイハイスクールアドベンチャーです。 既にPalmOSネイティブのデバイスは販売されておりませんが、もし実行環境をお持ちの方がいらっしゃれば、是非、トライしてみてください。 なお、NDKを使用しており、ARMプロセッサーのモデル以外では動作しません。 解像度は320×320を推奨しますが、160×160のデバイスでも動かないことはないです。

ダウンロードとインストール

アプリケーションとデータをこちらからダウンロードしてください。 展開して出てきた high.prc および全てのpdbファイルを HotSync でデバイスにインストールしてください。

あれこれ

NDKのこと

PalmOSはもともとモトローラの68KをCPUとして採用したデバイス向けのものだったが、ARMを採用した際に互換性のための68Kエミュレーションとは別に、ARMネイティブで動作する高速なサービスを組み込めるように NDKをリリースした。

68Kむけのバイナリコードを動かすのとはことなり、インターフェイスなどに制約はあるものの、ARMネイティブで動くコードは高速で、ハイハイスクールアドベンチャーも、グラフィックス周りをNDKによりARMネイティブ化できたことでリリースのめどが立った。

一応、68Kのコードもあるので、非ARMのデバイスで動かすこともできなくはないが、絶望的に遅いので全く推奨はしない。

なお、画面への描画の途中経過は見えず、最後にばっと表示される。 これは移植されたほとんどの環境でそうなのだが1)、これを見た Hayamiに「ダサイ」と言われた。

モダンなグラフィックライブラリは大体ダブルバッファ使っていたりするし、レンダリングは一気に行われるスタイルだったり、UI用のスレッド以外では表示の更新ができなかったりという制約の中でやっているので、そんなことをいわれてもどうにもならないのだ。

high.h
/*
 * High High School Adventure
 *
 *    Copyright(c)1985 ZOBplus
 *    Copyright(c)2002,2025 ZOBplus hiro <hiro@zob.ne.jp>
 */
 
#ifndef HIGH_H
#define HIGH_H
 
#define ZAMA_CREATOR_ID   'ZAMA'
#define ZAMA_PREFS_ID     (0)
#define ZAMA_PREFS_VER    (100)
 
#define ZAMA_ITEM_NUMBERS (12)
#define ZAMA_CMD_INVALID  (0)
#define ZAMA_CMD_END      (61)
 
#define ZAMA_SILK_NOTIFY  (1)
 
#define ZAMA_CODE_ISAKO   (135)
 
#define ZAMA_GLOBAL_VAR   (5000)
#define ZAMA_GRAPH_VAR    (5001)
 
enum ZamaDirection {
  DirInvalid = -1,
  DirNorth, DirSouth, DirWest, DirEast, DirUp, DirDown, DirEnter, DirExit,
  DirMax
};
 
enum ZamaSex {
  SexInvalid = 0,
  SexBoy,
  SexGirl,
  SexMax
};
 
enum ActType {
  ActComp = 0,
  ActAction
};
 
enum CmpOperator {
  CMP_NOP = 0,
  CMP_EQ,
  CMP_NE,
  CMP_GT,
  CMP_GE,
  CMP_LT,
  CMP_LE,
};
 
enum ActOperator {
  ACT_NOP = 0,
  ACT_MOVE,
  ACT_ASGN,
  ACT_MESG,
  ACT_DLOG,
  ACT_LOOK,
  ACT_SND,
  ACT_OVER,
};
 
enum RuleValueType {
  TYPE_NONE = 0,
  TYPE_FACT,
  TYPE_PLACE,
  TYPE_SYSTEM,
  TYPE_VECTOR,
};
 
typedef struct CmdHeaderType {
  UInt16 _act:1;
  UInt16 _op:3;
  UInt16 _pad:4;
  UInt16 _type:3;
  UInt16 _id:5;
} CmdHeaderType;
typedef CmdHeaderType *CmdHeaderPtr;
 
typedef struct CmdBodyType {
  UInt16 _type:3;
  UInt16 _id:5;
  UInt16 _value:8;
} CmdBodyType;
typedef CmdBodyType *CmdBodyPtr;
 
typedef struct CmdBlkType {
  CmdHeaderType _head;
  CmdBodyType   _body;
} CmdBlkType;
typedef CmdBlkType *CmdBlkPtr;
 
typedef struct RuleType {
  UInt8 _mapId;
  UInt8 _cmdN;
  UInt8 _objN;
  UInt8 _pad;
  UInt8 _args[44];
} RuleType;
typedef RuleType *RulePtr;
 
#define EndOfRule (0xff)
 
typedef struct ZamaPrefsType {
  UInt8   _lastSaved;
  Boolean _suspended;
  FontID  _curFont;
  Boolean _linedraw;
  Boolean _sound;
} ZamaPrefsType;
typedef ZamaPrefsType *ZamaPrefsPtr;
 
typedef struct ZamaMapType {
  UInt8 graphic[0x400];
  UInt8 reaction[0x100];
  UInt8 mesg[0x300];
} ZamaMapType;
typedef ZamaMapType *ZamaMapPtr;
 
typedef struct ZamaUserDataType {
  UInt8   vector[87][8];
  UInt8   place[ZAMA_ITEM_NUMBERS];
  UInt8   fact[15];
  union {
    struct {
      UInt8 mapID, mapW, cmdN, objN, dret, rand, dlogOk, dmesg;
    } n;
    UInt8 ary[8]; /* 0: mapID 1: mapW  2: cmdN 3: objN 4: dret 5: rand */
                  /* 6: dlogOk 7: dmesg 8: reserved */
  } sys;
} ZamaUserDataType;
typedef ZamaUserDataType *ZamaUserDataPtr;
 
typedef struct ZamaWordType {
  Char  word[4];
  UInt8 number;
} ZamaWordType;
typedef ZamaWordType *ZamaWordPtr;
 
typedef struct ZamaMesgType {
  UInt8 len;
  Char  mesg[1];
} ZamaMesgType;
typedef ZamaMesgType *ZamaMesgPtr;
 
typedef struct ZamaReactionType {
  UInt16 action;
  UInt8  number;
} ZamaReactionType;
typedef ZamaReactionType *ZamaReactionPtr;
 
#ifndef stdSilkHeight
#define stdSilkHeight (65)
#endif /* stdSilkHeight */
 
#endif /* HIGH_H */
high.c
/*
 * High-High School Adventure
 *   Copyright(c)2002-2003 ZOBplus hiro <hiro@zob.ne.jp>
 *   Copyright(c)ZOBplus
 */
 
#include <PalmOS.h>
#include <SonyCLIE.h>
#include <SmallFontSupport.h>
#ifdef USE_GRAPH2
#include "graph2.h"
#else /* USE_GRAPH2 */
#include "graph.h"
#endif /* USE_GRAPH2 */
#include "high.h"
#include "highrsc.h"
 
typedef struct {
  ZamaMapType      map;
  ZamaUserDataType user;
  UInt8            object[0x200];
  ZamaPrefsType    prefs;
 
  Char             cmd[5];
  Char             obj[5];
 
  RectangleType    pict;
  UInt16           _silkr; /* silk control */
  UInt32           _silkVer;
  Boolean          _resized; /* resized */
  Boolean          _ignoreKey;
 
  UInt32           _startup;
  Boolean          _over;
 
/* tsPatch support */
  Boolean          tsPatch;
  UInt32           tinyFontID;
  UInt32           tinyBoldFontID;
  UInt32           smallFontID;
  UInt32           smallSymbolFontID;
  UInt32           smallSymbol11FontID;
  UInt32           smallSymbol7FontID;
  UInt32           smallLedFontID;
  UInt32           smallBoldFontID;
} ZamaGlobalVarType;
 
static
ZamaGlobalVarType *
CreateGlobalVariables()
{
  ZamaGlobalVarType *ptr = NULL;
  Err err;
  if ((err = FtrPtrNew(ZAMA_CREATOR_ID, ZAMA_GLOBAL_VAR, sizeof(ZamaGlobalVarType), &ptr)) != errNone)
  {
    return NULL;
  }
  return ptr;
}
 
static
void
DeleteGlobalVariables()
{
  FtrPtrFree(ZAMA_CREATOR_ID, ZAMA_GLOBAL_VAR);
}
 
static
ZamaGlobalVarType *
GetGlobalVariables()
{
  ZamaGlobalVarType *ptr = NULL;
  Err err;
  if ((err = FtrGet(ZAMA_CREATOR_ID, ZAMA_GLOBAL_VAR, &ptr)) != errNone)
  {
    return NULL;
  }
  return ptr;
}
 
static
MemPtr
GetObjectPtr(UInt16 id)
{
  FormPtr form;
  form = FrmGetActiveForm();
  return FrmGetObjectPtr(form, FrmGetObjectIndex(form, id));
}
 
static
DmOpenRef
OpenDatabase(Char *name_)
{
  LocalID     dbID;
  DmOpenRef   dbP;
  Err         err;
  UInt16      cardNo;
 
  if ((err = SysCurAppDatabase(&cardNo, &dbID)) != errNone) {
    cardNo = 0;
  }
  if ((dbID = DmFindDatabase(cardNo, name_)) == 0) {
    /* error */
    return NULL;
  }
  if ((dbP = DmOpenDatabase(cardNo, dbID, dmModeReadOnly)) == 0) {
    /* error */
    return NULL;
  }
  return dbP;
}
 
static
Boolean
SaveGame(UInt16 fileno_)
{
  LocalID     dbID;
  DmOpenRef   dbP;
  MemHandle   rec;
  UInt16      err, i, index, attr, version;
  MemPtr      p;
  Boolean     res = true;
  UInt16      cardNo;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((err = SysCurAppDatabase(&cardNo, &dbID)) != errNone) {
    cardNo = 0;
  }
  while ((dbID = DmFindDatabase(cardNo, "ZAMAuser")) == 0) {
    /* create database */
    err = DmCreateDatabase(cardNo, "ZAMAuser", ZAMA_CREATOR_ID, 'data', false);
    if (err) {
      FrmAlert(ZAMA_SAVE_ALERT);
      return false;
    }
  }
  DmDatabaseInfo(cardNo, dbID, NULL, &attr, &version,
                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  attr |= dmHdrAttrBackup;
  version = 0x100; /* version 1.00 */
  DmSetDatabaseInfo(cardNo, dbID, NULL, &attr, &version,
                    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  if ((dbP = DmOpenDatabase(cardNo, dbID, dmModeReadWrite)) == 0) {
    /* error */
    FrmAlert(ZAMA_SAVE_ALERT);
    return false;
  }
  for (i = 0 ; i < 4 ; i++) {
    if (DmQueryRecord(dbP, i) == NULL) {
      if ((rec = DmNewHandle(dbP, sizeof(ZamaUserDataType))) == NULL) {
        FrmAlert(ZAMA_SAVE_ALERT);
        res = false;
        goto _done;
      }
      index  = i;
      if (DmAttachRecord(dbP, &index, rec, NULL) != errNone) {
        FrmAlert(ZAMA_SAVE_ALERT);
        res = false;
        goto _done;
      }
    }
  }
  if ((rec = DmGetRecord(dbP, fileno_)) == NULL) {
    FrmAlert(ZAMA_SAVE_ALERT);
    res = false;
    goto _done;
  }
  p = MemHandleLock(rec);
 
  DmWrite(p, 0, &z->user, sizeof(ZamaUserDataType));
 
  MemHandleUnlock(rec);
  DmReleaseRecord(dbP, fileno_, true);
  if (fileno_ != 0) {
    z->prefs._lastSaved = fileno_;
  }
 _done:;
  DmCloseDatabase(dbP);
  return res;
}
 
static
Boolean
LoadGame(UInt16 fileno_)
{
  DmOpenRef   dbP;
  MemHandle   rec;
  Char        sid[16];
  MemPtr      p;
  Boolean     res = true;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((dbP = OpenDatabase("ZAMAuser")) == NULL) {
    FrmCustomAlert(ZAMA_NODATA_ALERT, StrIToA(sid, fileno_), NULL, NULL);
    return false;
  }
  if ((rec = DmQueryRecord(dbP, fileno_)) == NULL) {
    FrmCustomAlert(ZAMA_NODATA_ALERT, StrIToA(sid, fileno_), NULL, NULL);
    res = false;
    goto _done;
  }
  p = MemHandleLock(rec);
 
  MemMove((MemPtr)&z->user, p, sizeof(ZamaUserDataType));
 
  MemHandleUnlock(rec);
  z->prefs._lastSaved = fileno_;
 _done:;
  DmCloseDatabase(dbP);
  return res;
}
 
#ifdef USE_GRAPH2
static
FontID
ZamaFontSelect(FontID curFont_)
{
  FormPtr       formP;
  UInt16        ret;
  Coord         x, y;
  WinHandle     hWin;
  RectangleType bounds;
  FontID        font;
  UInt16        small, fnt;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  formP = FrmInitForm(ZAMA_FONT_FORM);
  GGetDisplayExtent(&x, &y, false);
  if (y > 160) {
    /* silk turned off */
    hWin = FrmGetWindowHandle(formP);
    WinGetBounds(hWin, &bounds);
    bounds.topLeft.y += stdSilkHeight;
    if (bounds.topLeft.y + bounds.extent.y >= y) {
      bounds.topLeft.y = y - bounds.extent.y;
    }
    WinSetBounds(hWin, &bounds);
  }
  small = FrmGetObjectIndex(formP, ZAMA_SMALL_FONT);
  font = curFont_;
  if (font & fntAppFontCustomBase) {
    font -= fntAppFontCustomBase;
    CtlSetValue(FrmGetObjectPtr(formP, small), true);
  }
  switch (font) {
  case stdFont:       fnt = ZAMA_STD_FONT;        break;
  case boldFont:      fnt = ZAMA_BOLD_FONT;       break;
  case largeFont:     fnt = ZAMA_LARGE_FONT;      break;
  case largeBoldFont: fnt = ZAMA_LARGE_BOLD_FONT; break;
  default:
    CtlSetValue(FrmGetObjectPtr(formP, small), true);
    if (font == z->tinyFontID) {
      fnt = ZAMA_STD_FONT;
    } else if (font == z->tinyBoldFontID) {
      fnt = ZAMA_BOLD_FONT;
    } else if (font == z->smallFontID) {
      fnt = ZAMA_LARGE_FONT;
    } else if (font == z->smallBoldFontID) {
      fnt = ZAMA_LARGE_BOLD_FONT;
    } else {
      fnt = ZAMA_STD_FONT;
    }
    break;
  }
  fnt = FrmGetObjectIndex(formP, fnt);
  CtlSetValue(FrmGetObjectPtr(formP, fnt), true);
  FrmUpdateForm(ZAMA_FONT_FORM, frmRedrawUpdateCode);
  ret = FrmDoDialog(formP);
  fnt = FrmGetControlGroupSelection(formP, ZAMA_FONT_SELECT);
  if (fnt == frmNoSelectedControl) {
    ret = ZAMA_BUTTON_CANCEL;
  }
  if (fnt == FrmGetObjectIndex(formP, ZAMA_STD_FONT)) {
    fnt = stdFont;
  } else if (fnt == FrmGetObjectIndex(formP, ZAMA_BOLD_FONT)) {
    fnt = boldFont;
  } else if (fnt == FrmGetObjectIndex(formP, ZAMA_LARGE_FONT)) {
    fnt = largeFont;
  } else if (fnt == FrmGetObjectIndex(formP, ZAMA_LARGE_BOLD_FONT)) {
    fnt = largeBoldFont;
  } else {
    ret = ZAMA_BUTTON_CANCEL;
  }
  if (CtlGetValue(FrmGetObjectPtr(formP, small))) {
    if (z->tsPatch) {
      switch (fnt) {
      case stdFont:      fnt = z->tinyFontID; break;
      case boldFont:     fnt = z->tinyBoldFontID; break;
      case largeFont:    fnt = z->smallFontID; break;
      case largeBoldFont: fnt = z->smallBoldFontID; break;
      }
    } else {
      fnt += fntAppFontCustomBase;
    }
  }
  FrmDeleteForm(formP);
  return (ret == ZAMA_BUTTON_OK) ? fnt : curFont_;
}
#endif /* USE_GRAPH2 */
 
static
Boolean
ZamaSndPlay(UInt16 id)
{
  UInt16  volRefNum;
  Err     err;
  Char    *pathFmt =  = "/Palm/PROGRAMS/high/%d.wav";
  Char    pathName[1024];
  FileRef dbFileRef;
  UInt32  size;
  SndPtr  bufP;
  UInt32  vIterator;
  ZamaGlobalVarType *z = CreateGlobalVariables();
  if (z->prefs._sound) {
    /* play sound */
    StrPrintF(pathName, pathFmt, id);
    vIterator = vfsIteratorStart;
     err = VFSVokumeEnumerate(&volRefNum, &vIterator);
    if (err != errNone) {
      return false;
    }
    if (VFSFileOpen(volRefNum, pathName, vfsModeRead, &dbFileRef) != errNone) {
      return false;
    }
    VFSFileSize(dbFileRef, &size);
  }
  return true;
}
 
static
void
VOSplit(Char *srcP_)
{
  Char   *p;
  UInt16  i;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  StrCopy(z->cmd, "!!!!");
  StrCopy(z->obj, "!!!!");
  for (p = srcP_ ; *p && *p == ' ' ; p++); /* skip heading space */
  for (i = 0 ; *p && *p != ' ' && i < 4 ; i++) {
    z->cmd[i] = 1 + *p++;
  }
  for ( ; *p && *p != ' ' ; p++); /* skip until space */
  for ( ; *p && *p == ' ' ; p++); /* skip space */
  for (i = 0 ; *p && *p != ' ' && i < 4 ; i++) {
    z->obj[i] = 1 + *p++;
  }
}
 
static
UInt16
SearchWord(Char *word_, Boolean verb_)
{
  DmOpenRef   dbP;
  MemHandle   rec;
  ZamaWordPtr p;
  UInt16      index;
  UInt16      i, n;
 
  if (word_ == NULL || StrCompare("!!!!", word_) == 0) {
    return 0;
  }
  if ((dbP = OpenDatabase("ZAMAdict")) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "����", NULL, NULL);
    return 0;
  }
  index = (verb_) ? 0 : 1;
  n = 0;
  if ((rec = DmQueryRecord(dbP, index)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "����", NULL, NULL);
    goto _done;
  }
  p = (ZamaWordPtr)MemHandleLock(rec);
  for (i = 0 ; p[i].word[0] ; i++) {
    if (StrNCaselessCompare(word_, p[i].word, 4) == 0) {
      n = p[i].number;
      break;
    }
  }
  MemHandleUnlock(rec);
 _done:;
  DmCloseDatabase(dbP);
  return n;
}
 
static
MemHandle
SearchFixedMessage(UInt16 mesgId_)
{
  ZamaMesgPtr  p = NULL;
  UInt16       i;
  DmOpenRef    dbP;
  MemHandle    rec, mesg;
  ZamaMesgPtr  mesgP;
 
  if ((dbP = OpenDatabase("ZAMAdict")) == NULL) {
    /* error */
    FrmCustomAlert(ZAMA_FATAL_ALERT, "����", NULL, NULL);
    return 0;
  }
  mesg = 0;
  if ((rec = DmQueryRecord(dbP, 2)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "����", NULL, NULL);
    goto _done;
  }
  mesgId_ &= 0x7f;
  p = (ZamaMesgPtr)MemHandleLock(rec);
  for (i = 0 ; p->len > 0 && i < mesgId_ - 1 ; i++) {
    p = (ZamaMesgPtr)(p->mesg + p->len);
  }
  if (p && p->len) {
    mesg = MemHandleNew(sizeof(ZamaMesgType) + p->len - 1);
    mesgP = (ZamaMesgPtr)MemHandleLock(mesg);
    MemMove(mesgP, p, sizeof(ZamaMesgType) + p->len - 1);
    MemHandleUnlock(mesg);
  }
 
  MemHandleUnlock(rec);
 _done:;
  DmCloseDatabase(dbP);
  return mesg;
}
 
static
MemHandle
SearchMapMessage(UInt16 cmdN_, UInt16 objN_)
{
  ZamaMesgPtr      p = NULL;
  int              i;
  int              n = 0;
  ZamaReactionType mp;
  UInt8           *rp = map.reaction;
  MemHandle        mesg;
  ZamaMesgPtr      mesgP;
 
  cmdN_ = (cmdN_ << 8) | objN_;
  for (i = 0 ; *rp ; i++) {
    mp.action = (rp[0] << 8) | rp[1];
    mp.number = rp[2];
    if (cmdN_ == mp.action) {
      p = (ZamaMesgPtr)map.mesg;
      for (n = 0 ; p->len > 0 && n < mp.number - 1 ; n++) {
        p = (ZamaMesgPtr)(p->mesg + p->len);
      }
      break;
    }
    rp += 3;
  }
  mesg = 0;
  if (p && p->len) {
    mesg = MemHandleNew(sizeof(ZamaMesgType) + p->len - 1);
    mesgP = (ZamaMesgPtr)MemHandleLock(mesg);
    MemMove(mesgP, p, sizeof(ZamaMesgType) + p->len - 1);
    MemHandleUnlock(mesg);
  } else {
    cmdN_ >>= 8; /* restore Command ID */
    i = 0;
    if (cmdN_ <= 0x0e && cmdN_ >= 0x0b) {
      i = cmdN_ - 8;
    } else if (cmdN_ == 7 || cmdN_ == 8) {
      i = cmdN_ - 6;
    } else if (cmdN_ >= 0x11 && cmdN_ <= 0x18) {
      i = cmdN_ - 9;
    } else if (cmdN_ == 0x1c || cmdN_ == 0x1d) {
      i = cmdN_ - 12;
    } else if (cmdN_ == 0x20 || cmdN_ == 0x21) {
      i = cmdN_ - 14;
    } else if (cmdN_ == 0x26) {
      i = 0x14;
    } else if (cmdN_ == 0x28 || cmdN_ == 0x2f) {
      i = 0x15;
    } else if (cmdN_ == 0x29) {
      i = 7;
    } else if (objN_ == 0) {
      i = 0x30 + (SysRandom(0) % 4);
    }
    if (i) {
      mesg = SearchFixedMessage(i);
    }
  }
  return mesg;
}
 
static
void
ScrollMessageField(void)
{
  Int16        lines, pos, min, max, page;
  UInt16       scrollPos, textHeight, fieldHeight;
  FieldPtr     fldP;
  ScrollBarPtr scrP;
  fldP = GetObjectPtr(ZAMA_MESSAGE_FIELD);
  scrP = GetObjectPtr(ZAMA_SCROLL_BAR);
  SclGetScrollBar(scrP, &pos, &min, &max, &page);
  FldGetScrollValues(fldP, &scrollPos, &textHeight, &fieldHeight);
  lines = (pos - scrollPos) /** GScale()*/;
  if (lines > 0) {
    FldScrollField(fldP, lines, winDown);
  } else if (lines < 0) {
    FldScrollField(fldP, -lines, winUp);
  }
  FldSetDirty(fldP, true);
#ifdef USE_GRAPH2
  if (tsPatch) {
    FldDrawField(fldP);
  } else {
    GFldDrawField(fldP);
  }
#else /* USE_GRAPH2 */
  ZamaFldDrawField(fldP);
#endif /* USE_GRAPH2 */
}
 
static
void
UpdateMessageFieldScrollbar(void)
{
  UInt16       scrollPos, textHeight, fieldHeight;
  Int16        maxValue;
  FieldPtr     fldP;
  ScrollBarPtr scrP;
 
  fldP = GetObjectPtr(ZAMA_MESSAGE_FIELD);
  scrP = GetObjectPtr(ZAMA_SCROLL_BAR);
  maxValue = 0;
  FldGetScrollValues(fldP,&scrollPos, &textHeight, &fieldHeight);
  /* fieldHeight *= GScale(); */
  if (textHeight > fieldHeight) {
    maxValue = (textHeight - fieldHeight) + FldGetNumberOfBlankLines(fldP);
  } else if (scrollPos) {
    maxValue = scrollPos;
  }
  SclSetScrollBar(scrP, scrollPos, 0, maxValue, fieldHeight - 1);
}
 
static
void
CleanMessageField(void)
{
  FieldPtr  fldP;
  MemHandle hText;
 
  fldP = GetObjectPtr(ZAMA_MESSAGE_FIELD);
#ifdef USE_GRAPH2
  if (tsPatch) {
    FldEraseField(fldP);
  } else {
    GFldEraseField(fldP);
  }
#else /* USE_GRAPH2 */
  ZamaFldEraseField(fldP);
#endif /* USE_GRAPH2 */
  if ((hText = FldGetTextHandle(fldP)) != NULL) {
    FldSetTextHandle(fldP, NULL);
    MemHandleFree(hText);
    FldSetDirty(fldP, true);
  }
  UpdateMessageFieldScrollbar();
#ifdef USE_GRAPH2
  if (tsPatch) {
    FldDrawField(fldP);
  } else {
    GFldDrawField(fldP);
  }
#else /* USE_GRAPH2 */
  ZamaFldDrawField(fldP);
#endif /* USE_GRAPH2 */
}
 
static
void
PutMessageToField(Char *strP_, UInt16 len_)
{
  FieldPtr      fldP;
  MemHandle     hText;
  Char          *textP;
  UInt16        max;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  fldP  = GetObjectPtr(ZAMA_MESSAGE_FIELD);
  max   = FldGetTextLength(fldP);
  hText = FldGetTextHandle(fldP);
  FldSetTextHandle(fldP, NULL);
  if (hText == NULL) {
    hText = MemHandleNew(len_ + 1);
    textP = MemHandleLock(hText);
  } else {
    MemHandleResize(hText, max + len_ + 2);
    textP = MemHandleLock(hText);
    textP[max++] = '\n'; /* add newline */
    textP[max]   = 0;
  }
  MemMove(&textP[max], strP_, len_);
  textP[max + len_] = 0;
  MemHandleUnlock(hText);
 
  FldSetTextHandle(fldP, hText);
  FldSetDirty(fldP, true);
#ifdef USE_GRAPH2
  if (z->tsPatch) {
    FldDrawField(fldP);
  } else {
    GFldDrawField(fldP);
  }
#else /* USE_GRAPH2 */
  ZamaFldDrawField(fldP);
#endif /* USE_GRAPH2 */
  UpdateMessageFieldScrollbar();
}
 
static
void
DrawMessage(UInt16 mesgId_, UInt16 cmdN_, UInt16 objN_)
{
  Char          *strP;
  UInt16        len;
  MemHandle     mesg;
  ZamaMesgPtr   mesgP;
 
  if (mesgId_ & 0x80) {
    mesg = SearchFixedMessage(mesgId_ & 0x7f);
  } else {
    if (mesgId_ == 1) {
      mesgP = (ZamaMesgPtr)map.mesg;
      mesg  = MemHandleNew(sizeof(ZamaMesgType) + mesgP->len - 1);
      MemMove(MemHandleLock(mesg), mesgP, sizeof(ZamaMesgType) + mesgP->len - 1);
      MemHandleUnlock(mesg);
    } else {
      mesg = SearchMapMessage(cmdN_, objN_);
    }
  }
  strP = "�_��";
  len  = StrLen(strP);
  if (mesg) {
    mesgP = (ZamaMesgPtr)MemHandleLock(mesg);
    strP  = mesgP->mesg;
    len   = mesgP->len;
  }
  PutMessageToField(strP, len);
  if (mesg) {
    MemHandleUnlock(mesg);
    MemHandleFree(mesg);
  }
}
 
static
Boolean
LoadInitData(void)
{
  DmOpenRef dbP;
  MemHandle rec;
  MemPtr    p;
  Boolean   res = true;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((dbP = OpenDatabase("ZAMAinit")) == NULL) {
    /* error */
    FrmCustomAlert(ZAMA_FATAL_ALERT, "�����f�[�^", NULL, NULL);
    return false;
  }
  if ((rec = DmQueryRecord(dbP, 0)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "�����f�[�^", NULL, NULL);
    res = false;
    goto _done;
  }
  p   = (MemPtr)MemHandleLock(rec);
  MemMove(&z->user.vector, p, sizeof(z->user.vector));
  MemHandleUnlock(rec);
 
  if ((rec = DmQueryRecord(dbP, 1)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "�����f�[�^", NULL, NULL);
    res = false;
    goto _done;
  }
  p   = (MemPtr)MemHandleLock(rec);
  MemMove(&z->user.place, p, sizeof(z->user.place));
  MemHandleUnlock(rec);
 
  if ((rec = DmQueryRecord(dbP, 2)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "�����f�[�^", NULL, NULL);
    res = false;
    goto _done;
  }
  p   = (MemPtr)MemHandleLock(rec);
  MemMove(&z->user.fact, p, sizeof(z->user.fact));
  MemHandleUnlock(rec);
 _done:;
  DmCloseDatabase(dbP);
  return res;
}
 
static
Boolean
LoadMapData(UInt16 id)
{
  DmOpenRef dbP;
  MemHandle rec;
  MemPtr    p;
  Boolean   res = true;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((dbP = OpenDatabase("ZAMAmap")) == NULL) {
    /* error */
    FrmCustomAlert(ZAMA_FATAL_ALERT, "�n�}", NULL, NULL);
    return false;
  }
  if ((rec = DmQueryRecord(dbP, id)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "�n�}", NULL, NULL);
    res = false;
    goto _done;
  }
  p   = (MemPtr)MemHandleLock(rec);
  MemMove(&z->map, p, sizeof(ZamaMapType));
  MemHandleUnlock(rec);
 _done:;
  DmCloseDatabase(dbP);
  return true;
}
 
static
Boolean
LoadObjectData(UInt16 id)
{
  DmOpenRef dbP;
  MemHandle rec;
  MemPtr    p;
  Boolean   res = true;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((dbP = OpenDatabase("ZAMAobj")) == NULL) {
    /* error */
    FrmCustomAlert(ZAMA_FATAL_ALERT, "��̉摜", NULL, NULL);
    return false;
  }
  if ((rec = DmQueryRecord(dbP, id)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "��̉摜", NULL, NULL);
    res = false;
    goto _done;
  }
  p   = (MemPtr)MemHandleLock(rec);
  MemMove(z->object, p, 0x200);
  MemHandleUnlock(rec);
 _done:;
  DmCloseDatabase(dbP);
  return true;
}
 
static
UInt16
WinDrawOutline(RectanglePtr bP, UInt8 *data,
#ifdef USE_GRAPH2
               GColorName c
#else /* USE_GRAPH2 */
               ZamaColorName c
#endif /* USE_GRAPH2 */
               )
{
  Coord  x0, y0, x1, y1;
  UInt16 i = 0;
 
  x0 = data[i++];
  y0 = data[i++];
  for (;;) {
    x1 = data[i++];
    y1 = data[i++];
    if (y1 == 0xff) {
      if (x1 == 0xff) {
        /* end of line data */
        break;
      }
      /* reset line */
      x0 = data[i++];
      y0 = data[i++];
      continue;
    }
#ifdef USE_GRAPH2
    GDrawLine(NULL,
              bP->topLeft.x + x0, bP->topLeft.y + y0,
              bP->topLeft.x + x1, bP->topLeft.y + y1, c);
#else /* USE_GRAPH2 */
    ZamaDrawLine(bP->topLeft.x + x0, bP->topLeft.y + y0,
                 bP->topLeft.x + x1, bP->topLeft.y + y1, c);
#endif /* USE_GRAPH2 */
    x0 = x1; y0 = y1;
  }
  return i;
}
 
static
void
DrawObject(Boolean pre, UInt8 *data)
{
  UInt16           o = 0;
  Coord            xs, ys;
  UInt8            b, c;
  RectangleType    r;
 
  b  = data[o++];
  xs = (data[o++] / 2) + 32;
  ys = data[o++] + 32;
  RctSetRectangle(&r, xs, ys, 32 + 256 - xs, 32 + 152 - ys);
  WinPushDrawState();
#ifdef USE_GRAPH2
  o += WinDrawOutline(&r, &data[o], (pre)? gColorDarkYellow : b);
#else /* USE_GRAPH2 */
  o += WinDrawOutline(&r, &data[o], (pre)? DarkYellow : b);
#endif /* USE_GRAPH2 */
  xs = data[o++];
  ys = data[o++];
  while (xs != 0xff || ys != 0xff) {
    c = data[o++];
    /* in order to avoid paint loss */
#ifdef USE_GRAPH2
    GPaint(&r, xs, ys, (pre)? gColorDarkGray : c, (pre)? gColorDarkYellow : b);
#else /* USE_GRAPH2 */
    ZamaPaint(&r, xs, ys, (pre) ? DarkGray : c, (pre) ? DarkYellow : b);
#endif /* USE_GRAPH2 */
    xs = data[o++];
    ys = data[o++];
  }
  WinPopDrawState();
}
 
static
void
ObjectCheck(UInt16 mapID, Boolean msgOut)
{
  int              i;
  int              o = 0;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  for (i = 0 ; i < 12 ; i++) {
    if (z->user.place[i] == mapID && LoadObjectData(i + 1)) {
      /* draw object bitmap */
      o = 0;
      if (i == 1 /* Uniform */) {
        o = (z->user.fact[0] == 1) ? 0 : 256;
      }
      DrawObject(true,  &object[o]);
      DrawObject(false, &object[o]);
      if (msgOut) DrawMessage(0x96 + i, 0, 0);
    }
  }
}
 
static
void
DrawTeacher(void)
{
  Coord             x0, y0, x1, y1, oy;
  UInt16            i, j, k;
  UInt8             c = 0;
  UInt16            rep[] = { 18, 24, 2, 2, 2, 22, 9, 0xffff };
  UInt16            rep2[] = { 148, 14, 126, 6, 0, 0 };
  RectangleType     r, wr;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  oy = 32;
  if (LoadObjectData(15)) {
    RctSetRectangle(&r, 0, 0, 320, 320);
    y0 = 63;
    for (i = 0 ; i <= 172 ; i += 2) {
      x0 = z->object[i + 0];
      x1 = z->object[i + 1];
#ifdef USE_GRAPH2
    GDrawLine(NULL, x0, oy + y0, x1, oy + y0, gColorBlue);
#else /* USE_GRAPH2 */
    ZamaDrawLine(x0, oy + y0, x1, oy + y0, Blue);
#endif /* USE_GRAPH2 */
      ++y0;
    }
    for (j = 0 ; rep[j] != 0xffff ; j++) {
#ifdef USE_GRAPH2
      c  = z->object[i++];
      if (c == gColorRed) {
        c = gColorDarkRed;
      }
#else /* USE_GRAPH2 */
      c  = z->object[i++];
      if (c == Red) {
        c = DarkRed;
      }
#endif /* USE_GRAPH2 */
      x0 = z->object[i++];
      y0 = z->object[i++];
      for (k = 0 ; k <= rep[j] + 1 ; k++) {
        x1 = z->object[i++];
        y1 = z->object[i++];
#ifdef USE_GRAPH2
        GDrawLine(NULL, x0, oy + y0, x1, oy + y1, c);
#else /* USE_GRAPH2 */
        ZamaDrawLine(x0, oy + y0, x1, oy + y1, c);
#endif /* USE_GRAPH2 */
        x0 = x1;
        y0 = y1;
      }
      x0 = z->object[i++];
      y0 = z->object[i++];
      WinPushDrawState();
#ifdef USE_GRAPH2
      GPaint(&r, x0, oy + y0, c, c);
#else /* USE_GRAPH2 */
      ZamaPaint(&r, x0, oy + y0, c, c);
#endif /* USE_GRAPH2 */
      WinPopDrawState();
    }
    x0 = z->object[i++];
    y0 = z->object[i++];
#ifdef USE_GRAPH2
    GPaint(&r, x0, oy + y0, c, c);
#else /* USE_GRAPH2 */
    ZamaPaint(&r, x0, oy + y0, c, c);
#endif /* USE_GRAPH2 */
    for (j = 120 ; j < 124 ; j++) {
#ifdef USE_GRAPH2
      GDrawLine(NULL, j, oy + 64, j + 8, oy + 110, gColorYellow);
      GDrawLine(NULL, j + 9, oy + 110, j + 11, oy + 126, gColorWhite);
#else /* USE_GRAPH2 */
      ZamaDrawLine(j, oy + 64, j + 8, oy + 110, Yellow);
      ZamaDrawLine(j + 9, oy + 110, j + 11, oy + 126, White);
#endif /* USE_GRAPH2 */
    }
#ifdef USE_GRAPH2
    GDrawLine(NULL, 125, oy + 111, 133, oy + 109, gColorRed);
    GDrawLine(NULL, 133, oy + 109, 134, oy + 110, gColorRed);
    GDrawLine(NULL, 134, oy + 110, 125, oy + 112, gColorRed);
    GDrawLine(NULL, 125, oy + 112, 125, oy + 111, gColorRed);
    GDrawLine(NULL, 120, oy +  65, 123, oy +  64, gColorWhite);
    GDrawLine(NULL, 123, oy +  64, 121, oy +  62, gColorWhite);
    GDrawLine(NULL, 121, oy +  62, 120, oy +  65, gColorWhite);
    GPaint(&r, 122,oy +  63, gColorWhite, gColorWhite);
#else /* USE_GRAPH2 */
    ZamaDrawLine(125, oy + 111, 133, oy + 109, Red);
    ZamaDrawLine(133, oy + 109, 134, oy + 110, Red);
    ZamaDrawLine(134, oy + 110, 125, oy + 112, Red);
    ZamaDrawLine(125, oy + 112, 125, oy + 111, Red);
    ZamaDrawLine(120, oy +  65, 123, oy +  64, White);
    ZamaDrawLine(123, oy +  64, 121, oy +  62, White);
    ZamaDrawLine(121, oy +  62, 120, oy +  65, White);
    ZamaPaint(&r, 122,oy +  63, White, White);
#endif /* USE_GRAPH2 */
    for (k = 0 ; rep2[k + 1] != 0 ; k += 2) {
      for (j = 0, x0 = rep2[k] ; j < rep2[k + 1] ; j += 2) {
        y0 = z->object[i++];
        y1 = z->object[i++];
#ifdef USE_GRAPH2
        GDrawLine(NULL, x0, oy + y0, x0, oy + y1, gColorMagenta); ++x0;
        GDrawLine(NULL, x0, oy + y0, x0, oy + y1, gColorYellow);  ++x0;
#else /* USE_GRAPH2 */
        ZamaDrawLine(x0, oy + y0, x0, oy + y1, Magenta); ++x0;
        ZamaDrawLine(x0, oy + y0, x0, oy + y1, Yellow);  ++x0;
#endif /* USE_GRAPH2 */
        y0 = z->object[i++];
        y1 = z->object[i++];
#ifdef USE_GRAPH2
        GDrawLine(NULL, x0, oy + y0, x0, oy + y1, gColorWhite);   ++x0;
#else /* USE_GRAPH2 */
        ZamaDrawLine(x0, oy + y0, x0, oy + y1, White);   ++x0;
#endif /* USE_GRAPH2 */
      }
    }
 
#ifdef USE_GRAPH2
    RctSetRectangle(&wr, 149, oy + 78, 16, 6);
    GDrawRectangle(&wr, gColorBlack);
    RctSetRectangle(&wr, 150, oy + 79, 14, 4);
    GDrawRectangle(&wr, gColorWhite);
    RctSetRectangle(&wr, 156, oy + 78,  2, 6);
    GDrawRectangle(&wr, gColorBlack);
#else /* USE_GRAPH2 */
    RctSetRectangle(&wr, 149, oy + 78, 16, 6);
    ZamaDrawRectangle(&wr, Black);
    RctSetRectangle(&wr, 150, oy + 79, 14, 4);
    ZamaDrawRectangle(&wr, White);
    RctSetRectangle(&wr, 156, oy + 78,  2, 6);
    ZamaDrawRectangle(&wr, Black);
#endif /* USE_GRAPH2 */
 
    for (;;) {
      x1 = z->object[i++];
      y1 = z->object[i++];
      if (y1 == 0xff) {
        if (x1 == 0xff) {
          break;
        }
        x0 = z->object[i++];
        y0 = z->object[i++];
        continue;
      }
 
#ifdef USE_GRAPH2
      GDrawLine(NULL, x0, oy + y0, x1, oy + y1, gColorBlack);
#else /* USE_GRAPH2 */
      ZamaDrawLine(x0, oy + y0, x1, oy + y1, Black);
#endif /* USE_GRAPH2 */
      x0 = x1;
      y0 = y1;
    }
  }
}
 
static
void
CleanMap(
#ifdef USE_GRAPH2
         GColorName c_
#else /* USE_GRAPH2 */
         ZamaColorName c_
#endif /* USE_GRAPH2 */
)
{
  ZamaGlobalVarType *z = CreateGlobalVariables();
#ifdef USE_GRAPH2
  GDrawRectangle(&z->pict, c_);
#else /* USE_GRAPH2 */
  ZamaDrawRectangle(&z->pict, c_);
#endif /* USE_GRAPH2 */
}
 
static
void
DrawMap(Boolean putMesg_)
{
  UInt16        i = 0;
  Coord         x0, y0;
  UInt8         c;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  WinPushDrawState();
  i += z->map.graphic[i] * 3 + 1; /* skip HALF paint pattern */
 
  if (z->_startup == 0) {
    if (z->user.sys.n.mapID == 85 || z->user.sys.n.mapID == 84) {
      /* never draw */
#ifdef USE_GRAPH2
      CleanMap(gColorBlack);
#else /* USE_GRAPH2 */
      CleanMap(Black);
#endif /* USE_GRAPH2 */
      DrawMessage(0xcc, 0, 0);
      goto _done;
    }
  }
 
#ifdef USE_GRAPH2
  CleanMap(gColorBlue);
  /* draw outline */
  i += WinDrawOutline(&z->pict, &z->map.graphic[i], gColorWhite);
#else /* USE_GRAPH2 */
  CleanMap(Blue);
  /* draw outline */
  i += WinDrawOutline(&z->pict, &z->map.graphic[i], White);
#endif /* USE_GRAPH2 */
  /* paint */
  x0 = z->map.graphic[i++];
  y0 = z->map.graphic[i++];
  while (x0 != 0xff || y0 != 0xff) {
    c = z->map.graphic[i++];
#ifdef USE_GRAPH2
    GPaint(&z->pict, x0, y0, c, gColorWhite);
#else /* USE_GRAPH2 */
    ZamaPaint(&z->pict, x0, y0, c, White);
#endif /* USE_GRAPH2 */
    x0 = z->map.graphic[i++];
    y0 = z->map.graphic[i++];
  }
  if (z->map.graphic[i] == 0xff && z->map.graphic[i + 1] == 0xff) {
    i += 2;
  } else {
#ifdef USE_GRAPH2
    i += WinDrawOutline(&z->pict, &z->map.graphic[i], gColorWhite);
#else /* USE_GRAPH2 */
    i += WinDrawOutline(&z->pict, &z->map.graphic[i], White);
#endif /* USE_GRAPH2 */
  }
  if (z->map.graphic[i] == 0xff && z->map.graphic[i + 1] == 0xff) {
    i += 2;
  } else {
#ifdef USE_GRAPH2
    i += WinDrawOutline(&z->pict, &z->map.graphic[i], gColorBlack);
#else /* USE_GRAPH2 */
    i += WinDrawOutline(&z->pict, &z->map.graphic[i], Black);
#endif /* USE_GRAPH2 */
  }
  if (z->map.graphic[0]) {
#ifdef USE_GRAPH2
    GChromakeyPaint(&z->pict, &z->map.graphic[0], z->prefs._linedraw);
#else /* USE_GRAPH2 */
    ZamaChromakeyPaint(&z->pict, &z->map.graphic[0], z->prefs._linedraw);
#endif /* USE_GRAPH2 */
  }
  /* put message #0 */
  if (putMesg_) DrawMessage(1, 0, 0);
 _done:;
  WinPopDrawState();
}
 
static
void
GameInit(void)
{
  FormPtr    formP;
  ControlPtr btnP, chkP;
  FieldPtr   fldP;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  z->user.sys.n.mapID = 76;
  switch (z->_startup) {
  case ZAMA_CODE_ISAKO: z->user.sys.n.mapID = 84; break;
  default: break;
  }
 
  formP = FrmGetActiveForm();
  btnP  = GetObjectPtr(ZAMA_BUTTON_START);
  fldP  = GetObjectPtr(ZAMA_COMMAND_FIELD);
  chkP  = GetObjectPtr(ZAMA_CONTINUE);
 
  FldEraseField(fldP);
  FldSetUsable(fldP, false);
  CtlSetUsable(btnP, true);
  CtlShowControl(btnP);
  CtlSetUsable(chkP, z->prefs._suspended);
  CtlSetValue(chkP, z->prefs._suspended);
  if (z->prefs._suspended) {
    CtlShowControl(chkP);
  }
 
  FrmDrawForm(formP);
  CleanMessageField();
  LoadMapData(z->user.sys.n.mapID);
  DrawMap(false);
  PutMessageToField("�n�C�n�C�X�N�[���E�A�h�x���`���[", 52);
  PutMessageToField("   Copyright (c) 1985 ZOBplus   ", 52);
  PutMessageToField(" Copyright (c) 2002-2025 ZOBplus hiro", 52);
  z->_startup = 0; /* reset */
  z->_over = true; /* not yet started */
}
 
static
void
GameOver(void)
{
  FormPtr    formP;
  ControlPtr btnP, chkP;
  FieldPtr   fldP;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  formP = FrmGetActiveForm();
  btnP  = GetObjectPtr(ZAMA_BUTTON_START);
  fldP  = GetObjectPtr(ZAMA_COMMAND_FIELD);
  chkP  = GetObjectPtr(ZAMA_CONTINUE);
 
  z->prefs._suspended = false;
 
  FldEraseField(fldP);
  FldSetUsable(fldP, false);
  CtlSetUsable(btnP, true);
  CtlShowControl(btnP);
  CtlSetUsable(chkP, false);
  CtlSetValue(chkP, false);
 
  z->_over = true;
}
 
inline UInt8
getCond(UInt16 type_, UInt16 id_, UInt16 offset_)
{
  ZamaGlobalVarType *z = CreateGlobalVariables();
  UInt8 value;
  switch (type_) {
  case 0: value = 0; break;
  case 1: value = z->user.fact[id_]; break;
  case 2: value = z->user.place[id_]; break;
  case 3: value = z->user.sys.ary[id_]; break;
  case 4: value = z->user.vector[offset_ - 1][id_]; break;
  case 5:
  case 6:
  case 7:
  default: value = 0; break;
  }
  return value;
}
 
inline void
setStat(UInt16 type_, UInt16 id_, UInt16 offset_, UInt8 value_)
{
  ZamaGlobalVarType *z = CreateGlobalVariables();
  switch (type_) {
  case 0: break;
  case 1: z->user.fact[id_]   = value_; break;
  case 2: z->user.place[id_]  = value_; break;
  case 3: z->user.sys.ary[id_] = value_; break;
  case 4: z->user.vector[offset_ - 1][id_] = value_; break;
  case 5:
  case 6:
  case 7:
  default: break;
  }
}
 
static Boolean SexHandleEvent(EventPtr);
static Boolean FileHandleEvent(EventPtr);
static Boolean InvHandleEvent(EventPtr);
static Boolean CutHandleEvent(EventPtr);
 
static
Boolean
DialogHandler(UInt16 id_)
{
  FormPtr       formP;
  UInt16        ret;
  Boolean       redraw = false;
  ControlPtr    chkP;
  Coord         x, y;
  RectangleType bounds;
  WinHandle     hWin;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  do {
    formP = FrmInitForm(id_);
    if (z->_silkr) {
      if (z->_silkVer < 0x02) {
        SilkLibDisableResize(z->_silkr);
      } else {
        VskSetState(z->_silkr, vskStateEnable, 0);
      }
      WinGetDisplayExtent(&x, &y);
      if (y > 160) {
        hWin = FrmGetWindowHandle(formP);
        WinGetBounds(hWin, &bounds);
        bounds.topLeft.y += stdSilkHeight;
        WinSetBounds(hWin, &bounds);
      }
    }
    switch(id_) {
    case ZAMA_SEX_FORM:
       FrmSetEventHandler(formP, SexHandleEvent);
      break;
    case ZAMA_FILE_FORM:
      FrmSetEventHandler(formP, FileHandleEvent);
      if (z->prefs._lastSaved) {
        ret  = FrmGetObjectIndex(formP, ZAMA_FILE_ID1 - 1 + z->prefs._lastSaved);
        chkP = FrmGetObjectPtr(formP, ret);
        CtlSetValue(chkP, true);
      }
      FrmDrawForm(formP);
      break;
    case ZAMA_INV_FORM:
      FrmSetEventHandler(formP, InvHandleEvent);
      FrmEraseForm(formP);
      for (ret = 0 ; ret < ZAMA_ITEM_NUMBERS ; ret++) {
        if (z->user.place[ret] == 0xff) {
          FrmShowObject(formP, FrmGetObjectIndex(formP, ZAMA_INV_BASE + ret));
        } else {
          FrmHideObject(formP, FrmGetObjectIndex(formP, ZAMA_INV_BASE + ret));
        }
      }
      FrmDrawForm(formP);
      break;
    case ZAMA_CUT_FORM:
      FrmSetEventHandler(formP, CutHandleEvent);
      break;
    }
    z->user.sys.n.dlogOk = false;
    z->user.sys.n.dmesg  = 0;
    ret = FrmDoDialog(formP);
    if (z->user.sys.n.dmesg) {
      CleanMessageField();
      DrawMessage(user.sys.n.dmesg, 0, 0);
    }
    FrmDeleteForm(formP);
    if (z->_silkr) {
      if (z->_silkVer < 0x02) {
        SilkLibEnableResize(z->_silkr);
      } else {
        VskSetState(z->_silkr, vskStateEnable, 1);
      }
    }
  } while (!z->user.sys.n.dlogOk);
  if (z->user.sys.n.dmesg == 0) {
    CleanMessageField();
  }
  switch (id_) {
  case ZAMA_SEX_FORM:
    z->user.sys.n.mapID = 3; /* enter to the room */
    redraw = true;
    break;
  case ZAMA_FILE_FORM:
    if (z->user.sys.n.dret) {
      if (z->user.sys.n.cmdN == 0xf) {
        SaveGame(z->user.sys.n.dret);
      } else {
        redraw = LoadGame(z->user.sys.n.dret);
        if (redraw) {
#ifdef USE_GRAPH2
          GPaletteChange(gColorInvalid); /* initialize palette */
#else /* USE_GRAPH2 */
          ZamaPaletteChange(InvalidColor); /* initialize palette */
#endif /* USE_GRAPH2 */
        }
      }
    }
    break;
  case ZAMA_INV_FORM: /* restore message field */
#ifdef USE_GRAPH2
    if (z->tsPatch) {
      FldDrawField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
    } else {
      GFldDrawField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
    }
#else /* USE_GRAPH2 */
    ZamaFldDrawField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
#endif /* USE_GRAPH2 */
    break;
  case ZAMA_CUT_FORM: /* cut red or yellow */
    if (z->user.sys.n.dret == 0 || z->user.place[11] != 0xff) { /* fail */
      if (z->user.place[11] != 0xff) { /* no pinces */
        DrawMessage(0xe0, 0, 0);
      }
      /* color change to red */
#ifdef USE_GRAPH2
      GPaletteChange(gColorRed);
#else /* USE_GRAPH2 */
      ZamaPaletteChange(Red);
#endif /* USE_GRAPH2 */
      DrawMessage(0xc7, 0, 0);
      GameOver();
    } else {
      /* correctly choosen */
      z->user.place[11] = 0;
      z->user.sys.n.mapID = 74;
      ZamaSndPlay(3);
      redraw = true;
    }
    break;
  }
  return redraw;
}
 
static
Boolean
DarknessCheck(void)
{
  Boolean redraw = false;
  ZamaGlobalVarType *z = CreateGlobalVariables();
  if (z->user.sys.n.mapID != 84 && z->user.sys.n.mapID != 85) {
    if ((z->user.sys.n.mapID >= 47 && z->user.sys.n.mapID <= 49)||
        (z->user.sys.n.mapID >= 67 && z->user.sys.n.mapID <= 71)||
         z->user.sys.n.mapID == 61 || z->user.sys.n.mapID == 64 ||
         z->user.sys.n.mapID == 75 || z->user.sys.n.mapID == 65 ||
         z->user.sys.n.mapID == 74 || z->user.sys.n.mapID == 77) {
      if (z->user.fact[7] != 0) {
        if (z->user.fact[6] != 0) {
          /* semi-blue out */
#ifdef USE_GRAPH2
          GPaletteChange(gColorBlue);
#else /* USE_GRAPH2 */
          ZamaPaletteChange(Blue);
#endif /* USE_GRAPH2 */
        }
      } else {
        z->user.sys.n.mapW  = z->user.sys.n.mapID;
        z->user.sys.n.mapID = 84;
        redraw = true;
      }
    } else {
      if (z->user.fact[6] != 0) {
        /* normal state */
#ifdef USE_GRAPH2
        GPaletteChange(gColorInvalid);
#else /* USE_GRAPH2 */
        ZamaPaletteChange(InvalidColor);
#endif /* USE_GRAPH2 */
      }
    }
  }
  return redraw;
}
 
static
Boolean
RuleInterpreter(UInt16 cmdN_, UInt16 objN_)
{
  Boolean    res, ok, redraw;
  UInt16     i;
  RulePtr    rule;
  CmdBlkPtr  blk;
  UInt16     v1, v2;
  DmOpenRef  dbP;
  MemHandle  rec;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  res = false;
  if ((dbP = OpenDatabase("ZAMArule")) == NULL) {
    /* error */
    FrmCustomAlert(ZAMA_FATAL_ALERT, "���[��", NULL, NULL);
    return false;
  }
  if ((rec = DmQueryRecord(dbP, 0)) == NULL) {
    FrmCustomAlert(ZAMA_FATAL_ALERT, "���[��", NULL, NULL);
    goto _done;
  }
  rule = (RulePtr)MemHandleLock(rec);
 
  for (i = 0 ; rule[i]._mapId != EndOfRule ; i++) {
    if (rule[i]._mapId && rule[i]._mapId != z->user.sys.n.mapID) continue;
    if (rule[i]._cmdN  && rule[i]._cmdN  != cmdN_)            continue;
    if (rule[i]._objN  && rule[i]._objN  != objN_)            continue;
    /* check condition block */
    ok = true;
    for (blk = (CmdBlkPtr)rule[i]._args ; blk->_head._act == ActComp ; blk++) {
      v1 = getCond(blk->_head._type, blk->_head._id,
                   (blk->_body._type << 5) | blk->_body._id);
      if (blk->_head._type == TYPE_SYSTEM && blk->_head._id == 5) {
        z->user.sys.n.rand = SysRandom(0) % 256; /* update random number */
      }
      v2 = blk->_body._value;
      if (blk->_body._type && blk->_head._type != TYPE_VECTOR) {
        v2 = getCond(blk->_body._type, blk->_body._id, 0);
        if (blk->_body._type == TYPE_SYSTEM && blk->_body._id == 5) {
          z->user.sys.n.rand = SysRandom(0) % 256; /* update random number */
        }
      }
      switch (blk->_head._op) {
      case CMP_EQ: ok = ok && (v1 == v2); break;
      case CMP_NE: ok = ok && (v1 != v2); break;
      case CMP_GT: ok = ok && (v1 >  v2); break;
      case CMP_GE: ok = ok && (v1 >= v2); break;
      case CMP_LT: ok = ok && (v1 <  v2); break;
      case CMP_LE: ok = ok && (v1 <= v2); break;
      default:
        ok = false; /* no defalut operation is defined */
      }
      if (!ok) break; /* short circuit */
    }
    if (ok) break;
  }
  if (ok) {
    /* do action */
    redraw = false;
    ok  = false;
    for ( ; blk->_head._op ; blk++) {
      switch (blk->_head._op) {
      case ACT_MOVE:
        if (z->user.vector[z->user.sys.n.mapID - 1][blk->_body._value]) {
          /* moveable */
          z->user.sys.n.mapID =
            z->user.vector[z->user.sys.n.mapID - 1][blk->_body._value];
          redraw = true;
          res = true;
        } else {
          /* teacher check */
          if (z->user.fact[1] == z->user.sys.n.mapID && z->user.sys.n.rand > 85) {
            /* teacher catches you */
            DrawMessage(0xb5, 0, 0);
            /* game over */
            z->user.fact[1] = 0; /* teacher gone */
            GameOver();
            res = true;
          } else {
            /* you cannot move */
            DrawMessage(0xb6, 0, 0);
          }
          z->user.sys.n.rand = SysRandom(0) % 256;
          res = true;
        }
        break;
      case ACT_ASGN:
        v1 = (blk->_body._type << 5) | blk->_body._id;
        v2 = blk->_body._value;
        if (blk->_body._type && blk->_head._type != TYPE_VECTOR) {
          v2 = getCond(blk->_body._type, blk->_body._id, 0);
        }
        setStat(blk->_head._type, blk->_head._id, v1, v2);
        if (blk->_head._type == TYPE_PLACE || blk->_head._type == TYPE_FACT) {
          if (blk->_head._type == TYPE_PLACE) {
            if (v2 == 0xff) {
              redraw = true;
            } else {
              ObjectCheck(z->user.sys.n.mapID, true);
            }
          }
          ok = true;
        } else if(blk->_head._type == TYPE_SYSTEM) {
          if (blk->_head._id == 0) {
            redraw = true;
          } else if (blk->_head._id == 5) {
            z->user.sys.n.rand = SysRandom(0) % 256; /* update random number */
          }
        }
        res = true;
        break;
      case ACT_MESG:
        DrawMessage(blk->_body._value, 0, 0);
        res = true;
        break;
      case ACT_DLOG:
        redraw = DialogHandler(ZAMA_DIALOG_BASE + blk->_body._value);
        res = true;
        break;
      case ACT_LOOK:
        if (blk->_body._value == 0) { /* look back */
          z->user.sys.n.mapID = z->user.sys.n.mapW;
          z->user.sys.n.mapW  = 0;
        } else {
          z->user.sys.n.mapW  = z->user.sys.n.mapID;
          z->user.sys.n.mapID = blk->_body._value;
        }
        redraw = true;
        res = true;
        break;
      case ACT_SND:
        ZamaSndPlay(blk->_body._value);
        break;
      case ACT_OVER:
        ok = false;
        switch(blk->_body._value) {
        case 0: /* simply put dialog */
          z->user.fact[1] = 0; /* teacher gone */
          PutMessageToField("�f�������n������", 16);
          break;
        case 1: /* screen to red */
          PutMessageToField("�f�������n������", 16);
#ifdef USE_GRAPH2
          GPaletteChange(gColorRed);
#else /* USE_GRAPH2 */
          ZamaPaletteChange(Red);
#endif /* USE_GRAPH2 */
          break;
        case 2: /* game clear */
          PutMessageToField("�e����������", 12);
#ifdef USE_GRAPH2
          GPaletteChange(gColorInvalid);
#else /* USE_GRAPH2 */
          ZamaPaletteChange(InvalidColor);
#endif /* USE_GRAPH2 */
          FrmHelp(ZAMA_CREDIT_STR); /* put credit */
          break;
        }
        GameOver();
        res = true;
        break;
      default:
        /* error */
        res = false;
        break;
      }
    }
    if (ok) {
      PutMessageToField("�n.�j.", 6);
    }
    if (z->user.sys.n.mapID == 74) {
      switch (++z->user.fact[13]) {
      case 4:   DrawMessage(0xe2, 0, 0); break;
      case 6:   DrawMessage(0xe3, 0, 0); break;
      case 10:  DrawMessage(0xe4, 0, 0); break;
      default:  break;
      }
    }
    redraw = DarknessCheck() || redraw;
    if (redraw) {
      LoadMapData(z->user.sys.n.mapID);
      DrawMap(true);
      ObjectCheck(z->user.sys.n.mapID, true);
    }
  }
  MemHandleUnlock(rec);
 _done:;
  DmCloseDatabase(dbP);
  return res;
}
 
static
Boolean
CommandLoop(void)
{
  MemHandle     hStr;
  Char         *strP;
  UInt16        end, rd;
  FieldPtr      fldP;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((hStr = FldGetTextHandle(GetObjectPtr(ZAMA_COMMAND_FIELD))) == NULL) {
    /* fail to get string */
    return false;
  }
  strP = (Char*)MemHandleLock(hStr);
  end  = StrLen(strP);
  VOSplit(strP);
  CleanMessageField();
 
  z->user.sys.n.cmdN = SearchWord(z->cmd, true);
  z->user.sys.n.objN = SearchWord(z->obj, false);
  z->user.sys.n.rand = SysRandom(0) % 256;
 
  /* status check */
  if (z->user.fact[5] == 2) {
    z->user.vector[ 9 - 1][6] = 4;
    z->user.vector[10 - 1][6] = 19;
    z->user.vector[11 - 1][6] = 6;
    z->user.vector[14 - 1][6] = 7;
    z->user.vector[16 - 1][6] = 17;
    z->user.vector[24 - 1][6] = 8;
    z->user.vector[25 - 1][6] = 20;
    z->user.vector[26 - 1][6] = 22;
    z->user.vector[28 - 1][6] = 21;
    z->user.vector[30 - 1][6] = 5;
    z->user.vector[37 - 1][6] = 32;
    z->user.vector[38 - 1][6] = 33;
    z->user.vector[39 - 1][6] = 34;
    z->user.vector[40 - 1][6] = 31;
    z->user.vector[42 - 1][6] = 35;
    z->user.vector[44 - 1][6] = 36;
    z->user.fact[5] = 1;
  }
  if (z->user.fact[3] > 0 && z->user.fact[7] == 1) { /* light on */
    --z->user.fact[3]; /* battery */
    if (z->user.fact[3] < 8 && z->user.fact[3] > 0) {
      z->user.fact[6] = 1;
      DrawMessage(0xd9, 0, 0);
    }
    if (z->user.fact[3] == 0) { /* battery wear out */
      z->user.fact[7] = 0;
      DrawMessage(0xc0, 0, 0);
    }
  }
  if (z->user.fact[11] > 0) { /* count down */
    --z->user.fact[11];
    if (z->user.fact[11] == 0) {
      ZamaSndPlay(2);
      DrawMessage(0xd8, 0, 0);
      if (z->user.place[7] == 48) {
        z->user.vector[75 - 1][0] = 77;
        z->user.vector[68 - 1][2] = 77;
        DrawMessage(0xda, 0, 0);
      }
      if (z->user.place[7] == 255 || z->user.place[7] == z->user.sys.n.mapID) {
        /* explosion within the room where you are */
        /* change screen to red */
#ifdef USE_GRAPH2
        GPaletteChange(gColorRed);
#else /* USE_GRAPH2 */
        ZamaPaletteChange(Red);
#endif /* USE_GRAPH2 */
        DrawMessage(0xcf, 0, 0);
        DrawMessage(0xcb, 0, 0);
        /* game over */
        GameOver();
        goto _done;
      } else {
        z->user.place[7] = 0; /* explosion ... lose bomber */
      }
    }
  }
 
  if (z->user.sys.n.cmdN == ZAMA_CMD_INVALID || z->user.sys.n.cmdN >= ZAMA_CMD_END) {
    DrawMessage(0xaf + z->user.sys.n.rand % 5, 0, 0);
    goto _done;
  }
  if (! RuleInterpreter(z->user.sys.n.cmdN, z->user.sys.n.objN)) {
    DrawMessage(0, z->user.sys.n.cmdN, z->user.sys.n.objN);
  }
 
  /* teacher check */
  if (!z->_over) {
    rd = 100 + z->user.sys.n.mapID + ((z->user.fact[1] > 0) ? 1000 : 0);
    if (rd < SysRandom(0) % 3000) {
      if (z->user.fact[1] == z->user.sys.n.mapID) {
        DrawMap(false); /* erase teacher */
      }
      z->user.fact[1] = 0;
    } else {
      z->user.fact[1] = z->user.sys.n.mapID; /* appear teacher */
    }
  }
  if ((z->user.sys.n.mapID >= 50 && z->user.sys.n.mapID <= 53) ||
      (z->user.sys.n.mapID >= 64 && z->user.sys.n.mapID <= 77) ||
       z->user.sys.n.mapID == 83 || z->user.sys.n.mapID == 48 ||
       z->user.sys.n.mapID == 61 || z->user.sys.n.mapID == 1 ||
       z->user.sys.n.mapID == 86) {
    z->user.fact[1] = 0;
  }
  if (z->user.fact[1] == z->user.sys.n.mapID) {
    DrawTeacher();
    ZamaSndPlay(6);
    DrawMessage(0xb4, 0, 0);
  }
 _done:;
  MemHandleUnlock(hStr);
  fldP = GetObjectPtr(ZAMA_COMMAND_FIELD);
  FldDelete(fldP, 0, end);
  FldDrawField(fldP);
  return true;
}
 
static
Boolean
MainMenuEvent(EventPtr eventP)
{
  Boolean       handled = false;
  FormPtr       dlogP;
  FontID        id;
  UInt16        lines, plane, sound;
  Coord         x, y;
  FieldPtr      fldP;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  fldP = GetObjectPtr(ZAMA_COMMAND_FIELD);
  switch (eventP->data.menu.itemID) {
  case ZAMA_FONT_MENU:
    /* menu select */
#ifdef USE_GRAPH2
    id = ZamaFontSelect(prefs._curFont);
#else /* USE_GRAPH2 */
    id = ZamaFontSelect(prefs._curFont);
#endif /* USE_GRAPH2 */
    if (z->prefs._curFont != id) {
      z->prefs._curFont = id;
      fldP = GetObjectPtr(ZAMA_MESSAGE_FIELD);
      FldSetFont(fldP, id);
#ifdef USE_GRAPH2
      if (tsPatch) {
        FldDrawField(fldP);
      } else {
        GFldDrawField(fldP);
      }
#else /* USE_GRAPH2 */
      ZamaFldDrawField(fldP);
#endif /* USE_GRAPH2 */
      UpdateMessageFieldScrollbar();
    }
    handled = true;
    break;
  case ZAMA_PREF_MENU:
    /* pop-up prefs dialog */
    dlogP = FrmInitForm(ZAMA_PREF_FORM);
    lines = FrmGetObjectIndex(dlogP, ZAMA_DRAW_LINE);
    plane = FrmGetObjectIndex(dlogP, ZAMA_DRAW_PLANE);
    /* sound */
    sound = FrmGetObjectIndex(dlogP, ZAMA_SND_SWITCH);
    if (z->_silkr){
      WinGetDisplayExtent(&x, &y);
      if (y > 160) {
        RectangleType bounds;
        WinHandle     hWin;
        hWin = FrmGetWindowHandle(dlogP);
        WinGetBounds(hWin, &bounds);
        bounds.topLeft.y += stdSilkHeight;
        WinSetBounds(hWin, &bounds);
      }
    }
#ifndef USE_GRAPH2
    if (!ZamaHR()) {
      /* not support line draw mode */
      CtlSetUsable(FrmGetObjectPtr(dlogP, lines), false);
      z->prefs._linedraw = false;
    }
#endif /* USE_GRAPH2 */
    CtlSetValue(FrmGetObjectPtr(dlogP, lines), z->prefs._linedraw);
    CtlSetValue(FrmGetObjectPtr(dlogP, plane), !z->prefs._linedraw);
    CtlSetValue(FrmGetObjectPtr(dlogP, sound), z->prefs._sound);
    if (FrmDoDialog(dlogP) == ZAMA_BUTTON_OK) {
      /* change status */
#ifndef USE_GRAPH2
      if (ZamaHR()) {
#endif /* USE_GRAPH2 */
        z->prefs._linedraw =
            (FrmGetControlGroupSelection(dlogP, ZAMA_DRAW_STYLE) == lines);
#ifndef USE_GRAPH2
      }
#endif /* USE_GRAPH2 */
      z->prefs._sound = CtlGetValue(FrmGetObjectPtr(dlogP, sound));
    }
    FrmDeleteForm(dlogP);
    handled = true;
    break;
  case ZAMA_HELP_CMD:
    FrmHelp(ZAMA_HELP_STR);
    break;
  case ZAMA_ABOUT_CMD:
    dlogP = FrmInitForm(ZAMA_FRM_ABOUT);
    FrmDoDialog(dlogP);
    FrmDeleteForm(dlogP);
    break;
  }
  return handled;
}
 
static
Boolean
MainHeightChanged(EventPtr eventP)
{
  RectangleType bounds;
  FormPtr       formP;
  WinHandle     hWin;
  Int16         dy;
  Coord         nx, ny;
  UInt16        i, idx;
  FieldPtr      fldP;
  Boolean       res = true;
  UInt16        objs[] = {
    ZAMA_COMMAND_LABEL,
    ZAMA_BUTTON_START,
    ZAMA_CONTINUE,
    0
  };
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  formP = FrmGetActiveForm();
  hWin  = FrmGetWindowHandle(formP);
  WinGetBounds(hWin, &bounds);
  WinGetDisplayExtent(&nx, &ny);
  if (ny == bounds.topLeft.y + bounds.extent.y) {
    /* size has not changed */
    return res;
  }
  bounds.extent.y = ny - bounds.topLeft.y;
  bounds.extent.x = nx - bounds.topLeft.x;
  FrmEraseForm(formP);
  WinSetBounds(hWin, &bounds);
  /* relocate object */
  dy = (ny == 160) ? -stdSilkHeight : stdSilkHeight;
  /* GSI */
  for (i = 0 ; i < FrmGetNumberOfObjects(formP) ; i++) {
    if (FrmGetObjectType(formP, i) == frmGraffitiStateObj) {
      /* found GSI */
      FrmGetObjectPosition(formP, i, &nx, &ny);
      ny += dy;
      FrmSetObjectPosition(formP, i, nx, ny);
      break; /* needless to search any more */
    }
  }
  for (i = 0 ; objs[i] ; i++) {
    idx = FrmGetObjectIndex(formP, objs[i]);
    FrmGetObjectBounds(formP, idx, &bounds);
    bounds.topLeft.y += dy;
    FrmSetObjectBounds(formP, idx, &bounds);
  }
  /* move command field */
  fldP = FrmGetObjectPtr(formP, FrmGetObjectIndex(formP, ZAMA_COMMAND_FIELD));
  FldGetBounds(fldP, &bounds);
  bounds.topLeft.y += dy;
  FldSetBounds(fldP, &bounds);
  FrmSetFocus(formP, FrmGetObjectIndex(formP, ZAMA_COMMAND_FIELD));
  FldDrawField(fldP);
  /* extent message field */
  fldP = FrmGetObjectPtr(formP, FrmGetObjectIndex(formP, ZAMA_MESSAGE_FIELD));
  FldGetBounds(fldP, &bounds);
  bounds.extent.y += dy * 2;
  FldSetBounds(fldP, &bounds);
  /* update scrollbar */
  idx = FrmGetObjectIndex(formP, ZAMA_SCROLL_BAR);
  FrmGetObjectBounds(formP, idx, &bounds);
  bounds.extent.y += dy;
  FrmSetObjectBounds(formP, idx, &bounds);
  /* update */
  UpdateMessageFieldScrollbar();
  FrmDrawForm(formP);
#ifdef USE_GRAPH2
  if (tsPatch) {
    FldDrawField(fldP);
  } else {
    GFldDrawField(fldP);
  }
#else /* USE_GRAPH2 */
  ZamaFldDrawField(fldP);
#endif /* USE_GRAPH2 */
  DrawMap(false);
  ObjectCheck(z->user.sys.n.mapID, false);
 
  return res;
}
 
static
Boolean
MainHandleEvent(EventPtr eventP)
{
  Boolean       handled = false;
  FormPtr       formP;
  FieldPtr      fldP;
  ControlPtr    btnP, chkP;
  UInt16        lines;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  formP = FrmGetActiveForm();
  /* resize check */
  if (z->_silkr && z->_resized && MainHeightChanged(eventP)) {
    z->_resized = false;
  }
  if (eventP->eType == frmOpenEvent) {
    GameInit();
    handled = true;
  } else if (eventP->eType == frmUpdateEvent) {
    FrmDrawForm(formP);
#ifdef USE_GRAPH2
    if (z->tsPatch) {
      FldDrawField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
    } else {
      GFldDrawField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
    }
#else /* USE_GRAPH2 */
    ZamaFldDrawField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
#endif /* USE_GRAPH2 */
    DrawMap(false); /* maybe re-draw map */
    ObjectCheck(z->user.sys.n.mapID, true);
    FrmSetFocus(formP, FrmGetObjectIndex(formP, ZAMA_COMMAND_FIELD));
    handled = true;
  } else if (eventP->eType == ctlSelectEvent) {
    switch (eventP->data.ctlSelect.controlID) {
    case ZAMA_BUTTON_START:
      /* enable command field and disable start button */
      btnP = GetObjectPtr(ZAMA_BUTTON_START);
      fldP = GetObjectPtr(ZAMA_COMMAND_FIELD);
      chkP = GetObjectPtr(ZAMA_CONTINUE);
      FrmEraseForm(formP);
      CleanMessageField();
      CtlSetUsable(btnP, false);
      CtlSetUsable(chkP, false);
      FldSetUsable(fldP, true);
      /* init game */
#ifdef USE_GRAPH2
      GPaletteChange(gColorInvalid); /* initialize palette */
#else /* USE_GRAPH2 */
      ZamaPaletteChange(InvalidColor); /* initialize palette */
#endif /* USE_GRAPH2 */
      if (CtlGetValue(chkP)) { /* load */
        LoadGame(0);
        DarknessCheck();    /* need to check of darkness */
      } else {
        LoadInitData();
        z->user.sys.n.mapID = 1; /* set map to start point */
        SaveGame(0);        /* clear suspended data */
      }
      z->_over = false; /* start game */
      FldDrawField(fldP);
      FrmDrawForm(formP);
      FrmSetFocus(formP, FrmGetObjectIndex(formP, ZAMA_COMMAND_FIELD));
      CleanMessageField();
      LoadMapData(z->user.sys.n.mapID);
      DrawMap(true);
      ObjectCheck(z->user.sys.n.mapID, true);
      if (z->user.fact[1] == z->user.sys.n.mapID) { /* teacher check */
        DrawTeacher();
        DrawMessage(0xb4, 0, 0);
      }
      z->prefs._suspended = true; /* continuable */
      handled = true;
      break;
    }
  } else if (eventP->eType == keyDownEvent) {
    fldP  = GetObjectPtr(ZAMA_MESSAGE_FIELD);
    lines = FldGetVisibleLines(fldP) - 1;
    switch (eventP->data.keyDown.chr) {
    case pageUpChr:
      if (FldScrollable(fldP, winUp)) {
        FldScrollField(fldP, lines, winUp);
        UpdateMessageFieldScrollbar();
      }
      handled = true;
      break;
    case pageDownChr:
      if (FldScrollable(fldP, winDown)) {
        FldScrollField(fldP, lines, winDown);
        UpdateMessageFieldScrollbar();
      }
      handled = true;
      break;
    }
  } else if (eventP->eType == fldChangedEvent) {
    /* update scrollbar */
    if (eventP->data.fldChanged.fieldID == ZAMA_MESSAGE_FIELD) {
      UpdateMessageFieldScrollbar();
      handled = true;
    }
  } else if (eventP->eType == sclRepeatEvent || eventP->eType == sclExitEvent){
    ScrollMessageField();
    handled = true;
  } else if (eventP->eType == menuOpenEvent) {
    handled = true;
  } else if (eventP->eType == menuEvent) {
    handled = MainMenuEvent(eventP);
  } else if (eventP->eType == appStopEvent) {
    FrmEraseForm(formP);
    FrmDeleteForm(formP);
    handled = true;
  }
  return handled;
}
 
static
Boolean
SexHandleEvent(EventPtr eventP)
{
  UInt16  sid;
  Boolean handled = false;
  FormPtr formP   = FrmGetActiveForm();
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if (eventP->eType == ctlSelectEvent) {
    switch (eventP->data.ctlSelect.controlID) {
    case ZAMA_BUTTON_OK:
      sid = FrmGetControlGroupSelection(formP, ZAMA_SEX_GROUP);
      if (sid == FrmGetObjectIndex(formP, ZAMA_SEX_BOY)) {
        z->user.sys.n.dret   = z->user.fact[0] = 1;
        z->user.sys.n.dlogOk = true;
        z->user.sys.n.dmesg  = 0;
      } else if (sid == FrmGetObjectIndex(formP, ZAMA_SEX_GIRL)) {
        z->user.sys.n.dret   = z->user.fact[0] = 2;
        z->user.sys.n.dlogOk = true;
        z->user.sys.n.dmesg = 0;
      } else {
        z->user.sys.n.dret   = 0;
        z->user.sys.n.dlogOk = false;
        z->user.sys.n.dmesg  = 0xbc;
      }
      break;
    }
  }
  return handled;
}
 
static
Boolean
FileHandleEvent(EventPtr eventP)
{
  Boolean handled = false;
  UInt16  fid;
  FormPtr formP = FrmGetActiveForm();
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if (eventP->eType == ctlSelectEvent) {
    switch (eventP->data.ctlSelect.controlID) {
    case ZAMA_BUTTON_OK:
      fid = FrmGetControlGroupSelection(formP, ZAMA_FILE_GROUP);
      if (fid == FrmGetObjectIndex(formP, ZAMA_FILE_ID1)) {
        z->user.sys.n.dret = 1;
      } else if (fid == FrmGetObjectIndex(formP, ZAMA_FILE_ID2)) {
        z->user.sys.n.dret = 2;
      } else if (fid == FrmGetObjectIndex(formP, ZAMA_FILE_ID3)) {
        z->user.sys.n.dret = 3;
      } else {
        z->user.sys.n.dret = 0;
      }
      z->user.sys.n.dlogOk = true;
      break;
    }
  }
  return handled;
}
 
static
Boolean
InvHandleEvent(EventPtr eventP)
{
  Boolean handled = false;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if (eventP->eType == ctlSelectEvent) {
    switch (eventP->data.ctlSelect.controlID) {
    case ZAMA_BUTTON_OK:
      z->user.sys.n.dlogOk = true;
      break;
    }
  }
  return handled;
}
 
static
Boolean
CutHandleEvent(EventPtr eventP)
{
  UInt16  color;
  Boolean handled = false;
  FormPtr formP = FrmGetActiveForm();
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if (eventP->eType == ctlSelectEvent) {
    switch (eventP->data.ctlSelect.controlID) {
    case ZAMA_BUTTON_OK:
      z->user.sys.n.dlogOk = true; /* no time kidding */
      color = FrmGetControlGroupSelection(formP, ZAMA_CUT_GROUP);
      if (color == FrmGetObjectIndex(formP, ZAMA_CUT_RED)) {
        z->user.sys.n.dret = 1;
      } else {
        z->user.sys.n.dret = 0;
      }
      break;
    }
  }
  return handled;
}
 
static
Boolean
MainKeyHandleEvent(EventPtr eventP, UInt32 keys)
{
  Boolean handled = false;
  EventType event;
 
  if (FrmGetWindowHandle(FrmGetActiveForm()) != WinGetActiveWindow()) {
    /* maybe menu or another widget popping up */
    return false;
  }
 
  if (eventP->eType == nilEvent) { /* Game PAD */
    if (keys & (keyBitPageUp | keyBitPageDown | keyBitHard1 | keyBitHard2)) {
      /* move direction */
      char *dir = NULL;
      if (keys & keyBitPageUp) {
        dir = "n";
      } else if (keys & keyBitPageDown) {
        dir = "s";
      } else if (keys & keyBitHard1) {
        dir = "w";
      } else if (keys & keyBitHard2) {
        dir = "e";
      }
      if (dir) {
        FldInsert(GetObjectPtr(ZAMA_COMMAND_FIELD), dir, StrLen(dir));
        event.eType = keyDownEvent;
        event.data.keyDown.chr = chrLineFeed;
        EvtAddEventToQueue(&event);
        handled = true;
      }
    }
  }
 
  return handled;
}
 
static
Boolean
KeyHandleEvent(EventPtr eventP)
{
  UInt32       keys;
  Boolean      handled = false;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((keys = KeyCurrentState()) == 0) { /* no key has been pressed */
    return false;
  }
  switch (FrmGetActiveFormID()) {
  case ZAMA_MAIN_FORM:
    handled = MainKeyHandleEvent(eventP, keys);
    break;
  default:
    handled = false;
    break;
  }
  if (!handled) {
    EventType event;
    MemSet(&event, 0, sizeof(EventType));
    if (eventP->eType == nilEvent && keys & (keyBitHard3 | keyBitHard4)) {
      event.eType = keyDownEvent;
      event.data.keyDown.chr =(keys & keyBitHard3) ? vchrJogPush : vchrJogBack;
      EvtAddEventToQueue(&event);
      handled = true;
    } else if (eventP->eType == nilEvent &&
               keys & (keyBitPageUp | keyBitPageDown)) {
      event.eType = keyDownEvent;
      event.data.keyDown.chr = (keys & keyBitPageUp) ? vchrJogUp : vchrJogDown;
      EvtAddEventToQueue(&event);
      handled = true;
    }
  }
  z->_ignoreKey = handled;
  return handled;
}
 
static
Boolean
AppHandleEvent(EventPtr eventP)
{
  UInt16  formId;
  FormPtr formP;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  Boolean handled = false;
  if (eventP->eType == frmLoadEvent) {
    formId = eventP->data.frmLoad.formID;
    formP  = FrmInitForm(formId);
    FrmSetActiveForm(formP);
    FldSetFont(GetObjectPtr(ZAMA_MESSAGE_FIELD), z->prefs._curFont);
    switch (formId) {
    case ZAMA_MAIN_FORM:
      FrmSetEventHandler(formP, MainHandleEvent);
#ifdef USE_GRAPH2
      if (!tsPatch) {
        GFldModifyField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
      }
#else /* USE_GRAPH2 */
      ZamaFldModifyField(GetObjectPtr(ZAMA_MESSAGE_FIELD));
#endif /* USE_GRAPH2 */
      handled = true;
      break;
    default:
      break;
    }
  }
  return handled;
}
 
void
EventLoop(void)
{
  EventType event;
  UInt16    err;
  UInt16    formID;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  z->_ignoreKey = false;
  do {
    formID = FrmGetActiveFormID();
    EvtGetEvent(&event, evtWaitForever);
    if (!z->_ignoreKey && KeyHandleEvent(&event)) {
      continue;
    }
    z->_ignoreKey = false;
    if (event.eType == keyDownEvent && event.data.keyDown.chr == chrLineFeed) {
      /* accept command */
      if (formID == ZAMA_MAIN_FORM) {
        CommandLoop();
        continue;
      }
    }
    //    if (_silkr && event.eType == menuEvent) SilkLibDisableResize(_silkr);
    if (!SysHandleEvent(&event)) {
      if (!MenuHandleEvent(NULL, &event, &err)) {
#if 0
        if (event.eType == menuCmdBarOpenEvent) {
          /* command stroke */
          event.data.menuCmdBarOpen.preventFieldButtons = true;
        }
#endif
        if(!AppHandleEvent(&event)) {
          if (z->_silkr) {
            if (z->_silkVer < 0x02) {
              SilkLibDisableResize(z->_silkr);
            } else {
              VskSetState(z->_silkr, vskStateEnable, 0);
            }
          }
          FrmDispatchEvent(&event);
          if (z->_silkr) {
            if (z->_silkVer < 0x02) {
              SilkLibEnableResize(z->_silkr);
            } else {
              VskSetState(z->_silkr, vskStateEnable, 1);
            }
          }
        }
      }
    }
    //    if (_silkr) SilkLibEnableResize(_silkr);
  } while (event.eType != appStopEvent);
}
/* notification & silk */
static
Err
SilkHeightChange(SysNotifyParamType *paramP_)
{
  FormPtr       formP, afrmP;
  Coord         nx, ny;
  RectangleType bounds;
  Boolean      *resized;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  afrmP = FrmGetActiveForm();
  formP = FrmGetFormPtr(ZAMA_MAIN_FORM);
  WinGetBounds(FrmGetWindowHandle(formP), &bounds);
  WinGetDisplayExtent(&nx, &ny);
  if (afrmP != formP || ny == bounds.topLeft.y + bounds.extent.y) {
    /* works only for display hight change */
    if (paramP_) paramP_->handled = false;
    return errNone;
  }
  z->_resized = true; /* notify size has changed */
  GrfCleanState();
  GrfInitState();
  GsiInitialize();
  GsiSetShiftState(0, gsiShiftNone);
  if (paramP_) {
    resized = paramP_->userDataP;
    if (resized) *resized = true;
  }
  if (paramP_) paramP_->handled = true;
  return errNone;
}
 
static
Boolean
SilkStart(void)
{
  Err                err;
  LocalID            codeResId;
  SonySysFtrSysInfoP sonySysFtrSysInfoP;
  UInt16             cardNo;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  z->_silkr = 0;
  if ((err = FtrGet(sonySysFtrCreator,
                    sonySysFtrNumSysInfoP,
                    (UInt32*)&sonySysFtrSysInfoP))) {
    return false;
  }
  if ((sonySysFtrSysInfoP->extn & sonySysFtrSysInfoExtnSilk) &&
      (sonySysFtrSysInfoP->libr & sonySysFtrSysInfoLibrSilk)) {
    if ((err = SysLibFind(sonySysLibNameSilk, &z->_silkr))) {
      if (err == sysErrLibNotFound) {
        err = SysLibLoad('libr', sonySysFileCSilkLib, &z->_silkr);
      }
    }
  }
  z->_resized = false;
  if (err || z->_silkr == 0) {
    z->_silkr = 0;
    return false;
  }
  if (SilkLibOpen(z->_silkr) == errNone) {
    if ((z->_silkVer = VskGetAPIVersion(z->_silkr)) < 0x02) {
      SilkLibEnableResize(z->_silkr);
    } else {
      VskSetState(z->_silkr, vskStateEnable, 1);
      VskSetState(z->_silkr, vskStateResize, vskResizeMax);
    }
  }
 
  if ((err = SysCurAppDatabase(&cardNo, &codeResId)) != errNone) {
    return false;
  }
  err = SysNotifyRegister(cardNo, codeResId, sysNotifyDisplayChangeEvent,
                          SilkHeightChange,
                          sysNotifyNormalPriority,
                          &z->_resized);
  return err == errNone;
}
 
static
Boolean
SilkStop(void)
{
  Err     err;
  LocalID codeResId;
  UInt16  cardNo;
  Boolean res = true;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  if ((err = SysCurAppDatabase(&cardNo, &codeResId)) != errNone) {
    res = false;
  }
  if (res) {
    err = SysNotifyUnregister(cardNo, codeResId, sysNotifyDisplayChangeEvent,
                              sysNotifyNormalPriority);
  }
  if (z->_silkr) {
    if (z->_silkVer < 0x02) {
      SilkLibResizeDispWin(z->_silkr, silkResizeNormal);
      SilkLibDisableResize(z->_silkr);
    } else {
      VskSetState(z->_silkr, vskStateResize, vskResizeMax);
      VskSetState(z->_silkr, vskStateEnable, 0);
    }
    SilkLibClose(z->_silkr);
  }
  return res && err == errNone;
}
 
static
void
ZamaMapInit(void)
{
  ZamaGlobalVarType *z = CreateGlobalVariables();
  MemSet(z->map.graphic,  sizeof(z->map.graphic),  0xff);
  MemSet(z->map.reaction, sizeof(z->map.reaction), 0);
  MemSet(z->map.mesg,     sizeof(z->map.mesg),     0);
}
 
static
Boolean
InitTsPatch(void)
{
  UInt32  ver;
  Boolean ok = false;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
  z->tinyFontID = stdFont;
  z->tinyBoldFontID = boldFont;
  z->smallFontID = largeFont;
  z->smallSymbolFontID = symbolFont;
  z->smallSymbol11FontID = symbol11Font;
  z->smallSymbol7FontID = symbol7Font;
  z->smallLedFontID = ledFont;
  z->smallBoldFontID = largeBoldFont;
 
  if (FtrGet(SmallFontAppCreator, SMF_FTR_SMALL_FONT_SUPPORT, &ver) == errNone) {
    FtrGet(SmallFontAppCreator, SMF_FTR_TINY_FONT, &z->tinyFontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_TINY_BOLD_FONT, &z->tinyBoldFontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_SMALL_FONT, &z->smallFontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_SYMBOL_FONT, &z->smallSymbolFontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_SYMBOL11_FONT, &z->smallSymbol11FontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_SYMBOL7_FONT, &z->smallSymbol7FontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_LED_FONT, &z->smallLedFontID);
    FtrGet(SmallFontAppCreator, SMF_FTR_SMALL_BOLD_FONT, &z->smallBoldFontID);
    ok = true;
  }
  return ok;
}
 
static
Boolean
StartApplication(void)
{
  UInt16  size, ver;
  Boolean res = false;
  ZamaGlobalVarType *z = CreateGlobalVariables();
 
#ifdef USE_GRAPH2
  if (!GInit()) {
    return false;
  }
#else /* USE_GRAPH2 */
  if (!ZamaGraphInit()) {
    return false;
  }
#endif /* USE_GRAPH2 */
  res = true;
  RctSetRectangle(&z->pict, 32, 32, 256, 152);
  LoadInitData();
  size = sizeof(ZamaPrefsType);
  MemSet(&z->prefs, size, 0);
  z->prefs._linedraw = true;
  FtrGet(sysFtrCreator, sysFtrDefaultFont, (UInt32*)&z->prefs._curFont);
#ifndef USE_GRAPH2
  if (ZamaHR()) {
    z->prefs._curFont += hrStdFont;
  }
#endif /* USE_GRAPH2 */
  ZamaMapInit();
  ver = PrefGetAppPreferences(ZAMA_CREATOR_ID,
                              ZAMA_PREFS_ID,
                              &z->prefs, &size, true);
  if (ver != ZAMA_PREFS_VER) {
    /* upgrade ? */
  }
  SilkStart();
  z->tsPatch = InitTsPatch();
  return res;
}
 
static
Boolean
StopApplication(void)
{
  ZamaGlobalVarType *z = GetGlobalVariables();
#ifdef USE_GRAPH2
  GFinalize();
#else /* USE_GRAPH2 */
  ZamaGraphClean();
#endif /* USE_GRAPH2 */
  if (z->user.sys.n.mapID != 76) { /* not opening/clear screen */
    SaveGame(0);
  }
  PrefSetAppPreferences(ZAMA_CREATOR_ID,
                        ZAMA_PREFS_ID,
                        ZAMA_PREFS_VER,
                        &z->prefs,
                        sizeof(ZamaPrefsType), true);
  SilkStop();
  DeleteGlobalVariables();
  return true;
}
 
static void
ZamaSearchDrawName(const Char *strP_, Coord x_, Coord y_, UInt16 width_)
{
  Char *ptr = StrChr(strP_, linefeedChr);
  UInt16 titleLen = (ptr == NULL) ? StrLen(strP_) : (UInt16)(ptr - strP_);
  if (FntWidthToOffset(strP_, titleLen, width_, NULL, NULL) == titleLen) {
    WinDrawChars(strP_, titleLen, x_, y_);
  } else {
    Int16 titleWidth;
    titleLen = FntWidthToOffset(strP_, titleLen,
                                width_ - FntCharWidth(chrEllipsis),
                                NULL, &titleWidth);
    WinDrawChars(strP_, titleLen, x_, y_);
    WinDrawChar (chrEllipsis, x_ + titleWidth, y_);
  }
}
 
static void
ZamaSearch(FindParamsPtr findParams)
{
  MemHandle     recH;
  Char          *headerP;
  Boolean       done, match;
  RectangleType r;
  UInt16        pos, matchLength;
  UInt32        longPos;
 
  recH = DmGetResource(strRsc, ZAMA_SEARCH_HEADER);
  headerP = MemHandleLock(recH);
  done = FindDrawHeader(findParams, headerP);
  MemHandleUnlock(recH);
  DmReleaseResource(recH);
  if (done) return;
  findParams->more = false;
  if (findParams->recordNum == ZAMA_CODE_ISAKO && EvtSysEventAvail(true)) {
    findParams->more = true;
    return;
  }
  match = TxtFindString("������",
                        findParams->strToFind,
                        &longPos, &matchLength);
  pos = longPos;
  if (match) {
    done = FindSaveMatch(findParams, ZAMA_CODE_ISAKO,
                         pos, 0, matchLength, 0, 0);
    if (!done) {
      FindGetLineBounds(findParams, &r);
      ZamaSearchDrawName("������",
                         r.topLeft.x + 1, r.topLeft.y, r.extent.x - 2);
      ++findParams->lineNumber;
    }
  }
}
 
UInt32
PilotMain(UInt16 cmd, void *cmdPBP, UInt16 launchFlags)
{
  if (cmd == sysAppLaunchCmdNormalLaunch || cmd == sysAppLaunchCmdGoTo) {
    _startup = 0;
    if (cmd == sysAppLaunchCmdGoTo) {
      _startup = ((GoToParamsPtr)cmdPBP)->recordNum;
    }
    if (StartApplication()) {
      FrmGotoForm(ZAMA_MAIN_FORM);
      EventLoop();
      FrmCloseAllForms();
      StopApplication();
    }
  } else if (cmd == sysAppLaunchCmdFind) {
    ZamaSearch((FindParamsPtr)cmdPBP);
  } else if (cmd == sysAppLaunchCmdNotify) {
    SilkHeightChange(cmdPBP);
  }
  return 0;
}
graph2.c
/*
 * Graphics routine for High-High-School Adventure.
 *  Copyright(c)2003 ZOBplus hiro
 */
 
#include <PalmOS.h>
#include <SonyCLIE.h>
#include "high.h"
#include "graph2.h"
#include "glue.h"
 
#define MAX_QUEUE_SIZE (1024)
typedef struct {
  int       _Qstart, _Qend;
  PointType _Queue[MAX_QUEUE_SIZE];
} GPointQueueType;
typedef GPointQueueType *GPointQueuePtr;
 
/* global variables */
 
typedef struct {
  GPointQueueType  _pointQ;
  Boolean          _hDensity; /* OS5 high-density */
  UInt16           _hrLib;    /* OS4 CLIe High-Resolution */
  UInt16           _hrVer;    /* CLIe High-Resolution API Version */
  IndexedColorType _colors[gColorNameCandidate]; /* color map */
  RGBColorType     _defrgb[gColorNameCandidate]; /* dafault map */
  WinHandle        _canvas;   /* offscreen window */
  BitmapPtr        _bmpP;     /* canvas bitmap */
  UInt8            *_baseP;   /* canvas bitmap body */
  UInt16           _rowBytes; /* row bytes */
  RectangleType    _border;   /* canvas border */
  UInt32           _width, _height, _depth; /* properties */
  FontID           _fntTable[8]; /* for CLIe High Resolution Fonts */
} GraphGlobalVarType;
 
static
GraphGlobalVarType *
CreateGlobalVariables()
{
  GraphGlobalVarType *ptr = NULL;
  Err err;
  if ((err = FtrPtrNew(ZAMA_CREATOR_ID, ZAMA_GRAPH_VAR, sizeof(GraphGlobalVarType), &ptr)) != errNone)
  {
    return NULL;
  }
  return ptr;
}
 
static
void
DeleteGlobalVariables()
{
  FtrPtrFree(ZAMA_CREATOR_ID, ZAMA_GRAPH_VAR);
}
 
static
GraphGlobalVarType *
GetGlobalVariables()
{
  GraphGlobalVarType *ptr;
  Err err;
  if ((err = FtrGet(ZAMA_CREATOR_ID, ZAMA_GRAPH_VAR, &ptr)) != errNone)
  {
    return NULL;
  }
  return ptr;
}
 
static void
HDWinDrawChars(Char *strP_, UInt16 len_, Coord x_, Coord y_)
{
  WinHandle     curH, offH;
  BitmapPtr     bmpP;
  BitmapPtrV3   bmp3P;
  RectangleType r;
  Coord         w, h;
  Err           err;
  UInt16        coordSys;
 
  curH = WinGetDrawWindow();
  coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  w = FntCharsWidth(strP_, len_);
  h = FntCharHeight();
  bmpP  = BmpCreate(w, h, 8, NULL, &err);
  bmp3P = BmpCreateBitmapV3(bmpP, kCoordinatesStandard,
                            BmpGetBits(bmpP), NULL);
  offH  = WinCreateBitmapWindow((BitmapPtr)bmp3P, &err);
 
  WinSetDrawWindow(offH);
  WinDrawChars(strP_, len_, 0, 0);
  WinDeleteWindow(offH, false);
  BmpSetDensity((BitmapPtr)bmp3P, kCoordinatesDouble);
  offH  = WinCreateBitmapWindow((BitmapPtr)bmp3P, &err);
  RctSetRectangle(&r, 0, 0, w / 2, h / 2);
  WinCopyRectangle(offH, curH, &r, x_, y_, winOverlay);
  WinDeleteWindow(offH, false);
  BmpDelete((BitmapPtr)bmp3P);
  BmpDelete(bmpP);
  WinSetCoordinateSystem(coordSys);
}
 
static inline UInt16
GCoord2Offset(Coord x_, Coord y_)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  if (g->_hDensity || g->_hrLib) { /* High Resolution */
    return y_ * g->_rowBytes + x_;
  } else {
    return y_ * g->_rowBytes + (x_ / 2);
  }
}
 
static inline void
GSetPixel(Coord x_, Coord y_, IndexedColorType c_)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  UInt16 o  = GCoord2Offset(x_, y_);
  if (g->_hDensity) {
#if 0
    WinHandle draw = WinGetDrawWindow();
    WinSetDrawWindow(_canvas);
    WinDrawPixel(x_, y_);
    WinSetDrawWindow(draw);
#else
    g->_baseP[o] = c_;
#endif
  } else if (_hrLib) {
    g->_baseP[o] = c_;
  } else {
    if (x_ % 2) {
      g->_baseP[o] &= 0xf0;
      g->_baseP[o] |= (c_ & 0x0f);
    } else {
      g->_baseP[o] &= 0x0f;
      g->_baseP[o] |= (c_ << 4);
    }
  }
}
 
static inline IndexedColorType
GFetchPixel(Coord x_, Coord y_)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  UInt16 o = GCoord2Offset(x_, y_);
  if (g->_hDensity) {
#if 0
    IndexedColorType c;
    WinHandle        draw = WinGetDrawWindow();
    WinSetDrawWindow(_canvas);
    c = WinGetPixel(x_, y_);
    WinSetDrawWindow(draw);
    return c;
#else
    return g->_baseP[o];
#endif
  } else if (g->_hrLib) {
    return g->_baseP[o];
  } else {
    if (x_ % 2) {
      return g->_baseP[o] & 0x0f;
    } else {
      return (g->_baseP[o] & 0xf0) >> 4;
    }
  }
}
 
#define isSjis(k_) (((k_) >= 0x80 && (k_) < 0xa0)||((k_) >= 0xe0))
 
static inline void
GInitQueue(void)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  g->_pointQ._Qstart = g->_pointQ._Qend = 0;
}
 
static inline void
GShiftPoint(Coord x_, Coord y_)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  g->_pointQ._Queue[g->_pointQ._Qstart].x = x_;
  g->_pointQ._Queue[g->_pointQ._Qstart].y = y_;
  if (++g->_pointQ._Qstart == MAX_QUEUE_SIZE) {
    g->_pointQ._Qstart = 0;
  }
}
 
static inline PointType*
GUnshiftPoint(void)
{
  PointType *p;
  GraphGlobalVarType *g = GetGlobalVariables();
  if (g->_pointQ._Qstart == g->_pointQ._Qend) return NULL;
  p = &g->_pointQ._Queue[g->_pointQ._Qend++];
  if (g->_pointQ._Qend == MAX_QUEUE_SIZE) {
    g->_pointQ._Qend = 0;
  }
  return p;
}
 
static void
GInitColors(void)
{
  UInt16 i;
  RGBColorType rgb[] = {
    { 0, 0x00, 0x00, 0x00},
    { 0, 0x00, 0x00, 0xff},
    { 0, 0xff, 0x00, 0x00},
    { 0, 0xff, 0x00, 0xff},
    { 0, 0x00, 0xff, 0x00},
    { 0, 0x00, 0xff, 0xff},
    { 0, 0xff, 0xff, 0x00},
    { 0, 0xff, 0xff, 0xff},
    { 0, 0x55, 0x55, 0x55},
    { 0, 0x00, 0x00, 0x80},
    { 0, 0x80, 0x00, 0x00},
    { 0, 0x80, 0x00, 0x80},
    { 0, 0x00, 0x80, 0x00},
    { 0, 0x00, 0x80, 0x80},
    { 0, 0x80, 0x80, 0x00},
    { 0, 0xaa, 0xaa, 0xaa},
  };
  GraphGlobalVarType *g = GetGlobalVariables();
  for (i = 0 ; i < gColorNameCandidate ; i++) {
    g->_colors[i] = WinRGBToIndex(&rgb[i]);
    WinIndexToRGB(g->_colors[i], &g->_defrgb[i]);
    if (g->_hrLib == 0 && !g->_hDensity) {
      g->_colors[i] = i;
    }
  }
}
 
/* API */
 
Boolean
GInit(void)
{
  SonySysFtrSysInfoP sonySysFtrSysInfoP; /* Sony CLIe System Information */
  UInt32             wmVer, wmAttr;
  Err                err = 0;
  Boolean            res = false;
  Boolean            col = true;
  UInt16             i;
  FontID             ftab[] = {
    hrTinyFont, hrTinyBoldFont, hrSmallFont, hrSmallBoldFont,
    hrStdFont, hrBoldFont, hrLargeFont, hrLargeBoldFont
  };
  GraphGlobalVarType *g = CreateGlobalVariables();
  /* OS5 High Density Check */
  g->_hDensity = false;
  if (FtrGet(sysFtrCreator, sysFtrNumWinVersion, &wmVer) == errNone) {
    if (wmVer >= 4) { /* hd interface existing */
      WinScreenGetAttribute(winScreenDensity, &wmAttr);
      if (wmAttr == kDensityDouble) {
        _hDensity = true;
        WinSetCoordinateSystem(kCoordinatesStandard);
      }
    }
  }
  /* CLIe High Resolution Check */
  if ((err = FtrGet(sonySysFtrCreator,
                    sonySysFtrNumSysInfoP,
                    (UInt32*)&sonySysFtrSysInfoP)) == 0) {
    if (sonySysFtrSysInfoP->libr & sonySysFtrSysInfoLibrHR) {
      /* High-resolution library available */
      if ((err = SysLibFind(sonySysLibNameHR, &_hrLib))) {
        if (err == sysErrLibNotFound) {
          err = SysLibLoad('libr', sonySysFileCHRLib, &_hrLib);
        }
      }
    }
  }
  if (!g->_hDensity && (err || g->_hrLib == 0)) {
    g->_hrLib = 0; /* no library existing */
    g->_width = g->_height = 160;
    g->_depth = 8;
    WinScreenMode(winScreenModeSet, &g->_width, &g->_height, &g->_depth, &col);
    res = true;
  } else {
    g->_width = g->_height = 320;
    g->_depth = 8;
    res = true; /* only High-resolution CLIE/OS5 high density device support */
    if (g->_hDensity) {
      WinScreenMode(winScreenModeSet, &g->_width, &g->_height, &g->_depth, &col);
    } else {
      HROpen(g->_hrLib);
      HRGetAPIVersion(g->_hrLib, &g->_hrVer);
      HRWinScreenMode(g->_hrLib,
                      winScreenModeSet, &g->_width, &g->_height, &g->_depth, &col);
      for (i = 0 ; i < 8 ; i++) {
        g->_fntTable[i] = ftab[i];
      }
    }
  }
  WinScreenMode(winScreenModeGet, NULL, NULL, NULL, &col);
  if (!col) {
    if (g->_hrLib && !g->_hDensity) {
      HRClose(g->_hrLib);
    }
    return false; /* mono-chrome mode */
  }
  GInitColors();
  RctSetRectangle(&g->_border, 0, 0, g->_width, g->_height);
  if (g->_hDensity) {
    UInt16 coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
    g->_canvas = WinCreateOffscreenWindow(g->_width, g->_height,
                                       nativeFormat, &err);
    WinSetCoordinateSystem(coordSys);
  } else if (g->_hrLib) {
    g->_canvas = HRWinCreateOffscreenWindow(g->_hrLib,
                                         g->_width, g->_height,
                                         screenFormat, &err);
  }
  if (g->_canvas == NULL) {
    res = false;
  } else {
    _bmpP  = WinGetBitmap(g->_canvas);
    _baseP = BmpGetBits(g->_bmpP);
    GlueBmpGetDimensions(g->_bmpP, NULL, NULL, &g->_rowBytes);
  }
  return res;
}
 
Boolean
GFinalize(void)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  if (g->_hrLib && !g->_hDensity) {
    HRClose(g->_hrLib);
  }
  if (g->_canvas) {
    WinDeleteWindow(g->_canvas, false);
  }
  DeleteGlobalVariables();
  return true;
}
 
void
GChromakeyPaint(RectanglePtr clipP_, UInt8 *patP_, Boolean line_)
{
  IndexedColorType c;
  WinHandle        cur;
  UInt8            r, g, b, off;
  Coord            x, y, dx, lx, ox;
  UInt16           i, j, n, coordSys;
  UInt16           bl, bu, br, bd;
  RectangleType    rs;
  UInt8            pattern[][3] = {
    { 0x00, 0x00, 0x00 },
    { 0xff, 0x00, 0x00 },
    { 0x00, 0xff, 0x00 },
    { 0xff, 0xff, 0x00 },
    { 0x00, 0x00, 0xff },
    { 0xff, 0x00, 0xff },
    { 0x00, 0xff, 0xff },
    { 0xff, 0xff, 0xff },
  };
  GraphGlobalVarType *g = GetGlobalVariables();
  i = 0;
  n = patP_[i++];
  for (j = 0 ; j < n ; j++) {
    pattern[j + 1][0] = patP_[i + j * 3 + 0];
    pattern[j + 1][1] = patP_[i + j * 3 + 1];
    pattern[j + 1][2] = patP_[i + j * 3 + 2];
  }
 
  bl = clipP_->topLeft.x;
  bu = clipP_->topLeft.y;
  br = bl + clipP_->extent.x;
  bd = bu + clipP_->extent.y;
  cur = WinGetDrawWindow();
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  for (y = bu; y < bd ; y++) {
    for (x = bl ; x < br ; x += 8) {
      lx = (br - x < 8) ? br - x : 8;
      for (dx = 0, ox = 7 ; dx < lx ; dx++, ox--) {
        c   = GFetchPixel(x + dx, y);
        off = 1 << ox;
        for (j = 1 ; j <= n ; j++) {
          if (_colors[j] == c) {
            b = (pattern[j][0] & off) >> ox;
            r = (pattern[j][1] & off) >> ox;
            g = (pattern[j][2] & off) >> ox;
            GSetPixel(x + dx, y, _colors[(r << 1) | (g << 2) | b]);
            break;
          }
        }
      }
    }
    if (line_) {
      RctSetRectangle(&rs, bl, y, br - bl, 1);
      if (g->_hrLib) {
        HRWinCopyRectangle(g->_hrLib, g->_canvas, cur, &rs, bl, y, winPaint);
      } else {
        WinCopyRectangle(g->_canvas, cur, &rs, bl, y, winPaint);
      }
    }
  }
  if (!line_) {
    if (g->_hrLib) {
      HRWinCopyRectangle(g->_hrLib, g->_canvas, cur, clipP_, bl, bu, winPaint);
    } else {
      WinCopyRectangle(g->_canvas, cur, clipP_, bl, bu, winPaint);
    }
  }
  if (g->_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
}
 
static inline Boolean
_chk(Coord x_, Coord y_, IndexedColorType c_, IndexedColorType b_)
{
  IndexedColorType c = GFetchPixel(x_, y_);
  return c != c_ && c != b_;
}
 
void
GPaintSpec(GPaintSpecPtr specP_)
{
  PointType        *pP;
  Coord            bl, bu, br, bd;
  Coord            l, r, x, y;
  Coord            wx, wy;
  WinHandle        cur;
  Coord            ltx, lty, lbx, lby;
  Boolean          uf, df;
  UInt16           coordSys;
  GraphGlobalVarType *g = GetGlobalVariables();
 
  bl  = specP_->_clipP->topLeft.x;
  bu  = specP_->_clipP->topLeft.y;
  br  = bl + specP_->_clipP->extent.x;
  bd  = bu + specP_->_clipP->extent.y;
  x = specP_->_x + bl;
  y = specP_->_y + bu;
 
  ltx = lty = lbx = lby = -1;
 
  cur = WinGetDrawWindow();
  if (!_chk(x, y, g->_colors[specP_->_fg], g->_colors[specP_->_bg])){
    /* needless to paint */
    return;
  }
  GInitQueue();
 
  GShiftPoint(x, y);
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  WinSetForeColor(g->_colors[specP_->_fg]);
  while ((pP = GUnshiftPoint()) != NULL) {
    if (!_chk(pP->x, pP->y, g->_colors[specP_->_fg], g->_colors[specP_->_bg])) {
      /* needless to paint */
      continue;
    }
    for (l = pP->x ; l >= bl ; l--) {
      if (!_chk(l, pP->y, g->_colors[specP_->_fg], g->_colors[specP_->_bg])) {
        break;
      }
    }
    ++l;
    for (r = pP->x ; r < br ; r++) {
      if (!_chk(r, pP->y, g->_colors[specP_->_fg], g->_colors[specP_->_bg])) {
        break;
      }
    }
    --r;
    /* draw current line */
    if (g->_hrLib) {
      WinSetDrawWindow(g->_canvas);
      HRWinDrawLine(g->_hrLib, l, pP->y, r, pP->y);
      WinSetDrawWindow(cur);
      HRWinDrawLine(g->_hrLib, l, pP->y, r, pP->y);
    } else {
      WinSetDrawWindow(g->_canvas);
      WinDrawLine(l, pP->y, r, pP->y);
      WinSetDrawWindow(cur);
      WinDrawLine(l, pP->y, r, pP->y);
    }
    for (wx = l ; wx <= r ; wx++) {
      uf = df = false;
      /* scan upper line */
      wy = pP->y - 1;
      if (wy >= bu) {
        uf = _chk(wx, wy, g->_colors[specP_->_fg], g->_colors[specP_->_bg]);
        if (uf) {
          if (wx + 1 <= r && !_chk(wx + 1, wy,
                                   g->_colors[specP_->_fg],
                                   g->_colors[specP_->_bg])) {
            /* found right edge */
            GShiftPoint(wx, wy);
            uf = false;
          } else if (wx == r) {
            GShiftPoint(wx, wy);
          }
        }
      }
      /* scan lower line */
      wy = pP->y + 1;
      if (wy < bd) {
        df = _chk(wx, wy, g->_colors[specP_->_fg], g->_colors[specP_->_bg]);
        if (df) {
          if (wx + 1 <= r && !_chk(wx + 1, wy,
                                   g->_colors[specP_->_fg],
                                   g->_colors[specP_->_bg])) {
            /* found right edge */
            GShiftPoint(wx, wy);
            df = false;
          } else if (wx == r) {
            GShiftPoint(wx, wy);
          }
        }
      }
    }
  }
  if (_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
}
 
void
GPaint(RectanglePtr clipP_, Coord x_, Coord y_, GColorName f_, GColorName b_)
{
  GPaintSpecType spec;
  spec._clipP  = clipP_;
  spec._x      = x_;
  spec._y      = y_;
  spec._fg     = f_;
  spec._bg     = b_;
  spec._bgBmpP = NULL;
  GPaintSpec(&spec);
}
 
void
GDrawLine(RectanglePtr clipP_,
          Coord x0_, Coord y0_, Coord x1_, Coord y1_, GColorName c_)
{
  RectangleType cur;
  WinHandle     draw, windows[2];
  UInt16        i;
  UInt16        coordSys;
  GraphGlobalVarType *g = GetGlobalVariables();
 
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  draw = WinGetDrawWindow();
  WinSetForeColor(g->_colors[c_]);
  windows[0] = g->_canvas;
  windows[1] = draw;
  for (i = 0 ; i < 2; i++) {
    WinSetDrawWindow(windows[i]);
    if (g->_hrLib) {
      if (clipP_) {
        HRWinGetClip(g->_hrLib, &cur);
        HRWinSetClip(g->_hrLib, clipP_);
      }
      HRWinDrawLine(g->_hrLib, x0_, y0_, x1_, y1_);
      if (clipP_) {
        HRWinSetClip(g->_hrLib, &cur);
      }
    } else {
      if (clipP_) {
        WinGetClip(&cur);
        WinSetClip(clipP_);
      }
      WinDrawLine(x0_, y0_, x1_, y1_);
      if (clipP_) {
        WinSetClip(&cur);
      }
    }
  }
  if (g->_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
}
 
GColorName
GGetPixel(Coord x0_, Coord y0_)
{
  UInt16           i, coordSys;
  IndexedColorType c;
  GColorName       r = gColorInvalid;
  GraphGlobalVarType *g = GetGlobalVariables();
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  c = GFetchPixel(x0_, y0_);
  for (i = 0 ; i < gColorNameCandidate ; i++) {
    if (g->_colors[i] == c) {
      r = i;
      break;
    }
  }
  if (g->_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
  return r;
}
 
void
GDrawPixel(RectanglePtr clipP_, Coord x0_, Coord y0_, GColorName c_)
{
  UInt16 coordSys;
  GraphGlobalVarType *g = GetGlobalVariables();
 
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  WinSetForeColor(g->_colors[c_]);
  GSetPixel(x0_, y0_, g->_colors[c_]);
  if (g->_hrLib) {
    HRWinDrawPixel(g->_hrLib, x0_, y0_);
  } else {
    WinDrawPixel(x0_, y0_);
  }
  if (g->_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
}
 
void
GDrawRectangle(RectanglePtr rP_, GColorName c_)
{
  UInt16        coordSys;
  WinHandle     draw = WinGetDrawWindow();
  GraphGlobalVarType *g = GetGlobalVariables();
 
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  WinSetForeColor(g->_colors[c_]);
  if (g->_hrLib) {
    WinSetDrawWindow(g->_canvas);
    HRWinDrawRectangle(g->_hrLib, rP_, 0);
    WinSetDrawWindow(draw);
    HRWinDrawRectangle(g->_hrLib, rP_, 0);
  } else {
    WinSetDrawWindow(g->_canvas);
    WinDrawRectangle(rP_, 0);
    WinSetDrawWindow(draw);
    WinDrawRectangle(rP_, 0);
  }
  if (g->_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
}
 
void
GDrawChars(Boolean small_,
           Char *strP_, UInt16 len_, Coord x_, Coord y_, GColorName c_)
{
  UInt16    i;
  UInt16    coordSys;
  WinHandle windows[2];
  GraphGlobalVarType *g = GetGlobalVariables();
 
  if (g->_hDensity) {
    coordSys = WinSetCoordinateSystem(kCoordinatesDouble);
  }
  WinSetTextColor(g->_colors[c_]);
 
  windows[0] = g->_canvas;
  windows[1] = WinGetDrawWindow();
  if (strP_[len_ - 1] < ' ') {
    --len_;
  }
  for(i = 0 ; i < 2 ; i++) {
    WinSetDrawWindow(windows[i]);
    if (g->_hDensity) {
      if (small_){
        HDWinDrawChars(strP_, len_, x_, y_);
      } else {
        WinDrawChars(strP_, len_, x_, y_);
      }
    } else {
      HRWinDrawChars(g->_hrLib, strP_, len_, x_, y_);
    }
  }
  if (g->_hDensity) {
    WinSetCoordinateSystem(coordSys);
  }
}
 
void
GPaletteChange(GColorName c_)
{
  UInt16       i;
  RGBColorType *mapP, rgb;
  MemHandle    hRGB;
  GraphGlobalVarType *g = GetGlobalVariables();
 
  hRGB = MemHandleNew(sizeof(RGBColorType) * 256);
  mapP = (RGBColorType*)MemHandleLock(hRGB);
  WinPalette(winPaletteGet, 0, 256, mapP);
  if (c_ != gColorInvalid) {
    WinIndexToRGB(g->_colors[c_], &rgb);
  }
  for (i = gColorBlue ; i < gColorWhite ; i++) {
    mapP[g->_colors[i]] = (c_ == gColorInvalid) ? g->_defrgb[i] : rgb;
  }
  WinPalette(winPaletteSet, 0, 256, mapP);
  MemHandleUnlock(hRGB);
  MemHandleFree(hRGB);
}
 
FontID
GGetFont(void)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  return (!g->_hDensity && g->_hrLib) ? HRFntGetFont(g->_hrLib) : FntGetFont();
}
 
FontID
GSetFont(FontID id_)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  return (!g->_hDensity && g->_hrLib) ? HRFntSetFont(g->_hrLib, id_) : FntSetFont(id_);
}
 
void
GFldModifyField(FieldPtr fldP)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  if (g->_hDensity || g->_hrLib) {
    FldSetUsable(fldP, false);
  }
}
 
void
GFldDrawField(FieldPtr fldP)
{
  UInt16        lines, pos, offset, maxLength;
  UInt16        h, w, l;
  FontID        curFont = stdFont, fldFont;
  Char          *textP;
  RectangleType b;
  Boolean       small = false;
  GraphGlobalVarType *g = GetGlobalVariables();
 
  if (!g->_hDensity && g->_hrLib == 0) {
    FldDrawField(fldP);
    return;
  }
  WinPushDrawState();
  if (g->_hDensity) {
    WinSetCoordinateSystem(kCoordinatesDouble);
  }
  FldGetBounds(fldP, &b);
  if (_hDensity || _hrLib) {
    b.topLeft.x <<= 1;
    b.topLeft.y <<= 1;
    b.extent.x <<= 1;
    b.extent.y <<= 1;
  }
  fldFont = FldGetFont(fldP);
  textP = FldGetTextPtr(fldP);
  maxLength = FldGetTextLength(fldP);
  if (textP) {
    GFldEraseField(fldP);
    if (g->_hDensity) {
      if (fldFont & fntAppFontCustomBase) {
        fldFont -= fntAppFontCustomBase;
        small    = true;
      }
      curFont = FntSetFont(fldFont);
    } else if (g->_hrLib) {
      FontID hrFont;
      if (fldFont & fntAppFontCustomBase) {
        /* use small font */
        fldFont -= fntAppFontCustomBase;
        small    = true;
      }
      hrFont = g->_fntTable[fldFont + ((small) ? 0 : 4)];
      if (fldFont == largeBoldFont) {
        hrFont = g->_fntTable[(small) ? 3 : 7];
      }
      curFont = HRFntSetFont(g->_hrLib, hrFont);
    }
    h = FntLineHeight();
    w = b.extent.x;
    if (small) {
      if (g->_hDensity) {
        h /= 2;
        w *= 2;
      }
    }
    if (!g->_hDensity && g->_hrLib && g->_hrVer >= HR_VERSION_SUPPORT_FNTSIZE) {
      h = HRFntLineHeight(g->_hrLib);
    }
    lines = FldGetVisibleLines(fldP);
    if (g->_hDensity) {
      lines = b.extent.y / h;
    }
    offset = FldGetScrollPosition(fldP);
    for (pos = 0 ; pos < lines ; pos++) {
      l = FldWordWrap(&textP[offset], w);
      GDrawChars(small, &textP[offset],
                 l, b.topLeft.x, b.topLeft.y + pos * h, gColorBlue);
      offset += l;
      if (offset >= maxLength) {
        break;
      }
    }
    if (g->_hDensity) {
      FntSetFont(curFont);
    } else if (g->_hrLib) {
      HRFntSetFont(g->_hrLib, curFont);
    }
  }
  WinPopDrawState();
}
 
void
GFldEraseField(FieldPtr fldP)
{
  RectangleType b;
  GraphGlobalVarType *g = GetGlobalVariables();
  if (!g->_hDensity && g->_hrLib == 0) {
    FldEraseField(fldP);
    return;
  }
  FldGetBounds(fldP, &b);
  b.topLeft.x <<= 1;
  b.topLeft.y <<= 1;
  b.extent.x <<= 1;
  b.extent.y <<= 1;
  if (g->_hDensity) {
    WinPushDrawState();
    WinSetCoordinateSystem(kCoordinatesDouble);
    WinEraseRectangle(&b, 0);
    WinPopDrawState();
  } else if (g->_hrLib) {
    HRWinEraseRectangle(g->_hrLib, &b, 0);
  }
}
 
void
GGetDisplayExtent(Coord *xP, Coord *yP, Boolean hd)
{
  WinPushDrawState();
  if (_hDensity) {
    WinSetCoordinateSystem((hd) ? kCoordinatesDouble : kCoordinatesStandard);
  }
  WinGetDisplayExtent(xP, yP);
  WinPopDrawState();
}
 
UInt16
GScale(void)
{
  GraphGlobalVarType *g = GetGlobalVariables();
  return (g->_hDensity || g->_hrLib) ? 2 : 1;
}
1)
M5Stack Core/Core2版だけ途中も見える
ハイハイスクールアドベンチャー_palmos版.txt · 最終更新: by araki