#include #include #include #include #include ////////////////////////////////// Constants ////////////////////////////////// // Break conditions #define BREAK_FRAME 1 #define BREAK_POINT 2 // Extra properties #define EXT_PIXELS 0 #define EXT_SAMPLES 1 //////////////////////////////////// Types //////////////////////////////////// // Additional monitor state for simulations typedef struct { int32_t breaks; uint32_t left[256]; uint8_t pixels[384 * 224 * 4]; uint32_t right[256]; float samples[41700 * 2]; } Ext; ////////////////////////////////// Callbacks ////////////////////////////////// // Frame callback int wasmOnFrame(VB *sim) { ((Ext *) vbGetUserData(sim))->breaks |= BREAK_FRAME; return 1; } /////////////////////////////// Module Exports //////////////////////////////// // Instantiate a simulation EMSCRIPTEN_KEEPALIVE void* CreateSim() { size_t sizeOfSim = vbSizeOf(); uint8_t *pointer = malloc(sizeOfSim + sizeof (Ext)); // Configure sim VB *sim = vbInit((VB *) pointer); vbSetFrameCallback(sim, &wasmOnFrame); vbSetOption(sim, VB_PSEUDO_HALT, 1); // Configure extra Ext *ext = (Ext *) (pointer + sizeOfSim); ext->breaks = 0; vbSetUserData(sim, ext); // Initialize pixels with opaque black for (unsigned x = 0; x < 384 * 224; x++) ((uint32_t *) ext->pixels)[x] = 0xFF000000; return sim; } // Disassemble from a simulation EMSCRIPTEN_KEEPALIVE void* Disassemble( int bcondNotation, int conditionCase, int conditionCL, int conditionEZ, int conditionNotation, int hexCase, int hexNotation, int memoryNotation, int mnemonicCase, int operandOrder, int programCase, int programNotation, int setfNotation, int systemCase, int systemNotation, VB *sim, uint32_t address, unsigned length, int line ) { VBU_DasmConfig config; config.bcondNotation = bcondNotation; config.conditionCase = conditionCase; config.conditionCL = conditionCL; config.conditionEZ = conditionEZ; config.conditionNotation = conditionNotation; config.hexCase = hexCase; config.hexNotation = hexNotation; config.memoryNotation = memoryNotation; config.mnemonicCase = mnemonicCase; config.operandOrder = operandOrder; config.programCase = programCase; config.programNotation = programNotation; config.setfNotation = setfNotation; config.systemCase = systemCase; config.systemNotation = systemNotation; return vbuDisassemble(sim, address, &config, length, line); } // Process simulations EMSCRIPTEN_KEEPALIVE int Emulate(VB **sims, unsigned count, uint32_t *clocks) { for (unsigned x = 0; x < count; x++) ((Ext *) vbGetUserData(sims[x]))->breaks = 0; return vbEmulateEx(sims, count, clocks); } // Retrieve the break condition flags for a sim EMSCRIPTEN_KEEPALIVE int32_t GetBreaks(VB *sim) { return ((Ext *) vbGetUserData(sim))->breaks; } // Serialize disassembled lines into a linear buffer EMSCRIPTEN_KEEPALIVE void GetDasm(uint32_t *buffer, void *dasm, int count) { for (int x = 0; x < count; x++) { VBU_DasmLine *line = &((VBU_DasmLine *) dasm)[x]; // Numeric data *buffer++ = line->address; *buffer++ = line->codeLength; for (int y = 0; y < 4; y++) *buffer++ = line->code[y]; *buffer++ = line->isPC; // Text data -- Store offset of string pointer from start of dasm *buffer++ = (uint32_t) ((void *) &line->text.address - dasm); for (int y = 0; y < 4; y++) *buffer++ = (uint32_t) ((void *) &line->text.code[y] - dasm); *buffer++ = (uint32_t) ((void *) &line->text.mnemonic - dasm); *buffer++ = line->text.operandsLength; for (int y = 0; y < 3; y++) *buffer++ = (uint32_t) ((void *) &line->text.operands[y] - dasm); } } // Retrieve an extra property EMSCRIPTEN_KEEPALIVE void* GetExt(VB *sim, int id) { Ext *ext = (Ext *) vbGetUserData(sim); switch (id) { case EXT_PIXELS : return ext->pixels; case EXT_SAMPLES: return ext->samples; } return NULL; } // Retrieve anaglyph-tinted pixels from a sim EMSCRIPTEN_KEEPALIVE void GetPixels(VB *sim) { Ext *ext = (Ext *) vbGetUserData(sim); uint8_t *pixels = ext->pixels; vbGetPixels(sim, pixels, 4, 384 * 4, pixels + 1, 4, 384 * 4); for (unsigned x = 0; x < 384 * 224 * 4; x += 4, pixels += 4) *(uint32_t *) pixels = ext->left[pixels[0]] | ext->right[pixels[1]]; } // Determine the size in bytes of a pointer EMSCRIPTEN_KEEPALIVE int PointerSize() { return sizeof (void *); } // Memory management EMSCRIPTEN_KEEPALIVE void* Realloc(void *data, size_t size) { return realloc(data, size); } // Specify anaglyph colors EMSCRIPTEN_KEEPALIVE void SetAnaglyph(VB *sim, uint32_t left, uint32_t right) { Ext *ext = (Ext *) vbGetUserData(sim); // Erase all RGB values for (int x = 0; x < 256; x++) ext->left[x] = ext->right[x] = 0xFF000000; // Process all RGB channels for (int c = 0, shift = 16; c < 3; c++, shift -= 8) { double max; // Magnitude of channel value uint32_t *dest; // Lookup data // Select the magnitude and lookup channel dest = ext->left; max = (left >> shift & 0xFF) / 255.0; if (max == 0) { dest = ext->right; max = (right >> shift & 0xFF) / 255.0; if (max == 0) continue; } // Compute the resulting RGB values for (int x = 0; x < 256; x++) *dest++ |= (uint32_t) (x * max + 0.5) << (16 - shift); } }