diff --git a/apple2js.html b/apple2js.html
index 666b83e..1d5ca66 100644
--- a/apple2js.html
+++ b/apple2js.html
@@ -15,7 +15,7 @@
Apple ][js - An Apple 2 Emulator in JavaScript
-
+
@@ -778,8 +778,10 @@ function _mousemove(evt) {
if (gamepad) {
return;
}
- var x = evt.offsetX / $(this).width(),
- y = evt.offsetY / $(this).height(),
+ var s = $("#screen");
+ var offset = s.offset();
+ var x = (evt.pageX - offset.left) / s.width(),
+ y = (evt.pageY - offset.top) / s.height(),
z = x;
if (swapXY) {
@@ -806,7 +808,13 @@ function pauseRun(b) {
$(function() {
hashtag = document.location.hash;
- $("button,input[type=button],a.button").button();
+ $("button,input[type=button],a.button").button().focus(function() {
+ // Crazy hack required by Chrome
+ var self = this;
+ window.setTimeout(function() {
+ self.blur();
+ }, 1)
+ });
var canvas = document.getElementById("screen");
var context = canvas.getContext('2d');
diff --git a/js/apple2io.js b/js/apple2io.js
index 507a1d4..fe4a470 100644
--- a/js/apple2io.js
+++ b/js/apple2io.js
@@ -205,7 +205,11 @@ function Apple2IO(cpu, callbacks)
case LOC.STROBE:
_key &= 0x7f;
if (_buffer.length > 0) {
- _key = _buffer.shift().charCodeAt(0) | 0x80;
+ var val = _buffer.shift();
+ if (val == '\n') {
+ val = '\r';
+ }
+ _key = val.charCodeAt(0) | 0x80;
}
result = _keyDown ? 0x80 : 0x00;
break;
@@ -222,16 +226,16 @@ function Apple2IO(cpu, callbacks)
result = _button[2] ? 0x80 : 0;
break;
case LOC.PADDLE0:
- result = (delta < (_paddle[0] * 2560) ? 0x80 : 0x00);
+ result = (delta < (_paddle[0] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE1:
- result = (delta < (_paddle[1] * 2560) ? 0x80 : 0x00);
+ result = (delta < (_paddle[1] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE2:
- result = (delta < (_paddle[2] * 2560) ? 0x80 : 0x00);
+ result = (delta < (_paddle[2] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE3:
- result = (delta < (_paddle[3] * 2560) ? 0x80 : 0x00);
+ result = (delta < (_paddle[3] * 2756) ? 0x80 : 0x00);
break;
case LOC.PDLTRIG:
_trigger = cpu.cycles();
diff --git a/js/canvas2.js b/js/canvas2.js
index 6ac8ed7..eb9f695 100644
--- a/js/canvas2.js
+++ b/js/canvas2.js
@@ -10,6 +10,7 @@
* implied warranty.
*/
+/*jshint browser:true */
/*globals allocMemPages: false,
charset: false,
base64_encode: false, base64_decode: false */
@@ -40,7 +41,7 @@ function LoresPage(page)
var _black = [0x00,0x00,0x00];
var _white = [0xff,0xff,0xff];
- var _green = [0x00,0xff,0x00];
+ var _green = [0x00,0xff,0x88];
var _colors = [
[0x00,0x00,0x00], // 0 Black 0000 0 0
@@ -56,7 +57,7 @@ function LoresPage(page)
[0x40,0x40,0x40], // 10 Gray 2 1010 10
[0xff,0x96,0xbf], // 11 Pink 1011 11
[0x2f,0xbc,0x1a], // 12 Light Green 0110 6
- [0xb9,0xd0,0x60], // 13 Yellow 0111 7
+ [0xbf,0xd3,0x5a], // 13 Yellow 0111 7
[0x6f,0xe8,0xbf], // 14 Aqua 1110 14
[0xff,0xff,0xff] // 15 White 1111 15
@@ -127,7 +128,7 @@ function LoresPage(page)
return;
var data = pages[_page].data, fore, back;
- off = (col * 7 + row * 280 * 8) * 4;
+ off = (col * 14 + row * 560 * 8) * 4;
if (textMode || (mixedMode && row > 19)) {
if (val & 0x80 || ((val & 0x40) && _blink)) {
@@ -142,24 +143,47 @@ function LoresPage(page)
b <<= 1;
for (idx = 0; idx < 7; idx++) {
color = (b & 0x80) ? fore : back;
- data[off + 0] = color[0];
- data[off + 1] = color[1];
- data[off + 2] = color[2];
+ data[off + 0] = data[off + 4] = color[0];
+ data[off + 1] = data[off + 5] = color[1];
+ data[off + 2] = data[off + 6] = color[2];
b <<= 1;
- off += 4;
+ off += 8;
}
- off += 273 * 4;
+ off += 546 * 4;
}
} else {
- for (jdx = 0; jdx < 8; jdx++) {
- color = _colors[(jdx < 4) ? (val & 0x0f) : (val >> 4)];
- for (idx = 0; idx < 7; idx++) {
- data[off + 0] = color[0];
- data[off + 1] = color[1];
- data[off + 2] = color[2];
- off += 4;
+ if (_greenMode) {
+ fore = _green;
+ back = _black;
+ for (jdx = 0; jdx < 8; jdx++) {
+ b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
+ b |= (b << 4);
+ b |= (b << 8);
+ if (col & 0x1) {
+ b <<= 2;
+ }
+ for (idx = 0; idx < 14; idx++) {
+ color = (b & 0x8000) ? fore : back;
+ data[off + 0] = color[0];
+ data[off + 1] = color[1];
+ data[off + 2] = color[2];
+ b <<= 1;
+ off += 4;
+ }
+ off += 546 * 4;
+ }
+ } else {
+ for (jdx = 0; jdx < 8; jdx++) {
+ b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
+ color = _colors[b];
+ for (idx = 0; idx < 7; idx++) {
+ data[off + 0] = data[off + 4] = color[0];
+ data[off + 1] = data[off + 5] = color[1];
+ data[off + 2] = data[off + 6] = color[2];
+ off += 8;
+ }
+ off += 546 * 4;
}
- off += 273 * 4;
}
}
}
@@ -211,6 +235,7 @@ function LoresPage(page)
function HiresPage(page)
{
var _page = page;
+
var orangeCol = [0xff, 0x65, 0x00];
var greenCol = [0x00, 0xff, 0x00];
var blueCol = [0x09, 0x2a, 0xff];
@@ -221,7 +246,8 @@ function HiresPage(page)
var _buffer = [];
var _refreshing = false;
- var _green = false;
+ var _green = [0x00, 0xff, 0x80];
+ var _greenMode = false;
function _init() {
_buffer = allocMemPages(0x20);
@@ -241,6 +267,9 @@ function HiresPage(page)
return _buffer[base];
},
write: function(page, off, val) {
+ function dim(c) {
+ return [c[0] * 0.75, c[1] * 0.75, c[2] * 0.75];
+ }
var addr = (page << 8) | off,
base = addr - 0x2000 * _page;
if (_buffer[base] === val && !_refreshing)
@@ -267,7 +296,7 @@ function HiresPage(page)
var data = pages[_page].data,
dy = rowa * 8 + rowb,
- dx = col * 7 - 1,
+ dx = col * 14 - 2,
b0 = col > 0 ? _buffer[base - 1] : 0,
b2 = col < 39 ? _buffer[base + 1] : 0;
val |= (b2 & 0x3) << 7;
@@ -277,34 +306,37 @@ function HiresPage(page)
oddCol = (hbs ? orangeCol : greenCol),
evenCol = (hbs ? blueCol : violetCol);
- off = dx * 4 + dy * 280 * 4;
- for (var idx = 0; idx < 9; idx++, off += 4) {
+ off = dx * 4 + dy * 560 * 4;
+ for (var idx = 0; idx < 9; idx++, off += 8) {
val >>= 1;
if (v1) {
- if (_green) {
- color = greenCol;
+ if (_greenMode) {
+ color = _green;
} else if (v0 || v2) {
color = whiteCol;
} else {
color = odd ? oddCol : evenCol;
}
} else {
- if (_green) {
+ if (_greenMode) {
color = blackCol;
- } else if (odd && v0 && v2) {
- color = evenCol;
+ } else if (odd && v2 && v0) {
+ color = v0 ? dim(evenCol) : evenCol;
} else if (!odd && v0 && v2) {
- color = oddCol;
+ color = v2 ? dim(oddCol) : oddCol;
} else {
color = blackCol;
}
}
- if (dx > -1 && dx < 280) {
+ if (dx > -1 && dx < 560) {
data[off + 0] = color[0];
data[off + 1] = color[1];
data[off + 2] = color[2];
+ data[off + 4] = color[0];
+ data[off + 5] = color[1];
+ data[off + 6] = color[2];
}
dx++;
@@ -324,7 +356,7 @@ function HiresPage(page)
_refreshing = false;
},
green: function(on) {
- _green = on;
+ _greenMode = on;
this.refresh();
},
blit: function() {
@@ -333,13 +365,13 @@ function HiresPage(page)
getState: function() {
return {
page: _page,
- green: _green,
+ green: _greenMode,
buffer: base64_encode(_buffer)
};
},
setState: function(state) {
_page = state.page;
- _green = state.green;
+ _greenMode = state.green;
_buffer = base64_decode(state.buffer);
this.refresh();
@@ -389,9 +421,9 @@ function VideoModes(gr,hgr,gr2,hgr2) {
setContext: function(c) {
context = c;
- pages[1] = context.createImageData(280, 192);
- pages[2] = context.createImageData(280, 192);
- for (var idx = 0; idx < 280 * 192 * 4; idx++) {
+ pages[1] = context.createImageData(560, 192);
+ pages[2] = context.createImageData(560, 192);
+ for (var idx = 0; idx < 560 * 192 * 4; idx++) {
pages[1].data[idx] = 0xff;
pages[2].data[idx] = 0xff;
}
diff --git a/js/canvas2e.js b/js/canvas2e.js
index 97cdf62..02948fa 100644
--- a/js/canvas2e.js
+++ b/js/canvas2e.js
@@ -10,12 +10,10 @@
* implied warranty.
*/
+/*jshint browser:true */
/*globals allocMemPages: false, charset: false, base64_encode: false, base64_decode: false */
/*exported LoresPage, HiresPage, VideoModes */
-var GREEN = [0x00,0xff,0x00];
-// var WHITE = [0xff,0xff,0xff];
-var MONO = GREEN;
var textMode = true;
var mixedMode = false;
@@ -47,7 +45,7 @@ function LoresPage(page)
var _black = [0x00,0x00,0x00];
var _white = [0xff,0xff,0xff];
- var _green = [0x00,0xff,0x00];
+ var _green = [0x00,0xff,0x80];
var _colors = [
[0x00,0x00,0x00], // 0 Black 0000 0 0
@@ -165,7 +163,7 @@ function LoresPage(page)
if (textMode || (mixedMode && row > 19)) {
var b;
var flash = ((val & 0xc0) == 0x40) &&
- _blink && !_80colMode;
+ _blink && !_80colMode && !altCharMode;
fore = flash ? _black : (_greenMode ? _green : _white);
back = flash ? _white : _black;
@@ -194,12 +192,9 @@ function LoresPage(page)
b = charset[val * 8 + jdx];
for (idx = 0; idx < 7; idx++) {
color = (b & 0x01) ? back : fore;
- data[off + 0] = color[0];
- data[off + 1] = color[1];
- data[off + 2] = color[2];
- data[off + 4] = color[0];
- data[off + 5] = color[1];
- data[off + 6] = color[2];
+ data[off + 0] = data[off + 4] = color[0];
+ data[off + 1] = data[off + 5] = color[1];
+ data[off + 2] = data[off + 6] = color[2];
b >>= 1;
off += 8;
}
@@ -209,33 +204,73 @@ function LoresPage(page)
} else {
if (_80colMode) {
off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8) * 4;
- for (jdx = 0; jdx < 8; jdx++) {
- color = _colors[(jdx < 4) ?
- (val & 0x0f) : (val >> 4)];
- for (idx = 0; idx < 7; idx++) {
- data[off + 0] = color[0];
- data[off + 1] = color[1];
- data[off + 2] = color[2];
- off += 4;
+ if (_greenMode) {
+ fore = _green;
+ back = _black;
+ for (jdx = 0; jdx < 8; jdx++) {
+ b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
+ b |= (b << 4);
+ if (bank & 0x1) {
+ b <<= 1;
+ }
+ for (idx = 0; idx < 7; idx++) {
+ color = (b & 0x80) ? fore : back;
+ data[off + 0] = color[0];
+ data[off + 1] = color[1];
+ data[off + 2] = color[2];
+ b <<= 1;
+ off += 4;
+ }
+ off += 546 * 4;
+ }
+ } else {
+ for (jdx = 0; jdx < 8; jdx++) {
+ color = _colors[(jdx < 4) ?
+ (val & 0x0f) : (val >> 4)];
+ for (idx = 0; idx < 7; idx++) {
+ data[off + 0] = color[0];
+ data[off + 1] = color[1];
+ data[off + 2] = color[2];
+ off += 4;
+ }
+ off += 553 * 4;
}
- off += 553 * 4;
}
} else {
off = (col * 14 + row * 560 * 8) * 4;
- for (jdx = 0; jdx < 8; jdx++) {
- color = _colors[(jdx < 4) ?
- (val & 0x0f) : (val >> 4)];
- for (idx = 0; idx < 7; idx++) {
- data[off + 0] = color[0];
- data[off + 1] = color[1];
- data[off + 2] = color[2];
- data[off + 4] = color[0];
- data[off + 5] = color[1];
- data[off + 6] = color[2];
- off += 8;
+ if (_greenMode) {
+ fore = _green;
+ back = _black;
+ for (jdx = 0; jdx < 8; jdx++) {
+ b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
+ b |= (b << 4);
+ b |= (b << 8);
+ if (col & 0x1) {
+ b <<= 2;
+ }
+ for (idx = 0; idx < 14; idx++) {
+ color = (b & 0x8000) ? fore : back;
+ data[off + 0] = color[0];
+ data[off + 1] = color[1];
+ data[off + 2] = color[2];
+ b <<= 1;
+ off += 4;
+ }
+ off += 546 * 4;
+ }
+ } else {
+ for (jdx = 0; jdx < 8; jdx++) {
+ color = _colors[(jdx < 4) ?
+ (val & 0x0f) : (val >> 4)];
+ for (idx = 0; idx < 7; idx++) {
+ data[off + 0] = data[off + 4] = color[0];
+ data[off + 1] = data[off + 5] = color[1];
+ data[off + 2] = data[off + 6] = color[2];
+ off += 8;
+ }
+ off += 546 * 4;
}
- off += 546 * 4;
}
}
}
@@ -267,6 +302,7 @@ function LoresPage(page)
},
green: function(on) {
_greenMode = on;
+ this.refresh();
},
blit: function() {
context.putImageData(pages[_page], 0, 0);
@@ -274,14 +310,14 @@ function LoresPage(page)
getState: function() {
return {
page: _page,
- green: _green,
+ green: _greenMode,
buffer: [base64_encode(_buffer[0]),
base64_encode(_buffer[1])]
};
},
setState: function(state) {
_page = state.page;
- _green = state.green;
+ _greenMode = state.green;
_buffer[0] = base64_decode(state.buffer[0]);
_buffer[1] = base64_decode(state.buffer[1]);
@@ -350,7 +386,8 @@ function HiresPage(page)
var _buffer = [];
var _refreshing = false;
- var _green = false;
+ var _green = [0x00, 0xff, 0x80];
+ var _greenMode = false;
var _garish = false;
function _init() {
@@ -408,6 +445,9 @@ function HiresPage(page)
return _buffer[bank][base];
},
_write: function(page, off, val, bank) {
+ function dim(c) {
+ return [c[0] * 0.75, c[1] * 0.75, c[2] * 0.75];
+ }
var addr = (page << 8) | off, base = addr - 0x2000 * _page,
idx, jdx;
if (_buffer[bank][base] == val && !_refreshing)
@@ -462,18 +502,22 @@ function HiresPage(page)
off = dx * 4 + dy * 280 * 4;
for (idx = 0; idx < 7; idx++) {
- var dcolor = _green ? MONO : dcolors[r4[c[idx]]];
+ var dcolor = _greenMode ? _green : dcolors[r4[c[idx]]];
var bits = c[idx] | (c[idx + 1] << 4);
for (jdx = 0; jdx < 4; jdx++, off += 4) {
- var saturate = !MONO && (_garish || bits & 0xe);
- if (bits & 0x1 || saturate) {
+ if (bits & 0x1) {
data[off + 0] = dcolor[0];
data[off + 1] = dcolor[1];
data[off + 2] = dcolor[2];
+ } else if (_greenMode) {
+ data[off + 0] = 0;
+ data[off + 1] = 0;
+ data[off + 2] = 0;
} else {
- data[off + 0] = 0; // dcolor[0] >> 1;
- data[off + 1] = 0; // dcolor[1] >> 1;
- data[off + 2] = 0; // dcolor[2] >> 1;
+ dcolor = dim(dcolor);
+ data[off + 0] = dcolor[0];
+ data[off + 1] = dcolor[1];
+ data[off + 2] = dcolor[2];
}
bits >>= 1;
}
@@ -492,20 +536,20 @@ function HiresPage(page)
for (idx = 0; idx < 9; idx++, off += 8) {
val >>= 1;
if (v1) {
- if (_green) {
- color = MONO;
+ if (_greenMode) {
+ color = _green;
} else if (v0 || v2) {
color = whiteCol;
} else {
color = odd ? oddCol : evenCol;
}
} else {
- if (_green) {
+ if (_greenMode) {
color = blackCol;
- } else if (odd && v2 && (_garish || v0)) {
- color = evenCol;
- } else if (!odd && v0 && (_garish || v2)) {
- color = oddCol;
+ } else if (odd && v2 && v0) {
+ color = v0 ? dim(evenCol) : evenCol;
+ } else if (!odd && v0 && v2) {
+ color = v2 ? dim(oddCol) : oddCol;
} else {
color = blackCol;
}
@@ -542,12 +586,12 @@ function HiresPage(page)
_refreshing = false;
},
green: function(on) {
- _green = on;
+ _greenMode = on;
this.refresh();
},
garish: function(on) {
- _garish = on;
- this.refresh();
+ // _garish = on;
+ // this.refresh();
},
blit: function() {
context.putImageData(pages[_page], 0, 0);
@@ -555,7 +599,7 @@ function HiresPage(page)
getState: function() {
return {
page: _page,
- green: _green,
+ green: _greenMode,
garish: _garish,
buffer: [base64_encode(_buffer[0]),
base64_encode(_buffer[1])]
@@ -563,7 +607,7 @@ function HiresPage(page)
},
setState: function(state) {
_page = state.page;
- _green = state.green;
+ _greenMode = state.green;
_garish = state.garish;
_buffer[0] = base64_decode(state.buffer[0]);
_buffer[1] = base64_decode(state.buffer[1]);