Skip to content

Commit

Permalink
Beta update 7
Browse files Browse the repository at this point in the history
  • Loading branch information
morgan3d committed Aug 13, 2019
1 parent bd87195 commit 4ccbbc2
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 50 deletions.
16 changes: 13 additions & 3 deletions console/pyxlscript-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,9 @@ function pyxlToJS(src, noYield) {
// Remove single-line comments
src = src.replace(/\/\/.*$/gm, '');

// Replace spread operator
src = src.replace(//g, '...');

// Pull 'because' on a new line up to the previous line
src = src.replace(/\)[\t ]*((?:\n[\t ]*)+)[ \t]*because[ \t]+("[^\n"]")/g, ') because $2$1');

Expand Down Expand Up @@ -824,16 +827,23 @@ function pyxlToJS(src, noYield) {
// "\n" or ":") is replaced with an open paren. There are no
// negative lookbehinds in JavaScript, so we have to structure an
// explicit test.
src = src.replace(/^([ \t]*\S[^\n]*(?:[A-Za-z0-9_αβγΔδζηθιλμρσϕφχψτωΩ][ \t]|[\^=\-\+\*/><,\[{\(][ \t]*))if\b/gm,
function (match, prefix) {
{ // Allow multiple IF...THEN on a single line by processing repeatedly
let found = true
while (found) {
found = false;
src = src.replace(/^([ \t]*\S[^\n]*?(?:[A-Za-z0-9_αβγΔδζηθιλμρσϕφχψτωΩ][ \t]|[\^=\-\+\*/><,\[{\(][ \t]*))if\b/gm,
function (match, prefix) {
if (/else[ \t]*$/.test(prefix)) {
// This was an ELSE IF, leave alone
return match;
} else {
found = true;
// Functional IF, replace
return prefix + '(';
}
});
});
}
}

// THEN
src = src.replace(/\bthen\b/g, ') ? (');
Expand Down
33 changes: 25 additions & 8 deletions console/quadplay-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function startGIFRecording() {
document.getElementById('recording').innerHTML = 'RECORDING';
document.getElementById('recording').classList.remove('hidden');
const baseScale = 1;
const scale = ((updateImage.width <= 384/2) ? 2 : 1) * baseScale;
const scale = ((updateImage.width <= 384/2) ? (updateImage.width <= 64 ? 4 : 2) : 1) * baseScale;
gifRecording = new GIF({workers:4, quality:3, dither:false, width: scale * updateImage.width, height: scale * updateImage.height});
gifRecording.frameNum = 0;

Expand Down Expand Up @@ -220,10 +220,21 @@ const keyMap = [{'-x':[ascii('A'), 37], '+x':[ascii('D'), 39],
let prevRealGamepadState = [];

// Maps names of gamepads to arrays for mapping standard buttons
// to that gamepad's buttons
const gamepadRemap = {
// to that gamepad's buttons. gamepadButtonRemap[canonicalButton] = actualButton
const gamepadButtonRemap = {
'identity': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
'SNES30 Joy (Vendor: 2dc8 Product: ab20)': [1, 0, 4, 3, 6, 7, 5, 2,10,11, 8, 9, 12, 13, 14, 15, 16]
// Windows SNES30
'SNES30 Joy (Vendor: 2dc8 Product: ab20)': [1, 0, 4, 3, 6, 7, 5, 2,10,11, 8, 9, 12, 13, 14, 15, 16],

// Linux SNES30
'8Bitdo SNES30 GamePad (Vendor: 2dc8 Product: 2840)': [1, 0, 4, 3, 6, 7, 5, 2,10,11, 8, 9, 12, 13, 14, 15, 16],

'T.Flight Hotas X (Vendor: 044f Product: b108)':[0, 1, 3, 2, 4, 5, 6, 7, 10, 11, 8, 9, 12, 13, 14, 15, 16]
};

const gamepadAxisRemap = {
'identity': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
'T.Flight Hotas X (Vendor: 044f Product: b108)': [0, 1, 6, 2, 4, 5, 3, 7, 8, 9]
};

function getIdealGamepads() {
Expand All @@ -237,15 +248,17 @@ function getIdealGamepads() {
let pad = gamepads[i];
if (pad && pad.connected) {
// Construct a simplified web gamepad API
const remap = gamepadRemap[pad.id] || gamepadRemap.identity;
let mypad = {axes:[0, 0, 0, 0], buttons:[]};
const axisRemap = gamepadAxisRemap[pad.id] || gamepadAxisRemap.identity;
for (let a = 0; a < Math.min(4, pad.axes.length); ++a) {
mypad.axes[a] = (Math.abs(pad.axes[a]) > deadZone) ? Math.sign(pad.axes[a]) : 0;
const axis = pad.axes[axisRemap[a]];
mypad.axes[a] = (Math.abs(axis) > deadZone) ? Math.sign(axis) : 0;
}

// Process all 17 buttons/axes as digital buttons first
const buttonRemap = gamepadButtonRemap[pad.id] || gamepadButtonRemap.identity;
for (let b = 0; b < 17; ++b) {
const button = pad.buttons[remap[b]];
const button = pad.buttons[buttonRemap[b]];
// Different browsers follow different APIs for the value of buttons
mypad.buttons[b] = (typeof button === 'object') ? button.pressed : (button >= 0.5);
}
Expand Down Expand Up @@ -298,6 +311,8 @@ function soundSourceOnEnded() {


function internalSoundSourcePlay(handle, audioClip, startPositionMs, loop, volume, pitch, pan) {
pan = Math.min(1, Math.max(-1, pan))

// A new source must be created every time that the sound is played
const source = _ch_audioContext.createBufferSource();
source.buffer = audioClip.buffer;
Expand Down Expand Up @@ -362,6 +377,8 @@ function setSoundPan(handle, pan) {
if (! (handle && handle._)) {
throw new Error("Must call setSoundPan() on a sound returned from playAudioClip()");
}
pan = Math.min(1, Math.max(-1, pan))

handle._.pan = pan;
if (handle._.panNode.pan) {
handle._.panNode.pan.linearRampToValueAtTime(pan, _ch_audioContext.currentTime + audioRampTime);
Expand Down Expand Up @@ -571,7 +588,7 @@ function submitFrame() {
// Only record alternating frames to reduce file size
if (gifRecording.frameNum & 1) {
if (gifRecording.scale > 1) {
// Double pixels
// Repeat pixels
gifCtx.imageSmoothingEnabled = false;
gifCtx.drawImage(emulatorScreen,
0, 0, emulatorScreen.width, emulatorScreen.height,
Expand Down
33 changes: 18 additions & 15 deletions console/quadplay-ide.js
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,21 @@ const controlSchemeTable = {
lt: 'J',
dn: 'K',
rt: 'L'
})
}),

HOTAS: Object.seal({
a: '1',
b: '2',
c: '4',
d: '3',
p: 'ST',
q: 'SE',
up: '⍐',
lt: '⍇',
dn: '⍗',
rt: '⍈'
}),

};

function deviceControl(cmd) {
Expand All @@ -602,7 +616,7 @@ function deviceControl(cmd) {
const type = arguments[2];
const prompt = controlSchemeTable[type];
if (i === undefined || i < 0 || i > 3) { throw new Error('"setPadType" must be used with an index from 0 to 3'); }
if (! prompt) { throw new Error('"setPadType" must be used with one of the legal types, such as "Quadplay" or "PlayStation"'); }
if (! prompt) { throw new Error('"setPadType" must be used with one of the legal types, such as "Quadplay" or "PlayStation" (received "' + type + '")'); }
Runtime.pad[i].type = type;
Runtime.pad[i].prompt = prompt;
break;
Expand Down Expand Up @@ -849,17 +863,6 @@ function onProjectSelect(target, type, object) {
target.classList.add('selectedProjectElement');
}

/*
// Show in the editor
let c;
if (typeof index === 'string') {
const part = index.split('.');
c = gameSource[category][part[0]];
if (part.length > 1) { c = c[part[1]]; }
} else {
c = gameSource[category][index];
}*/

switch (type) {
case 'constant':
const index = object;
Expand Down Expand Up @@ -1072,7 +1075,7 @@ function visualizeModes(modeEditor) {
//////////////////////////////////////////////////////////////////////////////////////
// Convert to the layout API
const graph = new dagre.graphlib.Graph({directed:true, multigraph:true});
const nodeWidth = 76, nodeHeight = 28;
const nodeWidth = 96, nodeHeight = 28;
graph.setGraph({rankdir: 'LR'});
graph.setDefaultEdgeLabel(function() { return {}; });

Expand Down Expand Up @@ -2178,7 +2181,7 @@ function loadGameIntoIDE(url, callback) {
<br/>
<table style="margin-left: -2px; width: 100%">
<tr><td width=180>Sprite Pixels</td><td class="right">${Math.round(resourceStats.spritePixels / 1000)}k</td><td>/</td><td class="right" width=40>4719k</td><td class="right" width=45>(${Math.round(resourceStats.spritePixels*100/4718592)}%)</td></tr>
<tr><td>Spritesheets</td><td class="right">${resourceStats.spritesheets}</td><td>/</td><td class="right">64</td><td class="right">(${Math.round(resourceStats.spritesheets*100/64)}%)</td></tr>
<tr><td>Spritesheets</td><td class="right">${resourceStats.spritesheets}</td><td>/</td><td class="right">128</td><td class="right">(${Math.round(resourceStats.spritesheets*100/128)}%)</td></tr>
<tr><td>Max Spritesheet Width</td><td class="right">${resourceStats.maxSpritesheetWidth}</td><td>/</td><td class="right">1024</td><td class="right">(${Math.round(resourceStats.maxSpritesheetWidth*100/1024)}%)</td></tr>
<tr><td>Max Spritesheet Height</td><td class="right">${resourceStats.maxSpritesheetHeight}</td><td>/</td><td class="right">1024</td><td class="right">(${Math.round(resourceStats.maxSpritesheetHeight*100/1024)}%)</td></tr>
<tr><td>Source Statements</td><td class="right">${resourceStats.sourceStatements}</td><td>/</td><td class="right">8192</td><td class="right">(${Math.round(resourceStats.sourceStatements*100/8192)}%)</td></tr>
Expand Down
58 changes: 45 additions & 13 deletions console/quadplay-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,14 @@ function resize(a, n) {
function size(x) {
if (Array.isArray(x)) {
return x.length;
} else if (x === null || x === undefined) {
return 0;
} else {
let tx = typeof x;
if (tx === 'string') {
return x.length;
} else if (tx === 'object') {
return Object.keys(this).length;
return Object.keys(x).length;
} else {
return 0;
}
Expand Down Expand Up @@ -1145,15 +1147,16 @@ function _error(msg) {


function xy(x, y) {
if (x.x !== undefined) {
return {x:x.x, y:x.y};
}
if (x.x !== undefined) { return {x:x.x, y:x.y}; }
if (Array.isArray(x)) { return {x:x[0], y:x[1]}; }
if (arguments.length !== 2) { _error('xy() requires exactly two arguments'); }
return {x:x, y:y};
}


function xyz(x, y, z) {
if (x.x !== undefined) { return {x:x.x, y:x.y, z:x.z}; }
if (Array.isArray(x)) { return {x:x[0], y:x[1], z:x[2]}; }
if (arguments.length !== 3) { throw new Error('xyz() requires exactly three arguments'); }
return {x:x, y:y, z:z};
}
Expand Down Expand Up @@ -2166,7 +2169,7 @@ function drawText(font, str, P, color, shadow, outline, xAlign, yAlign, z, wrapW
if ((wrapWidth > 0) && (width > wrapWidth - font._spacing.x)) {
// Perform word wrap, we've exceeded the available width
// Search backwards for a place to break.
const breakChars = ' \n\t,.!:/\\)]}\'"|`-+=*';
const breakChars = ' \n\t,.!:/\\)]}\'"|`-+=*…\?¿¡';

// Avoid breaking more than 25% back along the string
const maxBreakSearch = Math.max(1, (c * 0.25) | 0);
Expand Down Expand Up @@ -3471,12 +3474,17 @@ function ceil(a) {
}
}

function round(a) {

function round(a, unit) {
if (typeof a === 'object') {
let c = a.constructor ? a.constructor() : Object.create(null);
for (let key in a) c[key] = Math.round(a[key]);
unit = unit || 1;
const invUnit = 1 / unit;
const c = a.constructor ? a.constructor() : Object.create(null);
for (let key in a) c[key] = Math.round(a[key] * invUnit) * unit;
return c;
} else {
} else if (unit) {
return Math.round(a / unit) * unit;
} else {
return Math.round(a);
}
}
Expand Down Expand Up @@ -4203,6 +4211,30 @@ function RGB_DOT_RGB(c1, c2) {
}


function MAT3x4_MATMUL_XYZW(A, v, c) {
const x = v.x, y = v.y, z = v.z, w = v.w;
c.x = A[0][0] * x + A[0][1] * y + A[0][2] * z + A[0][3] * w;
c.y = A[1][0] * x + A[1][1] * y + A[1][2] * z + A[1][3] * w;
c.z = A[2][0] * x + A[2][1] * y + A[2][2] * z + A[2][3] * w;
c.w = w;
}


function MAT3x4_MATMUL_XYZ(A, v, c) {
const x = v.x, y = v.y, z = v.z;
c.x = A[0][0] * x + A[0][1] * y + A[0][2] * z + A[0][3];
c.y = A[1][0] * x + A[1][1] * y + A[1][2] * z + A[1][3];
c.z = A[2][0] * x + A[2][1] * y + A[2][2] * z + A[2][3];
}


function MAT3x3_MATMUL_XYZ(A, v, c) {
const x = v.x, y = v.y, z = v.z;
c.x = A[0][0] * x + A[0][1] * y + A[0][2] * z;
c.y = A[1][0] * x + A[1][1] * y + A[1][2] * z;
c.z = A[2][0] * x + A[2][1] * y + A[2][2] * z;
}


function lerp(a, b, t) {
const ta = typeof a, tb = typeof b;
Expand Down Expand Up @@ -4570,7 +4602,7 @@ function because(reason) {
_lastBecause = reason;
}

function pushMode(mode) {
function pushMode(mode, ...args) {
_verifyLegalMode(mode);

// Push the stacks
Expand All @@ -4592,7 +4624,7 @@ function pushMode(mode) {
_systemPrint('Pushing into mode ' + mode.name + (_lastBecause ? ' because "' + _lastBecause + '"' : ''));

// Run the enter callback on the new mode
_gameMode._enter.apply(null, arguments);
_gameMode._enter.apply(null, ...args);

throw {nextMode: mode};

Expand Down Expand Up @@ -4645,7 +4677,7 @@ function popMode() {
}


function setMode(mode) {
function setMode(mode, ...args) {
_verifyLegalMode(mode);

// Erase the stacks
Expand Down Expand Up @@ -4673,7 +4705,7 @@ function setMode(mode) {
_systemPrint('Entering mode ' + mode.name + (_lastBecause ? ' because "' + _lastBecause + '"' : ''));

// Run the enter callback on the new mode
_gameMode._enter.apply(null, arguments);
_gameMode._enter.apply(null, args);

throw {nextMode: mode};
}
Expand Down
Loading

0 comments on commit 4ccbbc2

Please sign in to comment.