package mobilebasic; import com.view.Settings; import java.io.DataInputStream; import java.io.IOException; import java.util.Enumeration; import javax.microedition.io.Connector; import javax.microedition.io.file.FileConnection; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.game.Sprite; public class BasicCanvas extends Canvas implements Runnable { public static final int GAME_UP = 0x0001; public static final int GAME_DOWN = 0x0002; public static final int GAME_LEFT = 0x0004; public static final int GAME_RIGHT = 0x0008; public static final int GAME_FIRE = 0x0010; public static final int GAME_A = 0x0020; public static final int GAME_B = 0x0040; public static final int GAME_C = 0x0080; public static final int GAME_D = 0x0100; public int gameActionBits; private int widthInPixels; private int heightInPixels; public Font font; private int lineHeight; private int charWidth; public int widthInChars; public int heightInChars; private int nlines; private Image graphicsImage; private Image offScreenImage; public Graphics graphicsGc; private Graphics offScreenGc; /* * Sprite / Gobs (Graphic Objects) / Gels (Graphic Elements) * * Updating the sprite is very costly since there is no * direct access to the image data. Consequently all * images should be drawn first. If we have a image * per sprite then there could be a lot of duplication * particularily if there are many similar sprites. */ public java.util.Hashtable gelHashtable; private com.utils.Hashtable spriteHashtable; private Thread thread; public int yposText; public int xposText; private static char[][] lowerCaseKeys = new char[][]{{' ', '\n', '\u0001', '\u0002', '\b', '\t'}, {'%', '$', ',', '\"', '.', ':', '?', '\'', '(', ')', '!', '@', ';', '{', '}', '[', ']'}, {'a', 'b', 'c', '\u0430', '\u0431', '\u0432', '\u0433'}, {'d', 'e', 'f', '\u0434', '\u0435', '\u0451', '\u0436', '\u0437'}, {'g', 'h', 'i', '\u0438', '\u0439', '\u043a', '\u043b'}, {'j', 'k', 'l', '\u043c', '\u043d', '\u043e', '\u043f'}, {'m', 'n', 'o', '\u0440', '\u0441', '\u0442', '\u0443'}, {'p', 'q', 'r', 's', '\u0444', '\u0445', '\u0446', '\u0447'}, {'t', 'u', 'v', '\u0448', '\u0449', '\u044a', '\u044b', '\u044c'}, {'w', 'x', 'y', 'z', '\u044d', '\u044e', '\u044f'}, {'/', '+', '-', '%', '=', '<', '>', '&', '|', '^'}, {'\u0003', '\u0004'}}; private static char[][] upperCaseKeys = new char[][]{{' ', '\n', '\u0001', '\u0002', '\b', '\t'}, {'%', '$', ',', '\"', '.', ':', '?', '\'', '(', ')', '!', '@', ';', '{', '}', '[', ']'}, {'A', 'B', 'C', '\u0410', '\u0411', '\u0412', '\u0413'}, {'D', 'E', 'F', '\u0414', '\u0415', '\u0401', '\u0416', '\u0417'}, {'G', 'H', 'I', '\u0418', '\u0419', '\u041a', '\u041b'}, {'J', 'K', 'L', '\u041c', '\u041d', '\u041e', '\u041f'}, {'M', 'N', 'O', '\u0420', '\u0421', '\u0422', '\u0423'}, {'P', 'Q', 'R', 'S', '\u0424', '\u0425', '\u0426', '\u0427'}, {'T', 'U', 'V', '\u0428', '\u0429', '\u042a', '\u042b', '\u042c'}, {'W', 'X', 'Y', 'Z', '\u042d', '\u042e', '\u042f'}, {'/', '+', '-', '=', '<', '>', '&', '|', '^'}, {'\u0003', '\u0004'}}; private static char[][] keys = lowerCaseKeys; private StringBuffer inputLine; private int var_4c4; private int var_51d; private int var_54f; private boolean var_567; public int keyPressed; private int lastKeyIndex; private int keyClicks; private long keyTime; private long var_6d4; private boolean var_728; private char[] chArray; private Main main; public BasicCanvas(Main var1) { this.main = var1; gameActionBits = 0; gelHashtable = new java.util.Hashtable(); spriteHashtable = new com.utils.Hashtable(); yposText = 0; xposText = 0; inputLine = new StringBuffer(128); var_4c4 = 0; var_51d = 0; var_54f = 0; var_567 = false; keyPressed = 0; lastKeyIndex = -1; keyClicks = 0; keyTime = 0L; var_6d4 = 0L; chArray = new char[1]; setFullScreenMode(Settings.m_fullScreenZ); widthInPixels = getWidth(); heightInPixels = getHeight(); graphicsImage = Image.createImage(widthInPixels, heightInPixels); graphicsGc = this.graphicsImage.getGraphics(); offScreenImage = Image.createImage(widthInPixels, heightInPixels); offScreenGc = offScreenImage.getGraphics(); } public final void SetFontSize(int fontSize) { /* * FACE_ {MONOSPACE|PROPORTIONAL|SYSTEM} * SIZE_ {SMALL|MEDIUM|LARGE} * STYLE_ {BOLD|ITALIC|PLAIN|UNDERLINE} */ //System.out.println("fontSize = " + fontSize); switch (fontSize) { case 1: font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL); break; case 2: default: font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM); break; case 3: font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_LARGE); } charWidth = font.charWidth('W'); widthInChars = widthInPixels / charWidth; if (fontSize == 0 && widthInChars < 12) { //System.out.println("Auto: Changing to SMALL Font"); font = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL); charWidth = font.charWidth('W'); widthInChars = widthInPixels / charWidth; } lineHeight = font.getHeight(); heightInPixels = getHeight(); heightInChars = heightInPixels / lineHeight; graphicsGc.setFont(font); offScreenGc.setFont(font); } public final void Init() { gelHashtable.clear(); spriteHashtable.clear(); } public void DelGel(String key) { gelHashtable.remove(key); } public void DelSprite(String key) { spriteHashtable.remove(key); } /* * Called when the Canvas is getting the Focus again. * If pressing FIRE causes the BASIC program to display a form then the canvas * never gets key release events and the gameActionBits will still indicate * that the Fire button is pressed. This routine allows us to reset the * status before it is re-focussed. */ public final void Focus() { gameActionBits = 0; } public boolean printString(String string, int firstChar, int cursorChar, boolean wrapEnabled, boolean pauseEnabled) { heightInPixels = getHeight(); heightInChars = heightInPixels / lineHeight; int strlen = string.length(); for (int i = firstChar; i < strlen; ++i) { char ch; if ((ch = string.charAt(i)) == '\n' || xposText + charWidth > widthInPixels) { if (!wrapEnabled) { return true; } xposText = 0; yposText += lineHeight; if (yposText + lineHeight > heightInPixels) { if (main.listFlag) { return false; } if (pauseEnabled) { if (nlines >= heightInChars) { while (keyPressed == 0) { // Wait for key press Thread.yield(); } while (keyPressed != 0) { // Wait for key release Thread.yield(); } nlines = 0; } } else { nlines = 0; } Blit(0, lineHeight, widthInPixels, heightInPixels - lineHeight, 0, 0); yposText -= lineHeight; ++nlines; } } /* * Clear line if at start of line */ if (xposText == 0) { graphicsGc.setColor(0xffffff); graphicsGc.fillRect(0, yposText, widthInPixels, lineHeight); graphicsGc.setColor(0); } /* * Draw Character if not newline */ if (ch != '\n') { if (i == cursorChar && !main.listFlag) { graphicsGc.setColor(0); graphicsGc.fillRect(xposText, yposText, charWidth, lineHeight); graphicsGc.setColor(0xffffff); } else { graphicsGc.setColor(0); } graphicsGc.drawChar(ch, xposText + charWidth / 2, yposText, 17); xposText += charWidth; } } return true; } private void sub_1fc(int var1) { if (var1 == -1) { var_51d = 0; var_54f = this.var_4c4; if (xposText > 0) { printString("\n", 0, -1, true, false); xposText = 0; } } else if (var1 == 10) { String var2 = inputLine.toString(); inputLine.delete(0, inputLine.length()); printString(var2 + "\n", 0, -1, true, false); var2.substring(var_4c4); var_51d = var_4c4; var_54f = var_4c4; } else if (var1 == 1) { if (var_54f > var_4c4) { --var_54f; } } else if (var1 == 2) { ++var_54f; if (var_54f > inputLine.length()) { var_54f = inputLine.length(); } } else if (var1 == 8) { if (var_54f > var_4c4) { inputLine.deleteCharAt(var_54f - 1); --var_54f; } } else if (var1 == 9) { if (var_54f < inputLine.length()) { inputLine.deleteCharAt(var_54f); if (var_54f > inputLine.length()) { var_54f = inputLine.length(); } } } else { inputLine.insert(var_54f++, (char) var1); } if (var_54f < var_51d) { var_51d = var_54f; } else if (var_54f >= var_51d + widthInChars) { var_51d = var_54f - widthInChars + 1; } printString(inputLine.toString() + " ", var_51d, var_54f, false, false); xposText = 0; } private void sub_21b(int var1) { synchronized (this) { boolean var3 = false; byte var7; switch (var1) { case 35: var7 = 11; break; case 36: case 37: case 38: case 39: case 40: case 41: case 43: case 44: case 45: case 46: case 47: default: var7 = -1; break; case 42: var7 = 10; break; case 48: var7 = 0; break; case 49: var7 = 1; break; case 50: var7 = 2; break; case 51: var7 = 3; break; case 52: var7 = 4; break; case 53: var7 = 5; break; case 54: var7 = 6; break; case 55: var7 = 7; break; case 56: var7 = 8; break; case 57: var7 = 9; } if (var7 != -1) { label46: { keyTime = System.currentTimeMillis(); if (var7 == lastKeyIndex) { ++keyClicks; if (keyClicks != keys[var7].length) { break label46; } } else { if (lastKeyIndex == -1) { break label46; } char var6; if ((var6 = keys[lastKeyIndex][keyClicks]) == 3) { keys = lowerCaseKeys; } else if (var6 == 4) { keys = upperCaseKeys; } else { sub_1fc(var6); } } keyClicks = 0; } } lastKeyIndex = var7; } } private void sub_22e(int var1) { boolean var2 = System.currentTimeMillis() - this.var_6d4 > 500L; synchronized (this) { if (this.lastKeyIndex != -1) { char var4 = keys[this.lastKeyIndex][this.keyClicks]; this.sub_1fc(var4); this.lastKeyIndex = -1; this.keyClicks = 0; } this.keyTime = 0L; switch (this.getGameAction(var1)) { case 1: case 2: this.sub_1fc(var2 ? 8 : 1); case 3: case 4: case 7: default: break; case 5: case 6: this.sub_1fc(var2 ? 9 : 2); break; case 8: case 9: case 10: case 11: case 12: this.sub_1fc(10); } } } public void start() { var_728 = false; thread = new Thread(this); thread.start(); System.out.println("start()\n"); } public void sub_2b5() { this.var_728 = true; try { System.out.println("join()\n"); this.thread.join(); } catch (InterruptedException ex) { } this.thread = null; } int coun = 0; public void run() { while (!this.var_728) { try { if (this.keyTime > 0L) { synchronized (this) { long var1; if ((var1 = System.currentTimeMillis()) > this.keyTime + 500L && this.keyPressed > 0) { this.keyTime = 0L; this.keyClicks = 0; this.lastKeyIndex = -1; this.sub_1fc(this.keyPressed); } else if (var1 > this.keyTime + 1000L) { char var4 = keys[this.lastKeyIndex][this.keyClicks]; this.keyTime = 0L; this.keyClicks = 0; this.lastKeyIndex = -1; if (var4 == 3) { keys = lowerCaseKeys; } else if (var4 == 4) { keys = upperCaseKeys; } else { this.sub_1fc(var4); } } } } //#if MB191 //# if (this.main.thread == null) { //# this.repaint(); //# Thread.sleep(100L); //# } else { //# Thread.sleep(1L); //# } //#else this.repaint(); Thread.sleep(100L); //#endif } catch (InterruptedException vex) { } catch (ArrayIndexOutOfBoundsException ex) { } catch (Exception ex) { } } } public void keyPressed(int var1) { if (this.main.listFlag) { switch (this.getGameAction(var1)) { case 1: --this.main.offsetLine; break; case 2: this.main.offsetLine -= this.heightInChars; case 3: case 4: default: break; case 5: this.main.offsetLine += this.heightInChars; break; case 6: ++this.main.offsetLine; } main.listInCanvas(); } else { this.keyPressed = var1; if (var1 == -8) { this.sub_1fc(8); } switch (this.getGameAction(var1)) { case 1: this.gameActionBits = 1; break; case 2: this.gameActionBits = 4; case 3: case 4: case 7: default: break; case 5: this.gameActionBits = 8; break; case 6: this.gameActionBits = 2; break; case 8: this.gameActionBits = 16; break; case 9: this.gameActionBits = 32; break; case 10: this.gameActionBits = 64; break; case 11: this.gameActionBits = 128; break; case 12: this.gameActionBits = 256; } if (this.var_567) { if (var1 > 0) { this.sub_21b(var1); return; } this.var_6d4 = System.currentTimeMillis(); } } } public void keyReleased(int var1) { if (this.var_567 && var1 < 0) { this.sub_22e(var1); } this.keyPressed = 0; this.gameActionBits = 0; } public void Blit(int var1, int var2, int var3, int var4, int var5, int var6) { int var7 = this.graphicsGc.getClipX(); int var8 = this.graphicsGc.getClipY(); int var9 = this.graphicsGc.getClipWidth(); int var10 = this.graphicsGc.getClipHeight(); this.offScreenGc.drawImage(this.graphicsImage, -var1, -var2, 20); this.graphicsGc.setClip(var5, var6, var3, var4); this.graphicsGc.drawImage(this.offScreenImage, var5, var6, 20); this.graphicsGc.setClip(var7, var8, var9, var10); } public final void GelLoad(String var1, String var2) { Image var3 = null; try { if (var2.startsWith("file:")) { DataInputStream var4 = null; byte[] var7 = new byte[(var4 = ((FileConnection) Connector.open(var2)).openDataInputStream()).available() + 1]; int var8 = 0; int var6; while ((var6 = var4.read(var7, var8, var7.length - var8)) != -1) { if ((var8 += var6) == var7.length) { byte[] var9 = new byte[var7.length + 4096]; System.arraycopy(var7, 0, var9, 0, var8); var7 = var9; } } var3 = Image.createImage(var7, 0, var8); var4.close(); } else { var3 = Image.createImage("/" + var2); } this.gelHashtable.put(var1, var3); } catch (IOException ex) { } } public void AlphaGel(String name, int i) { Image img = (Image) gelHashtable.get(name); if (img == null) { return; } int w = img.getWidth(); int h = img.getHeight(); int length = w * h; int[] rgbData = new int[length]; img.getRGB(rgbData, 0, w, 0, 0, w, h); int pixel, r, g, b; for (int k = 0; k < length; k++) { pixel = rgbData[k]; r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; rgbData[k] = (i << 24) | ((r << 16) | (g << 8) | b); } gelHashtable.put(name, Image.createRGBImage(rgbData, w, h, true)); } public void ColorAlphaGel(String name, int a, int r1, int g1, int b1) { Image img = (Image) gelHashtable.get(name); if (img == null) { return; } int color = (0xff << 24) | (r1 << 16) | (g1 << 8) | b1; int w = img.getWidth(); int h = img.getHeight(); int length = w * h; int[] rgbData = new int[length]; img.getRGB(rgbData, 0, w, 0, 0, w, h); int pixel, r, g, b; for (int k = 0; k < length; k++) { pixel = rgbData[k]; if (pixel == color) { r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; rgbData[k] = (a << 24) | ((r << 16) | (g << 8) | b); } } gelHashtable.put(name, Image.createRGBImage(rgbData, w, h, true)); } public void GelGrab(String name, int x, int y, int w, int h) { Image image = Image.createImage(w, h); Graphics gr = image.getGraphics(); gr.drawImage(graphicsImage, -x, -y, 20); gelHashtable.put(name, image); } public int GelWidth(String name) { Image var2; int var3; if ((var2 = (Image) this.gelHashtable.get(name)) != null) { var3 = var2.getWidth(); } else { var3 = 0; } return var3; } public int GelHeight(String var1) { Image var2; int var3; if ((var2 = (Image) this.gelHashtable.get(var1)) != null) { var3 = var2.getHeight(); } else { var3 = 0; } return var3; } public void DrawGel(String nameGel, int x, int y) { Image img = (Image) gelHashtable.get(nameGel); if (img != null) { graphicsGc.drawImage(img, x, y, 20); } } public void SpriteGEL(String nameSpr, String nameGel) { Image img; if ((img = (Image) gelHashtable.get(nameGel)) != null) { spriteHashtable.put(nameSpr, new Sprite(img)); } else { throw new BasicError(256, "Invalid GEL"); } } public void SpriteMove(String var1, int var2, int var3) { Sprite var4; if ((var4 = (Sprite) spriteHashtable.get(var1)) != null) { var4.setPosition(var2, var3); } else { throw new BasicError(257, "Invalid Sprite"); } } public int SpriteHit(String name1, String name2) { Sprite spr1 = ((Sprite) spriteHashtable.get(name1)); Sprite spr2 = ((Sprite) spriteHashtable.get(name2)); if (spr1 != null && spr2 != null) { byte result = 0; if (spr1.collidesWith(spr2, true)) { result = 1; } return result; } else { throw new BasicError(257, "Invalid Sprite"); } } public void paint(Graphics g) { offScreenGc.drawImage(graphicsImage, 0, 0, 20); Enumeration spriteEnumeration = spriteHashtable.elements(); while (spriteEnumeration.hasMoreElements()) { ((Sprite) spriteEnumeration.nextElement()).paint(offScreenGc); } g.drawImage(offScreenImage, 0, 0, Graphics.TOP | Graphics.LEFT); } }