mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
Merge pull request #2 from whscullin/whscullin/more-cleanup
More cleanup.
This commit is contained in:
commit
e021c692ce
@ -134,7 +134,17 @@
|
|||||||
<h3>CPU</h3>
|
<h3>CPU</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="accelerator_toggle" onclick="updateSpeed()"/>
|
<select id="computer_type" value="apple2plus" onchange="updateCPU()">
|
||||||
|
<option value="apple2plus">Apple ][+</option>
|
||||||
|
<option value="apple2">Autostart Apple ][</option>
|
||||||
|
<option value="original">Apple ][</option>
|
||||||
|
<select>
|
||||||
|
<label for="computer_type">
|
||||||
|
Type
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="accelerator_toggle" onclick="updateCPU()"/>
|
||||||
<label for="accelerator_toggle">
|
<label for="accelerator_toggle">
|
||||||
Accelerated CPU
|
Accelerated CPU
|
||||||
</label>
|
</label>
|
||||||
@ -142,6 +152,13 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<h3>Joystick</h3>
|
<h3>Joystick</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="disable_mouse"
|
||||||
|
onclick="updateJoystick()" />
|
||||||
|
<label for="disable_mouse">
|
||||||
|
Disable Mouse Joystick
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="flip_x"
|
<input type="checkbox" id="flip_x"
|
||||||
onclick="updateJoystick()" />
|
onclick="updateJoystick()" />
|
||||||
@ -194,12 +211,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="save" title="Save Disk">
|
<div id="save" title="Save Disk">
|
||||||
<form action="#" onsubmit="return false;">
|
<form action="#" onsubmit="return false;">
|
||||||
|
<b>Save to Browser</a>
|
||||||
|
<br /><br />
|
||||||
Save Name: <input type="text" name="name" id="save_name"
|
Save Name: <input type="text" name="name" id="save_name"
|
||||||
style="width: 200px" />
|
style="width: 200px" />
|
||||||
</form>
|
</form>
|
||||||
|
<hr />
|
||||||
|
<div>
|
||||||
|
<b>Download to Local Disk</b>
|
||||||
|
<br /><br />
|
||||||
|
<a id="local_save_link" class="button">Download</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="manage" title="Manage Disks">
|
<div id="manage" title="Manage Disks">
|
||||||
</div>
|
</div>
|
||||||
|
<div id="http_load" title="Load URL">
|
||||||
|
<form action="#">
|
||||||
|
<input type="text" id="http_url" style="width: 500px"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div id="load" title="Load Disk">
|
<div id="load" title="Load Disk">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -138,7 +138,16 @@
|
|||||||
<h3>CPU</h3>
|
<h3>CPU</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="accelerator_toggle" onclick="updateSpeed()"/>
|
<select id="computer_type" value="apple2enh" onchange="updateCPU()">
|
||||||
|
<option value="apple2enh">Enhanced Apple //e</option>
|
||||||
|
<option value="apple2e">Apple //e</option>
|
||||||
|
<select>
|
||||||
|
<label for="computer_type">
|
||||||
|
Type
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="accelerator_toggle" onclick="updateCPU()"/>
|
||||||
<label for="accelerator_toggle">
|
<label for="accelerator_toggle">
|
||||||
Accelerated CPU
|
Accelerated CPU
|
||||||
</label>
|
</label>
|
||||||
@ -146,6 +155,13 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<h3>Joystick</h3>
|
<h3>Joystick</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="disable_mouse"
|
||||||
|
onclick="updateJoystick()" />
|
||||||
|
<label for="disable_mouse">
|
||||||
|
Disable Mouse Joystick
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="flip_x"
|
<input type="checkbox" id="flip_x"
|
||||||
onclick="updateJoystick()" />
|
onclick="updateJoystick()" />
|
||||||
@ -198,12 +214,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="save" title="Save Disk">
|
<div id="save" title="Save Disk">
|
||||||
<form action="#" onsubmit="return false;">
|
<form action="#" onsubmit="return false;">
|
||||||
|
<b>Save to Browser</a>
|
||||||
|
<br /><br />
|
||||||
Save Name: <input type="text" name="name" id="save_name"
|
Save Name: <input type="text" name="name" id="save_name"
|
||||||
style="width: 200px" />
|
style="width: 200px" />
|
||||||
</form>
|
</form>
|
||||||
|
<hr />
|
||||||
|
<div>
|
||||||
|
<b>Download to Local Disk</b>
|
||||||
|
<br /><br />
|
||||||
|
<a id="local_save_link" class="button">Download</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="manage" title="Manage Disks">
|
<div id="manage" title="Manage Disks">
|
||||||
</div>
|
</div>
|
||||||
|
<div id="http_load" title="Load URL">
|
||||||
|
<form action="#">
|
||||||
|
<input type="text" id="http_url" style="width: 500px"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div id="load" title="Load Disk">
|
<div id="load" title="Load Disk">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
102
js/apple2io.js
102
js/apple2io.js
@ -9,13 +9,16 @@
|
|||||||
* implied warranty.
|
* implied warranty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*globals debug: false, toHex: false, each: false */
|
/*globals debug: false */
|
||||||
/*exported Apple2IO */
|
/*exported Apple2IO */
|
||||||
|
|
||||||
function Apple2IO(cpu, callbacks)
|
function Apple2IO(cpu, callbacks)
|
||||||
{
|
{
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var _slot = [];
|
||||||
|
var _auxRom = null;
|
||||||
|
|
||||||
var _hz = 1023000;
|
var _hz = 1023000;
|
||||||
var _rate = 44000;
|
var _rate = 44000;
|
||||||
var _sample_size = 4096;
|
var _sample_size = 4096;
|
||||||
@ -85,16 +88,15 @@ function Apple2IO(cpu, callbacks)
|
|||||||
PADDLE2: 0x66, // bit 7: status of pdl-2 timer (read)
|
PADDLE2: 0x66, // bit 7: status of pdl-2 timer (read)
|
||||||
PADDLE3: 0x67, // bit 7: status of pdl-3 timer (read)
|
PADDLE3: 0x67, // bit 7: status of pdl-3 timer (read)
|
||||||
PDLTRIG: 0x70, // trigger paddles
|
PDLTRIG: 0x70, // trigger paddles
|
||||||
|
BANK: 0x73, // Back switched RAM card bank
|
||||||
SETIOUDIS:0x7E, // Enable double hires
|
SETIOUDIS:0x7E, // Enable double hires
|
||||||
CLRIOUDIS:0x7F // Disable double hires
|
CLRIOUDIS:0x7F // Disable double hires
|
||||||
};
|
};
|
||||||
|
|
||||||
function _debug() {
|
function _debug() {
|
||||||
// debug.apply(arguments);
|
debug.apply(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
var _locs = [];
|
|
||||||
|
|
||||||
function _tick() {
|
function _tick() {
|
||||||
var now = cpu.cycles();
|
var now = cpu.cycles();
|
||||||
var phase = _phase > 0 ? _high : _low;
|
var phase = _phase > 0 ? _high : _low;
|
||||||
@ -297,47 +299,95 @@ function Apple2IO(cpu, callbacks)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
registerSwitches: function apple2io_registerSwitches(a, locs) {
|
|
||||||
each(locs, function(key) {
|
|
||||||
var val = locs[key];
|
|
||||||
if (_locs[val]) {
|
|
||||||
debug('duplicate switch! ' + toHex(val));
|
|
||||||
}
|
|
||||||
_locs[val] = a;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
start: function apple2io_start() {
|
start: function apple2io_start() {
|
||||||
this.registerSwitches(this, LOC);
|
|
||||||
return 0xc0;
|
return 0xc0;
|
||||||
},
|
},
|
||||||
end: function apple2io_end() {
|
end: function apple2io_end() {
|
||||||
return 0xc0;
|
return 0xcf;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ioSwitch: function apple2io_ioSwitch(off, val) {
|
||||||
|
var result;
|
||||||
|
if (off < 0x80) {
|
||||||
|
result = _access(off, val);
|
||||||
|
} else {
|
||||||
|
var slot = (off & 0x70) >> 4;
|
||||||
|
if (_slot[slot]) {
|
||||||
|
result = _slot[slot].ioSwitch(off, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
read: function apple2io_read(page, off) {
|
read: function apple2io_read(page, off) {
|
||||||
var result = 0;
|
var result = 0;
|
||||||
if (_locs[off]) {
|
var slot;
|
||||||
result = _locs[off].ioSwitch(off);
|
switch (page) {
|
||||||
} else {
|
case 0xc0:
|
||||||
debug('I/O read: C0' + toHex(off));
|
result = this.ioSwitch(off);
|
||||||
|
break;
|
||||||
|
case 0xc1:
|
||||||
|
case 0xc2:
|
||||||
|
case 0xc3:
|
||||||
|
case 0xc4:
|
||||||
|
case 0xc5:
|
||||||
|
case 0xc6:
|
||||||
|
case 0xc7:
|
||||||
|
slot = page & 0x0f;
|
||||||
|
_auxRom = _slot[slot];
|
||||||
|
if (_slot[slot]) {
|
||||||
|
result = _slot[slot].read(page, off);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (_auxRom) {
|
||||||
|
result = _auxRom.read(page, off);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
write: function apple2io_write(page, off, val) {
|
write: function apple2io_write(page, off, val) {
|
||||||
if (_locs[off]) {
|
var slot;
|
||||||
_locs[off].ioSwitch(off, val);
|
switch (page) {
|
||||||
} else {
|
case 0xc0:
|
||||||
debug('I/O write: C0' + toHex(off));
|
this.ioSwitch(off);
|
||||||
|
break;
|
||||||
|
case 0xc1:
|
||||||
|
case 0xc2:
|
||||||
|
case 0xc3:
|
||||||
|
case 0xc4:
|
||||||
|
case 0xc5:
|
||||||
|
case 0xc6:
|
||||||
|
case 0xc7:
|
||||||
|
slot = page & 0x0f;
|
||||||
|
_auxRom = _slot[slot];
|
||||||
|
if (_slot[slot]) {
|
||||||
|
_slot[slot].write(page, off, val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (_auxRom) {
|
||||||
|
_auxRom.write(page, off, val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getState: function apple2io_getState() { return {}; },
|
getState: function apple2io_getState() { return {}; },
|
||||||
setState: function apple2io_setState() { },
|
setState: function apple2io_setState() { },
|
||||||
ioSwitch: function apple2io_ioSwitch(off, val) {
|
|
||||||
return _access(off, val);
|
addSlot: function apple2io_addSlot(slot, card) {
|
||||||
|
_slot[slot] = card;
|
||||||
},
|
},
|
||||||
|
|
||||||
keyDown: function apple2io_keyDown(ascii) {
|
keyDown: function apple2io_keyDown(ascii) {
|
||||||
_keyDown = true;
|
_keyDown = true;
|
||||||
_key = ascii | 0x80;
|
_key = ascii | 0x80;
|
||||||
},
|
},
|
||||||
|
|
||||||
keyUp: function apple2io_keyUp() {
|
keyUp: function apple2io_keyUp() {
|
||||||
_keyDown = false;
|
_keyDown = false;
|
||||||
_key = 0;
|
_key = 0;
|
||||||
@ -346,9 +396,11 @@ function Apple2IO(cpu, callbacks)
|
|||||||
buttonDown: function apple2io_buttonDown(b) {
|
buttonDown: function apple2io_buttonDown(b) {
|
||||||
_button[b] = true;
|
_button[b] = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
buttonUp: function apple2io_buttonUp(b) {
|
buttonUp: function apple2io_buttonUp(b) {
|
||||||
_button[b] = false;
|
_button[b] = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
paddle: function apple2io_paddle(p, v) {
|
paddle: function apple2io_paddle(p, v) {
|
||||||
_paddle[p] = v;
|
_paddle[p] = v;
|
||||||
},
|
},
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
* implied warranty.
|
* implied warranty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*jshint browser:true */
|
||||||
/*globals allocMemPages: false, debug: false,
|
/*globals allocMemPages: false, debug: false,
|
||||||
base64_encode: false, base64_decode: false,
|
base64_encode: false, base64_decode: false,
|
||||||
enhanced: false */
|
enhanced: false */
|
||||||
@ -173,6 +174,7 @@ function LoresPage(page, charset)
|
|||||||
base = addr - 0x400 * _page;
|
base = addr - 0x400 * _page;
|
||||||
return _buffer[bank][base];
|
return _buffer[bank][base];
|
||||||
},
|
},
|
||||||
|
|
||||||
_write: function(page, off, val, bank) {
|
_write: function(page, off, val, bank) {
|
||||||
var addr = (page << 8) | off,
|
var addr = (page << 8) | off,
|
||||||
base = addr - 0x400 * _page,
|
base = addr - 0x400 * _page,
|
||||||
@ -321,6 +323,7 @@ function LoresPage(page, charset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
var addr = 0x400 * _page;
|
var addr = 0x400 * _page;
|
||||||
_refreshing = true;
|
_refreshing = true;
|
||||||
@ -331,6 +334,7 @@ function LoresPage(page, charset)
|
|||||||
}
|
}
|
||||||
_refreshing = false;
|
_refreshing = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
blink: function() {
|
blink: function() {
|
||||||
var addr = 0x400 * _page;
|
var addr = 0x400 * _page;
|
||||||
_refreshing = true;
|
_refreshing = true;
|
||||||
@ -516,11 +520,14 @@ function HiresPage(page)
|
|||||||
},
|
},
|
||||||
|
|
||||||
_start: function() { return (0x20 * _page); },
|
_start: function() { return (0x20 * _page); },
|
||||||
|
|
||||||
_end: function() { return (0x020 * _page) + 0x1f; },
|
_end: function() { return (0x020 * _page) + 0x1f; },
|
||||||
|
|
||||||
_read: function(page, off, bank) {
|
_read: function(page, off, bank) {
|
||||||
var addr = (page << 8) | off, base = addr - 0x2000 * _page;
|
var addr = (page << 8) | off, base = addr - 0x2000 * _page;
|
||||||
return _buffer[bank][base];
|
return _buffer[bank][base];
|
||||||
},
|
},
|
||||||
|
|
||||||
_write: function(page, off, val, bank) {
|
_write: function(page, off, val, bank) {
|
||||||
function dim(c) {
|
function dim(c) {
|
||||||
return [c[0] * 0.75, c[1] * 0.75, c[2] * 0.75];
|
return [c[0] * 0.75, c[1] * 0.75, c[2] * 0.75];
|
||||||
@ -665,6 +672,7 @@ function HiresPage(page)
|
|||||||
off = dx * 4 + dy * 280 * 4 * 2;
|
off = dx * 4 + dy * 280 * 4 * 2;
|
||||||
for (idx = 0; idx < 9; idx++, off += 8) {
|
for (idx = 0; idx < 9; idx++, off += 8) {
|
||||||
val >>= 1;
|
val >>= 1;
|
||||||
|
|
||||||
if (v1) {
|
if (v1) {
|
||||||
if (_greenMode) {
|
if (_greenMode) {
|
||||||
color = _green;
|
color = _green;
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
* implied warranty.
|
* implied warranty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*globals toHex: false, debug: false*/
|
|
||||||
/*exported CPU6502 */
|
/*exported CPU6502 */
|
||||||
|
/*globals debug: false, toHex: false */
|
||||||
|
|
||||||
function CPU6502(options)
|
function CPU6502(options)
|
||||||
{
|
{
|
||||||
@ -1039,8 +1039,8 @@ function CPU6502(options)
|
|||||||
if (key in ops) {
|
if (key in ops) {
|
||||||
debug('overriding opcode ' + toHex(key));
|
debug('overriding opcode ' + toHex(key));
|
||||||
}
|
}
|
||||||
|
ops[key] = cops[key];
|
||||||
}
|
}
|
||||||
ops[key] = cops[key];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1379,14 +1379,14 @@ function CPU6502(options)
|
|||||||
' P=' + toHex(sr) +
|
' P=' + toHex(sr) +
|
||||||
' S=' + toHex(sp) +
|
' S=' + toHex(sp) +
|
||||||
' ' +
|
' ' +
|
||||||
(sr & flags.N ? 'N' : '-') +
|
((sr & flags.N) ? 'N' : '-') +
|
||||||
(sr & flags.V ? 'V' : '-') +
|
((sr & flags.V) ? 'V' : '-') +
|
||||||
'-' +
|
'-' +
|
||||||
(sr & flags.B ? 'B' : '-') +
|
((sr & flags.B) ? 'B' : '-') +
|
||||||
(sr & flags.D ? 'D' : '-') +
|
((sr & flags.D) ? 'D' : '-') +
|
||||||
(sr & flags.I ? 'I' : '-') +
|
((sr & flags.I) ? 'I' : '-') +
|
||||||
(sr & flags.Z ? 'Z' : '-') +
|
((sr & flags.Z) ? 'Z' : '-') +
|
||||||
(sr & flags.C ? 'C' : '-');
|
((sr & flags.C) ? 'C' : '-');
|
||||||
},
|
},
|
||||||
|
|
||||||
read: function(page, off) {
|
read: function(page, off) {
|
||||||
|
37
js/disk2.js
37
js/disk2.js
@ -10,12 +10,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*exported DiskII */
|
/*exported DiskII */
|
||||||
/*globals bytify, each: false, extend: false
|
/*globals bytify: false, each: false, extend: false, debug: false
|
||||||
base64_encode, base64_decode
|
base64_decode: false, base64_encode: false
|
||||||
Uint8Array
|
Uint8Array: false
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function DiskII(io, callbacks, slot)
|
function DiskII(io, slot, callbacks)
|
||||||
{
|
{
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -111,6 +111,7 @@ function DiskII(io, callbacks, slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _init() {
|
function _init() {
|
||||||
|
debug('Disk ][ in slot', slot);
|
||||||
each(LOC, function(key) {
|
each(LOC, function(key) {
|
||||||
LOC[key] += slot * 0x10;
|
LOC[key] += slot * 0x10;
|
||||||
});
|
});
|
||||||
@ -358,11 +359,15 @@ function DiskII(io, callbacks, slot)
|
|||||||
}
|
}
|
||||||
for (kdx = 0, jdx = 0x55; kdx < 0x100; kdx++) {
|
for (kdx = 0, jdx = 0x55; kdx < 0x100; kdx++) {
|
||||||
data[kdx] <<= 1;
|
data[kdx] <<= 1;
|
||||||
if (data2[jdx] & 0x01) data[kdx] |= 0x01;
|
if ((data2[jdx] & 0x01) !== 0) {
|
||||||
|
data[kdx] |= 0x01;
|
||||||
|
}
|
||||||
data2[jdx] >>= 1;
|
data2[jdx] >>= 1;
|
||||||
|
|
||||||
data[kdx] <<= 1;
|
data[kdx] <<= 1;
|
||||||
if (data2[jdx] & 0x01) data[kdx] |= 0x01;
|
if ((data2[jdx] & 0x01) !== 0) {
|
||||||
|
data[kdx] |= 0x01;
|
||||||
|
}
|
||||||
data2[jdx] >>= 1;
|
data2[jdx] >>= 1;
|
||||||
|
|
||||||
if (--jdx < 0) jdx = 0x55;
|
if (--jdx < 0) jdx = 0x55;
|
||||||
@ -492,7 +497,7 @@ function DiskII(io, callbacks, slot)
|
|||||||
if (callbacks.dirty) { callbacks.dirty(_drive, dirty); }
|
if (callbacks.dirty) { callbacks.dirty(_drive, dirty); }
|
||||||
}
|
}
|
||||||
|
|
||||||
var diskII_16 = [
|
var diskII = [
|
||||||
0xa2,0x20,0xa0,0x00,0xa2,0x03,0x86,0x3c,
|
0xa2,0x20,0xa0,0x00,0xa2,0x03,0x86,0x3c,
|
||||||
0x8a,0x0a,0x24,0x3c,0xf0,0x10,0x05,0x3c,
|
0x8a,0x0a,0x24,0x3c,0xf0,0x10,0x05,0x3c,
|
||||||
0x49,0xff,0x29,0x7e,0xb0,0x08,0x4a,0xd0,
|
0x49,0xff,0x29,0x7e,0xb0,0x08,0x4a,0xd0,
|
||||||
@ -561,25 +566,28 @@ function DiskII(io, callbacks, slot)
|
|||||||
0x03,0x4c,0x01,0x03,0x4c,0x2d,0xff,0xff
|
0x03,0x4c,0x01,0x03,0x4c,0x2d,0xff,0xff
|
||||||
];
|
];
|
||||||
*/
|
*/
|
||||||
var diskII = diskII_16;
|
|
||||||
|
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: function disk2_start() {
|
start: function disk2_start() {
|
||||||
io.registerSwitches(this, LOC);
|
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
|
|
||||||
end: function disk2_end() {
|
end: function disk2_end() {
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
|
|
||||||
ioSwitch: function disk2_ioSwitch(off, val) {
|
ioSwitch: function disk2_ioSwitch(off, val) {
|
||||||
return _access(off, val);
|
return _access(off, val);
|
||||||
},
|
},
|
||||||
|
|
||||||
read: function disk2_read(page, off) {
|
read: function disk2_read(page, off) {
|
||||||
return diskII[off];
|
return diskII[off];
|
||||||
},
|
},
|
||||||
|
|
||||||
write: function disk2_write() {},
|
write: function disk2_write() {},
|
||||||
|
|
||||||
reset: function disk2_reset() {
|
reset: function disk2_reset() {
|
||||||
if (_on) {
|
if (_on) {
|
||||||
_writeMode = false;
|
_writeMode = false;
|
||||||
@ -587,6 +595,7 @@ function DiskII(io, callbacks, slot)
|
|||||||
callbacks.driveLight(_drive, false);
|
callbacks.driveLight(_drive, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getState: function disk2_getState() {
|
getState: function disk2_getState() {
|
||||||
function getDriveState(drive) {
|
function getDriveState(drive) {
|
||||||
var result = {
|
var result = {
|
||||||
@ -613,7 +622,9 @@ function DiskII(io, callbacks, slot)
|
|||||||
drive: _drive
|
drive: _drive
|
||||||
};
|
};
|
||||||
_drives.forEach(function (drive, idx) {
|
_drives.forEach(function (drive, idx) {
|
||||||
result.drives[idx] = getDriveState(drive);
|
var _drive = result.drives[idx] = getDriveState(drive);
|
||||||
|
callbacks.driveLight(idx, _drive.on);
|
||||||
|
callbacks.dirty(idx, _drive.dirty);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
@ -635,7 +646,7 @@ function DiskII(io, callbacks, slot)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
state.drives.forEach(function(drive, idx) {
|
state.drives.forEach(function(drive, idx) {
|
||||||
_drives[idx] = setDriveState(state);
|
_drives[idx] = setDriveState(drive);
|
||||||
});
|
});
|
||||||
_skip = state.skip;
|
_skip = state.skip;
|
||||||
_latch = state.latch;
|
_latch = state.latch;
|
||||||
@ -741,8 +752,8 @@ function DiskII(io, callbacks, slot)
|
|||||||
var flags =
|
var flags =
|
||||||
prefix[0x10] | (prefix[0x11] << 8) |
|
prefix[0x10] | (prefix[0x11] << 8) |
|
||||||
(prefix[0x12] << 16) | (prefix[0x13] << 24);
|
(prefix[0x12] << 16) | (prefix[0x13] << 24);
|
||||||
_cur.readOnly = (flags & 0x80000000) ? true : false;
|
_cur.readOnly = (flags & 0x80000000) !== 0;
|
||||||
if (flags & 0x10) {
|
if ((flags & 0x10) !== 0) {
|
||||||
_cur.volume = flags & 0xff;
|
_cur.volume = flags & 0xff;
|
||||||
} else {
|
} else {
|
||||||
_cur.volume = 254;
|
_cur.volume = 254;
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*exported LanguageCard */
|
/*exported LanguageCard */
|
||||||
/*globals RAM: false */
|
/*globals debug: false
|
||||||
|
RAM: false */
|
||||||
|
|
||||||
function LanguageCard(io, rom) {
|
function LanguageCard(io, slot, rom) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var _io = io;
|
|
||||||
var _rom = rom;
|
var _rom = rom;
|
||||||
var _bank1 = null;
|
var _bank1 = null;
|
||||||
var _bank2 = null;
|
var _bank2 = null;
|
||||||
@ -34,6 +34,8 @@ function LanguageCard(io, rom) {
|
|||||||
var _write2 = null;
|
var _write2 = null;
|
||||||
|
|
||||||
function _init() {
|
function _init() {
|
||||||
|
debug('Language card in slot', slot);
|
||||||
|
|
||||||
_bank1 = new RAM(0xd0, 0xdf);
|
_bank1 = new RAM(0xd0, 0xdf);
|
||||||
_bank2 = new RAM(0xd0, 0xdf);
|
_bank2 = new RAM(0xd0, 0xdf);
|
||||||
_ram = new RAM(0xe0, 0xff);
|
_ram = new RAM(0xe0, 0xff);
|
||||||
@ -173,9 +175,9 @@ function LanguageCard(io, rom) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: function() {
|
start: function() {
|
||||||
_io.registerSwitches(this, LOC);
|
|
||||||
return 0xd0;
|
return 0xd0;
|
||||||
},
|
},
|
||||||
end: function() {
|
end: function() {
|
||||||
|
356
js/main2.js
356
js/main2.js
@ -1,27 +1,29 @@
|
|||||||
/* globals debug: false, gup: false, hup: false
|
/* globals debug: false, gup: false, hup: false, toHex: false,
|
||||||
CPU6502: false,
|
CPU6502: false,
|
||||||
RAM: false,
|
RAM: false,
|
||||||
Apple2ROM: false
|
Apple2ROM: false, IntBASIC: false, OriginalROM: false,
|
||||||
apple2_charset: false,
|
apple2_charset: false,
|
||||||
Apple2IO: false
|
Apple2IO: false
|
||||||
LoresPage: false, HiresPage: false, VideoModes: false
|
LoresPage: false, HiresPage: false, VideoModes: false
|
||||||
|
scanlines: true,
|
||||||
KeyBoard: false,
|
KeyBoard: false,
|
||||||
Parallel: false,
|
Parallel: false,
|
||||||
DiskII: false,
|
DiskII: false,
|
||||||
RAMFactor: false,
|
|
||||||
Printer: false,
|
Printer: false,
|
||||||
LanguageCard: false,
|
LanguageCard: false,
|
||||||
|
RAMFactor: false,
|
||||||
Thunderclock: false,
|
Thunderclock: false,
|
||||||
Prefs: false,
|
Prefs: false,
|
||||||
disk_index: false,
|
disk_index: false,
|
||||||
initAudio: false, enableSound: false,
|
initAudio: false, enableSound: false,
|
||||||
initGamepad: false, processGamepad: false, gamepad: false,
|
initGamepad: false, processGamepad: false, gamepad: false,
|
||||||
ApplesoftDump: false
|
ApplesoftDump: false, SYMBOLS: false
|
||||||
*/
|
*/
|
||||||
/* exported openLoad, openSave, doDelete,
|
/* exported openLoad, openSave, doDelete,
|
||||||
selectCategory, selectDisk, clickDisk, loadJSON,
|
selectCategory, selectDisk, clickDisk,
|
||||||
updateJoystick,
|
updateJoystick,
|
||||||
pauseRun, step
|
pauseRun, step,
|
||||||
|
restoreState, saveState,
|
||||||
dumpProgram, PageDebug
|
dumpProgram, PageDebug
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -35,6 +37,47 @@ var paused = false;
|
|||||||
|
|
||||||
var hashtag;
|
var hashtag;
|
||||||
|
|
||||||
|
var DEBUG = false;
|
||||||
|
var TRACE = false;
|
||||||
|
var MAX_TRACE = 256;
|
||||||
|
var trace = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page viewer
|
||||||
|
*/
|
||||||
|
|
||||||
|
function PageDebug(page)
|
||||||
|
{
|
||||||
|
var _page = page;
|
||||||
|
|
||||||
|
function _init() {
|
||||||
|
var r, c;
|
||||||
|
var row = $('<tr />').appendTo('#page' + toHex(_page));
|
||||||
|
$('<th>\\</th>').appendTo(row);
|
||||||
|
for (c = 0; c < 16; c++) {
|
||||||
|
$('<th>' + toHex(c) + '</th>').appendTo(row);
|
||||||
|
}
|
||||||
|
for (r = 0; r < 16; r++) {
|
||||||
|
row = $('<tr />').appendTo('#page' + toHex(_page));
|
||||||
|
$('<th>' + toHex(r * 16) + '</th>').appendTo(row);
|
||||||
|
for (c = 0; c < 16; c++) {
|
||||||
|
$('<td>--</td>').appendTo(row).attr('id', 'page' + toHex(_page) + '-' + toHex(r * 16 + c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_init();
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: function() { return _page; },
|
||||||
|
end: function() { return _page; },
|
||||||
|
read: null,
|
||||||
|
write: function(page, off, val) {
|
||||||
|
$('#page' + toHex(page) + '-' + toHex(off)).text(toHex(val));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var disk_categories = {'Local Saves': []};
|
var disk_categories = {'Local Saves': []};
|
||||||
var disk_sets = {};
|
var disk_sets = {};
|
||||||
var disk_cur_name = [];
|
var disk_cur_name = [];
|
||||||
@ -48,8 +91,8 @@ function DriveLights()
|
|||||||
on ? 'url(css/red-on-16.png)' :
|
on ? 'url(css/red-on-16.png)' :
|
||||||
'url(css/red-off-16.png)');
|
'url(css/red-off-16.png)');
|
||||||
},
|
},
|
||||||
dirty: function(drive, dirty) {
|
dirty: function() {
|
||||||
$('#disksave' + drive).button('option', 'disabled', !dirty);
|
// $('#disksave' + drive).button('option', 'disabled', !dirty);
|
||||||
},
|
},
|
||||||
label: function(drive, label) {
|
label: function(drive, label) {
|
||||||
if (label) {
|
if (label) {
|
||||||
@ -77,12 +120,11 @@ function DriveLights()
|
|||||||
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
|
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
|
||||||
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
|
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
|
||||||
|
|
||||||
var _saveDrive = 1;
|
var _currentDrive = 1;
|
||||||
var _loadDrive = 1;
|
|
||||||
|
|
||||||
function openLoad(drive, event)
|
function openLoad(drive, event)
|
||||||
{
|
{
|
||||||
_loadDrive = drive;
|
_currentDrive = parseInt(drive, 10);
|
||||||
if (event.metaKey) {
|
if (event.metaKey) {
|
||||||
openLoadHTTP(drive);
|
openLoadHTTP(drive);
|
||||||
} else {
|
} else {
|
||||||
@ -95,11 +137,18 @@ function openLoad(drive, event)
|
|||||||
|
|
||||||
function openSave(drive, event)
|
function openSave(drive, event)
|
||||||
{
|
{
|
||||||
_saveDrive = drive;
|
_currentDrive = parseInt(drive, 10);
|
||||||
|
|
||||||
|
var mimetype = 'application/octet-stream';
|
||||||
|
var data = disk2.getBinary(drive);
|
||||||
|
var a = $('#local_save_link');
|
||||||
|
|
||||||
|
var blob = new Blob([data], { 'type': mimetype });
|
||||||
|
a.attr('href', window.URL.createObjectURL(blob));
|
||||||
|
a.attr('download', drivelights.label(drive) + '.dsk');
|
||||||
|
|
||||||
if (event.metaKey) {
|
if (event.metaKey) {
|
||||||
dumpDisk(drive);
|
dumpDisk(drive);
|
||||||
} else if (event.altKey) {
|
|
||||||
openSaveLocal(drive);
|
|
||||||
} else {
|
} else {
|
||||||
$('#save_name').val(drivelights.label(drive));
|
$('#save_name').val(drivelights.label(drive));
|
||||||
$('#save').dialog('open');
|
$('#save').dialog('open');
|
||||||
@ -108,16 +157,30 @@ function openSave(drive, event)
|
|||||||
|
|
||||||
var loading = false;
|
var loading = false;
|
||||||
|
|
||||||
function loadAjax(url) {
|
function loadAjax(drive, url) {
|
||||||
loading = true;
|
loading = true;
|
||||||
$('#loading').dialog('open');
|
$('#loading').dialog('open');
|
||||||
|
|
||||||
$.ajax({ url: url,
|
$.ajax({
|
||||||
cache: false,
|
url: url,
|
||||||
dataType: 'jsonp',
|
dataType: 'json',
|
||||||
jsonp: false,
|
modifiedSince: true,
|
||||||
global: false
|
error: function(xhr, status, error) {
|
||||||
});
|
alert(error || status);
|
||||||
|
$('#loading').dialog('close');
|
||||||
|
loading = false;
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
if (data.type == 'binary') {
|
||||||
|
loadBinary(drive, data);
|
||||||
|
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
|
||||||
|
loadDisk(drive, data);
|
||||||
|
}
|
||||||
|
initGamepad(data.gamepad);
|
||||||
|
$('#loading').dialog('close');
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoad() {
|
function doLoad() {
|
||||||
@ -132,7 +195,7 @@ function doLoad() {
|
|||||||
|
|
||||||
var files = $('#local_file').prop('files');
|
var files = $('#local_file').prop('files');
|
||||||
if (files.length == 1) {
|
if (files.length == 1) {
|
||||||
doLoadLocal();
|
doLoadLocal(_currentDrive);
|
||||||
} else if (url) {
|
} else if (url) {
|
||||||
var filename;
|
var filename;
|
||||||
$('#load').dialog('close');
|
$('#load').dialog('close');
|
||||||
@ -141,22 +204,26 @@ function doLoad() {
|
|||||||
if (filename == '__manage') {
|
if (filename == '__manage') {
|
||||||
openManage();
|
openManage();
|
||||||
} else {
|
} else {
|
||||||
loadLocalStorage(_loadDrive, filename);
|
loadLocalStorage(_currentDrive, filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var r1 = /json\/disks\/(.*).json$/.exec(url);
|
var r1 = /json\/disks\/(.*).json$/.exec(url);
|
||||||
if (r1 && _loadDrive == 1) {
|
if (r1) {
|
||||||
filename = r1[1];
|
filename = r1[1];
|
||||||
document.location.hash = filename;
|
} else {
|
||||||
|
filename = url;
|
||||||
}
|
}
|
||||||
loadAjax(url);
|
var parts = document.location.hash.split('|');
|
||||||
|
parts[_currentDrive - 1] = filename;
|
||||||
|
document.location.hash = parts.join('|');
|
||||||
|
loadAjax(_currentDrive, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSave() {
|
function doSave() {
|
||||||
var name = $('#save_name').val();
|
var name = $('#save_name').val();
|
||||||
saveLocalStorage(_saveDrive, name);
|
saveLocalStorage(_currentDrive, name);
|
||||||
$('#save').dialog('close');
|
$('#save').dialog('close');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,14 +233,14 @@ function doDelete(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoadLocal() {
|
function doLoadLocal(drive) {
|
||||||
var files = $('#local_file').prop('files');
|
var files = $('#local_file').prop('files');
|
||||||
if (files.length == 1) {
|
if (files.length == 1) {
|
||||||
var file = files[0];
|
var file = files[0];
|
||||||
var parts = file.name.split('.');
|
var parts = file.name.split('.');
|
||||||
var ext = parts[parts.length - 1].toLowerCase();
|
var ext = parts[parts.length - 1].toLowerCase();
|
||||||
if ($.inArray(ext, DISK_TYPES) >= 0) {
|
if ($.inArray(ext, DISK_TYPES) >= 0) {
|
||||||
doLoadLocalDisk(file);
|
doLoadLocalDisk(drive, file);
|
||||||
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
|
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
|
||||||
doLoadLocalTape(file);
|
doLoadLocalTape(file);
|
||||||
} else {
|
} else {
|
||||||
@ -183,13 +250,13 @@ function doLoadLocal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoadLocalDisk(file) {
|
function doLoadLocalDisk(drive, file) {
|
||||||
var fileReader = new FileReader();
|
var fileReader = new FileReader();
|
||||||
fileReader.onload = function() {
|
fileReader.onload = function() {
|
||||||
var parts = file.name.split('.');
|
var parts = file.name.split('.');
|
||||||
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
|
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
|
||||||
if (disk2.setBinary(_saveDrive, name, ext, this.result)) {
|
if (disk2.setBinary(drive, name, ext, this.result)) {
|
||||||
drivelights.label(_saveDrive, name);
|
drivelights.label(drive, name);
|
||||||
$('#load').dialog('close');
|
$('#load').dialog('close');
|
||||||
initGamepad();
|
initGamepad();
|
||||||
}
|
}
|
||||||
@ -251,7 +318,7 @@ function doLoadLocalTape(file) {
|
|||||||
fileReader.readAsArrayBuffer(file);
|
fileReader.readAsArrayBuffer(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoadHTTP(_url) {
|
function doLoadHTTP(drive, _url) {
|
||||||
var url = _url || $('#http_url').val();
|
var url = _url || $('#http_url').val();
|
||||||
if (url) {
|
if (url) {
|
||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
@ -262,8 +329,8 @@ function doLoadHTTP(_url) {
|
|||||||
var parts = url.split(/[\/\.]/);
|
var parts = url.split(/[\/\.]/);
|
||||||
var name = decodeURIComponent(parts[parts.length - 2]);
|
var name = decodeURIComponent(parts[parts.length - 2]);
|
||||||
var ext = parts[parts.length - 1].toLowerCase();
|
var ext = parts[parts.length - 1].toLowerCase();
|
||||||
if (disk2.setBinary(_saveDrive, name, ext, req.response)) {
|
if (disk2.setBinary(drive, name, ext, req.response)) {
|
||||||
drivelights.label(_saveDrive, name);
|
drivelights.label(drive, name);
|
||||||
$('#http_load').dialog('close');
|
$('#http_load').dialog('close');
|
||||||
initGamepad();
|
initGamepad();
|
||||||
}
|
}
|
||||||
@ -273,23 +340,10 @@ function doLoadHTTP(_url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openLoadHTTP(drive) {
|
function openLoadHTTP(drive) {
|
||||||
_saveDrive = drive;
|
_currentDrive = parseInt(drive, 10);
|
||||||
$('#http_load').dialog('open');
|
$('#http_load').dialog('open');
|
||||||
}
|
}
|
||||||
|
|
||||||
function openSaveLocal(drive) {
|
|
||||||
_saveDrive = drive;
|
|
||||||
var mimetype = 'application/octet-stream';
|
|
||||||
var data = disk2.getBinary(drive);
|
|
||||||
var a = $('#local_save_link');
|
|
||||||
|
|
||||||
var blob = new Blob([data], { 'type': mimetype });
|
|
||||||
a.attr('href', window.URL.createObjectURL(blob));
|
|
||||||
a.attr('download', drivelights.label(drive) + '.dsk');
|
|
||||||
|
|
||||||
$('#local_save').dialog('open');
|
|
||||||
}
|
|
||||||
|
|
||||||
function openManage() {
|
function openManage() {
|
||||||
$('#manage').dialog('open');
|
$('#manage').dialog('open');
|
||||||
}
|
}
|
||||||
@ -307,23 +361,27 @@ var hgr2 = new HiresPage(2);
|
|||||||
var gr = new LoresPage(1, apple2_charset);
|
var gr = new LoresPage(1, apple2_charset);
|
||||||
var gr2 = new LoresPage(2, apple2_charset);
|
var gr2 = new LoresPage(2, apple2_charset);
|
||||||
|
|
||||||
var rom = new Apple2ROM();
|
var romVersion = prefs.readPref('computer_type');
|
||||||
var dumper = new ApplesoftDump(ram2);
|
var rom;
|
||||||
|
if (romVersion == 'apple2') {
|
||||||
|
rom = new IntBASIC();
|
||||||
|
} else if (romVersion == 'original') {
|
||||||
|
rom = new OriginalROM();
|
||||||
|
} else {
|
||||||
|
rom = new Apple2ROM();
|
||||||
|
}
|
||||||
|
|
||||||
var vm = new VideoModes(gr, hgr, gr2, hgr2);
|
var vm = new VideoModes(gr, hgr, gr2, hgr2);
|
||||||
var mmu = {
|
var dumper = new ApplesoftDump(cpu);
|
||||||
auxRom: function(slot, rom) {
|
|
||||||
cpu.addPageHandler(rom);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var drivelights = new DriveLights();
|
var drivelights = new DriveLights();
|
||||||
var io = new Apple2IO(cpu, vm);
|
var io = new Apple2IO(cpu, vm);
|
||||||
var keyboard = new KeyBoard(io);
|
var keyboard = new KeyBoard(io);
|
||||||
var parallel = new Parallel(io, new Printer(), 1);
|
var lc = new LanguageCard(io, 0, rom);
|
||||||
var disk2 = new DiskII(io, drivelights, 6);
|
var parallel = new Parallel(io, 1, new Printer());
|
||||||
var slinky = new RAMFactor(mmu, io, 2, 1024 * 1024);
|
var slinky = new RAMFactor(io, 2, 1024 * 1024);
|
||||||
var clock = new Thunderclock(mmu, io, 7);
|
var disk2 = new DiskII(io, 6, drivelights);
|
||||||
var lc = new LanguageCard(io, rom);
|
var clock = new Thunderclock(io, 7);
|
||||||
|
|
||||||
cpu.addPageHandler(ram1);
|
cpu.addPageHandler(ram1);
|
||||||
cpu.addPageHandler(gr);
|
cpu.addPageHandler(gr);
|
||||||
@ -332,13 +390,14 @@ cpu.addPageHandler(ram2);
|
|||||||
cpu.addPageHandler(hgr);
|
cpu.addPageHandler(hgr);
|
||||||
cpu.addPageHandler(hgr2);
|
cpu.addPageHandler(hgr2);
|
||||||
cpu.addPageHandler(ram3);
|
cpu.addPageHandler(ram3);
|
||||||
|
|
||||||
cpu.addPageHandler(lc);
|
|
||||||
cpu.addPageHandler(io);
|
cpu.addPageHandler(io);
|
||||||
cpu.addPageHandler(parallel);
|
cpu.addPageHandler(lc);
|
||||||
cpu.addPageHandler(slinky);
|
|
||||||
cpu.addPageHandler(disk2);
|
io.addSlot(0, lc);
|
||||||
cpu.addPageHandler(clock);
|
io.addSlot(1, parallel);
|
||||||
|
io.addSlot(2, slinky);
|
||||||
|
io.addSlot(6, disk2);
|
||||||
|
io.addSlot(7, clock);
|
||||||
|
|
||||||
var showFPS = false;
|
var showFPS = false;
|
||||||
|
|
||||||
@ -403,7 +462,7 @@ function step()
|
|||||||
|
|
||||||
var accelerated = false;
|
var accelerated = false;
|
||||||
|
|
||||||
function updateSpeed()
|
function updateCPU()
|
||||||
{
|
{
|
||||||
accelerated = $('#accelerator_toggle').prop('checked');
|
accelerated = $('#accelerator_toggle').prop('checked');
|
||||||
kHz = accelerated ? 4092 : 1023;
|
kHz = accelerated ? 4092 : 1023;
|
||||||
@ -429,6 +488,7 @@ function run(pc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ival = 30;
|
var ival = 30;
|
||||||
|
|
||||||
var now, last = Date.now();
|
var now, last = Date.now();
|
||||||
var runFn = function() {
|
var runFn = function() {
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
@ -447,9 +507,23 @@ function run(pc) {
|
|||||||
processHash(hash);
|
processHash(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
cpu.stepCycles(step);
|
if (DEBUG) {
|
||||||
|
cpu.stepCyclesDebug(TRACE ? 1 : step, function() {
|
||||||
|
var line = cpu.dumpRegisters() + ' ' +
|
||||||
|
cpu.dumpPC(undefined, SYMBOLS);
|
||||||
|
if (TRACE) {
|
||||||
|
debug(line);
|
||||||
|
} else {
|
||||||
|
trace.push(line);
|
||||||
|
if (trace.length > MAX_TRACE) {
|
||||||
|
trace.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cpu.stepCycles(step);
|
||||||
|
}
|
||||||
vm.blit();
|
vm.blit();
|
||||||
io.sampleTick();
|
io.sampleTick();
|
||||||
}
|
}
|
||||||
@ -479,6 +553,65 @@ function reset()
|
|||||||
cpu.reset();
|
cpu.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var state = null;
|
||||||
|
|
||||||
|
function storeStateLocal() {
|
||||||
|
window.localStorage['apple2.state'] = JSON.stringify(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreStateLocal() {
|
||||||
|
var data = window.localStorage['apple2.state'];
|
||||||
|
if (data) {
|
||||||
|
state = JSON.parse(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveState() {
|
||||||
|
if (state && !window.confirm('Overwrite Saved State?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
cpu: cpu.getState(),
|
||||||
|
ram1: ram1.getState(),
|
||||||
|
ram2: ram2.getState(),
|
||||||
|
ram3: ram3.getState(),
|
||||||
|
io: io.getState(),
|
||||||
|
lc: lc.getState(),
|
||||||
|
vm: vm.getState(),
|
||||||
|
disk2: disk2.getState(),
|
||||||
|
drivelights: drivelights.getState()
|
||||||
|
};
|
||||||
|
if (slinky) {
|
||||||
|
state.slinky = slinky.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.localStorage) {
|
||||||
|
storeStateLocal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreState() {
|
||||||
|
if (window.localStorage) {
|
||||||
|
restoreStateLocal();
|
||||||
|
}
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cpu.setState(state.cpu);
|
||||||
|
ram1.setState(state.ram1);
|
||||||
|
ram2.setState(state.ram2);
|
||||||
|
ram3.setState(state.ram3);
|
||||||
|
io.setState(state.io);
|
||||||
|
lc.setState(state.lc);
|
||||||
|
vm.setState(state.vm);
|
||||||
|
disk2.setState(state.disk2);
|
||||||
|
drivelights.setState(state.drivelights);
|
||||||
|
if (slinky && state.slinky) {
|
||||||
|
slinky.setState(state.slinky);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function loadBinary(bin) {
|
function loadBinary(bin) {
|
||||||
stop();
|
stop();
|
||||||
for (var idx = 0; idx < bin.length; idx++) {
|
for (var idx = 0; idx < bin.length; idx++) {
|
||||||
@ -499,7 +632,7 @@ function selectCategory() {
|
|||||||
}
|
}
|
||||||
var option = $('<option />').val(file.filename).text(name)
|
var option = $('<option />').val(file.filename).text(name)
|
||||||
.appendTo('#disk_select');
|
.appendTo('#disk_select');
|
||||||
if (disk_cur_name[_loadDrive] == name) {
|
if (disk_cur_name[_currentDrive] == name) {
|
||||||
option.attr('selected', 'selected');
|
option.attr('selected', 'selected');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -514,7 +647,7 @@ function clickDisk() {
|
|||||||
doLoad();
|
doLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadDisk(disk) {
|
function loadDisk(drive, disk) {
|
||||||
var name = disk.name;
|
var name = disk.name;
|
||||||
var category = disk.category;
|
var category = disk.category;
|
||||||
|
|
||||||
@ -522,25 +655,14 @@ function loadDisk(disk) {
|
|||||||
name += ' - ' + disk.disk;
|
name += ' - ' + disk.disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
disk_cur_cat[_loadDrive] = category;
|
disk_cur_cat[drive] = category;
|
||||||
disk_cur_name[_loadDrive] = name;
|
disk_cur_name[drive] = name;
|
||||||
|
|
||||||
drivelights.label(_loadDrive, name);
|
drivelights.label(drive, name);
|
||||||
disk2.setDisk(_loadDrive, disk);
|
disk2.setDisk(drive, disk);
|
||||||
initGamepad(disk.gamepad);
|
initGamepad(disk.gamepad);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadJSON(data) {
|
|
||||||
if (data.type == 'binary') {
|
|
||||||
loadBinary(data);
|
|
||||||
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
|
|
||||||
loadDisk(data);
|
|
||||||
}
|
|
||||||
initGamepad(data.gamepad);
|
|
||||||
$('#loading').dialog('close');
|
|
||||||
loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LocalStorage Disk Storage
|
* LocalStorage Disk Storage
|
||||||
*/
|
*/
|
||||||
@ -608,16 +730,20 @@ function loadLocalStorage(drive, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processHash(hash) {
|
function processHash(hash) {
|
||||||
if (hash.indexOf('://') > 0) {
|
var files = hash.split('|');
|
||||||
var parts = hash.split('.');
|
for (var idx = 0; idx < files.length; idx++) {
|
||||||
var ext = parts[parts.length - 1].toLowerCase();
|
var file = files[idx];
|
||||||
if (ext == 'json') {
|
if (file.indexOf('://') > 0) {
|
||||||
loadAjax(hash);
|
var parts = file.split('.');
|
||||||
|
var ext = parts[parts.length - 1].toLowerCase();
|
||||||
|
if (ext == 'json') {
|
||||||
|
loadAjax(idx + 1, file);
|
||||||
|
} else {
|
||||||
|
doLoadHTTP(idx + 1, file);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doLoadHTTP(hash);
|
loadAjax(idx + 1, 'json/disks/' + file + '.json');
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
loadAjax('json/disks/' + hash + '.json');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,6 +752,14 @@ function processHash(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function _keydown(evt) {
|
function _keydown(evt) {
|
||||||
|
if (!focused || (!evt.metaKey || evt.ctrlKey)) {
|
||||||
|
evt.preventDefault();
|
||||||
|
|
||||||
|
var key = keyboard.mapKeyEvent(evt);
|
||||||
|
if (key != 0xff) {
|
||||||
|
io.keyDown(key, evt.shiftKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (evt.keyCode === 112) { // F1 - Reset
|
if (evt.keyCode === 112) { // F1 - Reset
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
} else if (evt.keyCode === 113) { // F2 - Full Screen
|
} else if (evt.keyCode === 113) { // F2 - Full Screen
|
||||||
@ -647,36 +781,31 @@ function _keydown(evt) {
|
|||||||
elem.mozRequestFullScreen();
|
elem.mozRequestFullScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (evt.keyCode === 114) { // F3
|
||||||
|
io.keyDown(0x1b);
|
||||||
} else if (evt.keyCode == 16) { // Shift
|
} else if (evt.keyCode == 16) { // Shift
|
||||||
keyboard.shiftKey(true);
|
keyboard.shiftKey(true);
|
||||||
io.buttonDown(2);
|
io.buttonDown(2);
|
||||||
} else if (evt.keyCode == 17) { // Control
|
} else if (evt.keyCode == 17) { // Control
|
||||||
keyboard.controlKey(true);
|
keyboard.controlKey(true);
|
||||||
} else if (!focused && (!evt.metaKey || evt.ctrlKey)) {
|
|
||||||
evt.preventDefault();
|
|
||||||
|
|
||||||
var key = keyboard.mapKeyEvent(evt);
|
|
||||||
if (key != 0xff) {
|
|
||||||
io.keyDown(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _keyup(evt) {
|
function _keyup(evt) {
|
||||||
|
if (!focused)
|
||||||
|
io.keyUp();
|
||||||
|
|
||||||
if (evt.keyCode == 16) { // Shift
|
if (evt.keyCode == 16) { // Shift
|
||||||
keyboard.shiftKey(false);
|
keyboard.shiftKey(false);
|
||||||
io.buttonUp(2);
|
io.buttonUp(2);
|
||||||
} else if (evt.keyCode == 17) { // Control
|
} else if (evt.keyCode == 17) { // Control
|
||||||
keyboard.controlKey(false);
|
keyboard.controlKey(false);
|
||||||
} else {
|
|
||||||
if (!focused) {
|
|
||||||
io.keyUp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateScreen() {
|
function updateScreen() {
|
||||||
var green = $('#green_screen').prop('checked');
|
var green = $('#green_screen').prop('checked');
|
||||||
|
scanlines = $('#show_scanlines').prop('checked');
|
||||||
|
|
||||||
vm.green(green);
|
vm.green(green);
|
||||||
}
|
}
|
||||||
@ -774,21 +903,30 @@ $(function() {
|
|||||||
keyboard.create($('#keyboard'));
|
keyboard.create($('#keyboard'));
|
||||||
|
|
||||||
if (prefs.havePrefs()) {
|
if (prefs.havePrefs()) {
|
||||||
$('input[type=checkbox]').each(function() {
|
$('#options input[type=checkbox]').each(function() {
|
||||||
var val = prefs.readPref(this.id);
|
var val = prefs.readPref(this.id);
|
||||||
if (val)
|
if (val)
|
||||||
this.checked = JSON.parse(val);
|
this.checked = JSON.parse(val);
|
||||||
}).change(function() {
|
}).change(function() {
|
||||||
prefs.writePref(this.id, JSON.stringify(this.checked));
|
prefs.writePref(this.id, JSON.stringify(this.checked));
|
||||||
});
|
});
|
||||||
|
$('#options select').each(function() {
|
||||||
|
var val = prefs.readPref(this.id);
|
||||||
|
if (val)
|
||||||
|
this.value = val;
|
||||||
|
}).change(function() {
|
||||||
|
prefs.writePref(this.id, this.value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
if (romVersion != 'original') {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
run();
|
run();
|
||||||
setInterval(updateKHz, 1000);
|
setInterval(updateKHz, 1000);
|
||||||
updateSound();
|
updateSound();
|
||||||
updateScreen();
|
updateScreen();
|
||||||
updateSpeed();
|
updateCPU();
|
||||||
|
|
||||||
var cancel = function() { $(this).dialog('close'); };
|
var cancel = function() { $(this).dialog('close'); };
|
||||||
$('#loading').dialog({ autoOpen: false, modal: true });
|
$('#loading').dialog({ autoOpen: false, modal: true });
|
||||||
|
326
js/main2e.js
326
js/main2e.js
@ -1,25 +1,26 @@
|
|||||||
/* globals debug: false, gup: false, hup: false,
|
/* globals debug: false, gup: false, hup: false, toHex: false
|
||||||
CPU6502: false,
|
CPU6502: false,
|
||||||
Apple2eROM: false, Apple2eEnhancedROM: false,
|
Apple2eROM: false, Apple2eEnhancedROM: false,
|
||||||
apple2e_charset: false,
|
apple2e_charset: false,
|
||||||
Apple2IO: false
|
Apple2IO: false
|
||||||
LoresPage: false, HiresPage: false, VideoModes: false
|
LoresPage: false, HiresPage: false, VideoModes: false,
|
||||||
|
scanlines: true,
|
||||||
KeyBoard: false,
|
KeyBoard: false,
|
||||||
Parallel: false,
|
Parallel: false,
|
||||||
DiskII: false,
|
DiskII: false,
|
||||||
RAMFactor: false,
|
|
||||||
Printer: false,
|
Printer: false,
|
||||||
MMU: false,
|
MMU: false,
|
||||||
Slot3: false,
|
Slot3: false,
|
||||||
|
RAMFactor: false,
|
||||||
Thunderclock: false,
|
Thunderclock: false,
|
||||||
Prefs: false,
|
Prefs: false,
|
||||||
disk_index: false,
|
disk_index: false,
|
||||||
initAudio: false, enableSound: false,
|
initAudio: false, enableSound: false,
|
||||||
initGamepad: false, processGamepad: false, gamepad: false,
|
initGamepad: false, processGamepad: false, gamepad: false,
|
||||||
ApplesoftDump: false
|
ApplesoftDump: false, SYMBOLS: false,
|
||||||
*/
|
*/
|
||||||
/* exported openLoad, openSave, doDelete,
|
/* exported openLoad, openSave, doDelete,
|
||||||
selectCategory, selectDisk, clickDisk, loadJSON,
|
selectCategory, selectDisk, clickDisk,
|
||||||
updateJoystick,
|
updateJoystick,
|
||||||
pauseRun, step,
|
pauseRun, step,
|
||||||
restoreState, saveState,
|
restoreState, saveState,
|
||||||
@ -36,6 +37,47 @@ var paused = false;
|
|||||||
|
|
||||||
var hashtag;
|
var hashtag;
|
||||||
|
|
||||||
|
var DEBUG = false;
|
||||||
|
var TRACE = false;
|
||||||
|
var MAX_TRACE = 256;
|
||||||
|
var trace = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Page viewer
|
||||||
|
*/
|
||||||
|
|
||||||
|
function PageDebug(page)
|
||||||
|
{
|
||||||
|
var _page = page;
|
||||||
|
|
||||||
|
function _init() {
|
||||||
|
var r, c;
|
||||||
|
var row = $('<tr />').appendTo('#page' + toHex(_page));
|
||||||
|
$('<th>\\</th>').appendTo(row);
|
||||||
|
for (c = 0; c < 16; c++) {
|
||||||
|
$('<th>' + toHex(c) + '</th>').appendTo(row);
|
||||||
|
}
|
||||||
|
for (r = 0; r < 16; r++) {
|
||||||
|
row = $('<tr />').appendTo('#page' + toHex(_page));
|
||||||
|
$('<th>' + toHex(r * 16) + '</th>').appendTo(row);
|
||||||
|
for (c = 0; c < 16; c++) {
|
||||||
|
$('<td>--</td>').appendTo(row).attr('id', 'page' + toHex(_page) + '-' + toHex(r * 16 + c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_init();
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: function() { return _page; },
|
||||||
|
end: function() { return _page; },
|
||||||
|
read: null,
|
||||||
|
write: function(page, off, val) {
|
||||||
|
$('#page' + toHex(page) + '-' + toHex(off)).text(toHex(val));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var disk_categories = {'Local Saves': []};
|
var disk_categories = {'Local Saves': []};
|
||||||
var disk_sets = {};
|
var disk_sets = {};
|
||||||
var disk_cur_name = [];
|
var disk_cur_name = [];
|
||||||
@ -49,8 +91,8 @@ function DriveLights()
|
|||||||
on ? 'url(css/red-on-16.png)' :
|
on ? 'url(css/red-on-16.png)' :
|
||||||
'url(css/red-off-16.png)');
|
'url(css/red-off-16.png)');
|
||||||
},
|
},
|
||||||
dirty: function(drive, dirty) {
|
dirty: function() {
|
||||||
$('#disksave' + drive).button('option', 'disabled', !dirty);
|
// $('#disksave' + drive).button('option', 'disabled', !dirty);
|
||||||
},
|
},
|
||||||
label: function(drive, label) {
|
label: function(drive, label) {
|
||||||
if (label) {
|
if (label) {
|
||||||
@ -78,12 +120,11 @@ function DriveLights()
|
|||||||
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
|
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
|
||||||
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
|
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
|
||||||
|
|
||||||
var _saveDrive = 1;
|
var _currentDrive = 1;
|
||||||
var _loadDrive = 1;
|
|
||||||
|
|
||||||
function openLoad(drive, event)
|
function openLoad(drive, event)
|
||||||
{
|
{
|
||||||
_loadDrive = drive;
|
_currentDrive = parseInt(drive, 10);
|
||||||
if (event.metaKey) {
|
if (event.metaKey) {
|
||||||
openLoadHTTP(drive);
|
openLoadHTTP(drive);
|
||||||
} else {
|
} else {
|
||||||
@ -96,11 +137,18 @@ function openLoad(drive, event)
|
|||||||
|
|
||||||
function openSave(drive, event)
|
function openSave(drive, event)
|
||||||
{
|
{
|
||||||
_saveDrive = drive;
|
_currentDrive = parseInt(drive, 10);
|
||||||
|
|
||||||
|
var mimetype = 'application/octet-stream';
|
||||||
|
var data = disk2.getBinary(drive);
|
||||||
|
var a = $('#local_save_link');
|
||||||
|
|
||||||
|
var blob = new Blob([data], { 'type': mimetype });
|
||||||
|
a.attr('href', window.URL.createObjectURL(blob));
|
||||||
|
a.attr('download', drivelights.label(drive) + '.dsk');
|
||||||
|
|
||||||
if (event.metaKey) {
|
if (event.metaKey) {
|
||||||
dumpDisk(drive);
|
dumpDisk(drive);
|
||||||
} else if (event.altKey) {
|
|
||||||
openSaveLocal(drive);
|
|
||||||
} else {
|
} else {
|
||||||
$('#save_name').val(drivelights.label(drive));
|
$('#save_name').val(drivelights.label(drive));
|
||||||
$('#save').dialog('open');
|
$('#save').dialog('open');
|
||||||
@ -109,16 +157,30 @@ function openSave(drive, event)
|
|||||||
|
|
||||||
var loading = false;
|
var loading = false;
|
||||||
|
|
||||||
function loadAjax(url) {
|
function loadAjax(drive, url) {
|
||||||
loading = true;
|
loading = true;
|
||||||
$('#loading').dialog('open');
|
$('#loading').dialog('open');
|
||||||
|
|
||||||
$.ajax({ url: url,
|
$.ajax({
|
||||||
cache: false,
|
url: url,
|
||||||
dataType: 'jsonp',
|
dataType: 'json',
|
||||||
jsonp: false,
|
modifiedSince: true,
|
||||||
global: false
|
error: function(xhr, status, error) {
|
||||||
});
|
alert(error || status);
|
||||||
|
$('#loading').dialog('close');
|
||||||
|
loading = false;
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
if (data.type == 'binary') {
|
||||||
|
loadBinary(drive, data);
|
||||||
|
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
|
||||||
|
loadDisk(drive, data);
|
||||||
|
}
|
||||||
|
initGamepad(data.gamepad);
|
||||||
|
$('#loading').dialog('close');
|
||||||
|
loading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoad() {
|
function doLoad() {
|
||||||
@ -133,7 +195,7 @@ function doLoad() {
|
|||||||
|
|
||||||
var files = $('#local_file').prop('files');
|
var files = $('#local_file').prop('files');
|
||||||
if (files.length == 1) {
|
if (files.length == 1) {
|
||||||
doLoadLocal();
|
doLoadLocal(_currentDrive);
|
||||||
} else if (url) {
|
} else if (url) {
|
||||||
var filename;
|
var filename;
|
||||||
$('#load').dialog('close');
|
$('#load').dialog('close');
|
||||||
@ -142,22 +204,26 @@ function doLoad() {
|
|||||||
if (filename == '__manage') {
|
if (filename == '__manage') {
|
||||||
openManage();
|
openManage();
|
||||||
} else {
|
} else {
|
||||||
loadLocalStorage(_loadDrive, filename);
|
loadLocalStorage(_currentDrive, filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var r1 = /json\/disks\/(.*).json$/.exec(url);
|
var r1 = /json\/disks\/(.*).json$/.exec(url);
|
||||||
if (r1 && _loadDrive == 1) {
|
if (r1) {
|
||||||
filename = r1[1];
|
filename = r1[1];
|
||||||
document.location.hash = filename;
|
} else {
|
||||||
|
filename = url;
|
||||||
}
|
}
|
||||||
loadAjax(url);
|
var parts = document.location.hash.split('|');
|
||||||
|
parts[_currentDrive - 1] = filename;
|
||||||
|
document.location.hash = parts.join('|');
|
||||||
|
loadAjax(_currentDrive, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSave() {
|
function doSave() {
|
||||||
var name = $('#save_name').val();
|
var name = $('#save_name').val();
|
||||||
saveLocalStorage(_saveDrive, name);
|
saveLocalStorage(_currentDrive, name);
|
||||||
$('#save').dialog('close');
|
$('#save').dialog('close');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,14 +233,14 @@ function doDelete(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoadLocal() {
|
function doLoadLocal(drive) {
|
||||||
var files = $('#local_file').prop('files');
|
var files = $('#local_file').prop('files');
|
||||||
if (files.length == 1) {
|
if (files.length == 1) {
|
||||||
var file = files[0];
|
var file = files[0];
|
||||||
var parts = file.name.split('.');
|
var parts = file.name.split('.');
|
||||||
var ext = parts[parts.length - 1].toLowerCase();
|
var ext = parts[parts.length - 1].toLowerCase();
|
||||||
if ($.inArray(ext, DISK_TYPES) >= 0) {
|
if ($.inArray(ext, DISK_TYPES) >= 0) {
|
||||||
doLoadLocalDisk(file);
|
doLoadLocalDisk(drive, file);
|
||||||
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
|
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
|
||||||
doLoadLocalTape(file);
|
doLoadLocalTape(file);
|
||||||
} else {
|
} else {
|
||||||
@ -184,13 +250,13 @@ function doLoadLocal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoadLocalDisk(file) {
|
function doLoadLocalDisk(drive, file) {
|
||||||
var fileReader = new FileReader();
|
var fileReader = new FileReader();
|
||||||
fileReader.onload = function() {
|
fileReader.onload = function() {
|
||||||
var parts = file.name.split('.');
|
var parts = file.name.split('.');
|
||||||
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
|
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
|
||||||
if (disk2.setBinary(_saveDrive, name, ext, this.result)) {
|
if (disk2.setBinary(drive, name, ext, this.result)) {
|
||||||
drivelights.label(_saveDrive, name);
|
drivelights.label(drive, name);
|
||||||
$('#load').dialog('close');
|
$('#load').dialog('close');
|
||||||
initGamepad();
|
initGamepad();
|
||||||
}
|
}
|
||||||
@ -252,7 +318,7 @@ function doLoadLocalTape(file) {
|
|||||||
fileReader.readAsArrayBuffer(file);
|
fileReader.readAsArrayBuffer(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLoadHTTP(_url) {
|
function doLoadHTTP(drive, _url) {
|
||||||
var url = _url || $('#http_url').val();
|
var url = _url || $('#http_url').val();
|
||||||
if (url) {
|
if (url) {
|
||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
@ -263,8 +329,8 @@ function doLoadHTTP(_url) {
|
|||||||
var parts = url.split(/[\/\.]/);
|
var parts = url.split(/[\/\.]/);
|
||||||
var name = decodeURIComponent(parts[parts.length - 2]);
|
var name = decodeURIComponent(parts[parts.length - 2]);
|
||||||
var ext = parts[parts.length - 1].toLowerCase();
|
var ext = parts[parts.length - 1].toLowerCase();
|
||||||
if (disk2.setBinary(_saveDrive, name, ext, req.response)) {
|
if (disk2.setBinary(drive, name, ext, req.response)) {
|
||||||
drivelights.label(_saveDrive, name);
|
drivelights.label(drive, name);
|
||||||
$('#http_load').dialog('close');
|
$('#http_load').dialog('close');
|
||||||
initGamepad();
|
initGamepad();
|
||||||
}
|
}
|
||||||
@ -274,30 +340,18 @@ function doLoadHTTP(_url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openLoadHTTP(drive) {
|
function openLoadHTTP(drive) {
|
||||||
_saveDrive = drive;
|
_currentDrive = parseInt(drive, 10);
|
||||||
$('#http_load').dialog('open');
|
$('#http_load').dialog('open');
|
||||||
}
|
}
|
||||||
|
|
||||||
function openSaveLocal(drive) {
|
|
||||||
_saveDrive = drive;
|
|
||||||
var mimetype = 'application/octet-stream';
|
|
||||||
var data = disk2.getBinary(drive);
|
|
||||||
var a = $('#local_save_link');
|
|
||||||
|
|
||||||
var blob = new Blob([data], { 'type': mimetype });
|
|
||||||
a.attr('href', window.URL.createObjectURL(blob));
|
|
||||||
a.attr('download', drivelights.label(drive) + '.dsk');
|
|
||||||
|
|
||||||
$('#local_save').dialog('open');
|
|
||||||
}
|
|
||||||
|
|
||||||
function openManage() {
|
function openManage() {
|
||||||
$('#manage').dialog('open');
|
$('#manage').dialog('open');
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefs = new Prefs();
|
var prefs = new Prefs();
|
||||||
var enhanced = true;
|
var enhanced = prefs.readPref('computer_type') != 'apple2e';
|
||||||
var runTimer = null;
|
var runTimer = null;
|
||||||
|
|
||||||
var cpu = new CPU6502({'65C02': enhanced});
|
var cpu = new CPU6502({'65C02': enhanced});
|
||||||
|
|
||||||
var hgr = new HiresPage(1);
|
var hgr = new HiresPage(1);
|
||||||
@ -311,29 +365,30 @@ if (enhanced) {
|
|||||||
} else {
|
} else {
|
||||||
rom = new Apple2eROM();
|
rom = new Apple2eROM();
|
||||||
}
|
}
|
||||||
|
|
||||||
var vm = new VideoModes(gr, hgr, gr2, hgr2);
|
var vm = new VideoModes(gr, hgr, gr2, hgr2);
|
||||||
|
var dumper = new ApplesoftDump(cpu);
|
||||||
|
|
||||||
var drivelights = new DriveLights();
|
var drivelights = new DriveLights();
|
||||||
var io = new Apple2IO(cpu, vm);
|
var io = new Apple2IO(cpu, vm);
|
||||||
var keyboard = new KeyBoard(io);
|
var keyboard = new KeyBoard(io);
|
||||||
|
|
||||||
var mmu = new MMU(cpu, gr, gr2, hgr, hgr2, io, rom);
|
var mmu = new MMU(cpu, gr, gr2, hgr, hgr2, io, rom);
|
||||||
var dumper = new ApplesoftDump(mmu);
|
|
||||||
|
|
||||||
var parallel = new Parallel(io, new Printer(), 1);
|
|
||||||
var disk2 = new DiskII(io, drivelights, 6);
|
|
||||||
var slot3 = new Slot3(mmu, rom);
|
|
||||||
var slinky = new RAMFactor(mmu, io, 2, 1024 * 1024);
|
|
||||||
var clock = new Thunderclock(mmu, io, 7);
|
|
||||||
|
|
||||||
mmu.addSlot(1, parallel);
|
|
||||||
mmu.addSlot(2, slinky);
|
|
||||||
mmu.addSlot(3, slot3);
|
|
||||||
mmu.addSlot(6, disk2);
|
|
||||||
mmu.addSlot(7, clock);
|
|
||||||
|
|
||||||
cpu.addPageHandler(mmu);
|
cpu.addPageHandler(mmu);
|
||||||
|
|
||||||
|
var parallel = new Parallel(io, 1, new Printer());
|
||||||
|
var slinky = new RAMFactor(io, 2, 1024 * 1024);
|
||||||
|
var slot3 = new Slot3(io, 3, rom);
|
||||||
|
var disk2 = new DiskII(io, 6, drivelights);
|
||||||
|
var clock = new Thunderclock(io, 7);
|
||||||
|
|
||||||
|
io.addSlot(1, parallel);
|
||||||
|
io.addSlot(2, slinky);
|
||||||
|
io.addSlot(3, slot3);
|
||||||
|
io.addSlot(6, disk2);
|
||||||
|
io.addSlot(7, clock);
|
||||||
|
|
||||||
var showFPS = false;
|
var showFPS = false;
|
||||||
|
|
||||||
function updateKHz() {
|
function updateKHz() {
|
||||||
@ -397,7 +452,7 @@ function step()
|
|||||||
|
|
||||||
var accelerated = false;
|
var accelerated = false;
|
||||||
|
|
||||||
function updateSpeed()
|
function updateCPU()
|
||||||
{
|
{
|
||||||
accelerated = $('#accelerator_toggle').prop('checked');
|
accelerated = $('#accelerator_toggle').prop('checked');
|
||||||
kHz = accelerated ? 4092 : 1023;
|
kHz = accelerated ? 4092 : 1023;
|
||||||
@ -423,6 +478,7 @@ function run(pc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ival = 30;
|
var ival = 30;
|
||||||
|
|
||||||
var now, last = Date.now();
|
var now, last = Date.now();
|
||||||
var runFn = function() {
|
var runFn = function() {
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
@ -441,10 +497,24 @@ function run(pc) {
|
|||||||
processHash(hash);
|
processHash(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
mmu.resetVB();
|
mmu.resetVB();
|
||||||
cpu.stepCycles(step);
|
if (DEBUG) {
|
||||||
|
cpu.stepCyclesDebug(TRACE ? 1 : step, function() {
|
||||||
|
var line = cpu.dumpRegisters() + ' ' +
|
||||||
|
cpu.dumpPC(undefined, SYMBOLS);
|
||||||
|
if (TRACE) {
|
||||||
|
debug(line);
|
||||||
|
} else {
|
||||||
|
trace.push(line);
|
||||||
|
if (trace.length > MAX_TRACE) {
|
||||||
|
trace.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cpu.stepCycles(step);
|
||||||
|
}
|
||||||
vm.blit();
|
vm.blit();
|
||||||
io.sampleTick();
|
io.sampleTick();
|
||||||
}
|
}
|
||||||
@ -474,6 +544,59 @@ function reset()
|
|||||||
cpu.reset();
|
cpu.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var state = null;
|
||||||
|
|
||||||
|
function storeStateLocal() {
|
||||||
|
window.localStorage['apple2.state'] = JSON.stringify(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreStateLocal() {
|
||||||
|
var data = window.localStorage['apple2.state'];
|
||||||
|
if (data) {
|
||||||
|
state = JSON.parse(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveState() {
|
||||||
|
if (state && !window.confirm('Overwrite Saved State?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
cpu: cpu.getState(),
|
||||||
|
io: io.getState(),
|
||||||
|
mmu: mmu.getState(),
|
||||||
|
vm: vm.getState(),
|
||||||
|
disk2: disk2.getState(),
|
||||||
|
drivelights: drivelights.getState()
|
||||||
|
};
|
||||||
|
if (slinky) {
|
||||||
|
state.slinky = slinky.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.localStorage) {
|
||||||
|
storeStateLocal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreState() {
|
||||||
|
if (window.localStorage) {
|
||||||
|
restoreStateLocal();
|
||||||
|
}
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cpu.setState(state.cpu);
|
||||||
|
io.setState(state.io);
|
||||||
|
mmu.setState(state.mmu);
|
||||||
|
vm.setState(state.vm);
|
||||||
|
disk2.setState(state.disk2);
|
||||||
|
drivelights.setState(state.drivelights);
|
||||||
|
if (slinky && state.slinky) {
|
||||||
|
slinky.setState(state.slinky);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function loadBinary(bin) {
|
function loadBinary(bin) {
|
||||||
stop();
|
stop();
|
||||||
for (var idx = 0; idx < bin.length; idx++) {
|
for (var idx = 0; idx < bin.length; idx++) {
|
||||||
@ -494,7 +617,7 @@ function selectCategory() {
|
|||||||
}
|
}
|
||||||
var option = $('<option />').val(file.filename).text(name)
|
var option = $('<option />').val(file.filename).text(name)
|
||||||
.appendTo('#disk_select');
|
.appendTo('#disk_select');
|
||||||
if (disk_cur_name[_loadDrive] == name) {
|
if (disk_cur_name[_currentDrive] == name) {
|
||||||
option.attr('selected', 'selected');
|
option.attr('selected', 'selected');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,7 +632,7 @@ function clickDisk() {
|
|||||||
doLoad();
|
doLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadDisk(disk) {
|
function loadDisk(drive, disk) {
|
||||||
var name = disk.name;
|
var name = disk.name;
|
||||||
var category = disk.category;
|
var category = disk.category;
|
||||||
|
|
||||||
@ -517,25 +640,14 @@ function loadDisk(disk) {
|
|||||||
name += ' - ' + disk.disk;
|
name += ' - ' + disk.disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
disk_cur_cat[_loadDrive] = category;
|
disk_cur_cat[drive] = category;
|
||||||
disk_cur_name[_loadDrive] = name;
|
disk_cur_name[drive] = name;
|
||||||
|
|
||||||
drivelights.label(_loadDrive, name);
|
drivelights.label(drive, name);
|
||||||
disk2.setDisk(_loadDrive, disk);
|
disk2.setDisk(drive, disk);
|
||||||
initGamepad(disk.gamepad);
|
initGamepad(disk.gamepad);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadJSON(data) {
|
|
||||||
if (data.type == 'binary') {
|
|
||||||
loadBinary(data);
|
|
||||||
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
|
|
||||||
loadDisk(data);
|
|
||||||
}
|
|
||||||
initGamepad(data.gamepad);
|
|
||||||
$('#loading').dialog('close');
|
|
||||||
loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LocalStorage Disk Storage
|
* LocalStorage Disk Storage
|
||||||
*/
|
*/
|
||||||
@ -603,16 +715,20 @@ function loadLocalStorage(drive, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processHash(hash) {
|
function processHash(hash) {
|
||||||
if (hash.indexOf('://') > 0) {
|
var files = hash.split('|');
|
||||||
var parts = hash.split('.');
|
for (var idx = 0; idx < files.length; idx++) {
|
||||||
var ext = parts[parts.length - 1].toLowerCase();
|
var file = files[idx];
|
||||||
if (ext == 'json') {
|
if (file.indexOf('://') > 0) {
|
||||||
loadAjax(hash);
|
var parts = file.split('.');
|
||||||
|
var ext = parts[parts.length - 1].toLowerCase();
|
||||||
|
if (ext == 'json') {
|
||||||
|
loadAjax(idx + 1, file);
|
||||||
|
} else {
|
||||||
|
doLoadHTTP(idx + 1, file);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doLoadHTTP(hash);
|
loadAjax(idx + 1, 'json/disks/' + file + '.json');
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
loadAjax('json/disks/' + hash + '.json');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,19 +736,16 @@ function processHash(hash) {
|
|||||||
* Keyboard/Gamepad routines
|
* Keyboard/Gamepad routines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var _key;
|
|
||||||
function _keydown(evt) {
|
function _keydown(evt) {
|
||||||
if (!focused) {
|
if (!focused) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
var key = keyboard.mapKeyEvent(evt);
|
var key = keyboard.mapKeyEvent(evt);
|
||||||
if (key != 0xff) {
|
if (key != 0xff) {
|
||||||
if (_key != 0xff) io.keyUp();
|
|
||||||
io.keyDown(key, evt.shiftKey);
|
io.keyDown(key, evt.shiftKey);
|
||||||
_key = key;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (evt.keyCode === 112) {
|
if (evt.keyCode === 112) { // F1 - Reset
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
} else if (evt.keyCode === 113) { // F2 - Full Screen
|
} else if (evt.keyCode === 113) { // F2 - Full Screen
|
||||||
var elem = document.getElementById('screen');
|
var elem = document.getElementById('screen');
|
||||||
@ -653,12 +766,11 @@ function _keydown(evt) {
|
|||||||
elem.mozRequestFullScreen();
|
elem.mozRequestFullScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (evt.keyCode === 114) {
|
} else if (evt.keyCode === 114) { // F3
|
||||||
io.keyDown(0x1b);
|
io.keyDown(0x1b);
|
||||||
_key = 0x1b;
|
|
||||||
} else if (evt.keyCode == 16) { // Shift
|
} else if (evt.keyCode == 16) { // Shift
|
||||||
keyboard.shiftKey(true);
|
keyboard.shiftKey(true);
|
||||||
io.buttonDown(2, true);
|
io.buttonDown(2);
|
||||||
} else if (evt.keyCode == 17) { // Control
|
} else if (evt.keyCode == 17) { // Control
|
||||||
keyboard.controlKey(true);
|
keyboard.controlKey(true);
|
||||||
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
|
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
|
||||||
@ -669,14 +781,12 @@ function _keydown(evt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _keyup(evt) {
|
function _keyup(evt) {
|
||||||
_key = 0xff;
|
|
||||||
|
|
||||||
if (!focused)
|
if (!focused)
|
||||||
io.keyUp();
|
io.keyUp();
|
||||||
|
|
||||||
if (evt.keyCode == 16) { // Shift
|
if (evt.keyCode == 16) { // Shift
|
||||||
keyboard.shiftKey(false);
|
keyboard.shiftKey(false);
|
||||||
io.buttonDown(2, false);
|
io.buttonUp(2);
|
||||||
} else if (evt.keyCode == 17) { // Control
|
} else if (evt.keyCode == 17) { // Control
|
||||||
keyboard.controlKey(false);
|
keyboard.controlKey(false);
|
||||||
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
|
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
|
||||||
@ -688,6 +798,7 @@ function _keyup(evt) {
|
|||||||
|
|
||||||
function updateScreen() {
|
function updateScreen() {
|
||||||
var green = $('#green_screen').prop('checked');
|
var green = $('#green_screen').prop('checked');
|
||||||
|
scanlines = $('#show_scanlines').prop('checked');
|
||||||
|
|
||||||
vm.green(green);
|
vm.green(green);
|
||||||
}
|
}
|
||||||
@ -788,13 +899,20 @@ $(function() {
|
|||||||
keyboard.create($('#keyboard'));
|
keyboard.create($('#keyboard'));
|
||||||
|
|
||||||
if (prefs.havePrefs()) {
|
if (prefs.havePrefs()) {
|
||||||
$('input[type=checkbox]').each(function() {
|
$('#options input[type=checkbox]').each(function() {
|
||||||
var val = prefs.readPref(this.id);
|
var val = prefs.readPref(this.id);
|
||||||
if (val)
|
if (val)
|
||||||
this.checked = JSON.parse(val);
|
this.checked = JSON.parse(val);
|
||||||
}).change(function() {
|
}).change(function() {
|
||||||
prefs.writePref(this.id, JSON.stringify(this.checked));
|
prefs.writePref(this.id, JSON.stringify(this.checked));
|
||||||
});
|
});
|
||||||
|
$('#options select').each(function() {
|
||||||
|
var val = prefs.readPref(this.id);
|
||||||
|
if (val)
|
||||||
|
this.value = val;
|
||||||
|
}).change(function() {
|
||||||
|
prefs.writePref(this.id, this.value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
@ -802,7 +920,7 @@ $(function() {
|
|||||||
setInterval(updateKHz, 1000);
|
setInterval(updateKHz, 1000);
|
||||||
updateSound();
|
updateSound();
|
||||||
updateScreen();
|
updateScreen();
|
||||||
updateSpeed();
|
updateCPU();
|
||||||
|
|
||||||
var cancel = function() { $(this).dialog('close'); };
|
var cancel = function() { $(this).dialog('close'); };
|
||||||
$('#loading').dialog({ autoOpen: false, modal: true });
|
$('#loading').dialog({ autoOpen: false, modal: true });
|
||||||
@ -823,10 +941,6 @@ $(function() {
|
|||||||
modal: true,
|
modal: true,
|
||||||
width: 320,
|
width: 320,
|
||||||
buttons: {'Close': cancel }});
|
buttons: {'Close': cancel }});
|
||||||
$('#local_save').dialog({ autoOpen: false,
|
|
||||||
modal: true,
|
|
||||||
width: 530,
|
|
||||||
buttons: {'OK': cancel }});
|
|
||||||
$('#http_load').dialog({ autoOpen: false,
|
$('#http_load').dialog({ autoOpen: false,
|
||||||
modal: true,
|
modal: true,
|
||||||
width: 530,
|
width: 530,
|
||||||
|
223
js/mmu.js
223
js/mmu.js
@ -21,8 +21,6 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
|
|
||||||
var idx;
|
var idx;
|
||||||
|
|
||||||
var _auxRom = 0x00;
|
|
||||||
|
|
||||||
var _readPages = new Array(0x100);
|
var _readPages = new Array(0x100);
|
||||||
var _writePages = new Array(0x100);
|
var _writePages = new Array(0x100);
|
||||||
var _pages = new Array(0x100);
|
var _pages = new Array(0x100);
|
||||||
@ -47,6 +45,69 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
|
|
||||||
var _vbEnd = 0;
|
var _vbEnd = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O Switch locations
|
||||||
|
*/
|
||||||
|
|
||||||
|
var LOC = {
|
||||||
|
// 80 Column
|
||||||
|
_80STOREOFF: 0x00,
|
||||||
|
_80STOREON: 0x01,
|
||||||
|
|
||||||
|
// Aux RAM
|
||||||
|
RAMRDOFF: 0x02,
|
||||||
|
RAMRDON: 0x03,
|
||||||
|
|
||||||
|
RAMWROFF: 0x04,
|
||||||
|
RAMWRON: 0x05,
|
||||||
|
|
||||||
|
// Bank switched ROM
|
||||||
|
INTCXROMOFF: 0x06,
|
||||||
|
INTCXROMON: 0x07,
|
||||||
|
ALTZPOFF: 0x08,
|
||||||
|
ALTZPON: 0x09,
|
||||||
|
SLOTC3ROMOFF: 0x0A,
|
||||||
|
SLOTC3ROMON: 0x0B,
|
||||||
|
|
||||||
|
// Status
|
||||||
|
BSRBANK2: 0x11,
|
||||||
|
BSRREADRAM: 0x12,
|
||||||
|
RAMRD: 0x13,
|
||||||
|
RAMWRT: 0x14,
|
||||||
|
INTCXROM: 0x15,
|
||||||
|
ALTZP: 0x16,
|
||||||
|
SLOTC3ROM: 0x17,
|
||||||
|
_80STORE: 0x18,
|
||||||
|
VERTBLANK: 0x19,
|
||||||
|
|
||||||
|
PAGE1: 0x54, // select text/graphics page1 main/aux
|
||||||
|
PAGE2: 0x55, // select text/graphics page2 main/aux
|
||||||
|
|
||||||
|
// Bank 2
|
||||||
|
READBSR2: 0x80,
|
||||||
|
WRITEBSR2: 0x81,
|
||||||
|
OFFBSR2: 0x82,
|
||||||
|
READWRBSR2: 0x83,
|
||||||
|
|
||||||
|
// Shadow Bank 2
|
||||||
|
_READBSR2: 0x84,
|
||||||
|
_WRITEBSR2: 0x85,
|
||||||
|
_OFFBSR2: 0x86,
|
||||||
|
_READWRBSR2: 0x87,
|
||||||
|
|
||||||
|
// Bank 1
|
||||||
|
READBSR1: 0x88,
|
||||||
|
WRITEBSR1: 0x89,
|
||||||
|
OFFBSR1: 0x8a,
|
||||||
|
READWRBSR1: 0x8b,
|
||||||
|
|
||||||
|
// Shadow Bank 1
|
||||||
|
_READBSR1: 0x8c,
|
||||||
|
_WRITEBSR1: 0x8d,
|
||||||
|
_OFFBSR1: 0x8e,
|
||||||
|
_READWRBSR1: 0x8f
|
||||||
|
};
|
||||||
|
|
||||||
function _initSwitches() {
|
function _initSwitches() {
|
||||||
_bank1 = true;
|
_bank1 = true;
|
||||||
_readbsr = false;
|
_readbsr = false;
|
||||||
@ -64,28 +125,69 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _debug() {
|
function _debug() {
|
||||||
// debug.apply(arguments);
|
debug.apply(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
var _last = 0x00;
|
var _last = 0x00;
|
||||||
|
|
||||||
function EmptySlots() {
|
function Switches() {
|
||||||
|
var locs = {};
|
||||||
|
|
||||||
|
for (var loc in LOC) {
|
||||||
|
if (LOC.hasOwnProperty(loc)) {
|
||||||
|
locs[LOC[loc]] = loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: function slot_start() {
|
start: function() {
|
||||||
return 0xC1;
|
return 0xC0;
|
||||||
},
|
},
|
||||||
end: function slot_end() {
|
end: function() {
|
||||||
return 0xCF;
|
return 0xC0;
|
||||||
},
|
},
|
||||||
read: function slot_read() {
|
read: function(page, off) {
|
||||||
return 0x00;
|
var result;
|
||||||
|
if (off in locs) {
|
||||||
|
result = _access(off);
|
||||||
|
} else {
|
||||||
|
result = io.ioSwitch(off);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
},
|
},
|
||||||
write: function slot_write() {
|
write: function(page, off, val) {
|
||||||
|
if (off in locs) {
|
||||||
|
_access(off, val);
|
||||||
|
} else {
|
||||||
|
io.ioSwitch(off, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var emptyslots = new EmptySlots();
|
function AuxRom() {
|
||||||
|
return {
|
||||||
|
start: function() {
|
||||||
|
return 0xC1;
|
||||||
|
},
|
||||||
|
end: function() {
|
||||||
|
return 0xCF;
|
||||||
|
},
|
||||||
|
read: function(page, off) {
|
||||||
|
var result;
|
||||||
|
if (page == 0xc3) {
|
||||||
|
result = io.read(page, off);
|
||||||
|
} else {
|
||||||
|
result = rom.read(page, off);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
write: function() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var switches = new Switches();
|
||||||
|
var auxRom = new AuxRom();
|
||||||
|
|
||||||
var mem00_01 = [new RAM(0x0, 0x1), new RAM(0x0, 0x1)];
|
var mem00_01 = [new RAM(0x0, 0x1), new RAM(0x0, 0x1)];
|
||||||
var mem02_03 = [new RAM(0x2, 0x3), new RAM(0x2, 0x3)];
|
var mem02_03 = [new RAM(0x2, 0x3), new RAM(0x2, 0x3)];
|
||||||
@ -95,8 +197,8 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
var mem20_3F = [hires1.bank0(), hires1.bank1()];
|
var mem20_3F = [hires1.bank0(), hires1.bank1()];
|
||||||
var mem40_5F = [hires2.bank0(), hires2.bank1()];
|
var mem40_5F = [hires2.bank0(), hires2.bank1()];
|
||||||
var mem60_BF = [new RAM(0x60,0xBF), new RAM(0x60,0xBF)];
|
var mem60_BF = [new RAM(0x60,0xBF), new RAM(0x60,0xBF)];
|
||||||
var memC0_C0 = [io];
|
var memC0_C0 = [switches];
|
||||||
// var memC1_CF = [emptyslots, rom];
|
var memC1_CF = [io, auxRom];
|
||||||
var memD0_DF = [rom,
|
var memD0_DF = [rom,
|
||||||
new RAM(0xD0,0xDF), new RAM(0xD0,0xDF),
|
new RAM(0xD0,0xDF), new RAM(0xD0,0xDF),
|
||||||
new RAM(0xD0,0xDF), new RAM(0xD0,0xDF)];
|
new RAM(0xD0,0xDF), new RAM(0xD0,0xDF)];
|
||||||
@ -161,7 +263,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
_writePages[idx] = _pages[idx][0];
|
_writePages[idx] = _pages[idx][0];
|
||||||
// Slots
|
// Slots
|
||||||
for (idx = 0xc1; idx < 0xd0; idx++) {
|
for (idx = 0xc1; idx < 0xd0; idx++) {
|
||||||
_pages[idx] = [emptyslots, rom]; // memC1_CF;
|
_pages[idx] = memC1_CF;
|
||||||
_readPages[idx] = _pages[idx][0];
|
_readPages[idx] = _pages[idx][0];
|
||||||
_writePages[idx] = _pages[idx][0];
|
_writePages[idx] = _pages[idx][0];
|
||||||
}
|
}
|
||||||
@ -178,69 +280,6 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
_writePages[idx] = _pages[idx][0];
|
_writePages[idx] = _pages[idx][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* I/O Switch locations
|
|
||||||
*/
|
|
||||||
|
|
||||||
var LOC = {
|
|
||||||
// 80 Column
|
|
||||||
_80STOREOFF: 0x00,
|
|
||||||
_80STOREON: 0x01,
|
|
||||||
|
|
||||||
// Aux RAM
|
|
||||||
RAMRDOFF: 0x02,
|
|
||||||
RAMRDON: 0x03,
|
|
||||||
|
|
||||||
RAMWROFF: 0x04,
|
|
||||||
RAMWRON: 0x05,
|
|
||||||
|
|
||||||
// Bank switched ROM
|
|
||||||
INTCXROMOFF: 0x06,
|
|
||||||
INTCXROMON: 0x07,
|
|
||||||
ALTZPOFF: 0x08,
|
|
||||||
ALTZPON: 0x09,
|
|
||||||
SLOTC3ROMOFF: 0x0A,
|
|
||||||
SLOTC3ROMON: 0x0B,
|
|
||||||
|
|
||||||
// Status
|
|
||||||
BSRBANK2: 0x11,
|
|
||||||
BSRREADRAM: 0x12,
|
|
||||||
RAMRD: 0x13,
|
|
||||||
RAMWRT: 0x14,
|
|
||||||
INTCXROM: 0x15,
|
|
||||||
ALTZP: 0x16,
|
|
||||||
SLOTC3ROM: 0x17,
|
|
||||||
_80STORE: 0x18,
|
|
||||||
VERTBLANK: 0x19,
|
|
||||||
|
|
||||||
PAGE1: 0x54, // select text/graphics page1 main/aux
|
|
||||||
PAGE2: 0x55, // select text/graphics page2 main/aux
|
|
||||||
|
|
||||||
// Bank 2
|
|
||||||
READBSR2: 0x80,
|
|
||||||
WRITEBSR2: 0x81,
|
|
||||||
OFFBSR2: 0x82,
|
|
||||||
READWRBSR2: 0x83,
|
|
||||||
|
|
||||||
// Shadow Bank 2
|
|
||||||
_READBSR2: 0x84,
|
|
||||||
_WRITEBSR2: 0x85,
|
|
||||||
_OFFBSR2: 0x86,
|
|
||||||
_READWRBSR2: 0x87,
|
|
||||||
|
|
||||||
// Bank 1
|
|
||||||
READBSR1: 0x88,
|
|
||||||
WRITEBSR1: 0x89,
|
|
||||||
OFFBSR1: 0x8a,
|
|
||||||
READWRBSR1: 0x8b,
|
|
||||||
|
|
||||||
// Shadow Bank 1
|
|
||||||
_READBSR1: 0x8c,
|
|
||||||
_WRITEBSR1: 0x8d,
|
|
||||||
_OFFBSR1: 0x8e,
|
|
||||||
_READWRBSR1: 0x8f
|
|
||||||
};
|
|
||||||
|
|
||||||
function _updateBanks() {
|
function _updateBanks() {
|
||||||
if (_auxRamRead) {
|
if (_auxRamRead) {
|
||||||
for (idx = 0x02; idx < 0xC0; idx++) {
|
for (idx = 0x02; idx < 0xC0; idx++) {
|
||||||
@ -549,7 +588,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
case LOC._80STORE: // 0xC018
|
case LOC._80STORE: // 0xC018
|
||||||
result = _80store ? 0x80 : 0x00;
|
result = _80store ? 0x80 : 0x00;
|
||||||
break;
|
break;
|
||||||
case LOC.VERTBLANK: // 0xC018
|
case LOC.VERTBLANK: // 0xC019
|
||||||
// result = cpu.cycles() % 20 < 5 ? 0x80 : 0x00;
|
// result = cpu.cycles() % 20 < 5 ? 0x80 : 0x00;
|
||||||
result = (cpu.cycles() < _vbEnd) ? 0x80 : 0x00;
|
result = (cpu.cycles() < _vbEnd) ? 0x80 : 0x00;
|
||||||
break;
|
break;
|
||||||
@ -577,17 +616,11 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
lores1.start();
|
lores1.start();
|
||||||
lores2.start();
|
lores2.start();
|
||||||
|
|
||||||
// Do us afterward because we override some of the above
|
|
||||||
io.registerSwitches(this, LOC);
|
|
||||||
|
|
||||||
return 0x00;
|
return 0x00;
|
||||||
},
|
},
|
||||||
end: function mmu_end() {
|
end: function mmu_end() {
|
||||||
return 0xff;
|
return 0xff;
|
||||||
},
|
},
|
||||||
ioSwitch: function mmu_ioswitch(off, val) {
|
|
||||||
return _access(off, val);
|
|
||||||
},
|
|
||||||
reset: function() {
|
reset: function() {
|
||||||
_initSwitches();
|
_initSwitches();
|
||||||
_updateBanks();
|
_updateBanks();
|
||||||
@ -603,24 +636,6 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
write: function mmu_write(page, off, val) {
|
write: function mmu_write(page, off, val) {
|
||||||
_writePages[page].write(page, off, val);
|
_writePages[page].write(page, off, val);
|
||||||
},
|
},
|
||||||
addSlot: function mmu_addSlot(slot, card) {
|
|
||||||
if (slot == 3) {
|
|
||||||
_pages[0xc0 + slot][1] = card;
|
|
||||||
}
|
|
||||||
_pages[0xc0 + slot][0] = card;
|
|
||||||
card.start();
|
|
||||||
},
|
|
||||||
auxRom: function mmu_auxRom(slot, rom) {
|
|
||||||
var idx;
|
|
||||||
if (_auxRom != slot) {
|
|
||||||
_debug("Slot " + slot + " expansion rom added");
|
|
||||||
_auxRom = slot;
|
|
||||||
for (idx = 0xc8; idx < 0xd0; idx++) {
|
|
||||||
_pages[idx][0] = rom;
|
|
||||||
}
|
|
||||||
_updateBanks();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetVB: function mmu_resetVB() {
|
resetVB: function mmu_resetVB() {
|
||||||
_vbEnd = cpu.cycles() + 1000;
|
_vbEnd = cpu.cycles() + 1000;
|
||||||
},
|
},
|
||||||
@ -631,7 +646,6 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
bank1: _bank1,
|
bank1: _bank1,
|
||||||
last: _last,
|
last: _last,
|
||||||
|
|
||||||
auxRom: _auxRom,
|
|
||||||
intcxrom: _intcxrom,
|
intcxrom: _intcxrom,
|
||||||
slot3rom: _slot3rom,
|
slot3rom: _slot3rom,
|
||||||
auxRamRead: _auxRamRead,
|
auxRamRead: _auxRamRead,
|
||||||
@ -655,7 +669,6 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
|
|||||||
_writebsr = state.writebsr;
|
_writebsr = state.writebsr;
|
||||||
_bank1 = state.bank1;
|
_bank1 = state.bank1;
|
||||||
|
|
||||||
_auxRom = state.auxRom;
|
|
||||||
_intcxrom = state.intcxrom;
|
_intcxrom = state.intcxrom;
|
||||||
_slot3rom = state.slot3rom;
|
_slot3rom = state.slot3rom;
|
||||||
_auxRamRead = state.auxRamRead;
|
_auxRamRead = state.auxRamRead;
|
||||||
|
@ -10,18 +10,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*exported Parallel */
|
/*exported Parallel */
|
||||||
|
/*globals debug: false */
|
||||||
|
|
||||||
function Parallel(io, cbs, slot) {
|
function Parallel(io, slot, cbs) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
slot = slot || 1;
|
slot = slot || 1;
|
||||||
|
|
||||||
|
debug('Parallel card in slot', slot);
|
||||||
|
|
||||||
var LOC = {
|
var LOC = {
|
||||||
IOREG: 0x80
|
IOREG: 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
var _cbs = cbs;
|
|
||||||
|
|
||||||
var rom = [
|
var rom = [
|
||||||
0x18,0xb0,0x38,0x48,0x8a,0x48,0x98,0x48,
|
0x18,0xb0,0x38,0x48,0x8a,0x48,0x98,0x48,
|
||||||
0x08,0x78,0x20,0x58,0xff,0xba,0x68,0x68,
|
0x08,0x78,0x20,0x58,0xff,0xba,0x68,0x68,
|
||||||
@ -57,18 +58,23 @@ function Parallel(io, cbs, slot) {
|
|||||||
0xff,0xf0,0x03,0xfe,0x38,0x07,0x70,0x84
|
0xff,0xf0,0x03,0xfe,0x38,0x07,0x70,0x84
|
||||||
];
|
];
|
||||||
|
|
||||||
|
LOC.IOREG += 0x10 * slot;
|
||||||
|
|
||||||
|
function _access(off, val) {
|
||||||
|
if (off == LOC.IOREG && val && 'putChar' in cbs) {
|
||||||
|
cbs.putChar(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: function() {
|
start: function() {
|
||||||
LOC.IOREG += 0x10 * slot;
|
|
||||||
io.registerSwitches(this, LOC);
|
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
end: function() {
|
end: function() {
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
ioSwitch: function(off, val) {
|
ioSwitch: function (off, val) {
|
||||||
if (off == LOC.IOREG && val && 'putChar' in _cbs)
|
return _access(off, val);
|
||||||
_cbs.putChar(val);
|
|
||||||
},
|
},
|
||||||
read: function(page, off) {
|
read: function(page, off) {
|
||||||
return rom[off];
|
return rom[off];
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
* implied warranty.
|
* implied warranty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*exported RAMFactor*/
|
/*exported RAMFactor */
|
||||||
/*globals allocMem: false, bytify: false, each: false,
|
/*globals allocMem: false, bytify: false, debug: false, each: false,
|
||||||
base64_encode: false, base64_decode: false
|
base64_encode: false, base64_decode: false
|
||||||
*/
|
*/
|
||||||
function RAMFactor(mmu, io, slot, size) {
|
function RAMFactor(io, slot, size) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var rom = [
|
var rom = [
|
||||||
@ -1066,6 +1066,8 @@ function RAMFactor(mmu, io, slot, size) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function _init() {
|
function _init() {
|
||||||
|
debug('RAMFactor card in slot', slot);
|
||||||
|
|
||||||
each(LOC, function(key) {
|
each(LOC, function(key) {
|
||||||
LOC[key] += slot * 0x10;
|
LOC[key] += slot * 0x10;
|
||||||
});
|
});
|
||||||
@ -1154,19 +1156,6 @@ function RAMFactor(mmu, io, slot, size) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
var auxRomFn = {
|
|
||||||
start: function auxRom_start() {
|
|
||||||
return 0xc8;
|
|
||||||
},
|
|
||||||
end: function auxRom_end() {
|
|
||||||
return 0xcf;
|
|
||||||
},
|
|
||||||
read: function auxRom_read(page, off) {
|
|
||||||
return rom[_firmware * 0x1000 + (page - 0xC0) * 0x100 + off];
|
|
||||||
},
|
|
||||||
write: function auxRom_write() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1177,17 +1166,19 @@ function RAMFactor(mmu, io, slot, size) {
|
|||||||
end: function ramfactor_end() {
|
end: function ramfactor_end() {
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
read: function ramfactor_read(page, off) {
|
ioSwitch: function (off, val) {
|
||||||
mmu.auxRom(slot, auxRomFn);
|
|
||||||
|
|
||||||
return rom[slot * 0x100 + off];
|
|
||||||
},
|
|
||||||
write: function ramfactor_write() {
|
|
||||||
mmu.auxRom(slot, auxRomFn);
|
|
||||||
},
|
|
||||||
ioSwitch: function ramfactor_ioSwitch(off, val) {
|
|
||||||
return _access(off, val);
|
return _access(off, val);
|
||||||
},
|
},
|
||||||
|
read: function ramfactor_read(page, off) {
|
||||||
|
var result;
|
||||||
|
if (page == 0xc0 + slot) {
|
||||||
|
result = rom[slot * 0x100 + off];
|
||||||
|
} else {
|
||||||
|
result = rom[_firmware * 0x1000 + (page - 0xC0) * 0x100 + off];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
write: function ramfactor_write() {},
|
||||||
reset: function ramfactor_reset() {
|
reset: function ramfactor_reset() {
|
||||||
_firmware = 0;
|
_firmware = 0;
|
||||||
},
|
},
|
||||||
|
19
js/slot3.js
19
js/slot3.js
@ -9,25 +9,12 @@
|
|||||||
* implied warranty.
|
* implied warranty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*exported Slot3*/
|
/*exported Slot3 */
|
||||||
|
|
||||||
function Slot3(mmu, rom)
|
function Slot3(io, slot, rom)
|
||||||
{
|
{
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var auxRomFn = {
|
|
||||||
start: function auxRom_start() {
|
|
||||||
return 0xc8;
|
|
||||||
},
|
|
||||||
end: function auxRom_end() {
|
|
||||||
return 0xcf;
|
|
||||||
},
|
|
||||||
read: function auxRom_read(page, off) {
|
|
||||||
return rom.read(page, off);
|
|
||||||
},
|
|
||||||
write: function auxRom_write() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: function slot3_start() {
|
start: function slot3_start() {
|
||||||
return 0xc3;
|
return 0xc3;
|
||||||
@ -36,11 +23,9 @@ function Slot3(mmu, rom)
|
|||||||
return 0xc3;
|
return 0xc3;
|
||||||
},
|
},
|
||||||
read: function slot3_read(page, off) {
|
read: function slot3_read(page, off) {
|
||||||
mmu.auxRom(0x3, auxRomFn);
|
|
||||||
return rom.read(page, off);
|
return rom.read(page, off);
|
||||||
},
|
},
|
||||||
write: function slot3_write() {
|
write: function slot3_write() {
|
||||||
mmu.auxRom(0x3, auxRomFn);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*exported Thunderclock */
|
/*exported Thunderclock */
|
||||||
/*global each: false */
|
/*global debug: false, each: false */
|
||||||
|
|
||||||
function Thunderclock(mmu, io, slot)
|
function Thunderclock(io, slot)
|
||||||
{
|
{
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -287,24 +287,13 @@ function Thunderclock(mmu, io, slot)
|
|||||||
};
|
};
|
||||||
|
|
||||||
function _init() {
|
function _init() {
|
||||||
|
debug('Thunderclock card in slot', slot);
|
||||||
|
|
||||||
each(LOC, function(key) {
|
each(LOC, function(key) {
|
||||||
LOC[key] += slot * 0x10;
|
LOC[key] += slot * 0x10;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var auxRomFn = {
|
|
||||||
start: function auxRom_start() {
|
|
||||||
return 0xc8;
|
|
||||||
},
|
|
||||||
end: function auxRom_end() {
|
|
||||||
return 0xcf;
|
|
||||||
},
|
|
||||||
read: function auxRom_read(page, off) {
|
|
||||||
return rom[(page - 0xc8) * 256 + off];
|
|
||||||
},
|
|
||||||
write: function auxRom_write() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _command = 0;
|
var _command = 0;
|
||||||
var _bits = [];
|
var _bits = [];
|
||||||
|
|
||||||
@ -372,19 +361,21 @@ function Thunderclock(mmu, io, slot)
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
start: function thunderclock_start() {
|
start: function thunderclock_start() {
|
||||||
io.registerSwitches(this, LOC);
|
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
end: function thunderclock_end() {
|
end: function thunderclock_end() {
|
||||||
return 0xc0 + slot;
|
return 0xc0 + slot;
|
||||||
},
|
},
|
||||||
read: function thunderclock_read(page, off) {
|
read: function thunderclock_read(page, off) {
|
||||||
mmu.auxRom(slot, auxRomFn);
|
var result;
|
||||||
|
if (page < 0xc8) {
|
||||||
return rom[off];
|
result = rom[off];
|
||||||
|
} else {
|
||||||
|
result = rom[(page - 0xc8) * 256 + off];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
},
|
},
|
||||||
write: function thunderclock_write() {
|
write: function thunderclock_write() {
|
||||||
mmu.auxRom(slot, auxRomFn);
|
|
||||||
},
|
},
|
||||||
ioSwitch: function thunderclock_ioSwitch(off, val) {
|
ioSwitch: function thunderclock_ioSwitch(off, val) {
|
||||||
return _access(off, val);
|
return _access(off, val);
|
||||||
|
@ -21,10 +21,9 @@ var _samples = [];
|
|||||||
|
|
||||||
var audioContext;
|
var audioContext;
|
||||||
var audioNode;
|
var audioNode;
|
||||||
var AC = window.AudioContext;
|
|
||||||
|
|
||||||
if (typeof AC !== 'undefined') {
|
if (window.AudioContext) {
|
||||||
audioContext = new AC();
|
audioContext = new window.AudioContext();
|
||||||
audioNode = audioContext.createScriptProcessor(4096, 1, 1);
|
audioNode = audioContext.createScriptProcessor(4096, 1, 1);
|
||||||
|
|
||||||
audioNode.onaudioprocess = function(event) {
|
audioNode.onaudioprocess = function(event) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
|
/* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
@ -6,18 +6,22 @@ function Printer() {
|
|||||||
putChar: function(val) {
|
putChar: function(val) {
|
||||||
if (!_printer || _printer.closed) {
|
if (!_printer || _printer.closed) {
|
||||||
_printer = window.open('', '_blank','toolbar=0,location=0');
|
_printer = window.open('', '_blank','toolbar=0,location=0');
|
||||||
_printer.document.title = 'Printer';
|
if (_printer) {
|
||||||
_printer.document.write('<div style="font: 12px courier">');
|
_printer.document.title = 'Printer';
|
||||||
_printer.document.write('<span>');
|
_printer.document.write('<div style="font: 12px courier">');
|
||||||
window.focus();
|
_printer.document.write('<span>');
|
||||||
|
window.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var c = String.fromCharCode(val & 0x7f);
|
if (_printer) {
|
||||||
if (c == '\r') {
|
var c = String.fromCharCode(val & 0x7f);
|
||||||
_printer.document.write('<br /></span>');
|
if (c == '\r') {
|
||||||
} else if (c == ' ') {
|
_printer.document.write('<br /></span>');
|
||||||
_printer.document.write(' ');
|
} else if (c == ' ') {
|
||||||
} else {
|
_printer.document.write(' ');
|
||||||
_printer.document.write(c);
|
} else {
|
||||||
|
_printer.document.write(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
loadJSON({
|
{
|
||||||
"name": "DOS 3.3 Master",
|
"name": "DOS 3.3 Master",
|
||||||
"category": "System",
|
"category": "System",
|
||||||
"type": "dsk",
|
"type": "dsk",
|
||||||
@ -636,4 +636,4 @@ loadJSON({
|
|||||||
"AwhOEiBECI2UE6kAja0Tuo4cEyCLCCDaCK2sE6IWICwL0AkgYgggWQ1MPggg8QkgYgggQAutqxPQBaIPIM0KIB0LTA4IqYCFdoXZhTM4rdID6QfpHjABYCBY/KIVIM0KTNMDogG9HxMKCgoKnSETyhDzINwDhACFASDjA4QChQMgLRAg6A+pAI2rE2CpAIUiIFj8ohYgzQqiFyDNCiCO/aAAoh8gzQq5rxMg7f2iICDNCpgYaSiqIM0KyMAJ0OMgjv2iISDNCiBv/a0AAqIAICwL0LiNrBOMrhNgIFj8qQ+FJK2uExhpKKogzQqpA4UiIFj8rawTogogLAvQB6kAjQ==",
|
"AwhOEiBECI2UE6kAja0Tuo4cEyCLCCDaCK2sE6IWICwL0AkgYgggWQ1MPggg8QkgYgggQAutqxPQBaIPIM0KIB0LTA4IqYCFdoXZhTM4rdID6QfpHjABYCBY/KIVIM0KTNMDogG9HxMKCgoKnSETyhDzINwDhACFASDjA4QChQMgLRAg6A+pAI2rE2CpAIUiIFj8ohYgzQqiFyDNCiCO/aAAoh8gzQq5rxMg7f2iICDNCpgYaSiqIM0KyMAJ0OMgjv2iISDNCiBv/a0AAqIAICwL0LiNrBOMrhNgIFj8qQ+FJK2uExhpKKogzQqpA4UiIFj8rawTogogLAvQB6kAjQ==",
|
||||||
"AAAAAAAAAAAAAAAAIg4iDSIMIgsiCiIJIggiByIGIgUiBCIDIgIiASIAAwIDAQMABA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
"AAAAAAAAAAAAAAAAIg4iDSIMIgsiCiIJIggiByIGIgUiBCIDIgIiASIAAwIDAQMABA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
]
|
]
|
||||||
]});
|
]}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
loadJSON({
|
{
|
||||||
"name": "ProDOS",
|
"name": "ProDOS",
|
||||||
"category": "System",
|
"category": "System",
|
||||||
"type": "dsk",
|
"type": "dsk",
|
||||||
@ -635,4 +635,4 @@ loadJSON({
|
|||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
]
|
]
|
||||||
]});
|
]}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
|
# Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
# documentation for any purpose is hereby granted without fee, provided that
|
# documentation for any purpose is hereby granted without fee, provided that
|
||||||
# the above copyright notice appear in all copies and that both that
|
# the above copyright notice appear in all copies and that both that
|
||||||
@ -17,9 +17,9 @@ $Getopt::Std::STANDARD_HELP_VERSION = 1;
|
|||||||
my %opts;
|
my %opts;
|
||||||
getopts('rn:c:t:', \%opts);
|
getopts('rn:c:t:', \%opts);
|
||||||
|
|
||||||
sub HELP_MESSAGE() {
|
sub HELP_MESSAGE() {
|
||||||
my $fh = shift;
|
my $fh = shift;
|
||||||
print $fh "dsk2js.pl [-c category] [-n name] [-t type] imagefile\n"
|
print $fh "dsk2js.pl [-c category] [-n name] [-t type] imagefile\n"
|
||||||
};
|
};
|
||||||
sub VERSION_MESSAGE() { my $fh = shift; print $fh "Version 1.0\n" };
|
sub VERSION_MESSAGE() { my $fh = shift; print $fh "Version 1.0\n" };
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ if ($ext eq '2mg') {
|
|||||||
my $sector = 0;
|
my $sector = 0;
|
||||||
my $track = 0;
|
my $track = 0;
|
||||||
|
|
||||||
print "loadJSON({\n";
|
print "{\n";
|
||||||
print " \"name\": \"$name\",\n";
|
print " \"name\": \"$name\",\n";
|
||||||
print " \"type\": \"$ext\",\n";
|
print " \"type\": \"$ext\",\n";
|
||||||
print " \"category\": \"$category\",\n";
|
print " \"category\": \"$category\",\n";
|
||||||
@ -127,6 +127,6 @@ for ($track = 0; $track < 0x23; $track++) {
|
|||||||
}
|
}
|
||||||
print "\n ]";
|
print "\n ]";
|
||||||
}
|
}
|
||||||
print "\n]});\n";
|
print "\n]}\n";
|
||||||
|
|
||||||
close(DISK);
|
close(DISK);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user