package net.violet.platform.vasm;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public final class Vasm {
enum HARDWARE {
V1
}
/**
* Source pour le point bleu.
*/
private static final String POINTBLEU = "pointbleu.vasm";
/**
* Source pour la démo.
*/
private static final String DEMO = "demo.vasm";
/**
* Source pour nabwait.
*/
private static final String WAIT = "wait.vasm";
/**
* Source pour nabasleep.
*/
private static final String ASLEEP = "asleep_v1.0.vasm";
/**
* Source pour nab msg.
*/
private static final String MSG = "msg_v0.9.vasm";
public enum VASM_FILE {
V1(HARDWARE.V1);
private final HARDWARE mHardware = HARDWARE.V1;
private final String bluePointFileName;
private final String demoFileName;
private final String waitFileName;
private final String sleepFileName;
private final String msgFileName;
private VASM_FILE(HARDWARE inHardware) {
this.bluePointFileName = "Nabaztag_" + Vasm.POINTBLEU;
this.demoFileName = "Nabaztag_" + Vasm.DEMO;
this.waitFileName = "Nabaztag_" + Vasm.WAIT;
this.sleepFileName = "Nabaztag_" + Vasm.ASLEEP;
this.msgFileName = "Nabaztag_" + Vasm.MSG;
}
private static Map<HARDWARE, VASM_FILE> VASM_FILE_HARDWARE;
static {
final Map<HARDWARE, VASM_FILE> theMap = new HashMap<HARDWARE, VASM_FILE>();
for (final VASM_FILE aVasmFile : VASM_FILE.values()) {
theMap.put(aVasmFile.getHardware(), aVasmFile);
}
VASM_FILE.VASM_FILE_HARDWARE = Collections.unmodifiableMap(theMap);
}
public static VASM_FILE findByHardware(HARDWARE inHardware) {
return VASM_FILE.VASM_FILE_HARDWARE.get(inHardware);
}
public Map<Pair<String, EAddrType>, Integer> getOpCodes() {
if (HARDWARE.V1.equals(this.mHardware)) {
return Vasm.OPCODES_V1;
}
// sinon OpCodes de daldal
return Vasm.OPCODES_DALDAL;
}
public String getBluePointFileName() {
return this.bluePointFileName;
}
public String getDemoFileName() {
return this.demoFileName;
}
public String getWaitFileName() {
return this.waitFileName;
}
public String getSleepFileName() {
return this.sleepFileName;
}
public String getMsgFileName() {
return this.msgFileName;
}
public HARDWARE getHardware() {
return this.mHardware;
}
}
private static final int MAX_FILE_SIZE = 360000;
private static final int MAX_FILECUT_SIZE = 30000;
private static final byte[] AMBER = new byte[]{'a', 'm', 'b', 'e', 'r'};
private static final byte[] MIND = new byte[]{'m', 'i', 'n', 'd'};
/**
* Chemin vers les fichiers source.
*/
private static final String SOURCE_DIRECTORY = Vasm.class.getCanonicalName().replace(".", "/").replaceFirst("/[^/]+$", "/");
/**
* Chemin vers les fichiers audio.
*/
private static final String AUDIO_DIRECTORY = Vasm.SOURCE_DIRECTORY + "audio/";
/**
* Cache des codes source.
*/
private static final Map<String, String> SOURCE_FILES = new HashMap<String, String>();
/**
* Cache des fichiers audio (ex audiooki).
*/
private static final Map<String, byte[]> AUDIO_FILES = new HashMap<String, byte[]>();
/**
* Taille du cache des binaires compilés.
*/
private static final int BINARY_CACHE_SIZE = 256;
/**
* Cache des binaires compilés.
*/
private static final Map<String, byte[]> BINARY_CACHE = new LinkedHashMap<String, byte[]>() {
@Override
protected boolean removeEldestEntry(Map.Entry<String, byte[]> entry) {
return (size() > Vasm.BINARY_CACHE_SIZE);
}
};
/**
* Classe qui représente l'association entre equ/labels et la valeur.
*/
static class AssoVasm {
private final Map<String, Object> mEquMap;
public AssoVasm() {
this.mEquMap = new HashMap<String, Object>();
}
public void add(String inLabel, String inStrValue) {
this.mEquMap.put(inLabel, inStrValue);
}
public void add(String inLabel, int inValue) {
this.mEquMap.put(inLabel, inValue);
}
public String find(String l) {
final Object theEqu = this.mEquMap.get(l);
final String theResult;
if (theEqu instanceof String) {
theResult = (String) theEqu;
} else {
theResult = null;
}
return theResult;
}
public int findi(String l) {
final Object theEqu = this.mEquMap.get(l);
final int theResult;
if (theEqu instanceof Integer) {
theResult = ((Integer) theEqu).intValue();
} else {
theResult = -1;
}
return theResult;
}
}
// fin de la classe Asso
private final ByteArrayOutputStream mBinary;
private int mLineNumber;
private static int atoi(String inS) {
if (inS == null) {
return 0;
}
final String s = inS.trim();
if (s.length() == 0) {
return 0;
}
if ((s.startsWith("0x")) || (s.startsWith("0X"))) {
return Integer.parseInt(s.substring(2), 16);
}
final Integer y = new Integer(s);
return y.intValue();
}
private static int htoi(String s) {
int i;
int res = 0;
for (i = 0; i < s.length(); i++) {
res <<= 4;
final byte c = (byte) s.charAt(i);
if ((c >= '0') && (c <= '9')) {
res += c - '0';
}
if ((c >= 'a') && (c <= 'f')) {
res += c - 'a' + 10;
}
if ((c >= 'A') && (c <= 'F')) {
res += c - 'A' + 10;
}
}
return res;
}
private static byte[] getfilebytes(String filename) throws IOException {
// TODO : check is the : cases are useful
final byte[] theResult;
// Include dans vasm/audio/
theResult = Vasm.getAudio(filename);
return theResult;
}
private enum EOpType {
OP_r,
OP_w,
OP_i
}
enum EAddrType {
TYPE_o(0, new EOpType[]{}),
TYPE_r(1, new EOpType[]{EOpType.OP_r}),
TYPE_w(2, new EOpType[]{EOpType.OP_w}),
TYPE_ri(1, new EOpType[]{EOpType.OP_r, EOpType.OP_i}),
TYPE_rr(1, new EOpType[]{EOpType.OP_r, EOpType.OP_r}),
TYPE_rir(2, new EOpType[]{EOpType.OP_r, EOpType.OP_i, EOpType.OP_r}),
TYPE_rrw(3, new EOpType[]{EOpType.OP_r, EOpType.OP_r, EOpType.OP_w}),
TYPE_rw(3, new EOpType[]{EOpType.OP_r, EOpType.OP_w}),
TYPE_i(1, new EOpType[]{EOpType.OP_i}),
TYPE_ii(2, new EOpType[]{EOpType.OP_i, EOpType.OP_i}),
TYPE_iiii(4, new EOpType[]{EOpType.OP_i, EOpType.OP_i, EOpType.OP_i, EOpType.OP_i});
private final int mSize;
private final EOpType[] mOpTypes;
public int getSize() {
return this.mSize;
}
private EAddrType(int inSize, EOpType[] inOpTypes) {
this.mSize = inSize;
this.mOpTypes = inOpTypes;
}
public static EAddrType fromOpTypes(EOpType[] inOpTypes) {
EAddrType theResult = null;
for (final EAddrType theType : EAddrType.values()) {
if (Arrays.equals(theType.mOpTypes, inOpTypes)) {
theResult = theType;
break;
}
}
return theResult;
}
}
/**
* Table d'association opcode V1 (avec type) -> valeur (de base).
*/
private static final Map<Pair<String, EAddrType>, Integer> OPCODES_V1;
static {
OPCODES_V1 = new HashMap<Pair<String, EAddrType>, Integer>();
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LD", EAddrType.TYPE_ri), 0x00);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ADD", EAddrType.TYPE_ri), 0x10);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SUB", EAddrType.TYPE_ri), 0x20);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("AND", EAddrType.TYPE_ri), 0x30);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("OR", EAddrType.TYPE_ri), 0x40);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LDR", EAddrType.TYPE_ri), 0x50);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("STR", EAddrType.TYPE_ri), 0x60);
int theValue = 0x70;
// len = 0,0,0,0,0,1,1,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("NOP", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("TRANSITION", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("RTI", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("CLRCC", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SETCC", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ADDCC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SUBCC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("INCW", EAddrType.TYPE_rr), theValue++);
/* 0x78 */
// len = 1,1,1,1,1,1,1,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("DECW", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MULW", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("INPUTRST", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("INT", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ACK", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("WAIT", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("WAIT", EAddrType.TYPE_i), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("RND", EAddrType.TYPE_r), theValue++);
/* 0x80 */
// len = 1,1,1,1,1,1,1,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("DEC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("INC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("CLR", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("NEG", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("NOT", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("TST", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LD", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ADD", EAddrType.TYPE_rr), theValue++);
/* 0x88 */
// len = 1,1,1,1,1,1,1,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SUB", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MUL", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("AND", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("OR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("EOR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LSL", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LSR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ASR", EAddrType.TYPE_rr), theValue++);
/* 0x90 */
// len = 1,1,1,1,1,2,1,2,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ROL", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ROR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("CMP", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BIT", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LDR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LDR", EAddrType.TYPE_rir), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("STR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("STR", EAddrType.TYPE_rir), theValue++);
/* 0x98 */
// len = 3,3,3,2,2,2,2,2,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LDT", EAddrType.TYPE_rrw), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LDTW", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("INPUT", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("RTIJ", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BRA", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BEQ", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BNE", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BGT", EAddrType.TYPE_w), theValue++);
/* 0xA0 */
// len = 2,2,2,2,2,2,2,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BGE", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BLT", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BLE", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BHI", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BHS", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BLO", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BLS", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LED", EAddrType.TYPE_rr), theValue++);
/* 0xA8 */
// len = 1,1,2,2,2,0,1,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("PALETTE", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("ECHO", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("PUSH", EAddrType.TYPE_ii), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("PULL", EAddrType.TYPE_ii), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BSR", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("RTS", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MOTOR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MIDIPLAY", EAddrType.TYPE_r), theValue++);
/* 0xB0 */
// len = 0,1,0,1,1,1,1,1,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MIDISTOP", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("WAVPLAY", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("WAVSTOP", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MSEC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SEC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BUT3", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("VOL", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MVOL", EAddrType.TYPE_r), theValue++);
/* 0xB8 */
// len = 1,1,3,3,1,1,1,0,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("PUSHBUTTON", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SRC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BRAT", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("BSRT", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("OSC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("INV", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("DIV", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("HSV", EAddrType.TYPE_o), theValue++);
/* 0xC0 */
// len = 1,1,1,1,1,1,1,4,
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MOTORGET", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MUSIC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("DOWNLOAD", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("MOTORRST", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SEND", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("SENDREADY", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("LASTPING", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_V1.put(new Pair<String, EAddrType>("TRAME", EAddrType.TYPE_iiii), theValue++);
assert theValue == 0xC8;
}
/**
* Table d'association opcode DALDAL (avec type) -> valeur (de base).
*/
private static final Map<Pair<String, EAddrType>, Integer> OPCODES_DALDAL;
static {
OPCODES_DALDAL = new HashMap<Pair<String, EAddrType>, Integer>();
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LD", EAddrType.TYPE_ri), 0x00);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ADD", EAddrType.TYPE_ri), 0x10);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SUB", EAddrType.TYPE_ri), 0x20);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("AND", EAddrType.TYPE_ri), 0x30);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("OR", EAddrType.TYPE_ri), 0x40);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LDR", EAddrType.TYPE_ri), 0x50);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("STR", EAddrType.TYPE_ri), 0x60);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("CMP", EAddrType.TYPE_ri), 0x70);
int theValue = 0x80;
// len = 0,0,0,0,0,1,1,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("NOP", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("TRANSITION", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("RTI", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("CLRCC", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SETCC", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ADDCC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SUBCC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("INCW", EAddrType.TYPE_rr), theValue++);
/* 0x88 */
// len = 1,1,1,1,1,1,1,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("DECW", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MULW", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("INPUTRST", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("INT", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ACK", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("WAIT", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("WAIT", EAddrType.TYPE_i), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("RND", EAddrType.TYPE_r), theValue++);
/* 0x90 */
// len = 1,1,1,1,1,1,1,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("DEC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("INC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("CLR", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("NEG", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("NOT", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("TST", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LD", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ADD", EAddrType.TYPE_rr), theValue++);
/* 0x98 */
// len = 1,1,1,1,1,1,1,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SUB", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MUL", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("AND", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("OR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("EOR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LSL", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LSR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ASR", EAddrType.TYPE_rr), theValue++);
/* 0xA0 */
// len = 1,1,1,1,1,2,1,2,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ROL", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ROR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("CMP", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BIT", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LDR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LDR", EAddrType.TYPE_rir), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("STR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("STR", EAddrType.TYPE_rir), theValue++);
/* 0xA8 */
// len = 3,3,3,2,2,2,2,2,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LDT", EAddrType.TYPE_rrw), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LDTW", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("INPUT", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("RTIJ", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BRA", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BEQ", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BNE", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BGT", EAddrType.TYPE_w), theValue++);
/* 0xB0 */
// len = 2,2,2,2,2,2,2,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BGE", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BLT", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BLE", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BHI", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BHS", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BLO", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BLS", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LED", EAddrType.TYPE_rr), theValue++);
/* 0xB8 */
// len = 1,1,2,2,2,0,1,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("PALETTE", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ECHO", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("PUSH", EAddrType.TYPE_ii), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("PULL", EAddrType.TYPE_ii), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BSR", EAddrType.TYPE_w), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("RTS", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MOTOR", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MIDIPLAY", EAddrType.TYPE_r), theValue++);
/* 0xC0 */
// len = 0,1,0,1,1,1,1,1,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MIDISTOP", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("WAVPLAY", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("WAVSTOP", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MSEC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SEC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BUT3", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("VOL", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MVOL", EAddrType.TYPE_r), theValue++);
/* 0xC8 */
// len = 1,1,3,3,1,1,1,0,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("PUSHBUTTON", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SRC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BRAT", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("BSRT", EAddrType.TYPE_rw), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("OSC", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("INV", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("DIV", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("HSV", EAddrType.TYPE_o), theValue++);
/* 0xD0 */
// len = 1,1,1,1,1,1,1,4,
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MOTORGET", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MUSIC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("DOWNLOAD", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("MOTORRST", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SEND", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SENDREADY", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LASTPING", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("TRAME", EAddrType.TYPE_iiii), theValue++);
/* 0xD8 */
// len = 0,1,1,1,1,1
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("STOPNET", EAddrType.TYPE_o), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("FADE", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("FADE", EAddrType.TYPE_rr), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("LDC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("ADDC", EAddrType.TYPE_r), theValue++);
Vasm.OPCODES_DALDAL.put(new Pair<String, EAddrType>("SETC", EAddrType.TYPE_r), theValue++);
assert theValue == 0xDD;
}
private int cutline(String src, int inI0, String[] words, int n) {
int i;
final int l = src.length();
int k = 0;
int go = 1;
byte c;
int i0 = inI0;
// on avance jusqu'au prochain det de ligne
while (go > 0) {
if (i0 >= l) {
go = 0;
} else {
c = (byte) src.charAt(i0);
if ((c < 32) && (c != 9)) {
i0++;
} else {
go = 0;
}
if (c == 10) {
this.mLineNumber++;
}
}
}
i = i0;
go = 1;
while (go > 0) {
if (i >= l) {
go = 0;
} else {
c = (byte) src.charAt(i);
if (i0 >= 0) {
if (c <= 32) {
words[k++] = src.substring(i0, i);
i0 = -1;
}
} else if (c > 32) {
i0 = i;
}
if ((c < 32) && (c != 9)) {
go = 0;
} else if (k >= n) {
go = 0;
} else {
i++;
}
}
}
if ((i == l) && (i0 >= 0)) {
words[k++] = src.substring(i0, l);
}
while (k < n) {
words[k++] = "";
}
go = 1;
while (go > 0) {
if (i >= l) {
go = 0;
} else {
c = (byte) src.charAt(i);
if ((c == 10) || (c == 13)) {
go = 0;
} else {
i++;
}
}
}
return i;
}
static String[] cutvirg(String src, AssoVasm equ) {
final String theArgsStrTrimmed = src.trim();
final String[] theArgs;
if (theArgsStrTrimmed.equals("")) {
theArgs = new String[0];
} else {
theArgs = theArgsStrTrimmed.split(",");
final int nbArgs = theArgs.length;
for (int indexArgs = 0; indexArgs < nbArgs; indexArgs++) {
final String theArgTrimmed = theArgs[indexArgs].trim();
final String theVal = equ.find(theArgTrimmed);
if (theVal != null) {
theArgs[indexArgs] = theVal;
} else {
theArgs[indexArgs] = theArgTrimmed;
}
}
}
return theArgs;
}
/**
* Retourne le type d'addressage de l'instruction à partir des opérandes.
*
* @param args le tableau qui contient les opérandes.
* @return le type d'adressage.
*/
static EAddrType typeoper(String[] args) {
final int nbArgs = args.length;
final EOpType[] theOpTypes = new EOpType[nbArgs];
int indexArgs;
for (indexArgs = 0; indexArgs < nbArgs; indexArgs++) {
final String theArg = args[indexArgs];
final EOpType theOpType;
switch (theArg.charAt(0)) {
case 'R':
case 'r':
theOpType = EOpType.OP_r;
break;
case '@':
theOpType = EOpType.OP_w;
break;
default:
theOpType = EOpType.OP_i;
}
theOpTypes[indexArgs] = theOpType;
}
return EAddrType.fromOpTypes(theOpTypes);
}
private static int checkint(String s, int start, int end) {
int i;
byte c;
for (i = start; i < end; i++) {
c = (byte) s.charAt(i);
if ((c < '0') || (c > '9')) {
if ((c != '-') || (i != start)) {
return 0;
}
}
}
return 1;
}
private static int checkhexa(String s, int start, int end) {
int i;
byte c;
for (i = start + 1; i < end; i++) {
c = (byte) s.charAt(i);
if (((c < '0') || (c > '9')) && ((c < 'a') || (c > 'f')) && ((c < 'A') || (c > 'F'))) {
return 0;
}
}
return 1;
}
private void checkInt(String reg) throws VasmException {
if (reg.charAt(0) == '$') {
if (Vasm.checkhexa(reg, 1, reg.length()) == 0) {
throw new VasmException(this.mLineNumber, reg + " is not an int");
// message d'erreur
}
this.mBinary.write(Vasm.htoi(reg.substring(1, reg.length())));
} else {
if (Vasm.checkint(reg, 0, reg.length()) == 0) {
throw new VasmException(this.mLineNumber, reg + " is not an int");
}
this.mBinary.write(Vasm.atoi(reg));
}
}
private void checkRegOP(int inOp, String reg) throws VasmException {
if (Vasm.checkint(reg, 1, reg.length()) == 0) {
throw new VasmException(this.mLineNumber, reg + " is not a register");
}
this.mBinary.write(inOp + Vasm.atoi(reg.substring(1, reg.length())));
}
private void checkReg(int inOp, String reg) throws VasmException {
this.mBinary.write(inOp);
if (Vasm.checkint(reg, 1, reg.length()) == 0) {
throw new VasmException(this.mLineNumber, reg + " is not a register");
}
this.mBinary.write(Vasm.atoi(reg.substring(1, reg.length())));
}
private void checkReg2(int inOp, String a, String b) throws VasmException {
this.mBinary.write(inOp);
if (Vasm.checkint(a, 1, a.length()) == 0) {
throw new VasmException(this.mLineNumber, a + " is not a register");
}
if (Vasm.checkint(b, 1, b.length()) == 0) {
throw new VasmException(this.mLineNumber, b + " is not a register");
}
this.mBinary.write(((Vasm.atoi(a.substring(1, a.length())) & 15) << 4) + (Vasm.atoi(b.substring(1, b.length())) & 15));
}
private void checkAbs(String label, List<Pair<String, Integer>> inLinks) throws VasmException {
final int theIndex = this.mBinary.size();
if (theIndex == 0) {
throw new VasmException(this.mLineNumber, "fdb error");
}
// Ajout de l'offset courant pour écrire l'adresse absolue.
inLinks.add(new Pair<String, Integer>(label, theIndex));
this.mBinary.write(0);
this.mBinary.write(0);
}
private Vasm() {
this.mBinary = new ByteArrayOutputStream();
}
private void includebin(int inLine, String name) throws VasmException, IOException {
final byte[] content = Vasm.getfilebytes(name);
if (content == null) {
throw new VasmException(inLine, "unknown file : " + name);
}
int x = content[0] & 255;
x = (x << 8) + (content[1] & 255);
x = (x << 8) + (content[2] & 255);
x = (x << 8) + (content[3] & 255);
for (int i = 0; i < x; i++) {
this.mBinary.write(content[i + 4]);
}
}
private ByteArrayOutputStream asm(String src, int offset0, VASM_FILE theVasm_file) throws VasmException {
try {
int i = 0;
this.mLineNumber = 1;
final String[] words = new String[3];
// Liste des offsets où écrire les adresses absolues des labels
// (lors de la deuxième passe).
final List<Pair<String, Integer>> links = new LinkedList<Pair<String, Integer>>();
final AssoVasm labels = new AssoVasm();
final AssoVasm equ = new AssoVasm();
int offset = offset0;
int rmb_index = 0;
int src_index = 0;
int countfile = 0;
final ByteArrayOutputStream offfile = new ByteArrayOutputStream();
final ByteArrayOutputStream datafile = new ByteArrayOutputStream();
final Map<Pair<String, EAddrType>, Integer> theOpCodes = theVasm_file.getOpCodes();
while (i < src.length()) {
i = cutline(src, i, words, 3);
// System.out.println(words[0]+StringShop.SPACE+words[1]+
// StringShop.SPACE+words[2]);
if ((words[0].length() == 0) || (words[0].charAt(0) != ';')) {
if ((words[0].length() != 0) && (words[0].charAt(0) == '@')) {
labels.add(words[0], offset);
}
if (words[1].compareToIgnoreCase("END") == 0) {
// Deuxième passe: on écrit les adresses absolues.
final byte[] theBinary = this.mBinary.toByteArray();
for (final Pair<String, Integer> theLink : links) {
final int theAddress = labels.findi(theLink.getFirst());
if (theAddress < 0) {
throw new VasmException(this.mLineNumber, "cannot link " + theLink.getFirst() + " : unknown label");
}
final int theOffset = theLink.getSecond();
theBinary[theOffset] = (byte) ((theAddress >> 8) & 255);
theBinary[theOffset + 1] = (byte) (theAddress & 255);
}
final int theCodeSize = theBinary.length;
final int theResultSize = theCodeSize + 8 + offfile.size() + datafile.size();
final ByteArrayOutputStream theResultStream = new ByteArrayOutputStream(theResultSize);
LibBasic.writeIntTo4Bytes(theResultStream, theCodeSize);
theResultStream.write(theBinary);
LibBasic.writeIntTo4Bytes(theResultStream, countfile);
offfile.writeTo(theResultStream);
datafile.writeTo(theResultStream);
return theResultStream;
}
if (words[1].compareToIgnoreCase("EQU") == 0) {
equ.add(words[0], words[2]);
} else if (words[1].compareToIgnoreCase("RMB") == 0) {
equ.add(words[0], String.valueOf(rmb_index));
rmb_index += Vasm.atoi(words[2]);
} else if (words[1].compareToIgnoreCase("FCB") == 0) {
final String[] args = Vasm.cutvirg(words[2], equ);
for (final String theArg : args) {
checkInt(theArg);
}
offset += args.length;
} else if (words[1].compareToIgnoreCase("FDB") == 0) {
final String[] args = Vasm.cutvirg(words[2], equ);
for (final String theArg : args) {
checkAbs(theArg, links);
}
offset += 2 * args.length;
} else if ((words[0].length() != 0) && (words[0].charAt(0) == '/') && (words[1].compareToIgnoreCase("FILE") == 0)) {
final byte[] theContent = Vasm.getfilebytes(words[2]);
if (theContent == null) {
throw new VasmException(this.mLineNumber, "unknown file : " + words[2]);
}
final int theContentLength = theContent.length;
if (theContentLength > Vasm.MAX_FILE_SIZE) {
datafile.write(theContent, 0, Vasm.MAX_FILE_SIZE);
} else {
datafile.write(theContent);
}
LibBasic.writeIntTo4Bytes(offfile, datafile.size());
equ.add(words[0], String.valueOf(countfile));
countfile++;
} else if ((words[0].length() != 0) && (words[0].charAt(0) == '/') && (words[1].compareToIgnoreCase("FILECUT") == 0)) {
final byte[] theContent = Vasm.getfilebytes(words[2]);
if (theContent == null) {
throw new VasmException(this.mLineNumber, "unknown file : " + words[2]);
}
final int theContentLength = theContent.length;
if (theContentLength > Vasm.MAX_FILECUT_SIZE) {
datafile.write(theContent, 0, Vasm.MAX_FILECUT_SIZE);
} else {
datafile.write(theContent);
}
LibBasic.writeIntTo4Bytes(offfile, datafile.size());
equ.add(words[0], String.valueOf(countfile));
countfile++;
} else if ((words[0].length() != 0) && (words[0].charAt(0) == '/') && (words[1].compareToIgnoreCase("SRCDEF") == 0)) {
equ.add(words[0], String.valueOf(src_index));
src_index++;
} else if (words[1].compareToIgnoreCase("BINARY") == 0) {
includebin(this.mLineNumber, words[2]);
} else if (words[1].length() != 0) {
final String[] args = Vasm.cutvirg(words[2], equ);
final EAddrType theAddrType = Vasm.typeoper(args);
if (theAddrType == null) {
throw new VasmException(this.mLineNumber, "unknown addressing mode : " + words[2]);
}
final Pair<String, EAddrType> opcode = new Pair<String, EAddrType>(words[1].toUpperCase(), theAddrType);
final Integer theInstructionValue = theOpCodes.get(opcode);
if (theInstructionValue == null) {
throw new VasmException(this.mLineNumber, "unknown instruction : " + words[1] + " (" + theAddrType + ")");
}
final int op = theInstructionValue.intValue();
offset += 1 + theAddrType.getSize();
switch (theAddrType) {
case TYPE_ri:
checkRegOP(op, args[0]);
checkInt(args[1]);
break;
case TYPE_o:
this.mBinary.write(op);
break;
case TYPE_r:
checkReg(op, args[0]);
break;
case TYPE_rr:
checkReg2(op, args[0], args[1]);
break;
case TYPE_w:
this.mBinary.write(op);
checkAbs(args[0], links);
break;
case TYPE_rrw:
checkReg2(op, args[0], args[1]);
checkAbs(args[2], links);
break;
case TYPE_rw:
checkReg(op, args[0]);
checkAbs(args[1], links);
break;
case TYPE_i:
this.mBinary.write(op);
checkInt(args[0]);
break;
case TYPE_rir:
checkReg2(op, args[0], args[2]);
checkInt(args[1]);
break;
case TYPE_ii:
this.mBinary.write(op);
checkInt(args[0]);
checkInt(args[1]);
break;
case TYPE_iiii:
this.mBinary.write(op);
checkInt(args[0]);
checkInt(args[1]);
checkInt(args[2]);
checkInt(args[3]);
break;
}
}
}
}
throw new VasmException(this.mLineNumber, "end of file");
} catch (final Throwable t) {
throw new VasmException(this.mLineNumber, "exception (" + t.getMessage() + ")", t);
}
}
private static int checksum(byte[] buf) {
try {
final int l = buf.length;
int i = 0;
byte chk = 0;
for (i = 0; i < l; i++) {
chk += buf[i];
}
return chk;
} catch (final Throwable t) {
return -1;
}
}
static String getSource(String inSourceFileName) throws IOException {
String theResult;
synchronized (Vasm.SOURCE_FILES) {
theResult = Vasm.SOURCE_FILES.get(inSourceFileName);
if (theResult == null) {
final InputStream theStream = Vasm.class.getClassLoader().getResourceAsStream(Vasm.SOURCE_DIRECTORY + inSourceFileName);
if (theStream == null) {
throw new FileNotFoundException(inSourceFileName);
}
final BufferedReader theReader = new BufferedReader(new InputStreamReader(theStream));
final StringBuilder theResultBuilder = new StringBuilder();
while (true) {
final String theLine = theReader.readLine();
if (theLine == null) {
break;
}
theResultBuilder.append(theLine).append("\n");
}
theResult = theResultBuilder.toString();
Vasm.SOURCE_FILES.put(inSourceFileName, theResult);
}
}
return theResult;
}
static byte[] getAudio(String inAudioFileName) throws IOException {
byte[] theResult;
theResult = Vasm.AUDIO_FILES.get(inAudioFileName);
if (theResult == null) {
synchronized (Vasm.AUDIO_FILES) {
theResult = Vasm.AUDIO_FILES.get(inAudioFileName);
if (theResult == null) {
final InputStream theStream = Vasm.class.getClassLoader().getResourceAsStream(Vasm.AUDIO_DIRECTORY + inAudioFileName);
if (theStream == null) {
throw new FileNotFoundException(inAudioFileName);
}
final ByteArrayOutputStream theResultBuilder = new ByteArrayOutputStream();
final byte[] theBuffer = new byte[2048];
while (true) {
final int nbRead = theStream.read(theBuffer);
if (nbRead < 0) {
break;
}
theResultBuilder.write(theBuffer, 0, nbRead);
}
theResult = theResultBuilder.toByteArray();
Vasm.AUDIO_FILES.put(inAudioFileName, theResult);
}
}
}
return theResult;
}
static byte[] asmonly(String src, VASM_FILE theVasm_file) throws VasmException {
final Vasm theVasm = new Vasm();
final byte[] res = theVasm.asm(src, 0, theVasm_file).toByteArray();
return res;
}
public static ByteArrayOutputStream maketrame(String inSourceFileName, String inData, int id, int timeout, VASM_FILE theVasm_file) throws VasmException {
final String theCacheKey = inSourceFileName + ":" + inData;
try {
final ByteArrayOutputStream theResult = new ByteArrayOutputStream();
byte[] theCachedData;
synchronized (Vasm.BINARY_CACHE) {
theCachedData = Vasm.BINARY_CACHE.get(theCacheKey);
if (theCachedData == null) {
String theSource = Vasm.getSource(inSourceFileName);
if (inData != null) {
theSource = theSource.replaceAll("<data>", inData);
}
final Vasm theVasm = new Vasm();
final ByteArrayOutputStream theBinary = theVasm.asm(theSource, 17, theVasm_file);
theCachedData = theBinary.toByteArray();
Vasm.BINARY_CACHE.put(theCacheKey, theCachedData);
}
}
theResult.write((byte) 5);
LibBasic.writeIntTo3Bytes(theResult, theCachedData.length + 15);
theResult.write(Vasm.AMBER);
LibBasic.writeIntTo4Bytes(theResult, id);
theResult.write((byte) timeout);
theResult.write(theCachedData);
theResult.write((byte) (255 - Vasm.checksum(theResult.toByteArray()) - Vasm.checksum(Vasm.MIND)));
theResult.write(Vasm.MIND);
return theResult;
} catch (final IOException anException) {
throw new VasmException(anException);
}
}
static void emptyCache() {
synchronized (Vasm.BINARY_CACHE) {
Vasm.BINARY_CACHE.clear();
}
}
}