ResumeTest.java
0001 import com.nttdocomo.ui.Canvas;
0002 import com.nttdocomo.ui.Dialog;
0003 import com.nttdocomo.ui.Display;
0004 import com.nttdocomo.ui.Font;
0005 import com.nttdocomo.ui.Graphics;
0006 import com.nttdocomo.ui.IApplication;
0007 import com.nttdocomo.ui.Image;
0008 import com.nttdocomo.ui.MediaImage;
0009 import com.nttdocomo.ui.MediaManager;
0010 import com.nttdocomo.ui.PhoneSystem;
0011 
0012 // レジューム処理の動作確認用アプリ。問題が起きる版。
0013 
0014 /**
0015  @author mieki256
0016  */
0017 public class ResumeTest extends IApplication {
0018 
0019     Main l_main = new Main();
0020 
0021     public void start() {
0022 
0023         Display.setCurrent(l_main);
0024         l_main.exec();
0025     }
0026 
0027     public void resume() {
0028 
0029         // 実処理クラスが復帰して、リジューム用処理が呼び出せるようになるまで繰り返す
0030         while (l_main == null) {
0031             Thread.yield();
0032         }
0033         l_main.resumeJobEnable = true;
0034         l_main.mcResume();
0035     }
0036 }
0037 
0038 /**
0039  * 実処理
0040  
0041  */
0042 final class Main extends Canvas {
0043 
0044     /**
0045      * リジューム処理実行中フラグ
0046      */
0047     public boolean resumeJobEnable;
0048 
0049     /**
0050      * ProcessEvent実行中フラグ
0051      */
0052     boolean processEventJobEnable;
0053 
0054     /**
0055      * FPS。1秒間に何回画面を書き換えるか
0056      */
0057     static final int FPS = 25;
0058 
0059     /**
0060      * 1ループのwait時間。FPSから算出。
0061      */
0062     static final int SLEEP_VALUE = 1000 / FPS;
0063 
0064     /**
0065      * アプリ画面横幅
0066      */
0067     static final int SCREEN_W = 240;
0068 
0069     /**
0070      * アプリ画面縦幅
0071      */
0072     static final int SCREEN_H = 240;
0073 
0074     /**
0075      * リピートボタン情報
0076      */
0077     private int c_repbtn;
0078 
0079     /**
0080      * トリガボタン情報
0081      */
0082     private int trgBtn;
0083 
0084     /**
0085      * 割り込みにより記録されたボタン情報
0086      */
0087     private int keyBtnInterrupt;
0088 
0089     /**
0090      * 一意の値(同時押しを無効)にしたトリガボタン情報
0091      */
0092     private int trgBtnUniq;
0093 
0094     /**
0095      * キー情報取得をしない状態を指定するための時間カウンタ
0096      */
0097     private int keyNoCheckEnableCount;
0098 
0099     /**
0100      * キートリガチェック時の待ちフレーム数。
0101      <p>
0102      * 各シーンの切り替わり時などで、念のために、多少なりともwaitを入れてからトリガをチェックしている。
0103      </p>
0104      */
0105     static final int KEY_CHK_WAITFRAME = 4;
0106 
0107     // キーのビット情報
0108     static final int KB_UP = (<< Display.KEY_UP(<< Display.KEY_2);
0109     static final int KB_DOWN = (<< Display.KEY_DOWN(<< Display.KEY_8);
0110     static final int KB_LEFT = (<< Display.KEY_LEFT(<< Display.KEY_4);
0111     static final int KB_RIGHT = (<< Display.KEY_RIGHT(<< Display.KEY_6);
0112     static final int KB_SELECT = (<< Display.KEY_SELECT(<< Display.KEY_5);
0113     static final int KB_SOFT1 = (<< Display.KEY_SOFT1);
0114     static final int KB_SOFT2 = (<< Display.KEY_SOFT2);
0115 
0116     /**
0117      * 画面描画に使う Graphics オブジェクト
0118      */
0119     private Graphics g = getGraphics();
0120 
0121     private interface IG {
0122 
0123         public int NUMBERIMG = 0;
0124         public int STATUS = 1;
0125         public int ICON = 2;
0126         public int BTNMARK = 3;
0127 
0128         /**
0129          * 画像ファイル総数
0130          */
0131         public int IMAGE_MAX = 4;
0132     }
0133 
0134     /**
0135      * 画像イメージ格納用
0136      */
0137     private Image[] img = new Image[IG.IMAGE_MAX];
0138 
0139     /**
0140      * 画面描画に使う Font オブジェクト(システムフォント)
0141      */
0142     private Font m_font;
0143 
0144     /**
0145      * システムフォント描画位置調整用(単位はドット)
0146      */
0147     private int stringH;
0148 
0149     /**
0150      * システムフォント文字サイズ(単位はドット)
0151      */
0152     private int fontSize;
0153 
0154     /**
0155      * メインループ用記録カウンタ:ループ処理開始時間
0156      */
0157     private long mainLoopStartTime;
0158 
0159     /**
0160      * メインループ記録カウンタ:待ち時間
0161      */
0162     private int mainLoopWaitTime;
0163 
0164     /**
0165      * フレームカウンタ
0166      */
0167     private int frameCounter = 0;
0168 
0169     /**
0170      * リジューム時に待つ時間
0171      */
0172     static final int RESUME_WAIT_TIME = FPS;
0173 
0174     /**
0175      * リジューム時の処理キャンセルタイマー
0176      */
0177     private int resumeWaitTimer;
0178 
0179     /**
0180      * メインステップ変数
0181      */
0182     private int mainStep;
0183 
0184     /**
0185      * シーンカウンタ変数
0186      */
0187     private int sceneStep;
0188 
0189     // ----------------------------------------
0190 
0191     /**
0192      * キー入力用ワークを全消去
0193      */
0194     private void clearAllKeyWork() {
0195 
0196         clearKeyWork();
0197         keyNoCheckEnableCount = FPS / 4;
0198     }
0199 
0200     /**
0201      * キー入力用ワークを消去(キー入力キャンセルタイマーはセットしない)
0202      */
0203     private void clearKeyWork() {
0204 
0205         c_repbtn = 0;
0206         keyBtnInterrupt = 0;
0207         trgBtn = 0;
0208         trgBtnUniq = 0;
0209     }
0210 
0211     /**
0212      * キー入力用ワークの内容を設定
0213      */
0214     private void setKeyWork(int key) {
0215 
0216         int oldkey = c_repbtn;
0217         key |= keyBtnInterrupt;
0218         keyBtnInterrupt = 0;
0219         c_repbtn = key;
0220 
0221         trgBtn = (oldkey ^ c_repbtn& c_repbtn;
0222         trgBtnUniq = getKeyUniqBit(trgBtn);
0223     }
0224 
0225     /**
0226      * リジューム関係のwaitカウンタを初期化
0227      */
0228     public void initResumeWaitWork() {
0229 
0230         clearKeyWork();
0231         keyNoCheckEnableCount = RESUME_WAIT_TIME;
0232         resumeWaitTimer = RESUME_WAIT_TIME;
0233     }
0234 
0235     /**
0236      * リジューム処理。
0237      <ul>
0238      <li>キーワークをクリアする。</li>
0239      <li>サウンドを再開再生する。</li>
0240      </ul>
0241      */
0242     public void mcResume() {
0243 
0244         resumeJobEnable = true;
0245 
0246         saveProcessHistory(ProcessKind.RESUME);
0247 
0248         initResumeWaitWork();
0249 
0250         // 本来ここにサウンド再開処理
0251 
0252         // ログ描画
0253         drawLogInterrupt();
0254 
0255         // キー入力がなくなるまで待つ
0256         do {
0257             try {
0258                 Thread.sleep(SLEEP_VALUE);
0259             catch (InterruptedException e) {
0260             }
0261             setKeyWork(getKeypadState());
0262         while (c_repbtn != || trgBtn != 0);
0263 
0264         resumeJobEnable = false;
0265     }
0266 
0267     // イベント通知処理
0268     public void processEvent(int a_type, int a_param) {
0269 
0270         if (processEventJobEnablereturn;
0271         processEventJobEnable = true;
0272 
0273         if (a_type == Display.RESUME_VM_EVENT) {
0274             // リジューム時はワークをクリア
0275             saveProcessHistory(ProcessKind.EVENT);
0276             initResumeWaitWork();
0277         }
0278 
0279         if (a_type == Display.KEY_PRESSED_EVENT) {
0280             // キーが押された
0281             if (keyNoCheckEnableCount <= 0keyBtnInterrupt |= (0x01 << a_param);
0282         }
0283 
0284         processEventJobEnable = false;
0285     }
0286 
0287     // ----------------------------------------
0288 
0289     /**
0290      * コンストラクタ
0291      */
0292     public Main() {
0293 
0294         resumeJobEnable = true;
0295 
0296         // 念のためにキーワークだけでもクリアしておく
0297         clearAllKeyWork();
0298         keyNoCheckEnableCount = RESUME_WAIT_TIME;
0299     }
0300 
0301     // ----------------------------------------
0302 
0303     /**
0304      * メイン処理担当
0305      */
0306     public void exec() {
0307 
0308         // ----------------------------------------
0309         // ワーク初期化
0310 
0311         resumeJobEnable = true;
0312         processEventJobEnable = false;
0313 
0314         System.gc();
0315 
0316         // バックライトON
0317         PhoneSystem.setAttribute(PhoneSystem.DEV_BACKLIGHT, PhoneSystem.ATTR_BACKLIGHT_ON);
0318 
0319         g = getGraphics()// グラフィック生成
0320 
0321         // 画面全体クリア
0322         g.lock();
0323         g.setClip(00, SCREEN_W, SCREEN_H);
0324         g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0325         g.fillRect(00, SCREEN_W, SCREEN_H);
0326         g.unlock(true);
0327 
0328         // フォント設定
0329         m_font = Font.getFont(Font.SIZE_TINY)// フォントをTINYにする
0330         g.setFont(m_font)// フォントを設定
0331         stringH = m_font.getAscent() - m_font.getHeight();
0332         fontSize = m_font.getHeight();
0333 
0334         // ボタン情報初期化
0335         clearAllKeyWork();
0336         keyNoCheckEnableCount = FPS / 2;
0337 
0338         System.gc();
0339 
0340         loadImage();
0341 
0342         System.gc();
0343 
0344         // カウンター初期化
0345         mainLoopWaitTime = SLEEP_VALUE; // フレーム間隔
0346         resumeWaitTimer = 0;
0347         frameCounter = 0;
0348 
0349         sceneStep = 0;
0350 
0351         mainStep = 0;
0352 
0353         initLogWork();
0354 
0355         resumeJobEnable = false;
0356 
0357         // ----------------------------------------
0358         // メインループ
0359 
0360         while (true) {
0361 
0362             saveProcessHistory(ProcessKind.LOOPSTART);
0363 
0364             mainLoopStartTime = System.currentTimeMillis();
0365 
0366             if (resumeJobEnable) {
0367                 // リジューム中なら待つ
0368                 try {
0369                     Thread.sleep(SLEEP_VALUE);
0370                 catch (InterruptedException e) {
0371                 }
0372                 continue;
0373             }
0374 
0375             // キーワーク設定
0376 
0377             if (keyNoCheckEnableCount > || resumeJobEnable) {
0378                 // キー情報を取得しない処理
0379                 int key = getKeypadState();
0380                 key |= keyBtnInterrupt;
0381                 clearKeyWork();
0382                 if (!resumeJobEnable) {
0383                     if (key == 0keyNoCheckEnableCount--;
0384                 }
0385             else {
0386                 // キー情報取得処理
0387                 saveProcessHistory(ProcessKind.KEYSET);
0388                 setKeyWork(getKeypadState());
0389             }
0390 
0391             try {
0392 
0393                 if (!resumeJobEnable) {
0394                     // リジューム処理終了待ちではないので、メイン処理を実行
0395 
0396                     if (resumeWaitTimer > 0) {
0397                         // リジューム直後なので待つ
0398                         resumeWaitTimer--;
0399                     else {
0400 
0401                         // メイン処理
0402                         saveProcessHistory(ProcessKind.MAIN);
0403 
0404                         switch (mainStep) {
0405                             case 0:
0406                                 // 起動時の入力待ち
0407 
0408                                 // 描画
0409                                 saveProcessHistory(ProcessKind.DRAWSTART);
0410 
0411                                 g.lock();
0412                                 g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0413                                 g.fillRect(00, SCREEN_W, SCREEN_H);
0414                                 g.setColor(Graphics.getColorOfName(Graphics.BLACK));
0415                                 printCenter("START [OK]", SCREEN_H / 2);
0416                                 g.unlock(true);
0417 
0418                                 saveProcessHistory(ProcessKind.KEYCHECK);
0419 
0420                                 if (trgBtnUniq == KB_SELECT) {
0421                                     mainStep++;
0422                                 }
0423 
0424                                 break;
0425                             case 1:
0426                                 setSoftKeyText("休止""終了");
0427                                 setLogSaveEnable();
0428                                 mainStep++;
0429                                 break;
0430                             case 2:
0431                                 // 処理経過を描画
0432                             {
0433 
0434                                 saveProcessHistory(ProcessKind.KEYCHECK);
0435 
0436                                 if (trgBtnUniq == KB_SOFT1) {
0437                                     // 一時停止
0438                                     mainStep++;
0439                                 }
0440 
0441                                 if (trgBtnUniq == KB_SOFT2) {
0442                                     // アプリ終了
0443                                     IApplication.getCurrentApp().terminate();
0444                                 }
0445 
0446                                 if (trgBtnUniq == KB_SELECT) {
0447                                     sceneStep++;
0448                                 }
0449 
0450                                 // 描画
0451                                 {
0452                                     saveProcessHistory(ProcessKind.DRAWSTART);
0453 
0454                                     g.lock();
0455                                     g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0456                                     g.fillRect(00, SCREEN_W, SCREEN_H);
0457 
0458                                     int x, y;
0459 
0460                                     // アイコン描画
0461                                     x = SCREEN_W - 10;
0462                                     y = SCREEN_H - 10;
0463                                     int idx = frameCounter % 5;
0464                                     drawIcon(g, x, y, idx);
0465 
0466                                     // ログを描画
0467                                     drawLog(g);
0468 
0469                                     g.unlock(true);
0470                                 }
0471 
0472                             }
0473                                 break;
0474                             case 3:
0475                                 setSoftKeyText("再開""");
0476                                 saveProcessHistory(ProcessKind.PAUSESTART);
0477                                 setLogSaveDisable();
0478                                 mainStep++;
0479 
0480                             case 4:
0481                             {
0482                                 // 描画
0483                                 {
0484                                     saveProcessHistory(ProcessKind.DRAWSTART);
0485 
0486                                     g.lock();
0487                                     g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0488                                     g.fillRect(00, SCREEN_W, SCREEN_H);
0489 
0490                                     // ログを描画
0491                                     drawLogHistory(g);
0492 
0493                                     g.unlock(true);
0494                                 }
0495 
0496                                 saveProcessHistory(ProcessKind.KEYCHECK);
0497 
0498                                 if ((c_repbtn & (<< Display.KEY_UP)) != 0) {
0499                                     decrementLogReadPointer();
0500                                 }
0501 
0502                                 if ((c_repbtn & (<< Display.KEY_DOWN)) != 0) {
0503                                     incrementLogReadPointer();
0504                                 }
0505 
0506                                 if (trgBtnUniq == KB_SOFT1) {
0507                                     setSoftKeyText("休止""終了");
0508                                     setLogSaveEnable();
0509                                     saveProcessHistory(ProcessKind.PAUSEEND);
0510                                     mainStep -= 2;
0511                                 }
0512                             }
0513                                 break;
0514                         }
0515 
0516                     }
0517 
0518                 }
0519 
0520                 // キューに溜まったサウンド再生・停止要求をこなす
0521                 if (!resumeJobEnable) {
0522                     // 本来ここでサウンド再生 or 停止処理
0523                 }
0524 
0525                 saveProcessHistory(ProcessKind.MAIN_END);
0526 
0527                 if (!resumeJobEnable) {
0528                     // リジューム中ではない
0529 
0530                     // バックライト操作
0531                     if ((frameCounter % (* FPS)) == 0) {
0532                         PhoneSystem.setAttribute(PhoneSystem.DEV_BACKLIGHT, PhoneSystem.ATTR_BACKLIGHT_ON);
0533                     }
0534                 }
0535 
0536                 if (resumeJobEnablemainLoopStartTime = System.currentTimeMillis();
0537                 System.gc();
0538                 while (System.currentTimeMillis() < mainLoopStartTime + mainLoopWaitTime)
0539                     Thread.yield();
0540 
0541                 frameCounter++;
0542 
0543             catch (Exception e) {
0544                 String s = "情報:" + e + "\nmStep=" + mainStep;
0545                 displayDialogMessage("エラー発生", s);
0546                 IApplication.getCurrentApp().terminate();
0547             }
0548             saveProcessHistory(ProcessKind.LOOPEND);
0549         }
0550     }
0551 
0552     // 画面描画
0553     public void paint(Graphics g) {
0554 
0555     }
0556 
0557     /**
0558      * ダイアログメッセージを表示する
0559      
0560      @param titleStr
0561      *            ダイアログタイトル文字列
0562      @param message
0563      *            ダイアログメッセージ文字列
0564      */
0565     private void displayDialogMessage(String titleStr, String message) {
0566 
0567         Dialog d = new Dialog(Dialog.DIALOG_ERROR, titleStr);
0568         d.setText(message);
0569         d.show();
0570     }
0571 
0572     /**
0573      * キーの同時入力を避けるために一意の値にする
0574      
0575      @param keystatus
0576      *            キー情報
0577      @return 一意にしたキー情報
0578      */
0579     int getKeyUniqBit(int keystatus) {
0580 
0581         int key = 0;
0582         if ((keystatus & KB_UP!= 0) {
0583             key = KB_UP;
0584         else if ((keystatus & KB_DOWN!= 0) {
0585             key = KB_DOWN;
0586         else if ((keystatus & KB_LEFT!= 0) {
0587             key = KB_LEFT;
0588         else if ((keystatus & KB_RIGHT!= 0) {
0589             key = KB_RIGHT;
0590         else if ((keystatus & KB_SELECT!= 0) {
0591             key = KB_SELECT;
0592         else if ((keystatus & KB_SOFT1!= 0) {
0593             key = KB_SOFT1;
0594         else if ((keystatus & KB_SOFT2!= 0) {
0595             key = KB_SOFT2;
0596         }
0597 
0598         return key;
0599     }
0600 
0601     /**
0602      * 割り込み時のログ描画
0603      */
0604     void drawLogInterrupt() {
0605 
0606         g.lock();
0607         g.setColor(Graphics.getColorOfRGB(255227227));
0608         g.fillRect(00, SCREEN_W, SCREEN_H);
0609 
0610         // ログを描画
0611         drawLog(g);
0612 
0613         g.unlock(true);
0614     }
0615 
0616     // ----------------------------------------
0617     // 以降文字列描画系
0618 
0619     /**
0620      * ベースライン調整を考慮した座標で文字列描画する
0621      
0622      @param s
0623      *            文字列
0624      @param x
0625      *            描画位置 x
0626      @param y
0627      *            描画位置 y
0628      */
0629     public void _drawString(String s, int x, int y) {
0630 
0631         g.drawString(s, x, y + fontSize + stringH);
0632     }
0633 
0634     /**
0635      * 文字列をセンタリング描画する。
0636      
0637      @param str
0638      *            文字列
0639      @param y
0640      *            描画位置 y
0641      @return 描画開始位置 x
0642      */
0643     int printCenter(String str, int y) {
0644 
0645         int x = (SCREEN_W - m_font.stringWidth(str)) 2;
0646         g.drawString(str, x, y + fontSize + stringH);
0647         return x;
0648     }
0649 
0650     /**
0651      * 影つき文字列をセンタリング描画する。
0652      <ul>
0653      <li>fgcolor、shadowcolor には、Graphics.getColorOfName() か Graphics.getColorOfRGB() で値を渡す</li>
0654      </ul>
0655      
0656      @param str
0657      *            文字列
0658      @param y
0659      *            描画位置 y
0660      @param fgcolor
0661      *            前景色
0662      @param shadowcolor
0663      *            背景色
0664      */
0665     void printCenterWithShadow(String str, int y, int fgcolor, int shadowcolor) {
0666 
0667         int x = (SCREEN_W - m_font.stringWidth(str)) 2;
0668         printWithShadow(str, x, y, fgcolor, shadowcolor);
0669     }
0670 
0671     /**
0672      * 影つき文字列を xy座標を指定して描画する。
0673      <ul>
0674      <li>fgcolor、bgcolor には、Graphics.getColorOfName() か Graphics.getColorOfRGB() で値を渡す</li>
0675      </ul>
0676      
0677      @param str
0678      *            文字列
0679      @param x
0680      *            描画位置 x
0681      @param y
0682      *            描画位置 y
0683      @param fgcolor
0684      *            前景色
0685      @param shadowcolor
0686      *            影色
0687      */
0688     void printWithShadow(String str, int x, int y, int fgcolor, int shadowcolor) {
0689 
0690         y += fontSize + stringH;
0691 
0692         g.setColor(shadowcolor);
0693         g.drawString(str, x + 1, y + 1);
0694 
0695         g.setColor(fgcolor);
0696         g.drawString(str, x, y);
0697     }
0698 
0699     /**
0700      * 画像に基づく文字列表示メソッド処理指定用・ゼロの桁表示有効
0701      */
0702     static final boolean ZERO_DISP_ENABLE = true;
0703 
0704     /**
0705      * 画像に基づく文字列表示メソッド処理指定用・ゼロの桁表示無効
0706      */
0707     static final boolean ZERO_DISP_DISABLE = false;
0708 
0709     /**
0710      * 画像に基づく文字列表示メソッド処理指定用・数字の左詰め表示
0711      */
0712     static final boolean ALIGN_LEFT = true;
0713 
0714     /**
0715      * 画像に基づく文字列表示メソッド処理指定用・数字の右詰め表示
0716      */
0717     static final boolean ALIGN_RIGHT = false;
0718 
0719     /**
0720      * 画像に基づく文字列表示メソッド処理指定用・描画有効
0721      */
0722     static final boolean DRAW_ENABLE = true;
0723 
0724     /**
0725      * 画像に基づく文字列表示メソッド処理指定用・描画をせずに横幅だけを取得する
0726      */
0727     static final boolean DRAW_DISABLE = false;
0728 
0729     /**
0730      * フォント種類
0731      */
0732     private interface FontKind {
0733 
0734         /**
0735          * 数字(小サイズ)
0736          */
0737         public int MICRO = 0;
0738 
0739     }
0740 
0741     /**
0742      * フォント種類に割り当てる、画像ナンバー、横幅、縦幅、スペーシングを列挙したテーブル
0743      */
0744     static final short[] ASCII_WH = {
0745         // Img_No, W, H, spacing
0746         IG.NUMBERIMG, 460// 小
0747     };
0748 
0749     static final int ASCII_WH_OFFSET = 4;
0750 
0751     /**
0752      * 数値を描画
0753      
0754      @param g
0755      *            Graphics クラス
0756      @param num
0757      *            表示したい数値
0758      @param keta
0759      *            桁
0760      @param x
0761      *            表示位置 x
0762      @param y
0763      *            表示位置 y
0764      @param zerodisp
0765      *            ZERO_DISP_ENABLE = ゼロで埋める / ZERO_DISP_DISABLE = ゼロで埋めない
0766      @param alignleft
0767      *            ALIGN_LEFT = 左詰 / ALIGN_RIGHT = 右詰
0768      @param drawEnable
0769      *            DRAW_ENABLE = 描画する / DRAW_DISABLE = 描画しない(横幅のみ取得)
0770      @param kind
0771      *            フォント種類 (FontKind を参照)
0772      @return 描画されるであろう横幅
0773      */
0774     int drawNumberXSmall(Graphics g, long num, int keta, int x, int y, boolean zerodisp, boolean alignleft, boolean drawEnable, int kind) {
0775 
0776         int string_w = 0// 描画横幅記録用
0777 
0778         int wadd = 0;
0779 
0780         int n = kind * ASCII_WH_OFFSET;
0781         int ign = ASCII_WH[n++]// 画像ナンバー
0782         int sw = ASCII_WH[n++]// 1文字の横幅
0783         int sh = ASCII_WH[n++]// 1文字の縦幅
0784         int xadd = ASCII_WH[n++]// 1文字描くごとに補正する値
0785 
0786         // 桁単位で計算するための値の初期値を求める
0787         int a = 1;
0788         int k = 1;
0789         while (k < keta) {
0790             a *= 10;
0791             k++;
0792         }
0793 
0794         int w = sw;
0795         w += wadd;
0796 
0797         // 桁の数だけループ
0798         for (int i = keta; i > 0; i--, a /= 10) {
0799             long nokori = num % a;
0800 
0801             // m に、その桁の値を取り出す
0802             long m = num;
0803             if (m != 0) {
0804                 m /= a;
0805             }
0806 
0807             if (zerodisp || (intm != || i == 1) {
0808 
0809                 // 以下の条件のどれかに合致した場合、処理をする。
0810                 // ・ゼロ表示が有効
0811                 // ・その桁が 0 ではない
0812                 // ・最後の桁
0813 
0814                 if (drawEnable) {
0815                     int sx = (int) (m * sw);
0816                     g.drawImage(img[ign], x, y, sx, 0, sw, sh);
0817                 }
0818 
0819                 if (((intm != && !zerodisp|| i == 1) {
0820                     // 以下の条件のどれかに合致した場合、それ以降はゼロ表示を有効にする。
0821                     // ・その桁が0ではなく、かつ、ゼロ表示が無効
0822                     // ・最後の桁
0823                     zerodisp = true;
0824                 }
0825             }
0826 
0827             if (zerodisp || !alignleft) {
0828                 x += (sw + xadd);
0829                 string_w += (sw + xadd);
0830             }
0831             num = nokori;
0832         }
0833 
0834         return string_w;
0835     }
0836 
0837     /**
0838      * フォントの横幅を得る
0839      
0840      @param kind
0841      *            フォント種類。FontKind を参照のこと。
0842      @return 横幅ドット数
0843      */
0844     int getFontW(int kind) {
0845 
0846         return ASCII_WH[(kind * ASCII_WH_OFFSET1];
0847     }
0848 
0849     /**
0850      * フォントの縦幅を得る
0851      
0852      @param kind
0853      *            フォント種類。FontKind を参照のこと。
0854      @return 縦幅ドット数
0855      */
0856     int getFontH(int kind) {
0857 
0858         return ASCII_WH[(kind * ASCII_WH_OFFSET2];
0859     }
0860 
0861     /**
0862      * 画像読み込み(res/から)
0863      */
0864     private void loadImage() {
0865 
0866         for (int i = 0; i < IG.IMAGE_MAX; i++) {
0867             String fn = Integer.toString(i".gif";
0868             MediaImage tempImg = MediaManager.getImage("resource:///" + fn);
0869             try {
0870                 tempImg.use();
0871             catch (Exception e) {
0872             }
0873             img[i= tempImg.getImage();
0874         }
0875     }
0876 
0877     /**
0878      * ステータス画像の縦幅
0879      */
0880     private final static int STATUS_IMG_H = 6;
0881 
0882     /**
0883      * ステータス画像を描画
0884      
0885      @param g
0886      *            Graphics
0887      @param x
0888      *            描画位置 x
0889      @param y
0890      *            描画位置 y
0891      @param kind
0892      *            ステータス画像種類
0893      @return 描画した幅
0894      */
0895     private int drawStatus(Graphics g, int x, int y, int kind) {
0896 
0897         int imgLen = ProcessKind.LENGTH;
0898         int ign = IG.STATUS;
0899         int w = img[ign].getWidth();
0900         int h = img[ign].getHeight();
0901         h /= imgLen;
0902         int sy = h * kind;
0903 
0904         if (kind == ProcessKind.SCENE) {
0905             w = 16;
0906         }
0907 
0908         if (kind == ProcessKind.STEP) {
0909             w = 14;
0910         }
0911 
0912         g.drawImage(img[ign], x, y, 0, sy, w, h);
0913 
0914         return w;
0915     }
0916 
0917     /**
0918      * アイコン画像を描画
0919      
0920      @param g
0921      *            Graphics
0922      @param x
0923      *            描画位置 x
0924      @param y
0925      *            描画位置 y
0926      @param indexNumber
0927      *            パターンナンバー
0928      */
0929     private void drawIcon(Graphics g, int x, int y, int indexNumber) {
0930 
0931         final int imgLen = 5;
0932         if (indexNumber >= imgLenreturn;
0933 
0934         int ign = IG.ICON;
0935         int w = img[ign].getWidth();
0936         int h = img[ign].getHeight();
0937         w /= imgLen;
0938         int sx = w * indexNumber;
0939         g.drawImage(img[ign], x, y, sx, 0, w, h);
0940     }
0941 
0942     /**
0943      * ビットパターンを画像で描画
0944      
0945      @param g
0946      *            Graphics
0947      @param x
0948      *            描画位置 x
0949      @param y
0950      *            描画位置 y
0951      @param bitPattern
0952      *            描画したい値(32bit)
0953      */
0954     private int drawBitPattern(Graphics g, int x, int y, int bitPattern) {
0955 
0956         int ign = IG.BTNMARK;
0957         int w = img[ign].getWidth();
0958         int h = img[ign].getHeight();
0959         w /= 2;
0960         int dx = x + (w * (32 1));
0961         int allw = 0;
0962         for (int i = 0; i < 32; i++) {
0963             int fg = bitPattern & 0x01;
0964             int sx = w * fg;
0965             g.drawImage(img[ign], dx, y, sx, 0, w, h);
0966             dx -= w;
0967             bitPattern >>= 1;
0968             allw += w;
0969         }
0970 
0971         return allw;
0972     }
0973 
0974     /**
0975      * ソフトキーのラベルを設定する
0976      
0977      @param labelStrLeft
0978      *            ソフトキー1ラベル
0979      @param labelStrRight
0980      *            ソフトキー2ラベル
0981      */
0982     private void setSoftKeyText(String labelStrLeft, String labelStrRight) {
0983 
0984         String l1;
0985         String l2;
0986 
0987         l1 = labelStrLeft;
0988         if (l1 == nulll1 = "";
0989 
0990         l2 = labelStrRight;
0991         if (l2 == nulll2 = "";
0992 
0993         setSoftLabel(SOFT_KEY_1, l1);
0994         setSoftLabel(SOFT_KEY_2, l2);
0995     }
0996 
0997     /**
0998      * ログを取る際の処理種類
0999      */
1000     public interface ProcessKind {
1001 
1002         public int LOOPSTART = 0;
1003         public int LOOPEND = 1;
1004         public int KEYSET = 2;
1005         public int MAIN = 3;
1006         public int MAIN_END = 4;
1007         public int RESUME = 5;
1008         public int EVENT = 6;
1009         public int SCENE = 7;
1010         public int PAUSESTART = 8;
1011         public int PAUSEEND = 9;
1012         public int KEYCHECK = 10;
1013         public int DRAWSTART = 11;
1014         public int STEP = 12;
1015         public int LENGTH = 13;
1016     }
1017 
1018     /**
1019      * ログワーク最大数
1020      */
1021     private static final int LOG_MAX = 8192;
1022 
1023     /**
1024      * 処理種類ログワーク
1025      */
1026     private int[] logStatus = new int[LOG_MAX];
1027 
1028     /**
1029      * キー情報ログワーク
1030      */
1031     private int[] logBitPattern = new int[LOG_MAX];
1032 
1033     /**
1034      * シーンカウンタログワーク
1035      */
1036     private int[] logScene = new int[LOG_MAX];
1037 
1038     /**
1039      * フレームカウンタログワーク
1040      */
1041     private int[] logFrameCounter = new int[LOG_MAX];
1042 
1043     /**
1044      * ログワーク書き込み用ポインタ
1045      */
1046     private int logWritePointer;
1047 
1048     /**
1049      * ログワーク読み込み用ポインタ
1050      */
1051     private int logReadPointer;
1052 
1053     /**
1054      * ログを取るかどうかのフラグ
1055      */
1056     private boolean logSaveEnable;
1057 
1058     /**
1059      * 1画面あたりに表示するログの行数
1060      */
1061     private static final int LOG_LINE_PER_PAGE = SCREEN_H / STATUS_IMG_H;
1062 
1063     /**
1064      * ログワーク初期化
1065      */
1066     private void initLogWork() {
1067 
1068         for (int i = 0; i < LOG_MAX; i++) {
1069             logStatus[i= -1;
1070             logBitPattern[i0;
1071         }
1072 
1073         logWritePointer = 0;
1074         logReadPointer = 0;
1075         setLogSaveDisable();
1076     }
1077 
1078     /**
1079      * ログ記録を有効化
1080      */
1081     private void setLogSaveEnable() {
1082 
1083         logSaveEnable = true;
1084     }
1085 
1086     /**
1087      * ログ記録を無効化
1088      */
1089     private void setLogSaveDisable() {
1090 
1091         logSaveEnable = false;
1092     }
1093 
1094     /**
1095      * ログを記録
1096      
1097      @param kind
1098      *            記録する処理種類
1099      */
1100     public void saveProcessHistory(int kind) {
1101 
1102         if (!logSaveEnablereturn;
1103 
1104         logStatus[logWritePointer= kind;
1105         logBitPattern[logWritePointer= trgBtnUniq;
1106         logScene[logWritePointer(mainStep * 1000(sceneStep % 1000);
1107         logFrameCounter[logWritePointer= frameCounter;
1108 
1109         logWritePointer++;
1110         if (logWritePointer >= LOG_MAXlogWritePointer = 0;
1111     }
1112 
1113     /**
1114      * ログを画面に描画
1115      
1116      @param g
1117      *            Graphics
1118      */
1119     private void drawLog(Graphics g) {
1120 
1121         int dx = 0;
1122         int dy = SCREEN_H - STATUS_IMG_H;
1123 
1124         int idx = logWritePointer;
1125         for (int i = 0; i < LOG_LINE_PER_PAGE; i++) {
1126             idx--;
1127             if (idx < 0idx += LOG_MAX;
1128 
1129             int status = logStatus[idx];
1130             int bitpat = logBitPattern[idx];
1131             int scene = logScene[idx];
1132             int fcount = logFrameCounter[idx];
1133 
1134             if (status >= 0) {
1135                 drawLogOneLine(g, dx, dy, status, bitpat, scene, fcount);
1136                 dx = 0;
1137                 dy -= STATUS_IMG_H;
1138             }
1139         }
1140 
1141         logReadPointer = idx;
1142     }
1143 
1144     /**
1145      * ログを画面に描画(履歴表示時)
1146      
1147      @param g
1148      *            Graphics
1149      */
1150     private void drawLogHistory(Graphics g) {
1151 
1152         int dx = 0;
1153         int dy = 0;
1154 
1155         int idx = logReadPointer;
1156         for (int i = 0; i < LOG_LINE_PER_PAGE; i++) {
1157             int status = logStatus[idx];
1158             int bitpat = logBitPattern[idx];
1159             int scene = logScene[idx];
1160             int fcount = logFrameCounter[idx];
1161 
1162             if (status >= 0) {
1163                 drawLogOneLine(g, dx, dy, status, bitpat, scene, fcount);
1164             }
1165 
1166             dx = 0;
1167             dy += STATUS_IMG_H;
1168 
1169             idx++;
1170             if (idx >= LOG_MAXidx = 0;
1171         }
1172     }
1173 
1174     /**
1175      * ログ読み込みポインタを+1する
1176      */
1177     private void incrementLogReadPointer() {
1178 
1179         int checkIdx = logWritePointer - LOG_LINE_PER_PAGE + 1;
1180         if (checkIdx < 0checkIdx += LOG_MAX;
1181 
1182         int idx = logReadPointer;
1183         idx++;
1184         if (idx >= LOG_MAXidx = 0;
1185 
1186         if (idx != checkIdx) {
1187             logReadPointer = idx;
1188             // System.out.println("WP="+logWritePointer+" RP="+logReadPointer);
1189         }
1190     }
1191 
1192     /**
1193      * ログ読み込みポインタを-1する
1194      */
1195     private void decrementLogReadPointer() {
1196 
1197         int checkIdx = logWritePointer - 1;
1198         if (checkIdx < 0checkIdx += LOG_MAX;
1199 
1200         int idx = logReadPointer;
1201         idx--;
1202         if (idx < 0idx += LOG_MAX;
1203 
1204         if (idx != checkIdx) {
1205             logReadPointer = idx;
1206             // System.out.println("WP="+logWritePointer+" RP="+logReadPointer);
1207         }
1208     }
1209 
1210     /**
1211      * ログ一行分を画面に描画
1212      
1213      @param g
1214      *            Graphics
1215      @param x
1216      *            描画位置 x
1217      @param y
1218      *            描画位置 y
1219      @param status
1220      *            描画する処理種類
1221      @param bitpat
1222      *            描画するビットパターン値
1223      @param scene
1224      *            描画するシーンカウンタ値
1225      @param fcount
1226      *            描画するカウンタ値
1227      */
1228     private void drawLogOneLine(Graphics g, int x, int y, int status, int bitpat, int scene, int fcount) {
1229 
1230         int cnt_a = (scene != 0(scene / 10000;
1231         int cnt_b = (scene % 1000);
1232 
1233         int w;
1234         w = drawNumberXSmall(g, fcount, 8, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO);
1235         x += w;
1236         x += 2;
1237 
1238         w = drawStatus(g, x, y, status);
1239         x += w;
1240         x += 2;
1241 
1242         w = drawStatus(g, x, y, ProcessKind.SCENE);
1243         x += w;
1244         w = drawNumberXSmall(g, cnt_b, 3, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO);
1245         x += w;
1246         x += 2;
1247 
1248         w = drawBitPattern(g, x, y, bitpat);
1249         x += w;
1250 
1251         w = drawStatus(g, x, y, ProcessKind.STEP);
1252         x += w;
1253         w = drawNumberXSmall(g, cnt_a, 1, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO);
1254         x += w;
1255         x += 2;
1256 
1257         x = 0;
1258         y -= STATUS_IMG_H;
1259     }
1260 }