+-libraryjars C:\WTK2.5.2\lib\jsr75.jar;C:\WTK2.5.2\lib\jsr082.jar;C:\WTK2.5.2\lib\midpapi20.jar;C:\WTK2.5.2\lib\cldcapi11.jar
+-injars C:\Documents and Settings\chip.NEO\j2mewtk\2.5.2\apps\BlinkenCPU\bin\BlinkenCPU.jar
+-outjar C:\DOCUME~1\chip.NEO\LOCALS~1\Temp\BlinkenCPU.jar
+-keep public class * extends javax.microedition.midlet.MIDlet
+-dontusemixedcaseclassnames
+J2ME-WS: false
+J2ME-XMLRPC: false
+JSR082: true
+JSR179: false
+JSR180: false
+JSR184: false
+JSR211: false
+JSR226: false
+JSR229: false
+JSR234: false
+JSR238: false
+JSR239: false
+JSR75: true
+MMAPI: false
+SATSA-APDU: false
+SATSA-CRYPTO: false
+SATSA-JCRMI: false
+SATSA-PKI: false
+WMA0: true
+WMA1.1: false
+WMA2.0: false
+configuration: CLDC1.1
+platform: CUSTOM
+profile: MIDP2.0
+import java.io.*;
+import javax.microedition.lcdui.*;
+import javax.microedition.io.*;
+import javax.microedition.io.file.*;
+import javax.microedition.midlet.MIDlet;
+
+public class BlinkenCPU extends MIDlet implements CommandListener, Runnable {
+ private BlinkenCanvas canvas;
+ private Display display;
+ private BlinkenEngine engine;
+ private Thread thread;
+
+ private static final Command start = new Command("Start", Command.SCREEN, 1);
+ private static final Command stop = new Command("Stop", Command.SCREEN, 1);
+ private static final Command load = new Command("Load", Command.SCREEN, 2);
+ private static final Command clear = new Command("Clear", Command.SCREEN, 3);
+ private static final Command exit = new Command("Exit", Command.EXIT, 2);
+ private static final Command darn = new Command("Darn", Command.EXIT, 1);
+
+
+ public void startApp() {
+ display = Display.getDisplay(this);
+ engine = new BlinkenEngine();
+ engine.loadState();
+ canvas = new BlinkenCanvas(engine);
+
+ canvas.addCommand(load);
+ canvas.addCommand(clear);
+ canvas.addCommand(exit);
+ if (engine.loaded())
+ canvas.addCommand(start);
+ canvas.setCommandListener(this);
+ canvas.draw();
+
+ display.setCurrent(canvas);
+
+ thread = new Thread(this);
+ thread.start();
+ }
+
+ public void pauseApp() {
+ display.flashBacklight(0);
+ }
+
+ public void destroyApp(boolean unconditional) {
+ display.flashBacklight(0);
+ engine.saveState();
+ }
+
+ public void run() {
+ while (true) {
+ if (engine.running()) {
+ try {
+ display.flashBacklight(0x7FFFFFFF);
+ engine.step();
+ } catch (BlinkenEngineException e) {
+ engine.stop();
+ shitSauce("Execution error", e.error);
+ }
+ }
+ canvas.update();
+ canvas.draw();
+ try {
+ Thread.sleep(100);
+ } catch(InterruptedException e) {
+ }
+ }
+ }
+
+ public void commandAction(Command c, Displayable d) {
+ if (c == start) {
+ if (engine.loaded()) {
+ engine.run();
+ canvas.removeCommand(start);
+ canvas.addCommand(stop);
+ } else {
+ display.setCurrent(new Alert("Code not loaded"));
+ }
+ } else if (c == stop) {
+ engine.stop();
+ canvas.removeCommand(stop);
+ canvas.addCommand(start);
+ display.flashBacklight(0);
+ } else if (c == load) {
+ BlinkenFileSelect bfs = new BlinkenFileSelect(this, engine, display);
+ bfs.start();
+ } else if (c == clear) {
+ engine.clear();
+ } else if (c == exit) {
+ destroyApp(true);
+ notifyDestroyed();
+ } else if (c == darn) {
+ display.setCurrent(canvas);
+ }
+ }
+
+ public void loadFile(String file) {
+ try {
+ FileConnection fc = (FileConnection) Connector.open(file, Connector.READ);
+ if (!fc.exists()) {
+ display.setCurrent(new Alert("File does not exist"));
+ return;
+ }
+ InputStream f = fc.openInputStream();
+ try {
+ engine.compile(f);
+ canvas.addCommand(start);
+ } catch (BlinkenEngineException e) {
+ shitSauce("Failed to compile " + file, e.error);
+ }
+ f.close();
+ fc.close();
+ display.setCurrent(canvas);
+ } catch (IOException e) {
+ display.setCurrent(new Alert("File Open Failed\n" + e));
+ }
+ }
+
+ public void shitSauce(String title, String error) {
+ TextBox b = new TextBox(title, error, 1024, TextField.ANY | TextField.UNEDITABLE);
+ b.addCommand(darn);
+ b.setCommandListener(this);
+ display.setCurrent(b);
+ }
+}
+import javax.microedition.lcdui.game.GameCanvas;
+import javax.microedition.lcdui.Graphics;
+
+public class BlinkenCanvas extends GameCanvas {
+ private BlinkenEngine engine;
+ private int x, y;
+
+ public BlinkenCanvas(BlinkenEngine e) {
+ super(false);
+ engine = e;
+ x = y = 0;
+ }
+
+ public void draw() {
+ Graphics g = getGraphics();
+ g.setColor(0);
+ g.fillRect(0, 0, getWidth(), getHeight());
+
+ for (int i = 0; i < engine.width; i++) {
+ for (int j = 0; j < engine.height; j++) {
+ if (engine.values[i][j] != 0) {
+ g.setColor(0xFF0000);
+ } else {
+ g.setColor(0x400000);
+ }
+ g.fillArc(i*8, j*8, 8, 8, 0, 360);
+ }
+ }
+ g.setColor(0x00FF00);
+ g.drawRect(x*8, y*8, 8, 8);
+ flushGraphics();
+ }
+
+ public void update() {
+ int keys = getKeyStates();
+ if ((keys & LEFT_PRESSED) != 0) {
+ x--;
+ if (x < 0) x = engine.width - 1;
+ } else if ((keys & RIGHT_PRESSED) != 0) {
+ x++;
+ x = x % engine.width;
+ } else if ((keys & UP_PRESSED) != 0) {
+ y--;
+ if (y < 0) y = engine.height - 1;
+ } else if ((keys & DOWN_PRESSED) != 0) {
+ y++;
+ y = y % engine.height;
+ } else if ((keys & FIRE_PRESSED) != 0) {
+ engine.values[x][y] = engine.values[x][y] != 0 ? 0 : 1;
+ }
+ }
+}
+import javax.microedition.io.*;
+import javax.microedition.rms.*;
+import java.io.*;
+import java.util.Vector;
+
+public class BlinkenEngine {
+ public int width;
+ public int height;
+ public int[][] values;
+ private int[][] acc;
+ private int[][] store;
+ private boolean running;
+
+ // instruction codes
+ private static final int AND = 0;
+ private static final int OR = 1;
+ private static final int NOT = 2;
+ private static final int XOR = 3;
+ private static final int ADD = 4;
+ private static final int SUB = 5;
+ private static final int GTI = 6;
+ private static final int LTI = 7;
+ private static final int EQI = 8;
+ private static final int NEI = 9;
+ private static final int STO = 10;
+ private static final int RCL = 11;
+ private static final int SWP = 12;
+ private static final int ZERO = 13;
+ private static final int INC = 14;
+ private static final int DEC = 15;
+
+ // Memory reference codes
+ private static final int NORTH = 0;
+ private static final int EAST = 1;
+ private static final int SOUTH = 2;
+ private static final int WEST = 3;
+ private static final int NORTHEAST = 4;
+ private static final int SOUTHEAST = 5;
+ private static final int SOUTHWEST = 6;
+ private static final int NORTHWEST = 7;
+ private static final int SELF = 8;
+ private static final int STORE = 9;
+
+ private class BlinkenCode {
+ public int i;
+ public int m;
+
+ public BlinkenCode(int instruction, int memory) {
+ this.i = instruction;
+ this.m = memory;
+ }
+ }
+
+ private BlinkenCode[] code = null;
+
+ public BlinkenEngine(int w, int h) {
+ width = w;
+ height = h;
+
+ values = new int[w][h];
+ acc = new int[w][h];
+ store = new int[w][h];
+ running = false;
+ }
+
+ public BlinkenEngine() {
+ this(16,16);
+ }
+
+ private BlinkenCode parseLine(InputStream f) throws BlinkenEngineException {
+ String s = "";
+ String cmd = null, arg = null;
+ Vector words = new Vector();
+ int c, a;
+
+ while (true) {
+ try {
+ c = f.read();
+ } catch (IOException e) {
+ c = -1;
+ }
+ if (c == -1 || c == '\r' || c == '\n') {
+ words.addElement(s);
+ break;
+ } else if (c == ' ' || c == ' ') {
+ words.addElement(s);
+ s = "";
+ } else {
+ s += (char)c;
+ }
+ }
+ if (words.size() >= 1) {
+ cmd = ((String)words.elementAt(0)).toLowerCase();
+ if (cmd.length() == 0) {
+ if (c == -1) return null;
+ else return parseLine(f);
+ }
+ }
+ if (words.size() >= 2) {
+ arg = ((String)words.elementAt(1)).toLowerCase();
+ }
+
+ if (cmd.equals("and")) {
+ c = AND;
+ } else if (cmd.equals("or")) {
+ c = OR;
+ } else if (cmd.equals("not")) {
+ c = NOT;
+ } else if (cmd.equals("xor")) {
+ c = XOR;
+ } else if (cmd.equals("add")) {
+ c = ADD;
+ } else if (cmd.equals("sub")) {
+ c = SUB;
+ } else if (cmd.equals("gti")) {
+ c = GTI;
+ } else if (cmd.equals("lti")) {
+ c = LTI;
+ } else if (cmd.equals("eqi")) {
+ c = EQI;
+ } else if (cmd.equals("nei")) {
+ c = NEI;
+ } else if (cmd.equals("sto")) {
+ c = STO;
+ } else if (cmd.equals("rcl")) {
+ c = RCL;
+ } else if (cmd.equals("swp")) {
+ c = SWP;
+ } else if (cmd.equals("zero")) {
+ c = ZERO;
+ } else if (cmd.equals("inc")) {
+ c = INC;
+ } else if (cmd.equals("dec")) {
+ c = DEC;
+ } else {
+ throw new BlinkenEngineException("Unknown instruction " + cmd);
+ }
+
+ switch (c) {
+ case NOT:
+ case STO:
+ case RCL:
+ case SWP:
+ case ZERO:
+ case INC:
+ case DEC:
+ a = 0;
+ break;
+ case LTI:
+ case GTI:
+ case EQI:
+ case NEI:
+ a = Integer.parseInt(arg);
+ break;
+ default:
+ arg = arg.toLowerCase();
+ if (arg.equals("n")) {
+ a = NORTH;
+ } else if (arg.equals("e")) {
+ a = EAST;
+ } else if (arg.equals("s")) {
+ a = SOUTH;
+ } else if (arg.equals("w")) {
+ a = WEST;
+ } else if (arg.equals("ne")) {
+ a = NORTHEAST;
+ } else if (arg.equals("se")) {
+ a = SOUTHEAST;
+ } else if (arg.equals("nw")) {
+ a = NORTHWEST;
+ } else if (arg.equals("sw")) {
+ a = SOUTHWEST;
+ } else if (arg.equals("self")) {
+ a = SELF;
+ } else if (arg.equals("o")) {
+ a = STORE;
+ } else {
+ throw new BlinkenEngineException("Invalid memory reference " + arg);
+ }
+ }
+
+ return new BlinkenCode(c, a);
+ }
+
+ public void compile(InputStream f) throws BlinkenEngineException {
+ BlinkenCode c;
+ Vector v = new Vector();
+
+ while (true) {
+ c = parseLine(f);
+ if (c == null) break;
+ v.addElement(c);
+ }
+ code = new BlinkenCode[v.size()];
+ v.copyInto(code);
+ }
+
+ public void run() {
+ running = true;
+ }
+
+ public void stop() {
+ running = false;
+ }
+
+ public void clear() {
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ values[i][j] = store[i][j] = 0;
+ }
+ }
+ }
+
+ public boolean running() {
+ return running;
+ }
+
+ public boolean loaded() {
+ return code != null;
+ }
+
+ public void step() throws BlinkenEngineException {
+ int PC;
+
+ if (!running) return;
+
+ // First, copy values into acc
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ acc[i][j] = values[i][j];
+ }
+ }
+
+ for (PC = 0; PC < code.length; PC++) {
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ int v = 0;
+
+ switch (code[PC].i) {
+ case NOT:
+ case GTI:
+ case LTI:
+ case EQI:
+ case NEI:
+ case STO:
+ case RCL:
+ case SWP:
+ case ZERO:
+ case INC:
+ case DEC:
+ break;
+ default:
+ if (code[PC].m == STORE) {
+ v = store[i][j];
+ } else {
+ int ii = i;
+ int jj = j;
+
+ switch (code[PC].m) {
+ case NORTH:
+ jj--;
+ break;
+ case EAST:
+ ii++;
+ break;
+ case SOUTH:
+ jj++;
+ break;
+ case WEST:
+ ii--;
+ break;
+ case NORTHEAST:
+ jj--;
+ ii++;
+ break;
+ case SOUTHEAST:
+ jj++;
+ ii++;
+ break;
+ case SOUTHWEST:
+ jj++;
+ ii--;
+ break;
+ case NORTHWEST:
+ jj--;
+ ii--;
+ break;
+ case SELF:
+ }
+ if (ii < 0)
+ ii += width;
+ else
+ ii %= width;
+ if (jj < 0)
+ jj += height;
+ else
+ jj %= height;
+
+ v = values[ii][jj];
+ }
+ }
+
+ switch (code[PC].i) {
+ case AND:
+ acc[i][j] = acc[i][j] & v;
+ break;
+ case OR:
+ acc[i][j] = acc[i][j] | v;
+ break;
+ case NOT:
+ acc[i][j] = (~acc[i][j]) & 1;
+ break;
+ case XOR:
+ acc[i][j] = acc[i][j] ^ v;
+ break;
+ case ADD:
+ acc[i][j] += v;
+ break;
+ case SUB:
+ acc[i][j] -= v;
+ break;
+ case GTI:
+ acc[i][j] = (acc[i][j] > code[PC].m ? 1 : 0);
+ break;
+ case LTI:
+ acc[i][j] = (acc[i][j] < code[PC].m ? 1 : 0);
+ break;
+ case EQI:
+ acc[i][j] = (acc[i][j] == code[PC].m ? 1 : 0);
+ break;
+ case NEI:
+ acc[i][j] = (acc[i][j] != code[PC].m ? 1 : 0);
+ break;
+ case STO:
+ store[i][j] = acc[i][j];
+ break;
+ case RCL:
+ acc[i][j] = store[i][j];
+ break;
+ case SWP:
+ int tmp = acc[i][j];
+ acc[i][j] = store[i][j];
+ store[i][j] = tmp;
+ break;
+ case ZERO:
+ acc[i][j] = 0;
+ break;
+ case INC:
+ acc[i][j]++;
+ break;
+ case DEC:
+ acc[i][j]--;
+ break;
+ default:
+ throw new BlinkenEngineException("Bad instruction code: " + code[PC].i);
+ }
+ }
+ }
+ }
+
+ // Swap values and acc
+ int[][] tmp = values;
+ values = acc;
+ acc = tmp;
+ }
+
+ // Save the engine state in a RecordStore
+ public void saveState() {
+ RecordStore rs = null;
+ byte[] tmp;
+
+ try {
+ RecordStore.deleteRecordStore("state");
+ } catch (RecordStoreException e) {
+ System.out.println("Could not delete RecordStore. No biggie. " + e.toString());
+ }
+ try {
+ rs = RecordStore.openRecordStore("state", true);
+ } catch (RecordStoreException e) {
+ System.out.println("Could not open RecordStore: " + e.toString());
+ return;
+ }
+
+ try {
+ ByteArrayOutputStream b = new ByteArrayOutputStream();
+ DataOutputStream f = new DataOutputStream(b);
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ f.writeInt(values[i][j]);
+ f.writeInt(store[i][j]);
+ }
+ }
+ tmp = b.toByteArray();
+ f.close();
+ b.close();
+ } catch (IOException e) {
+ System.out.println("IO Error storing data: " + e.toString());
+ tmp = new byte[0];
+ }
+ try {
+ rs.addRecord(tmp, 0, tmp.length);
+ } catch (RecordStoreException e) {
+ System.out.println("Error writing data: " + e.toString());
+ }
+
+ if (code != null) {
+ tmp = new byte[code.length * 2];
+ for (int i = 0; i < code.length; i++) {
+ tmp[i*2] = (byte) code[i].i;
+ tmp[i*2+1] = (byte) code[i].m;
+ }
+ } else {
+ tmp = new byte[0];
+ }
+ try {
+ rs.addRecord(tmp, 0, tmp.length);
+ } catch (RecordStoreException e) {
+ System.out.println("Failure adding code to RecordStore: " + e.toString());
+ }
+
+ try {
+ rs.closeRecordStore();
+ } catch (RecordStoreException e) {
+ }
+ }
+
+ // Load state from RecordStore
+ public void loadState() {
+ RecordStore rs;
+ byte[] tmp;
+
+ try {
+ rs = RecordStore.openRecordStore("state", false);
+ } catch (RecordStoreException e) {
+ System.out.println("Could not open RecordStore: " + e.toString());
+ return;
+ }
+
+ try {
+ tmp = rs.getRecord(1);
+ ByteArrayInputStream b = new ByteArrayInputStream(tmp);
+ DataInputStream f = new DataInputStream(b);
+
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ values[i][j] = f.readInt();
+ store[i][j] = f.readInt();
+ }
+ }
+ f.close();
+ b.close();
+ } catch (RecordStoreException e) {
+ System.out.println("Error retrieving data record: " + e.toString());
+ } catch (IOException e) {
+ System.out.println("Error reading data: " + e.toString());
+ }
+
+ try {
+ tmp = rs.getRecord(2);
+ if (tmp != null) {
+ code = new BlinkenCode[tmp.length / 2];
+ for (int i = 0; i < code.length; i++) {
+ code[i] = new BlinkenCode((int)tmp[i*2], (int)tmp[i*2+1]);
+ }
+ }
+ } catch (RecordStoreException e) {
+ System.out.println("Could not read Code: " + e.toString());
+ }
+
+ try {
+ rs.closeRecordStore();
+ } catch (RecordStoreException e) {
+ System.out.println("Failure closing RecordStore: " + e.toString());
+ }
+ }
+}
+// Java: Raising the bar for pedantry
+
+public class BlinkenEngineException extends Exception {
+ public String error;
+
+ public BlinkenEngineException(String e) {
+ error = e;
+ }
+}
+import javax.microedition.lcdui.*;
+import javax.microedition.io.*;
+import javax.microedition.io.file.*;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+
+class LoadThread extends Thread {
+ private BlinkenCPU blink;
+ private String file;
+
+ public LoadThread(BlinkenCPU b, String fn) {
+ super();
+ blink = b;
+ file = fn;
+ }
+
+ public void run() {
+ blink.loadFile(file);
+ }
+}
+
+
+public class BlinkenFileSelect extends Thread implements CommandListener {
+ private List fileSelect;
+ private BlinkenCPU blink;
+ private Display display;
+ private BlinkenEngine engine;
+ private String location;
+
+ private static final Command load = new Command("Load", Command.OK, 1);
+ private static final String[] locations = { "file:///other/", "file:///c:/other/", "file:///" };
+
+ public BlinkenFileSelect(BlinkenCPU b, BlinkenEngine e, Display d) {
+ super();
+ blink = b;
+ engine = e;
+ display = d;
+ }
+
+ public void run() {
+ FileConnection fc = null;
+ Enumeration roots = FileSystemRegistry.listRoots();
+
+ while (roots.hasMoreElements()) {
+ location = "file:///" + roots.nextElement() + "other/";
+ try {
+ fc = (FileConnection) Connector.open(location, Connector.READ);
+ } catch (IOException e) {
+ blink.shitSauce("IO Error", "Could not open " + location);
+ continue;
+ }
+ if (fc.isDirectory()) {
+ break;
+ } else {
+ fc = null;
+ }
+ }
+ if (fc == null) {
+ blink.shitSauce("Directory not found", "No suitable directory found for data files");
+ return;
+ }
+
+ Vector v = new Vector();
+ Enumeration names;
+ try {
+ names = fc.list("*.bc", false);
+ } catch (IOException e) {
+ blink.shitSauce("IO Error", "Could not list directory");
+ return;
+ }
+ while (names.hasMoreElements())
+ v.addElement(names.nextElement());
+ if (v.size() == 0) {
+ display.setCurrent(new Alert("No files found"));
+ return;
+ }
+ String[] files = new String[v.size()];
+ v.copyInto(files);
+
+ fileSelect = new List("Select Code", List.IMPLICIT, files, null);
+ fileSelect.setSelectCommand(load);
+ fileSelect.setCommandListener(this);
+ display.setCurrent(fileSelect);
+ }
+
+ public void commandAction(Command c, Displayable d) {
+ if (c == load) {
+ LoadThread lt = new LoadThread(blink, location + fileSelect.getString(fileSelect.getSelectedIndex()));
+ lt.start();
+ }
+ }
+}