Compare commits

..
21 Commits
Author SHA1 Message Date
GuyPerfect 6e9b727b31 Fix botched disassembler backport 2026-10-19 19:01:25 -05:00
GuyPerfect 7ab5bd28bf Fix affine world width assignment logic 2026-10-19 18:20:00 -05:00
GuyPerfect 41cd7bc089 Backport Shrooms2 disassembler 2026-10-17 22:01:08 -05:00
GuyPerfect 31b7403252 Correction for negative affine parallax 2026-05-21 16:23:23 -05:00
GuyPerfect 29ade46a0a Fix for affine parameter address resolution 2026-03-28 16:46:32 -05:00
GuyPerfect 534ce852f4 Adjust brightness values 2025-11-23 12:08:36 -06:00
GuyPerfect 4ed3b72995 Fix nullary function declarations 2025-08-27 09:53:01 -05:00
GuyPerfect 8598eab087 Fix double CPU clocks in reads/writes, assuage unused argument in vsuWrite() 2025-08-24 11:03:51 -05:00
GuyPerfect fe9c5c4781 Adjustment for VSU hardware behavior on erroneous address writes 2025-08-18 20:16:41 -05:00
GuyPerfect a9a02e2d15 Merging pull request 2025-08-17 13:32:01 -05:00
GuyPerfect ab29f47004 Merge pull request 'Fix issues with H-Bias rendering' (#1) from hbias-fix into main
Reviewed-on: #1
2025-08-17 18:22:53 +00:00
GuyPerfect 531e4a8c3e Fix handler address for FIV exception 2025-08-17 13:21:53 -05:00
GuyPerfect f295e02aaf Style adjustments for previous 2025-08-17 13:11:29 -05:00
GuyPerfect 67928da1e6 Merge pull request 'Add Floogle's latest audio fixes' (#3) from floogle-audio-fixes into main
Reviewed-on: #3
2025-08-17 18:02:04 +00:00
SonicSwordcane 4ebdad0c2d Add Floogle's latest audio fixes 2025-08-15 00:24:07 -04:00
SonicSwordcane 5d4a422e61 Fix handler address for FIV exception 2025-08-15 00:07:04 -04:00
SonicSwordcane 8b020ad808 Fix issues with HBias rendering 2025-08-14 23:46:39 -04:00
GuyPerfect 483714c0d6 Pushing current web edits 2025-03-23 07:26:43 -05:00
GuyPerfect ecbd103917 Manage IRQ on writes to INTENB 2025-03-04 10:19:12 -06:00
GuyPerfect b2412d9487 Fix shameful syntax error 2025-03-01 15:51:49 -06:00
GuyPerfect dd1045553b Even more VSU edge cases 2025-03-01 15:42:16 -06:00
11 changed files with 926 additions and 713 deletions
+3 -3
View File
@@ -234,7 +234,7 @@ static int cpuOnExecute(VB *sim) {
#define VB_ON_READ VB_DIRECT_READ
#endif
static int cpuRead(VB *sim, uint32_t address, int type, int32_t *value) {
uint32_t cycles = 4; /* TODO: Research this */
uint32_t cycles = 0; /* TODO: Research this */
/* Retrieve the value from the simulation state directly */
busRead(sim, address, type, value);
@@ -289,7 +289,7 @@ static int cpuReadFetch(VB *sim, int fetch, uint32_t address, int32_t *value) {
#endif
static int cpuWrite(VB *sim, uint32_t address, int type, int32_t value) {
int cancel = 0;
uint32_t cycles = 3; /* TODO: Research this */
uint32_t cycles = 0; /* TODO: Research this */
/* Reset pseudo-halt */
if (sim->ph.enabled)
@@ -495,7 +495,7 @@ static int cpuException(VB *sim) {
sim->cpu.eipc = sim->cpu.pc;
sim->cpu.psw.ep = 1;
sim->cpu.nextPC = 0xFFFF0000 |
((cause & 0xFFF0) == 0xFF60 ? 0xFF60 : cause & 0xFFF0);
((cause & 0xFFF0) == 0xFF70 ? 0xFF60 : cause & 0xFFF0);
}
/* All exceptions */
+2 -1
View File
@@ -361,6 +361,7 @@ struct VB {
/* Other state */
uint32_t clocks; /* Clocks until modification */
uint8_t freqmask; /* Frequency mask */
uint8_t modmask; /* Modifications masked */
uint16_t next; /* Next frequency value */
int sample; /* Current sample index */
@@ -899,7 +900,7 @@ VBAPI vbOnWrite vbSetWriteCallback(VB *sim, vbOnWrite callback) {
}
/* Determine the size of a simulation instance */
VBAPI size_t vbSizeOf() {
VBAPI size_t vbSizeOf(void) {
return sizeof (VB);
}
+1 -1
View File
@@ -166,7 +166,7 @@ VBAPI vbOnSamples vbSetSamplesCallback (VB *sim, vbOnSamples callback);
VBAPI uint32_t vbSetSystemRegister (VB *sim, unsigned index, uint32_t value);
VBAPI void* vbSetUserData (VB *sim, void *tag);
VBAPI vbOnWrite vbSetWriteCallback (VB *sim, vbOnWrite callback);
VBAPI size_t vbSizeOf ();
VBAPI size_t vbSizeOf (void);
VBAPI int32_t vbWrite (VB *sim, uint32_t address, int type, int32_t value);
+32 -22
View File
@@ -41,16 +41,17 @@ static const uint8_t BG_TEMPLATES[][64] = {
};
/* 8-bit color magnitude by brightness level */
/* Generated as BRIGHT8[n] = round((n / 132) ** 1.6 * 255) */
static const uint8_t BRIGHT8[] = {
0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 28,
30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 57, 59,
61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90,
92, 94, 96, 98,100,102,104,106,108,110,112,113,115,117,119,121,
123,125,127,129,131,133,135,137,139,141,142,144,146,148,150,152,
154,156,158,160,162,164,166,168,170,171,173,175,177,179,181,183,
185,187,189,191,193,195,197,198,200,202,204,206,208,210,212,214,
216,218,220,222,224,226,227,229,231,233,235,237,239,241,243,245,
247,249,251,253,255
0, 12, 19, 24, 29, 33, 37, 41, 44, 48, 51, 54, 57, 60, 63, 65,
68, 71, 73, 76, 78, 81, 83, 86, 88, 90, 92, 95, 97, 99,101,103,
105,107,109,111,113,115,117,119,121,123,125,127,128,130,132,134,
136,137,139,141,142,144,146,148,149,151,153,154,156,157,159,161,
162,164,165,167,168,170,172,173,175,176,178,179,181,182,184,185,
186,188,189,191,192,194,195,197,198,199,201,202,203,205,206,208,
209,210,212,213,214,216,217,218,220,221,222,224,225,226,228,229,
230,231,233,234,235,236,238,239,240,242,243,244,245,246,248,249,
250,251,253,254,255
};
@@ -319,6 +320,7 @@ static void vipWriteWorld(VB *sim, uint32_t offset, int type, int32_t value) {
uint32_t base; /* Base BG map index */
uint8_t *bg; /* Background template */
uint32_t count; /* Number of BG maps in background */
int32_t width; /* Computed affine width */
World *world; /* World state */
uint32_t z; /* Iterator */
@@ -380,10 +382,10 @@ static void vipWriteWorld(VB *sim, uint32_t offset, int type, int32_t value) {
case 5: world->mp = SignExtend(value, 15); break;
case 6: world->my = SignExtend(value, 13); break;
case 7: /* W */
value = SignExtend(value, 13) + 1;
world->wNaffine = value < 0 ? 0 : value;
value = SignExtend(value, 10) + 1;
world->wAffine = value < 0 ? 0 : value;
width = SignExtend(value, 13) + 1;
world->wNaffine = width < 0 ? 0 : width;
width = SignExtend(value, 10) + 1;
world->wAffine = width < 0 ? 0 : width;
world->width = world->bgm != 2 ? world->wNaffine : world->wAffine;
break;
case 8: /* H */
@@ -436,6 +438,9 @@ static void vipWriteIO(
case 0x5F802>>1: /* INTENB */
sim->vip.intenb = (sim->vip.intenb & mask) | (value & 0xE01F);
if (sim->vip.intenb & sim->vip.intpnd)
sim->cpu.irq |= 0x0010;
else sim->cpu.irq &= ~0x0010;
break;
case 0x5F804>>1: /* INTCLR */
sim->vip.intpnd &= ~value;
@@ -981,7 +986,7 @@ static void vipDrawHBias(VB *sim, World *world) {
/* Process all visible lines */
param = &sim->vip.ram[world->paramBase +
((y1 - world->gy) << 2) + (i << 1)];
for (y = y1; y < y2; y++, param += 2) {
for (y = y1; y < y2; y++, param += 4) {
/* Configure window bounds */
wnd.y1 = y;
@@ -989,7 +994,7 @@ static void vipDrawHBias(VB *sim, World *world) {
/* Draw the background into the window */
vipDrawBackground(sim->vip.shadow[i], &wnd, world,
mx + busReadBuffer(param, VB_S16), my);
mx - busReadBuffer(param, VB_S16), my);
}
}
@@ -1001,7 +1006,7 @@ static void vipDrawAffine(VB *sim, World *world) {
Cell *cell; /* Source cell */
uint8_t *col, *row; /* Output pixel */
uint8_t pixel; /* Character pixel value */
uint8_t *param; /* World parameter memory */
uint32_t param; /* World parameter memory */
int32_t px, py; /* Pixel source coordinates */
int32_t dx, dy, mp, mx, my; /* Affine parameters */
int32_t wx; /* Base world X coordinate */
@@ -1048,21 +1053,26 @@ static void vipDrawAffine(VB *sim, World *world) {
wx = x1 - wx;
/* Process all visible rows */
param = &sim->vip.ram[world->paramBase | (y1 - world->gy) << 4];
param = world->paramBase + ((y1 - world->gy) << 4);
row = &sim->vip.shadow[i][x1 * 224 + y1];
for (y = y1; y < y2; y++, param += 16, row++) {
/* Parse line parameters */
mx = (int32_t) busReadBuffer(param + 0, VB_S16) << 6;
mp = (int32_t) busReadBuffer(param + 2, VB_S16);
my = (int32_t) busReadBuffer(param + 4, VB_S16) << 6;
dx = (int32_t) busReadBuffer(param + 6, VB_S16);
dy = (int32_t) busReadBuffer(param + 8, VB_S16);
mx = (int32_t) busReadBuffer(&sim->vip.ram[param | 0], VB_S16) << 6;
mp = (int32_t) busReadBuffer(&sim->vip.ram[param | 2], VB_S16);
my = (int32_t) busReadBuffer(&sim->vip.ram[param | 4], VB_S16) << 6;
dx = (int32_t) busReadBuffer(&sim->vip.ram[param | 6], VB_S16);
dy = (int32_t) busReadBuffer(&sim->vip.ram[param | 8], VB_S16);
/* Adjust left-edge parameters */
if ((mp < 0) ^ i) {
if (mp < 0) {
mx += dx * (wx - mp);
my += dy * (wx - mp);
} else {
mx += dx * (wx + mp);
my += dy * (wx + mp);
}
} else {
mx += dx * wx;
my += dy * wx;
+45 -27
View File
@@ -82,12 +82,12 @@ static void vsuNextFreqMod(VB *sim, Channel *chan) {
/* Modulation */
else {
next = (int32_t) chan->freq.written +
sim->vsu.modulation[sim->vsu.freqmod.sample];
if (next < 0)
next = 0;
if (next > 2047)
next = 2047;
next = ((int32_t) chan->freq.written +
sim->vsu.modulation[sim->vsu.freqmod.sample]) & 0x7FF;
if (sim->vsu.freqmod.freqmask == 1)
next = (next & 0x700) | (chan->freq.written & 0x0FF);
else if (sim->vsu.freqmod.freqmask == 2)
next = (next & 0x0FF) | (chan->freq.written & 0x700);
}
/* Configure state */
@@ -132,14 +132,19 @@ static void vsuEmulateChannel(VB *sim, Channel *chan) {
}
/* Envelope modification */
if (chan->env.enb && !chan->env.modmask && chan->env.clocks == 0) {
if (chan->env.clocks == 0) {
uint8_t new_envelope = chan->env.value;
if (chan->env.dir == 0 && chan->env.value != 0)
chan->env.value--;
new_envelope--;
else if (chan->env.dir == 1 && chan->env.value != 15)
chan->env.value++;
else if (chan->env.rep)
chan->env.value = chan->env.reload;
else chan->env.modmask = 1;
new_envelope++;
else if (chan->env.rep && chan->env.modmask != 2) {
new_envelope = chan->env.reload;
chan->env.modmask = 0;
} else if (!chan->env.modmask)
chan->env.modmask = 1;
if (chan->env.enb && !chan->env.modmask)
chan->env.value = new_envelope;
chan->env.clocks = ((uint32_t) chan->env.interval + 1) * 307220;
}
@@ -215,6 +220,7 @@ static void vsuWriteEV0(VB *sim, int index, uint8_t value) {
chan->env.interval = value & 7;
chan->env.value = value >> 4 & 15;
chan->env.reload = chan->env.value;
if (chan->env.modmask == 1) chan->env.modmask = 2;
if (index == 4) {
chan->freqmod = vsuCheckFreqMod(sim);
vsuNextFreqMod(sim, chan);
@@ -231,6 +237,12 @@ static void vsuWriteEV1(VB *sim, int index, uint8_t value) {
/* Parse fields */
chan->env.enb = value & 1;
chan->env.rep = value >> 1 & 1;
if (
!chan->env.rep && (
(chan->env.reload == 0 && chan->env.dir == 0) ||
(chan->env.reload == 15 && chan->env.dir == 1)
)
) chan->env.modmask = 1;
/* Processing by channel */
switch (index) {
@@ -257,7 +269,9 @@ static void vsuWriteFQH(VB *sim, int index, uint16_t value) {
value = value << 8 & 0x0700;
chan->freq.current = (chan->freq.current & 0x00FF) | value;
chan->freq.written = (chan->freq.written & 0x00FF) | value;
if (index == 4)
if (index != 4)
return;
sim->vsu.freqmod.freqmask = 2;
vsuNextFreqMod(sim, chan);
}
@@ -266,7 +280,9 @@ static void vsuWriteFQL(VB *sim, int index, uint8_t value) {
Channel *chan = &sim->vsu.channels[index];
chan->freq.current = (chan->freq.current & 0x0700) | value;
chan->freq.written = (chan->freq.written & 0x0700) | value;
if (index == 4)
if (index != 4)
return;
sim->vsu.freqmod.freqmask = 1;
vsuNextFreqMod(sim, chan);
}
@@ -282,7 +298,12 @@ static void vsuWriteINT(VB *sim, int index, uint8_t value) {
/* Update state */
chan->int_.clocks = 76805 * ((uint32_t) chan->int_.interval + 1);
chan->env.modmask = 0;
if (chan->env.enb)
if (
!chan->env.rep && (
(chan->env.reload == 0 && chan->env.dir == 0) ||
(chan->env.reload == 15 && chan->env.dir == 1)
)
) chan->env.modmask = 1;
chan->env.clocks = 307220 * ((uint32_t) chan->env.interval + 1);
if (index != 5) {
chan->wave.sample = 0;
@@ -373,7 +394,7 @@ static void vsuEmulate(VB *sim, uint32_t clocks) {
/* Clocks until next state change */
chan->until = chan->clocks;
if (chan->env.enb && !chan->env.modmask &&
if (chan->env.enb && chan->env.modmask != 2 &&
chan->env.clocks < chan->until)
chan->until = chan->env.clocks;
if (chan->int_.auto_ && chan->int_.clocks < chan->until)
@@ -383,7 +404,7 @@ static void vsuEmulate(VB *sim, uint32_t clocks) {
/* Manage clocks */
chan->clocks -= chan->until;
if (chan->env.enb && !chan->env.modmask)
if (chan->env.enb && chan->env.modmask != 2)
chan->env.clocks -= chan->until;
if (chan->int_.auto_)
chan->int_.clocks -= chan->until;
@@ -507,6 +528,7 @@ static void vsuReset(VB *sim) {
sim->vsu.freqmod.clocks = 0;
sim->vsu.freqmod.dir = 0;
sim->vsu.freqmod.enb = 0;
sim->vsu.freqmod.freqmask = 0;
sim->vsu.freqmod.func = 0;
sim->vsu.freqmod.interval = 0;
sim->vsu.freqmod.modmask = 0;
@@ -526,21 +548,17 @@ static void vsuReset(VB *sim) {
/* Write a typed value to the VSU bus */
static void vsuWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
/* Only byte writes are allowed */
switch (type) {
case VB_S16:
case VB_U16:
case VB_S32:
return;
}
(void) type;
/* Unmapped */
if (address & 3)
if (address & 1)
return;
/* Working variables */
address &= 0x7FF;
address &= 0x7FC;
/* Clear frequency mask */
sim->vsu.freqmod.freqmask = 0;
/* Wave memory */
if (address < 0x280) {
+728 -590
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -257,7 +257,7 @@ static void* isxFrom(uint8_t *bytes, size_t length, size_t *romLength) {
src < lowMax + 0x1000001 - highMin;
src <<= 1
);
rom = VBU_REALLOC(NULL, src);
rom = VBU_MEMMGR(NULL, src);
if (rom == NULL)
return NULL;
*romLength = src;
+37 -19
View File
@@ -5,28 +5,28 @@
#include <string.h>
#include <vbu.h>
/* Memory management */
#ifndef VBU_REALLOC
#include <stdlib.h>
#define VBU_REALLOC realloc
#else
extern void* VBU_REALLOC(void *, size_t);
#endif
/***************************** Library Functions *****************************/
/* Sign-extend an integer of variable width */
static int32_t SignExtend(int32_t value, int32_t bits) {
#ifndef VB_SIGNED_PROPAGATE
value &= ~((uint32_t) 0xFFFFFFFF << bits);
bits = (int32_t) 1 << (bits - (int32_t) 1);
return (value ^ bits) - bits;
#else
return value << (32 - bits) >> (32 - bits);
#endif
/* Memory manager */
#ifdef VBU_MEMMGR
extern void* VBU_MEMMGR(void *ptr, size_t size);
#else
#include <stdlib.h>
static void* VBU_MEMMGR(void *ptr, size_t size) {
/* Free a buffer */
if (size == 0) {
if (ptr != NULL)
free(ptr);
return NULL;
}
/* Create or resize a buffer */
return realloc(ptr, size);
}
#endif
@@ -46,14 +46,21 @@ VBUAPI int vbuCodeSize(VB *sim, uint32_t address) {
}
/* Initialize disassembler options with default settings */
VBUAPI VBU_DasmConfig* vbuDasmInit(VBU_DasmConfig *config) {
VBUAPI VBU_DasmConfig* vbuDasmDefaults(VBU_DasmConfig *config) {
/* Error checking */
if (config == NULL)
return NULL;
/* Supply default configuration */
config->bcondNotation = VBU_JOINED;
config->branchNotation = VBU_ABSOLUTE;
config->conditionCase = VBU_LOWER;
config->conditionCL = VBU_L;
config->conditionEZ = VBU_Z;
config->conditionNotation = VBU_NAMES;
config->hexCase = VBU_UPPER;
config->hexNotation = VBU_0X;
config->hexNotation = VBU_PREFIX_0X;
config->immediateNotation = VBU_NONE;
config->memoryNotation = VBU_OUTSIDE;
config->mnemonicCase = VBU_UPPER;
@@ -69,6 +76,17 @@ VBUAPI VBU_DasmConfig* vbuDasmInit(VBU_DasmConfig *config) {
/* Disassemble from a simulation */
VBUAPI VBU_DasmLine* vbuDisassemble(VB *sim, uint32_t address,
VBU_DasmConfig *config, unsigned length, int line) {
VBU_DasmConfig defs; /* Default settings */
/* Error checking */
if (sim == NULL || length == 0)
return NULL;
/* Supply default configuration */
if (config == NULL)
config = vbuDasmDefaults(&defs);
/* Disassemble instructions */
return dasmDisassemble(sim, address, config, length, line);
}
+12 -9
View File
@@ -17,23 +17,25 @@ extern "C" {
/********************************* Constants *********************************/
/* Disassembler options */
#define VBU_0X 0
#define VBU_ABSOLUTE 0
#define VBU_C 1
#define VBU_DEST_FIRST 1
#define VBU_DEST_LAST 0
#define VBU_DOLLAR 1
#define VBU_E 0
#define VBU_H 2
#define VBU_INSIDE 1
#define VBU_JOINED 0
#define VBU_L 0
#define VBU_LOWER 1
#define VBU_NAMES 1
#define VBU_NONE 0
#define VBU_NUMBER 1
#define VBU_NUMBERS 0
#define VBU_OUTSIDE 0
#define VBU_PREFIX_0X 0
#define VBU_PREFIX_DOLLAR 1
#define VBU_PREFIX_NUMBER 1
#define VBU_RELATIVE 1
#define VBU_SPLIT 1
#define VBU_SUFFIX_H 2
#define VBU_UPPER 0
#define VBU_Z 1
@@ -44,13 +46,14 @@ extern "C" {
/* Disassembler text options */
typedef struct { /* Defaults listed first */
uint8_t bcondNotation; /* JOINED, SPLIT */
uint8_t branchNotation; /* ABSOLUTE, RELATIVE */
uint8_t conditionCase; /* LOWER, UPPER */
uint8_t conditionCL; /* L, C */
uint8_t conditionEZ; /* Z, E */
uint8_t conditionNotation; /* NAMES, NUMBERS */
uint8_t hexCase; /* UPPER, LOWER */
uint8_t hexNotation; /* 0X, H, DOLLAR */
uint8_t immediateNotation; /* NONE, NUMBER */
uint8_t hexNotation; /* PREFIX_0X, SUFFIX_H, PREFIX_DOLLAR */
uint8_t immediateNotation; /* NONE, SUFFIX_NUMBER */
uint8_t memoryNotation; /* OUTSIDE, INSIDE */
uint8_t mnemonicCase; /* UPPER, LOWER */
uint8_t operandOrder; /* DEST_LAST, DEST_FIRST */
@@ -66,7 +69,7 @@ typedef struct {
/* Parsed */
uint32_t address; /* Memory address */
uint16_t code[4]; /* Instruction bytes */
uint8_t code[4]; /* Instruction bytes */
uint8_t codeLength; /* Number of items in code */
uint8_t isPC; /* Set if PC is on this line */
@@ -86,8 +89,8 @@ typedef struct {
/******************************* API Commands ********************************/
VBUAPI int vbuCodeSize (VB *sim, uint32_t address);
VBUAPI VBU_DasmConfig* vbuDasmInit (VBU_DasmConfig *config);
VBUAPI VBU_DasmLine* vbuDisassemble(VB *sim, uint32_t address, VBU_DasmConfig *config, unsigned length, int line);
VBUAPI VBU_DasmConfig* vbuDasmDefaults(VBU_DasmConfig *config);
VBUAPI VBU_DasmLine* vbuDisassemble (VB *sim, uint32_t address, VBU_DasmConfig *config, unsigned length, int line);
VBUAPI void* vbuFromISX (void *bytes, size_t length, size_t *romLength);
+6
View File
@@ -293,6 +293,12 @@ new class Core {
}, [ output.buffer ]);
}
// Reset simulation state
reset(message) {
this.vbReset(message.sim);
this.dom.postMessage({ promised: true });
}
// Specify anaglyph colors
setAnaglyph(message) {
this.SetAnaglyph(message.sim, message.left, message.right);
+31 -12
View File
@@ -436,8 +436,17 @@ class Sim extends HTMLElement {
response.lines.map(l=>new DasmLine(GUARD, l));
}
// Reset simulation state
reset() {
return this.#core.toCore({
command : "reset",
promised: true,
sim : this.#pointer
});
}
// Specify anaglyph colors
async setAnaglyph(left, right) {
setAnaglyph(left, right) {
// Error checking
if (!Number.isSafeInteger(left ) || left < 0 || left > 0xFFFFFF)
@@ -455,7 +464,7 @@ class Sim extends HTMLElement {
this.#anaglyph[1] = right;
// Send the colors to the core
await this.#core.toCore({
return this.#core.toCore({
command : "setAnaglyph",
promised: true,
sim : this.#pointer,
@@ -475,7 +484,7 @@ class Sim extends HTMLElement {
}
// Specify new game pad keys
async setKeys(keys) {
setKeys(keys) {
// Error checking
if (!Number.isSafeInteger(keys) || keys < 0 || keys > 0xFFFF)
@@ -487,7 +496,7 @@ class Sim extends HTMLElement {
this.#keys = keys;
// Send the keys to the core
await this.#core.toCore({
return this.#core.toCore({
command : "setKeys",
promised: true,
sim : this.#pointer,
@@ -496,7 +505,7 @@ class Sim extends HTMLElement {
}
// Specify audio panning
async setPanning(panning) {
setPanning(panning) {
// Error checking
if (!Number.isFinite(panning) ||panning < -1 || panning > +1) {
@@ -508,7 +517,7 @@ class Sim extends HTMLElement {
this.#panning = panning;
// Send the panning to the core
await this.#core.toCore({
return this.#core.toCore({
command : "setPanning",
promised: true,
sim : this.#pointer,
@@ -529,7 +538,7 @@ class Sim extends HTMLElement {
}
// Specify audio volume
async setVolume(volume) {
setVolume(volume) {
// Error checking
if (!Number.isFinite(volume) ||volume < 0 || volume > 10) {
@@ -541,7 +550,7 @@ class Sim extends HTMLElement {
this.#volume = volume;
// Send the volume to the core
await this.#core.toCore({
return this.#core.toCore({
command : "setVolume",
promised: true,
sim : this.#pointer,
@@ -596,7 +605,7 @@ class VB {
#commands; // Computed method table
#core; // Core worker
#proxy; // Self proxy for sim access
#sims; // All sims
#sims; // Mapping of Sim|pointer -> proxy
#state; // Operations state
@@ -683,8 +692,8 @@ class VB {
///////////////////////////// Static Methods //////////////////////////////
// Create a core instance
static async create(options) {
return await new VB(GUARD).#construct(options);
static create(options) {
return new VB(GUARD).#construct(options);
}
@@ -769,6 +778,16 @@ class VB {
/////////////////////////////// Properties ////////////////////////////////
// Number of managed simulations
get size() { return this.#sims.size / 2; }
// Managed simulations
get sims() { return [... this.#sims.keys()].filter(s=>s instanceof Sim); }
///////////////////////////// Public Methods //////////////////////////////
// Create one or more sims
@@ -809,7 +828,7 @@ class VB {
if (
!Array.isArray(sims) ||
sims.length == 0 ||
sims.find(s=>!this.#sims.has(s))
sims.some(s=>!this.#sims.has(s))
) {
throw new TypeError("Must specify a Sim or array of Sims " +
"that belong to this core.");