Canvas update

Render both dimensions x2 for better visual results.
This commit is contained in:
Will Scullin 2014-02-05 10:53:08 -08:00
parent 088a5a7922
commit 9226b47f24
4 changed files with 172 additions and 92 deletions

View File

@ -694,10 +694,9 @@ function _keyup(evt) {
function updateScreen() {
var green = $("#green_screen").prop("checked");
var scanlines = $("#show_scanlines").prop("checked");
scanlines = $("#show_scanlines").prop("checked");
vm.green(green);
$("#scanlines").toggle(scanlines);
}
var flipX = false;
@ -764,7 +763,7 @@ $(function() {
$(window).keydown(_keydown);
$(window).keyup(_keyup);
$("canvas,#scanlines,#joystick").mousedown(function(evt) {
$("canvas").mousedown(function(evt) {
if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1);
}
@ -877,8 +876,7 @@ $(function() {
<div role="textbox" class="overscan"
onKeyDown="_keydown(event);"
onKeyUp="_keyup(event);">
<canvas id="screen" width="560" height="192"></canvas>
<img id="scanlines" src="css/scanlines.png" />
<canvas id="screen" width="560" height="384"></canvas>
</div>
</td>
</tr>

View File

@ -701,10 +701,9 @@ function _keyup(evt) {
function updateScreen() {
var green = $("#green_screen").prop("checked");
var scanlines = $("#show_scanlines").prop("checked");
scanlines = $("#show_scanlines").prop("checked");
vm.green(green);
$("#scanlines").toggle(scanlines);
}
var flipX = false;
@ -771,7 +770,7 @@ $(function() {
$(window).keydown(_keydown);
$(window).keyup(_keyup);
$("canvas,#scanlines,#joystick").mousedown(function(evt) {
$("canvas").mousedown(function(evt) {
if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1);
}
@ -888,8 +887,7 @@ $(function() {
<div role="textbox" class="overscan"
onKeyDown="_keydown(event);"
onKeyUp="_keyup(event);">
<canvas id="screen" width="560" height="192"></canvas>
<img id="scanlines" src="css/scanlines.png" />
<canvas id="screen" width="560" height="384"></canvas>
</div>
</td>
</tr>

View File

@ -1,5 +1,5 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2014 Will Scullin <scullin@scullinsteel.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -26,6 +26,13 @@ var hiresMode = false;
var pageMode = 1;
var pages = [];
var context = null;
var scanlines = false;
/****************************************************************************
*
* Text/Lores Graphics
*
***************************************************************************/
function LoresPage(page)
{
@ -41,7 +48,7 @@ function LoresPage(page)
var _black = [0x00,0x00,0x00];
var _white = [0xff,0xff,0xff];
var _green = [0x00,0xff,0x88];
var _green = [0x00,0xff,0x80];
var _colors = [
[0x00,0x00,0x00], // 0 Black 0000 0 0
@ -85,10 +92,42 @@ function LoresPage(page)
_buffer = allocMemPages(0x4);
for (var idx = 0; idx < 0x400; idx++) {
_buffer[idx] = 0; // Math.floor(Math.random()*256);
_buffer[idx] = 0;
}
}
function _drawPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2;
if (!scanlines) {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2;
} else {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0 >> 1;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1 >> 1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1;
}
}
function _drawHalfPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = c0;
data[off + 1] = c1;
data[off + 2] = c2;
if (!scanlines) {
data[off + 560 * 4] = c0;
data[off + 560 * 4 + 1] = c1;
data[off + 560 * 4 + 2] = c2;
} else {
data[off + 560 * 4] = c0 >> 1;
data[off + 560 * 4 + 1] = c1 >> 1;
data[off + 560 * 4 + 2] = c2 >> 1;
}
}
_init();
return {
@ -128,7 +167,7 @@ function LoresPage(page)
return;
var data = pages[_page].data, fore, back;
off = (col * 14 + row * 560 * 8) * 4;
off = (col * 14 + row * 560 * 8 * 2) * 4;
if (textMode || (mixedMode && row > 19)) {
if (val & 0x80 || ((val & 0x40) && _blink)) {
@ -143,13 +182,11 @@ function LoresPage(page)
b <<= 1;
for (idx = 0; idx < 7; idx++) {
color = (b & 0x80) ? fore : back;
data[off + 0] = data[off + 4] = color[0];
data[off + 1] = data[off + 5] = color[1];
data[off + 2] = data[off + 6] = color[2];
_drawPixel(data, off, color);
b <<= 1;
off += 8;
}
off += 546 * 4;
off += 546 * 4 + 560 * 4;
}
} else {
if (_greenMode) {
@ -164,25 +201,21 @@ function LoresPage(page)
}
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];
_drawHalfPixel(data, off, color);
b <<= 1;
off += 4;
}
off += 546 * 4;
off += 546 * 4 + 560 * 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];
_drawPixel(data, off, color);
off += 8;
}
off += 546 * 4;
off += 546 * 4 + 560 * 4;
}
}
}
@ -255,7 +288,24 @@ function HiresPage(page)
for (var idx = 0; idx < 0x2000; idx++)
_buffer[idx] = 0; // Math.floor(Math.random()*256);
}
function _drawPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2;
if (!scanlines) {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2;
} else {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0 >> 1;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1 >> 1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1;
}
}
_init();
return {
@ -306,7 +356,7 @@ function HiresPage(page)
oddCol = (hbs ? orangeCol : greenCol),
evenCol = (hbs ? blueCol : violetCol);
off = dx * 4 + dy * 560 * 4;
off = dx * 4 + dy * 560 * 4 * 2;
for (var idx = 0; idx < 9; idx++, off += 8) {
val >>= 1;
@ -331,14 +381,9 @@ function HiresPage(page)
}
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];
_drawPixel(data, off, color);
}
dx++;
dx += 2;
v0 = v1;
v1 = v2;
@ -421,9 +466,9 @@ function VideoModes(gr,hgr,gr2,hgr2) {
setContext: function(c) {
context = c;
pages[1] = context.createImageData(560, 192);
pages[2] = context.createImageData(560, 192);
for (var idx = 0; idx < 560 * 192 * 4; idx++) {
pages[1] = context.createImageData(560, 384);
pages[2] = context.createImageData(560, 384);
for (var idx = 0; idx < 560 * 384 * 4; idx++) {
pages[1].data[idx] = 0xff;
pages[2].data[idx] = 0xff;
}

View File

@ -24,6 +24,7 @@ var altCharMode = false;
var doubleHiresMode = false;
var pages = [];
var context = null;
var scanlines = false;
/****************************************************************************
*
@ -76,6 +77,38 @@ function LoresPage(page)
}
}
function _drawPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2;
if (!scanlines) {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2;
} else {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0 >> 1;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1 >> 1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1;
}
}
function _drawHalfPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = c0;
data[off + 1] = c1;
data[off + 2] = c2;
if (!scanlines) {
data[off + 560 * 4] = c0;
data[off + 560 * 4 + 1] = c1;
data[off + 560 * 4 + 2] = c2;
} else {
data[off + 560 * 4] = c0 >> 1;
data[off + 560 * 4 + 1] = c1 >> 1;
data[off + 560 * 4 + 2] = c2 >> 1;
}
}
_init();
return {
@ -172,38 +205,34 @@ function LoresPage(page)
}
if (_80colMode) {
off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8) * 4;
off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8 * 2) * 4;
for (jdx = 0; jdx < 8; jdx++) {
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];
_drawHalfPixel(data, off, color);
b >>= 1;
off += 4;
}
off += 553 * 4;
off += 553 * 4 + 560 * 4;
}
} else {
off = (col * 14 + row * 560 * 8) * 4;
off = (col * 14 + row * 560 * 8 * 2) * 4;
for (jdx = 0; jdx < 8; jdx++) {
b = charset[val * 8 + jdx];
for (idx = 0; idx < 7; idx++) {
color = (b & 0x01) ? back : fore;
data[off + 0] = data[off + 4] = color[0];
data[off + 1] = data[off + 5] = color[1];
data[off + 2] = data[off + 6] = color[2];
_drawPixel(data, off, color);
b >>= 1;
off += 8;
}
off += 546 * 4;
off += 546 * 4 + 560 * 4;
}
}
} else {
if (_80colMode) {
off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8) * 4;
off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8 * 2) * 4;
if (_greenMode) {
fore = _green;
back = _black;
@ -215,9 +244,7 @@ function LoresPage(page)
}
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];
_drawHalfPixel(data, off, color);
b <<= 1;
off += 4;
}
@ -228,16 +255,14 @@ function LoresPage(page)
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];
_drawHalfPixel(data, off, color);
off += 4;
}
off += 553 * 4;
}
}
} else {
off = (col * 14 + row * 560 * 8) * 4;
off = (col * 14 + row * 560 * 8 * 2) * 4;
if (_greenMode) {
fore = _green;
@ -251,25 +276,21 @@ function LoresPage(page)
}
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];
_drawHalfPixel(data, off, color);
b <<= 1;
off += 4;
}
off += 546 * 4;
off += 546 * 4 + 560 * 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];
for (idx = 0; idx < 7; idx++) {
_drawPixel(data, off, color);
off += 8;
}
off += 546 * 4;
off += 546 * 4 + 560 * 4;
}
}
}
@ -398,6 +419,38 @@ function HiresPage(page)
}
}
function _drawPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2;
if (!scanlines) {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2;
} else {
data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0 >> 1;
data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1 >> 1;
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1;
}
}
function _drawHalfPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = c0;
data[off + 1] = c1;
data[off + 2] = c2;
if (!scanlines) {
data[off + 560 * 4] = c0;
data[off + 560 * 4 + 1] = c1;
data[off + 560 * 4 + 2] = c2;
} else {
data[off + 560 * 4] = c0 >> 1;
data[off + 560 * 4 + 1] = c1 >> 1;
data[off + 560 * 4 + 2] = c2 >> 1;
}
}
_init();
return {
@ -503,7 +556,7 @@ function HiresPage(page)
c[8] = b4 & 0x0f;
}
dx = mcol * 14;
off = dx * 4 + dy * 280 * 4;
off = dx * 4 + dy * 280 * 4 * 2;
for (idx = 1; idx < 8; idx++) {
var dcolor = dcolors[r4[c[idx]]];
@ -511,33 +564,23 @@ function HiresPage(page)
for (jdx = 0; jdx < 4; jdx++, off += 4) {
if (_greenMode) {
if (bits & 0x10) {
data[off + 0] = _green[0];
data[off + 1] = _green[1];
data[off + 2] = _green[2];
_drawHalfPixel(data, off, _green);
} else {
data[off + 0] = 0;
data[off + 1] = 0;
data[off + 2] = 0;
_drawHalfPixel(data, off, blackCol);
}
} else if (((bits & 0x3c) == 0x3c) ||
((bits & 0xf0) == 0xf0) ||
((bits & 0x1e) == 0x1e) ||
((bits & 0x78) == 0x78)) {
data[off + 0] = 0xff;
data[off + 1] = 0xff;
data[off + 2] = 0xff;
_drawHalfPixel(data, off, whiteCol);
} else if (((c[idx] == c[idx + 1]) &&
(bits & 0xf0)) ||
((c[idx] == c[idx - 1]) &&
(bits & 0x01e)) ||
(bits & 0x10)) {
data[off + 0] = dcolor[0];
data[off + 1] = dcolor[1];
data[off + 2] = dcolor[2];
} else {
data[off + 0] = 0;
data[off + 1] = 0;
data[off + 2] = 0;
_drawHalfPixel(data, off, dcolor);
} else {
_drawHalfPixel(data, off, blackCol);
}
bits >>= 1;
}
@ -558,11 +601,12 @@ function HiresPage(page)
b2 = col < 39 ? _buffer[bank][base + 1] : 0;
val |= (b2 & 0x3) << 7;
var v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1,
odd = !(col & 0x1), color,
odd = !(col & 0x1),
color,
oddCol = (hbs ? orangeCol : greenCol),
evenCol = (hbs ? blueCol : violetCol);
off = dx * 4 + dy * 280 * 4;
off = dx * 4 + dy * 280 * 4 * 2;
for (idx = 0; idx < 9; idx++, off += 8) {
val >>= 1;
if (v1) {
@ -586,12 +630,7 @@ function HiresPage(page)
}
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];
_drawPixel(data, off, color);
}
dx += 2;
@ -736,9 +775,9 @@ function VideoModes(gr,hgr,gr2,hgr2) {
setContext: function(c) {
context = c;
pages[1] = c.createImageData(560, 192);
pages[2] = c.createImageData(560, 192);
for (var idx = 0; idx < 560 * 192 * 4; idx++) {
pages[1] = c.createImageData(560, 384);
pages[2] = c.createImageData(560, 384);
for (var idx = 0; idx < 560 * 384 * 4; idx++) {
pages[1].data[idx] = 0xff;
pages[2].data[idx] = 0xff;
}