import com.nttdocomo.ui.Canvas; import com.nttdocomo.ui.Dialog; import com.nttdocomo.ui.Display; import com.nttdocomo.ui.Font; import com.nttdocomo.ui.Graphics; import com.nttdocomo.ui.IApplication; import com.nttdocomo.ui.Image; import com.nttdocomo.ui.MediaImage; import com.nttdocomo.ui.MediaManager; import com.nttdocomo.ui.PhoneSystem; /** * @author mieki256 レジューム処理のテスト用アプリ */ public class ResumeTest extends IApplication { Main l_main = new Main(); public void start() { Display.setCurrent(l_main); l_main.exec(); } public void resume() { // 実処理クラスが復帰して、リジューム用処理が呼び出せるようになるまで繰り返す while (l_main == null) { Thread.yield(); } l_main.resumeJobEnable = true; l_main.mcResume(); } } /** * 実処理 * */ final class Main extends Canvas { /** * リジューム処理実行中フラグ */ public boolean resumeJobEnable; /** * ProcessEvent実行中フラグ */ boolean processEventJobEnable; /** * FPS。1秒間に何回画面を書き換えるか */ static final int FPS = 25; /** * 1ループのwait時間。FPSから算出。 */ static final int SLEEP_VALUE = 1000 / FPS; /** * アプリ画面横幅 */ static final int SCREEN_W = 240; /** * アプリ画面縦幅 */ static final int SCREEN_H = 240; /** * リピートボタン情報 */ private int c_repbtn; /** * トリガボタン情報 */ private int trgBtn; /** * 割り込みにより記録されたボタン情報 */ private int keyBtnInterrupt; /** * 一意の値(同時押しを無効)にしたトリガボタン情報 */ private int trgBtnUniq; /** * キー情報取得をしない状態を指定するための時間カウンタ */ private int keyNoCheckEnableCount; /** * キートリガチェック時の待ちフレーム数。 *

* 各シーンの切り替わり時などで、念のために、多少なりともwaitを入れてからトリガをチェックしている。 *

*/ static final int KEY_CHK_WAITFRAME = 4; // キーのビット情報 static final int KB_UP = (1 << Display.KEY_UP) | (1 << Display.KEY_2); static final int KB_DOWN = (1 << Display.KEY_DOWN) | (1 << Display.KEY_8); static final int KB_LEFT = (1 << Display.KEY_LEFT) | (1 << Display.KEY_4); static final int KB_RIGHT = (1 << Display.KEY_RIGHT) | (1 << Display.KEY_6); static final int KB_SELECT = (1 << Display.KEY_SELECT) | (1 << Display.KEY_5); static final int KB_SOFT1 = (1 << Display.KEY_SOFT1); static final int KB_SOFT2 = (1 << Display.KEY_SOFT2); /** * 画面描画に使う Graphics オブジェクト */ private Graphics g = getGraphics(); private interface IG { public int NUMBERIMG = 0; public int STATUS = 1; public int ICON = 2; public int BTNMARK = 3; /** * 画像ファイル総数 */ public int IMAGE_MAX = 4; } /** * 画像イメージ格納用 */ private Image[] img = new Image[IG.IMAGE_MAX]; /** * 画面描画に使う Font オブジェクト(システムフォント) */ private Font m_font; /** * システムフォント描画位置調整用(単位はドット) */ private int stringH; /** * システムフォント文字サイズ(単位はドット) */ private int fontSize; /** * メインループ用記録カウンタ:ループ処理開始時間 */ private long mainLoopStartTime; /** * メインループ記録カウンタ:待ち時間 */ private int mainLoopWaitTime; /** * フレームカウンタ */ private int frameCounter = 0; /** * リジューム時に待つ時間 */ static final int RESUME_WAIT_TIME = FPS; /** * リジューム時の処理キャンセルタイマー */ private int resumeWaitTimer; /** * メインステップ変数 */ private int mainStep; /** * シーンカウンタ変数 */ private int sceneStep; // ---------------------------------------- /** * キー入力用ワークを全消去 */ private void clearAllKeyWork() { clearKeyWork(); keyNoCheckEnableCount = FPS / 4; } /** * キー入力用ワークを消去(キー入力キャンセルタイマーはセットしない) */ private void clearKeyWork() { c_repbtn = 0; keyBtnInterrupt = 0; trgBtn = 0; trgBtnUniq = 0; } /** * キー入力用ワークの内容を設定 */ private void setKeyWork(int key) { int oldkey = c_repbtn; key |= keyBtnInterrupt; keyBtnInterrupt = 0; c_repbtn = key; trgBtn = (oldkey ^ c_repbtn) & c_repbtn; trgBtnUniq = getKeyUniqBit(trgBtn); } /** * リジューム関係のwaitカウンタを初期化 */ public void initResumeWaitWork() { clearKeyWork(); keyNoCheckEnableCount = RESUME_WAIT_TIME; resumeWaitTimer = RESUME_WAIT_TIME; } /** * リジューム処理。 * */ public void mcResume() { resumeJobEnable = true; saveProcessHistory(ProcessKind.RESUME); initResumeWaitWork(); // 本来ここにサウンド再開処理 // ログ描画 drawLogInterrupt(); // キー入力がなくなるまで待つ do { try { Thread.sleep(SLEEP_VALUE); } catch (InterruptedException e) { } setKeyWork(getKeypadState()); } while (c_repbtn != 0 || trgBtn != 0); resumeJobEnable = false; } // イベント通知処理 public void processEvent(int a_type, int a_param) { if (processEventJobEnable) return; processEventJobEnable = true; if (a_type == Display.RESUME_VM_EVENT) { // リジューム時はワークをクリア saveProcessHistory(ProcessKind.EVENT); initResumeWaitWork(); } if (a_type == Display.KEY_PRESSED_EVENT) { // キーが押された if (keyNoCheckEnableCount <= 0) keyBtnInterrupt |= (0x01 << a_param); } processEventJobEnable = false; } // ---------------------------------------- /** * コンストラクタ */ public Main() { resumeJobEnable = true; // 念のためにキーワークだけでもクリアしておく clearAllKeyWork(); keyNoCheckEnableCount = RESUME_WAIT_TIME; } // ---------------------------------------- /** * メイン処理担当 */ public void exec() { // ---------------------------------------- // ワーク初期化 resumeJobEnable = true; processEventJobEnable = false; System.gc(); // バックライトON PhoneSystem.setAttribute(PhoneSystem.DEV_BACKLIGHT, PhoneSystem.ATTR_BACKLIGHT_ON); g = getGraphics(); // グラフィック生成 // 画面全体クリア g.lock(); g.setClip(0, 0, SCREEN_W, SCREEN_H); g.setColor(Graphics.getColorOfName(Graphics.WHITE)); g.fillRect(0, 0, SCREEN_W, SCREEN_H); g.unlock(true); // フォント設定 m_font = Font.getFont(Font.SIZE_TINY); // フォントをTINYにする g.setFont(m_font); // フォントを設定 stringH = m_font.getAscent() - m_font.getHeight(); fontSize = m_font.getHeight(); // ボタン情報初期化 clearAllKeyWork(); keyNoCheckEnableCount = FPS / 2; System.gc(); loadImage(); System.gc(); // カウンター初期化 mainLoopWaitTime = SLEEP_VALUE; // フレーム間隔 resumeWaitTimer = 0; frameCounter = 0; sceneStep = 0; mainStep = 0; initLogWork(); resumeJobEnable = false; // ---------------------------------------- // メインループ while (true) { saveProcessHistory(ProcessKind.LOOPSTART); mainLoopStartTime = System.currentTimeMillis(); if (resumeJobEnable) { // リジューム中なら待つ try { Thread.sleep(SLEEP_VALUE); } catch (InterruptedException e) { } continue; } // キーワーク設定 if (keyNoCheckEnableCount > 0 || resumeJobEnable) { // キー情報を取得しない処理 int key = getKeypadState(); key |= keyBtnInterrupt; clearKeyWork(); if (!resumeJobEnable) { if (key == 0) keyNoCheckEnableCount--; } } else { // キー情報取得処理 saveProcessHistory(ProcessKind.KEYSET); setKeyWork(getKeypadState()); } try { if (!resumeJobEnable) { // リジューム処理終了待ちではないので、メイン処理を実行 if (resumeWaitTimer > 0) { // リジューム直後なので待つ resumeWaitTimer--; } else { // メイン処理 saveProcessHistory(ProcessKind.MAIN); switch (mainStep) { case 0: // 起動時の入力待ち // 描画 saveProcessHistory(ProcessKind.DRAWSTART); g.lock(); g.setColor(Graphics.getColorOfName(Graphics.WHITE)); g.fillRect(0, 0, SCREEN_W, SCREEN_H); g.setColor(Graphics.getColorOfName(Graphics.BLACK)); printCenter("START [OK]", SCREEN_H / 2); g.unlock(true); saveProcessHistory(ProcessKind.KEYCHECK); if (trgBtnUniq == KB_SELECT) { mainStep++; } break; case 1: setSoftKeyText("休止", "終了"); setLogSaveEnable(); mainStep++; break; case 2: // 処理経過を描画 { saveProcessHistory(ProcessKind.KEYCHECK); if (trgBtnUniq == KB_SOFT1) { // 一時停止 mainStep++; } if (trgBtnUniq == KB_SOFT2) { // アプリ終了 IApplication.getCurrentApp().terminate(); } if (trgBtnUniq == KB_SELECT) { sceneStep++; } // 描画 { saveProcessHistory(ProcessKind.DRAWSTART); g.lock(); g.setColor(Graphics.getColorOfName(Graphics.WHITE)); g.fillRect(0, 0, SCREEN_W, SCREEN_H); int x, y; // アイコン描画 x = SCREEN_W - 10; y = SCREEN_H - 10; int idx = frameCounter % 5; drawIcon(g, x, y, idx); // ログを描画 drawLog(g); g.unlock(true); } } break; case 3: setSoftKeyText("再開", ""); saveProcessHistory(ProcessKind.PAUSESTART); setLogSaveDisable(); mainStep++; case 4: { // 描画 { saveProcessHistory(ProcessKind.DRAWSTART); g.lock(); g.setColor(Graphics.getColorOfName(Graphics.WHITE)); g.fillRect(0, 0, SCREEN_W, SCREEN_H); // ログを描画 drawLogHistory(g); g.unlock(true); } saveProcessHistory(ProcessKind.KEYCHECK); if ((c_repbtn & (1 << Display.KEY_UP)) != 0) { decrementLogReadPointer(); } if ((c_repbtn & (1 << Display.KEY_DOWN)) != 0) { incrementLogReadPointer(); } if (trgBtnUniq == KB_SOFT1) { setSoftKeyText("休止", "終了"); setLogSaveEnable(); saveProcessHistory(ProcessKind.PAUSEEND); mainStep -= 2; } } break; } } } // キューに溜まったサウンド再生・停止要求をこなす if (!resumeJobEnable) { // 本来ここでサウンド再生 or 停止処理 } saveProcessHistory(ProcessKind.MAIN_END); if (!resumeJobEnable) { // リジューム中ではない // バックライト操作 if ((frameCounter % (3 * FPS)) == 0) { PhoneSystem.setAttribute(PhoneSystem.DEV_BACKLIGHT, PhoneSystem.ATTR_BACKLIGHT_ON); } } if (resumeJobEnable) mainLoopStartTime = System.currentTimeMillis(); System.gc(); while (System.currentTimeMillis() < mainLoopStartTime + mainLoopWaitTime) Thread.yield(); frameCounter++; } catch (Exception e) { String s = "情報:" + e + "\nmStep=" + mainStep; displayDialogMessage("エラー発生", s); IApplication.getCurrentApp().terminate(); } saveProcessHistory(ProcessKind.LOOPEND); } } // 画面描画 public void paint(Graphics g) { } /** * ダイアログメッセージを表示する * * @param titleStr * ダイアログタイトル文字列 * @param message * ダイアログメッセージ文字列 */ private void displayDialogMessage(String titleStr, String message) { Dialog d = new Dialog(Dialog.DIALOG_ERROR, titleStr); d.setText(message); d.show(); } /** * キーの同時入力を避けるために一意の値にする * * @param keystatus * キー情報 * @return 一意にしたキー情報 */ int getKeyUniqBit(int keystatus) { int key = 0; if ((keystatus & KB_UP) != 0) { key = KB_UP; } else if ((keystatus & KB_DOWN) != 0) { key = KB_DOWN; } else if ((keystatus & KB_LEFT) != 0) { key = KB_LEFT; } else if ((keystatus & KB_RIGHT) != 0) { key = KB_RIGHT; } else if ((keystatus & KB_SELECT) != 0) { key = KB_SELECT; } else if ((keystatus & KB_SOFT1) != 0) { key = KB_SOFT1; } else if ((keystatus & KB_SOFT2) != 0) { key = KB_SOFT2; } return key; } /** * 割り込み時のログ描画 */ void drawLogInterrupt() { g.lock(); g.setColor(Graphics.getColorOfRGB(255, 227, 227)); g.fillRect(0, 0, SCREEN_W, SCREEN_H); // ログを描画 drawLog(g); g.unlock(true); } // ---------------------------------------- // 以降文字列描画系 /** * ベースライン調整を考慮した座標で文字列描画する * * @param s * 文字列 * @param x * 描画位置 x * @param y * 描画位置 y */ public void _drawString(String s, int x, int y) { g.drawString(s, x, y + fontSize + stringH); } /** * 文字列をセンタリング描画する。 * * @param str * 文字列 * @param y * 描画位置 y * @return 描画開始位置 x */ int printCenter(String str, int y) { int x = (SCREEN_W - m_font.stringWidth(str)) / 2; g.drawString(str, x, y + fontSize + stringH); return x; } /** * 影つき文字列をセンタリング描画する。 * * * @param str * 文字列 * @param y * 描画位置 y * @param fgcolor * 前景色 * @param shadowcolor * 背景色 */ void printCenterWithShadow(String str, int y, int fgcolor, int shadowcolor) { int x = (SCREEN_W - m_font.stringWidth(str)) / 2; printWithShadow(str, x, y, fgcolor, shadowcolor); } /** * 影つき文字列を xy座標を指定して描画する。 * * * @param str * 文字列 * @param x * 描画位置 x * @param y * 描画位置 y * @param fgcolor * 前景色 * @param shadowcolor * 影色 */ void printWithShadow(String str, int x, int y, int fgcolor, int shadowcolor) { y += fontSize + stringH; g.setColor(shadowcolor); g.drawString(str, x + 1, y + 1); g.setColor(fgcolor); g.drawString(str, x, y); } /** * 画像に基づく文字列表示メソッド処理指定用・ゼロの桁表示有効 */ static final boolean ZERO_DISP_ENABLE = true; /** * 画像に基づく文字列表示メソッド処理指定用・ゼロの桁表示無効 */ static final boolean ZERO_DISP_DISABLE = false; /** * 画像に基づく文字列表示メソッド処理指定用・数字の左詰め表示 */ static final boolean ALIGN_LEFT = true; /** * 画像に基づく文字列表示メソッド処理指定用・数字の右詰め表示 */ static final boolean ALIGN_RIGHT = false; /** * 画像に基づく文字列表示メソッド処理指定用・描画有効 */ static final boolean DRAW_ENABLE = true; /** * 画像に基づく文字列表示メソッド処理指定用・描画をせずに横幅だけを取得する */ static final boolean DRAW_DISABLE = false; /** * フォント種類 */ private interface FontKind { /** * 数字(小サイズ) */ public int MICRO = 0; } /** * フォント種類に割り当てる、画像ナンバー、横幅、縦幅、スペーシングを列挙したテーブル */ static final short[] ASCII_WH = { // Img_No, W, H, spacing IG.NUMBERIMG, 4, 6, 0, // 小 }; static final int ASCII_WH_OFFSET = 4; /** * 数値を描画 * * @param g * Graphics クラス * @param num * 表示したい数値 * @param keta * 桁 * @param x * 表示位置 x * @param y * 表示位置 y * @param zerodisp * ZERO_DISP_ENABLE = ゼロで埋める / ZERO_DISP_DISABLE = ゼロで埋めない * @param alignleft * ALIGN_LEFT = 左詰 / ALIGN_RIGHT = 右詰 * @param drawEnable * DRAW_ENABLE = 描画する / DRAW_DISABLE = 描画しない(横幅のみ取得) * @param kind * フォント種類 (FontKind を参照) * @return 描画されるであろう横幅 */ int drawNumberXSmall(Graphics g, long num, int keta, int x, int y, boolean zerodisp, boolean alignleft, boolean drawEnable, int kind) { int string_w = 0; // 描画横幅記録用 int wadd = 0; int n = kind * ASCII_WH_OFFSET; int ign = ASCII_WH[n++]; // 画像ナンバー int sw = ASCII_WH[n++]; // 1文字の横幅 int sh = ASCII_WH[n++]; // 1文字の縦幅 int xadd = ASCII_WH[n++]; // 1文字描くごとに補正する値 // 桁単位で計算するための値の初期値を求める int a = 1; int k = 1; while (k < keta) { a *= 10; k++; } int w = sw; w += wadd; // 桁の数だけループ for (int i = keta; i > 0; i--, a /= 10) { long nokori = num % a; // m に、その桁の値を取り出す long m = num; if (m != 0) { m /= a; } if (zerodisp || (int) m != 0 || i == 1) { // 以下の条件のどれかに合致した場合、処理をする。 // ・ゼロ表示が有効 // ・その桁が 0 ではない // ・最後の桁 if (drawEnable) { int sx = (int) (m * sw); g.drawImage(img[ign], x, y, sx, 0, sw, sh); } if (((int) m != 0 && !zerodisp) || i == 1) { // 以下の条件のどれかに合致した場合、それ以降はゼロ表示を有効にする。 // ・その桁が0ではなく、かつ、ゼロ表示が無効 // ・最後の桁 zerodisp = true; } } if (zerodisp || !alignleft) { x += (sw + xadd); string_w += (sw + xadd); } num = nokori; } return string_w; } /** * フォントの横幅を得る * * @param kind * フォント種類。FontKind を参照のこと。 * @return 横幅ドット数 */ int getFontW(int kind) { return ASCII_WH[(kind * ASCII_WH_OFFSET) + 1]; } /** * フォントの縦幅を得る * * @param kind * フォント種類。FontKind を参照のこと。 * @return 縦幅ドット数 */ int getFontH(int kind) { return ASCII_WH[(kind * ASCII_WH_OFFSET) + 2]; } /** * 画像読み込み(res/から) */ private void loadImage() { for (int i = 0; i < IG.IMAGE_MAX; i++) { String fn = Integer.toString(i) + ".gif"; MediaImage tempImg = MediaManager.getImage("resource:///" + fn); try { tempImg.use(); } catch (Exception e) { } img[i] = tempImg.getImage(); } } /** * ステータス画像の縦幅 */ private final static int STATUS_IMG_H = 6; /** * ステータス画像を描画 * * @param g * Graphics * @param x * 描画位置 x * @param y * 描画位置 y * @param kind * ステータス画像種類 * @return 描画した幅 */ private int drawStatus(Graphics g, int x, int y, int kind) { int imgLen = ProcessKind.LENGTH; int ign = IG.STATUS; int w = img[ign].getWidth(); int h = img[ign].getHeight(); h /= imgLen; int sy = h * kind; if (kind == ProcessKind.SCENE) { w = 16; } if (kind == ProcessKind.STEP) { w = 14; } g.drawImage(img[ign], x, y, 0, sy, w, h); return w; } /** * アイコン画像を描画 * * @param g * Graphics * @param x * 描画位置 x * @param y * 描画位置 y * @param indexNumber * パターンナンバー */ private void drawIcon(Graphics g, int x, int y, int indexNumber) { final int imgLen = 5; if (indexNumber >= imgLen) return; int ign = IG.ICON; int w = img[ign].getWidth(); int h = img[ign].getHeight(); w /= imgLen; int sx = w * indexNumber; g.drawImage(img[ign], x, y, sx, 0, w, h); } /** * ビットパターンを画像で描画 * * @param g * Graphics * @param x * 描画位置 x * @param y * 描画位置 y * @param bitPattern * 描画したい値(32bit) */ private int drawBitPattern(Graphics g, int x, int y, int bitPattern) { int ign = IG.BTNMARK; int w = img[ign].getWidth(); int h = img[ign].getHeight(); w /= 2; int dx = x + (w * (32 - 1)); int allw = 0; for (int i = 0; i < 32; i++) { int fg = bitPattern & 0x01; int sx = w * fg; g.drawImage(img[ign], dx, y, sx, 0, w, h); dx -= w; bitPattern >>= 1; allw += w; } return allw; } /** * ソフトキーのラベルを設定する * * @param labelStrLeft * ソフトキー1ラベル * @param labelStrRight * ソフトキー2ラベル */ private void setSoftKeyText(String labelStrLeft, String labelStrRight) { String l1; String l2; l1 = labelStrLeft; if (l1 == null) l1 = ""; l2 = labelStrRight; if (l2 == null) l2 = ""; setSoftLabel(SOFT_KEY_1, l1); setSoftLabel(SOFT_KEY_2, l2); } /** * ログを取る際の処理種類 */ public interface ProcessKind { public int LOOPSTART = 0; public int LOOPEND = 1; public int KEYSET = 2; public int MAIN = 3; public int MAIN_END = 4; public int RESUME = 5; public int EVENT = 6; public int SCENE = 7; public int PAUSESTART = 8; public int PAUSEEND = 9; public int KEYCHECK = 10; public int DRAWSTART = 11; public int STEP = 12; public int LENGTH = 13; } /** * ログワーク最大数 */ private static final int LOG_MAX = 8192; /** * 処理種類ログワーク */ private int[] logStatus = new int[LOG_MAX]; /** * キー情報ログワーク */ private int[] logBitPattern = new int[LOG_MAX]; /** * シーンカウンタログワーク */ private int[] logScene = new int[LOG_MAX]; /** * フレームカウンタログワーク */ private int[] logFrameCounter = new int[LOG_MAX]; /** * ログワーク書き込み用ポインタ */ private int logWritePointer; /** * ログワーク読み込み用ポインタ */ private int logReadPointer; /** * ログを取るかどうかのフラグ */ private boolean logSaveEnable; /** * 1画面あたりに表示するログの行数 */ private static final int LOG_LINE_PER_PAGE = SCREEN_H / STATUS_IMG_H; /** * ログワーク初期化 */ private void initLogWork() { for (int i = 0; i < LOG_MAX; i++) { logStatus[i] = -1; logBitPattern[i] = 0; } logWritePointer = 0; logReadPointer = 0; setLogSaveDisable(); } /** * ログ記録を有効化 */ private void setLogSaveEnable() { logSaveEnable = true; } /** * ログ記録を無効化 */ private void setLogSaveDisable() { logSaveEnable = false; } /** * ログを記録 * * @param kind * 記録する処理種類 */ public void saveProcessHistory(int kind) { if (!logSaveEnable) return; logStatus[logWritePointer] = kind; logBitPattern[logWritePointer] = trgBtnUniq; logScene[logWritePointer] = (mainStep * 1000) + (sceneStep % 1000); logFrameCounter[logWritePointer] = frameCounter; logWritePointer++; if (logWritePointer >= LOG_MAX) logWritePointer = 0; } /** * ログを画面に描画 * * @param g * Graphics */ private void drawLog(Graphics g) { int dx = 0; int dy = SCREEN_H - STATUS_IMG_H; int idx = logWritePointer; for (int i = 0; i < LOG_LINE_PER_PAGE; i++) { idx--; if (idx < 0) idx += LOG_MAX; int status = logStatus[idx]; int bitpat = logBitPattern[idx]; int scene = logScene[idx]; int fcount = logFrameCounter[idx]; if (status >= 0) { drawLogOneLine(g, dx, dy, status, bitpat, scene, fcount); dx = 0; dy -= STATUS_IMG_H; } } logReadPointer = idx; } /** * ログを画面に描画(履歴表示時) * * @param g * Graphics */ private void drawLogHistory(Graphics g) { int dx = 0; int dy = 0; int idx = logReadPointer; for (int i = 0; i < LOG_LINE_PER_PAGE; i++) { int status = logStatus[idx]; int bitpat = logBitPattern[idx]; int scene = logScene[idx]; int fcount = logFrameCounter[idx]; if (status >= 0) { drawLogOneLine(g, dx, dy, status, bitpat, scene, fcount); } dx = 0; dy += STATUS_IMG_H; idx++; if (idx >= LOG_MAX) idx = 0; } } /** * ログ読み込みポインタを+1する */ private void incrementLogReadPointer() { int checkIdx = logWritePointer - LOG_LINE_PER_PAGE + 1; if (checkIdx < 0) checkIdx += LOG_MAX; int idx = logReadPointer; idx++; if (idx >= LOG_MAX) idx = 0; if (idx != checkIdx) { logReadPointer = idx; // System.out.println("WP="+logWritePointer+" RP="+logReadPointer); } } /** * ログ読み込みポインタを-1する */ private void decrementLogReadPointer() { int checkIdx = logWritePointer - 1; if (checkIdx < 0) checkIdx += LOG_MAX; int idx = logReadPointer; idx--; if (idx < 0) idx += LOG_MAX; if (idx != checkIdx) { logReadPointer = idx; // System.out.println("WP="+logWritePointer+" RP="+logReadPointer); } } /** * ログ一行分を画面に描画 * * @param g * Graphics * @param x * 描画位置 x * @param y * 描画位置 y * @param status * 描画する処理種類 * @param bitpat * 描画するビットパターン値 * @param scene * 描画するシーンカウンタ値 * @param fcount * 描画するカウンタ値 */ private void drawLogOneLine(Graphics g, int x, int y, int status, int bitpat, int scene, int fcount) { int cnt_a = (scene != 0) ? (scene / 1000) : 0; int cnt_b = (scene % 1000); int w; w = drawNumberXSmall(g, fcount, 8, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO); x += w; x += 2; w = drawStatus(g, x, y, status); x += w; x += 2; w = drawStatus(g, x, y, ProcessKind.SCENE); x += w; w = drawNumberXSmall(g, cnt_b, 3, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO); x += w; x += 2; w = drawBitPattern(g, x, y, bitpat); x += w; w = drawStatus(g, x, y, ProcessKind.STEP); x += w; w = drawNumberXSmall(g, cnt_a, 1, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO); x += w; x += 2; x = 0; y -= STATUS_IMG_H; } }