converted src/platform to typescript; stack debug view

This commit is contained in:
Steven Hugg 2018-08-16 19:19:20 -04:00
parent d76de58738
commit d8a98989f5
36 changed files with 715 additions and 497 deletions

View File

@ -48,7 +48,7 @@ TODO:
- how to revert included files?
- go to error in include files
- BOM in upload/download?
- find version of neslib.h compatible with cc65
- stack view for Z80 platforms using memory map
FYI: Image links for the books on http://8bitworkshop.com/ are broken
On the website the additional grey spacing next to the program line numbers is not dynamically resized when the web browser window size is changed. Intentional?

View File

@ -20,10 +20,10 @@
"scripts": {
"build": "tsc",
"test": "npm run test-node",
"test-one": "mocha --recursive --timeout 60000",
"test-node": "mocha --recursive --timeout 60000 test/cli",
"test-worker": "mocha --recursive --timeout 60000 test/cli/testworker.js",
"test-profile": "mocha --recursive --timeout 60000 --prof test/cli"
"test-one": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000",
"test-node": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli",
"test-worker": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli/testworker.js",
"test-profile": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 --prof test/cli"
},
"repository": {
"type": "git",

View File

@ -36,6 +36,16 @@ body {
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="FileSaver.js/FileSaver.min.js"></script>
<script>
var exports = {};
function require(modname) {
if (modname == 'jquery') return $;
else if (modname.startsWith('.')) return exports;
else { console.log("Unknown require()", modname); return exports; }
}
</script>
<script src="gen/util.js"></script>
<script src="gen/pixed/pixeleditor.js"></script>

View File

@ -5,7 +5,7 @@
#pragma data-name (push,"CHARS")
const unsigned char TILESET[8*128] = {/*{w:8,h:8,bpp:1,count:128,brev:1}*/
const unsigned char TILESET[8*128] = {/*{w:8,h:8,bpp:1,count:64,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7c,0x7c,0x7c,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x6c,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0xfe,0x6c,0xfe,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xfe,0xd0,0xfe,0x16,0xfe,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0xdc,0x38,0x76,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6c,0x7c,0xec,0xee,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x70,0x70,0x70,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x38,0x38,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0xfe,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x1e,0x3c,0x78,0xf0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x7c,0xee,0xee,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x78,0x38,0x38,0x38,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x0e,0x7c,0xe0,0xee,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x0e,0x3c,0x0e,0x0e,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x7e,0xee,0xee,0xfe,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xe0,0xfc,0x0e,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0xfc,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xee,0x1c,0x1c,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0x7c,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0x7e,0x0e,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x70,0x70,0x38,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x1c,0x1c,0x38,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0x1c,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x7c,0xee,0xee,0xee,0xe0,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0xee,0xfe,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xee,0xfc,0xee,0xee,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xe0,0xe0,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0xec,0xee,0xee,0xee,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xe0,0xf0,0xe0,0xe0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xe0,0xf8,0xe0,0xe0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xe0,0xee,0xee,0xee,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xee,0xfe,0xee,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x38,0x38,0x38,0x38,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0e,0x0e,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0xfc,0xf8,0xec,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0xe0,0xe0,0xee,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0xee,0xfe,0xfe,0xee,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0xee,0xfe,0xfe,0xee,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xee,0xee,0xee,0xee,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

View File

@ -692,41 +692,38 @@ void new_player_ship() {
}
void set_sounds() {
/*
byte i;
byte enable = 0x1 | 0x2 | 0x8;
// missile fire sound
if (missiles[7].ypos != YOFFSCREEN) {
cv_set_frequency(CV_SOUNDCHANNEL_0, 2000-missiles[7].ypos*4);
cv_set_attenuation(CV_SOUNDCHANNEL_0, 18);
if (missiles[PLYRMISSILE].ypos != YOFFSCREEN) {
APU.pulse[0].period_low = missiles[PLYRMISSILE].ypos ^ 0xff;
APU.pulse[0].len_period_high = 0;
APU.pulse[0].control = 0x80 | 0x30 | 6;
} else {
cv_set_attenuation(CV_SOUNDCHANNEL_0, 32);
APU.pulse[0].control = 0x30;
}
// enemy explosion sound
if (enemy_exploding) {
cv_set_frequency(CV_SOUNDCHANNEL_1, 500+enemy_exploding*64);
cv_set_attenuation(CV_SOUNDCHANNEL_1, 14);
} else {
cv_set_attenuation(CV_SOUNDCHANNEL_1, 32);
if (player_exploding && player_exploding < 8) {
APU.noise.control = 4;
APU.noise.period = 8 + player_exploding;
APU.noise.len = 15;
} else if (enemy_exploding) {
APU.noise.control = 2;
APU.noise.period = 8 + enemy_exploding;
APU.noise.len = 8;
}
cv_set_attenuation(CV_SOUNDCHANNEL_2, 32);
// player explosion
if (player_exploding && player_exploding < 15) {
cv_set_frequency(CV_SOUNDCHANNEL_2, player_exploding*256);
cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 4+player_exploding);
cv_set_noise(true, 3);
} else {
// set diving sounds for spaceships
cv_set_attenuation(CV_SOUNDCHANNEL_NOISE, 32);
for (i=0; i<3; i++) {
byte y = attackers[i].y >> 8;
if (y >= 0x80) {
cv_set_frequency(CV_SOUNDCHANNEL_2, 4000+y*8);
cv_set_attenuation(CV_SOUNDCHANNEL_2, 28);
break;
}
// set diving sounds for spaceships
for (i=0; i<2; i++) {
register AttackingEnemy* a = i ? &attackers[4] : &attackers[0];
if (a->findex && !a->returning) {
byte y = a->y >> 8;
APU.triangle.counter = 0xc0;
APU.triangle.period_low = y;
APU.triangle.len_period_high = 1;
enable |= 0x4;
}
}
*/
APU.status = enable;
}
static char starx[32];
@ -843,8 +840,24 @@ void setup_tileset() {
}
}
const byte APUINIT[0x13] = {
0x30,0x08,0x00,0x00,
0x30,0x08,0x00,0x00,
0x80,0x00,0x00,0x00,
0x30,0x00,0x00,0x00,
0x00,0x00,0x00
};
void init_apu() {
// from https://wiki.nesdev.com/w/index.php/APU_basics
memcpy((void*)0x4000, APUINIT, sizeof(APUINIT));
APU.fcontrol = 0x40; // frame counter 5-step
APU.status = 0x0f; // turn on all channels except DMC
}
void main() {
setup_tileset();
init_apu();
init_stars();
player_score = 0;
while (1) {

137
presets/nes/transtable.c Normal file
View File

@ -0,0 +1,137 @@

//this example code shows how to put some text in nametable
#include "neslib.h"
#include <string.h>
#pragma data-name (push,"CHARS")
#pragma data-name(pop)
const unsigned char TILESET[48*16] = {/*{w:8,h:8,bpp:1,count:48,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x7e,0x42,0x42,0x46,0x46,0x46,0x7e,0x00,0x7e,0x42,0x42,0x46,0x46,0x46,0x7e,0x00,
0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x00,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x00,
0x3e,0x22,0x02,0x3e,0x30,0x30,0x3e,0x00,0x3e,0x22,0x02,0x3e,0x30,0x30,0x3e,0x00,
0x3c,0x24,0x04,0x1e,0x06,0x26,0x3e,0x00,0x3c,0x24,0x04,0x1e,0x06,0x26,0x3e,0x00,
0x44,0x44,0x44,0x7e,0x0c,0x0c,0x0c,0x00,0x44,0x44,0x44,0x7e,0x0c,0x0c,0x0c,0x00,
0x3c,0x20,0x20,0x3e,0x06,0x26,0x3e,0x00,0x3c,0x20,0x20,0x3e,0x06,0x26,0x3e,0x00,
0x3e,0x22,0x20,0x3e,0x26,0x26,0x3e,0x00,0x3e,0x22,0x20,0x3e,0x26,0x26,0x3e,0x00,
0x3e,0x02,0x02,0x06,0x06,0x06,0x06,0x00,0x3e,0x02,0x02,0x06,0x06,0x06,0x06,0x00,
0x3c,0x24,0x24,0x7e,0x46,0x46,0x7e,0x00,0x3c,0x24,0x24,0x7e,0x46,0x46,0x7e,0x00,
0x3e,0x22,0x22,0x3e,0x06,0x06,0x06,0x00,0x3e,0x22,0x22,0x3e,0x06,0x06,0x06,0x00,
0x3c,0x24,0x24,0x7e,0x62,0x62,0x62,0x00,0x3c,0x24,0x24,0x7e,0x62,0x62,0x62,0x00,
0x7c,0x44,0x44,0x7e,0x62,0x62,0x7e,0x00,0x7c,0x44,0x44,0x7e,0x62,0x62,0x7e,0x00,
0x7e,0x42,0x40,0x60,0x60,0x62,0x7e,0x00,0x7e,0x42,0x40,0x60,0x60,0x62,0x7e,0x00,
0x7e,0x42,0x42,0x62,0x62,0x62,0x7e,0x00,0x7e,0x42,0x42,0x62,0x62,0x62,0x7e,0x00,
0x7c,0x40,0x40,0x7c,0x60,0x60,0x7c,0x00,0x7c,0x40,0x40,0x7c,0x60,0x60,0x7c,0x00,
0x3c,0x20,0x20,0x3c,0x30,0x30,0x30,0x00,0x3c,0x20,0x20,0x3c,0x30,0x30,0x30,0x00,
0x7e,0x42,0x40,0x6e,0x62,0x62,0x7e,0x00,0x7e,0x42,0x40,0x6e,0x62,0x62,0x7e,0x00,
0x42,0x42,0x42,0x7e,0x62,0x62,0x62,0x00,0x42,0x42,0x42,0x7e,0x62,0x62,0x62,0x00,
0x10,0x10,0x10,0x18,0x18,0x18,0x18,0x00,0x10,0x10,0x10,0x18,0x18,0x18,0x18,0x00,
0x04,0x04,0x04,0x06,0x06,0x46,0x7e,0x00,0x04,0x04,0x04,0x06,0x06,0x46,0x7e,0x00,
0x44,0x44,0x44,0x7e,0x62,0x62,0x62,0x00,0x44,0x44,0x44,0x7e,0x62,0x62,0x62,0x00,
0x20,0x20,0x20,0x30,0x30,0x30,0x3e,0x00,0x20,0x20,0x20,0x30,0x30,0x30,0x3e,0x00,
0xfe,0x92,0x92,0xd2,0xd2,0xd2,0xd2,0x00,0xfe,0x92,0x92,0xd2,0xd2,0xd2,0xd2,0x00,
0x7e,0x42,0x42,0x62,0x62,0x62,0x62,0x00,0x7e,0x42,0x42,0x62,0x62,0x62,0x62,0x00,
0x7e,0x46,0x46,0x42,0x42,0x42,0x7e,0x00,0x7e,0x46,0x46,0x42,0x42,0x42,0x7e,0x00,
0x7e,0x42,0x42,0x7e,0x60,0x60,0x60,0x00,0x7e,0x42,0x42,0x7e,0x60,0x60,0x60,0x00,
0x7e,0x42,0x42,0x42,0x42,0x4e,0x7e,0x00,0x7e,0x42,0x42,0x42,0x42,0x4e,0x7e,0x00,
0x7c,0x44,0x44,0x7e,0x62,0x62,0x62,0x00,0x7c,0x44,0x44,0x7e,0x62,0x62,0x62,0x00,
0x7e,0x42,0x40,0x7e,0x06,0x46,0x7e,0x00,0x7e,0x42,0x40,0x7e,0x06,0x46,0x7e,0x00,
0x7e,0x10,0x10,0x18,0x18,0x18,0x18,0x00,0x7e,0x10,0x10,0x18,0x18,0x18,0x18,0x00,
0x42,0x42,0x42,0x62,0x62,0x62,0x7e,0x00,0x42,0x42,0x42,0x62,0x62,0x62,0x7e,0x00,
0x64,0x64,0x64,0x64,0x2c,0x2c,0x3c,0x00,0x64,0x64,0x64,0x64,0x2c,0x2c,0x3c,0x00,
0x49,0x49,0x49,0x49,0x69,0x69,0x7f,0x00,0x49,0x49,0x49,0x49,0x69,0x69,0x7f,0x00,
0x42,0x42,0x42,0x3c,0x62,0x62,0x62,0x00,0x42,0x42,0x42,0x3c,0x62,0x62,0x62,0x00,
0x42,0x42,0x42,0x7e,0x18,0x18,0x18,0x00,0x42,0x42,0x42,0x7e,0x18,0x18,0x18,0x00,
0x7e,0x42,0x02,0x7e,0x60,0x62,0x7e,0x00,0x7e,0x42,0x02,0x7e,0x60,0x42,0x7e,0x00,
0x10,0x10,0x18,0x18,0x18,0x00,0x18,0x00,0x10,0x10,0x18,0x18,0x18,0x00,0x18,0x00,
0x18,0x7e,0x40,0x7e,0x06,0x7e,0x18,0x00,0x18,0x7e,0x40,0x7e,0x06,0x7e,0x18,0x00,
0x00,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x18,0x00,0x00,0x00,
0x00,0x00,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,
0x18,0x18,0x08,0x10,0x00,0x00,0x00,0x00,0x18,0x18,0x08,0x10,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x18,0x08,0x10,0x00,0x00,0x00,0x00,0x18,0x18,0x08,0x10,0x00,
0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
void put_str(unsigned int addr, char* str) {
vram_adr(addr);
vram_write(str, strlen(str));
}
#pragma charmap(0x20, 0x2f);
#pragma charmap('!', 0x25);
#pragma charmap('$', 0x26);
#pragma charmap(':', 0x27);
#pragma charmap('-', 0x28);
#pragma charmap('.', 0x29);
#pragma charmap('\'', 0x2a);
#pragma charmap(',', 0x2b);
#pragma charmap('#', 0x2c);
#pragma charmap('_', 0x2d);
// 0-9
#pragma charmap(0x30, 0x1);
#pragma charmap(0x31, 0x2);
#pragma charmap(0x32, 0x3);
#pragma charmap(0x33, 0x4);
#pragma charmap(0x34, 0x5);
#pragma charmap(0x35, 0x6);
#pragma charmap(0x36, 0x7);
#pragma charmap(0x37, 0x8);
#pragma charmap(0x38, 0x9);
#pragma charmap(0x39, 0xa);
// A-Z
#pragma charmap(0x41, 0xb);
#pragma charmap(0x42, 0xc);
#pragma charmap(0x43, 0xd);
#pragma charmap(0x44, 0xe);
#pragma charmap(0x45, 0xf);
#pragma charmap(0x46, 0x10);
#pragma charmap(0x47, 0x11);
#pragma charmap(0x48, 0x12);
#pragma charmap(0x49, 0x13);
#pragma charmap(0x4a, 0x14);
#pragma charmap(0x4b, 0x15);
#pragma charmap(0x4c, 0x16);
#pragma charmap(0x4d, 0x17);
#pragma charmap(0x4e, 0x18);
#pragma charmap(0x4f, 0x19);
#pragma charmap(0x50, 0x1a);
#pragma charmap(0x51, 0x1b);
#pragma charmap(0x52, 0x1c);
#pragma charmap(0x53, 0x1d);
#pragma charmap(0x54, 0x1e);
#pragma charmap(0x55, 0x1f);
#pragma charmap(0x56, 0x20);
#pragma charmap(0x57, 0x21);
#pragma charmap(0x58, 0x22);
#pragma charmap(0x59, 0x23);
#pragma charmap(0x5a, 0x24);
void main(void)
{
//copy tileset to RAM
vram_adr(0x0);
vram_write((unsigned char*)TILESET, sizeof(TILESET));
// set palette color
pal_col(0,0x0);
pal_col(3,0x30);
put_str(NTADR_A(2,2),"HELLO, WORLD!");
put_str(NTADR_A(2,4),"THIS CODE PRINTS SOME TEXT");
put_str(NTADR_A(2,5),"USING CC65'S TRANSLATION");
put_str(NTADR_A(2,6),"TABLE PRAGMAS, ALLOWING US");
put_str(NTADR_A(2,7),"TO PUT TILES IN ANY ORDER");
put_str(NTADR_A(2,8),"-- EXCEPT CAN'T USE ZERO");
put_str(NTADR_A(2,10),"# $0123456789 A-Z _MAIN #");
ppu_on_all();//enable rendering
while(1);//do nothing, infinite loop
}

View File

@ -1,17 +1,24 @@
import { RAM, RasterVideo, dumpRAM, dumpStackToString } from "./emu";
import { hex } from "./util";
declare var Z80_fast, jt, CPU6809;
export interface OpcodeMetadata {
minCycles: number;
maxCycles: number;
insnLength: number;
insnlength: number;
opcode: number;
}
interface CpuState {
PC:number, T?:number, o?:number/*opcode*/,
PC:number, T?:number, o?:number,/*opcode*/
SP?:number
/*
A:number, X:number, Y:number, SP:number, R:boolean,
N,V,D,Z,C:boolean*/
};
interface EmuState {c:CpuState};
interface EmuState {c:CpuState, b?:number[]};
type DisasmLine = {line:string, nbytes:number};
export interface Platform {
@ -44,6 +51,7 @@ export interface Platform {
saveState?() : EmuState;
getDebugCallback?() : any; // TODO
getSP?() : number;
getOriginPC?() : number;
getDebugCategories() : string[];
getDebugInfo(category:string, state:EmuState) : string;
@ -188,7 +196,7 @@ abstract class BaseFrameBasedPlatform extends BaseDebugPlatform {
////// 6502
function getToolForFilename_6502(fn:string) : string {
export function getToolForFilename_6502(fn:string) : string {
if (fn.endsWith(".pla")) return "plasm";
if (fn.endsWith(".c")) return "cc65";
if (fn.endsWith(".s")) return "ca65";
@ -231,14 +239,19 @@ export abstract class Base6502Platform extends BaseFrameBasedPlatform {
getToolForFilename = getToolForFilename_6502;
getDefaultExtension() { return ".a"; };
// TODO: Memory category
getDebugCategories() { return ["CPU"]; }
getDebugInfo(category:string, state:EmuState) {
return cpuStateToLongString_6502(state.c);
getDebugCategories() {
return ['CPU','ZPRAM','Stack'];
}
getDebugInfo(category:string, state:EmuState) : string {
switch (category) {
case 'CPU': return cpuStateToLongString_6502(state.c);
case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100);
case 'Stack': return dumpStackToString(state.b, 0x100, 0x1ff, 0x100+state.c.SP);
}
}
}
function cpuStateToLongString_6502(c) : string {
export function cpuStateToLongString_6502(c) : string {
function decodeFlags(c) {
var s = "";
s += c.N ? " N" : " -";
@ -270,7 +283,7 @@ var OPMETA_6502 = {
],
}
function getOpcodeMetadata_6502(opcode, address) {
export function getOpcodeMetadata_6502(opcode, address) {
// TODO: more intelligent maximum cycles
return {
opcode:opcode,
@ -282,7 +295,7 @@ function getOpcodeMetadata_6502(opcode, address) {
////// Z80
function cpuStateToLongString_Z80(c) {
export function cpuStateToLongString_Z80(c) {
function decodeFlags(flags) {
var flagspec = "SZ-H-VNC";
var s = "";
@ -298,7 +311,7 @@ function cpuStateToLongString_Z80(c) {
;
}
function BusProbe(bus : MemoryBus) {
export function BusProbe(bus : MemoryBus) {
var active = false;
var callback;
this.activate = function(_callback) {
@ -328,7 +341,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
_cpu;
probe;
newCPU(membus, iobus) {
newCPU(membus : MemoryBus, iobus : MemoryBus) {
this.probe = new BusProbe(membus);
this._cpu = Z80_fast({
display: {},
@ -442,13 +455,17 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
// TODO
//this.getOpcodeMetadata = function() { }
getDebugCategories() { return ["CPU"]; }
getDebugInfo(category:string, state:EmuState) {
return cpuStateToLongString_Z80(state.c);
getDebugCategories() {
return ['CPU'];
}
getDebugInfo(category:string, state:EmuState) : string {
switch (category) {
case 'CPU': return cpuStateToLongString_Z80(state.c);
}
}
}
function getToolForFilename_z80(fn) {
export function getToolForFilename_z80(fn) {
if (fn.endsWith(".c")) return "sdcc";
if (fn.endsWith(".s")) return "sdasz80";
if (fn.endsWith(".ns")) return "naken";
@ -456,6 +473,60 @@ function getToolForFilename_z80(fn) {
return "z80asm";
}
////// 6809
export function cpuStateToLongString_6809(c) {
function decodeFlags(flags) {
var flagspec = "EFHINZVC";
var s = "";
for (var i=0; i<8; i++)
s += (flags & (128>>i)) ? flagspec.slice(i,i+1) : "-";
return s; // TODO
}
return "PC " + hex(c.PC,4) + " " + decodeFlags(c.CC) + "\n"
+ "SP " + hex(c.SP,4) + "\n"
+ " A " + hex(c.A,2) + "\n"
+ " B " + hex(c.B,2) + "\n"
+ " X " + hex(c.X,4) + "\n"
+ " Y " + hex(c.Y,4) + "\n"
+ " U " + hex(c.U,4) + "\n"
;
}
export abstract class Base6809Platform extends BaseZ80Platform {
newCPU(membus : MemoryBus) {
var cpu = new CPU6809();
cpu.init(membus.write, membus.read, 0);
return cpu;
}
runUntilReturn() {
var depth = 1;
this.runEval((c:CpuState) => {
if (depth <= 0)
return true;
var op = this.readAddress(c.PC);
// TODO: 6809 opcodes
if (op == 0x9d || op == 0xad || op == 0xbd) // CALL
depth++;
else if (op == 0x3b || op == 0x39) // RET
--depth;
return false;
});
}
cpuStateToLongString(c:CpuState) {
return cpuStateToLongString_6809(c);
}
disassemble(pc:number, read:(addr:number)=>number) : DisasmLine {
// TODO: don't create new CPU
return new CPU6809().disasm(read(pc), read(pc+1), read(pc+2), read(pc+3), read(pc+4), pc);
}
getDefaultExtension() { return ".asm"; };
//this.getOpcodeMetadata = function() { }
}
/// MAME SUPPORT
declare var FS, ENV, Module; // mame emscripten
@ -733,3 +804,4 @@ export function BaseMAMEPlatform() {
return null; // TODO
}
}

View File

@ -1,15 +1,17 @@
"use strict";
import { hex } from "./util";
// external modules
declare var jt, Javatari, Z80_fast, CPU6809;
// Emulator classes
var PLATFORMS = {};
export var PLATFORMS = {};
var frameUpdateFunction : (Canvas) => void = null;
export var frameUpdateFunction : (Canvas) => void = null;
function noise() {
export function noise() {
return (Math.random() * 256) & 0xff;
}
@ -29,7 +31,7 @@ function __createCanvas(mainElement:HTMLElement, width:number, height:number) {
return canvas;
}
var RasterVideo = function(mainElement:HTMLElement, width:number, height:number, options?) {
export var RasterVideo = function(mainElement:HTMLElement, width:number, height:number, options?) {
var self = this;
var canvas, ctx;
var imageData, arraybuf, buf8, datau32;
@ -134,7 +136,7 @@ mainElement.appendChild(borderElement);
*/
}
var VectorVideo = function(mainElement:HTMLElement, width:number, height:number) {
export var VectorVideo = function(mainElement:HTMLElement, width:number, height:number) {
var self = this;
var canvas, ctx;
var persistenceAlpha = 0.5;
@ -207,12 +209,14 @@ var VectorVideo = function(mainElement:HTMLElement, width:number, height:number)
}
}
var RAM = function(size:number) {
var memArray = new ArrayBuffer(size);
this.mem = new Uint8Array(memArray);
export class RAM {
mem : Uint8Array;
constructor(size:number) {
this.mem = new Uint8Array(new ArrayBuffer(size));
}
}
var AnimationTimer = function(frequencyHz:number, callback:() => void) {
export var AnimationTimer = function(frequencyHz:number, callback:() => void) {
var intervalMsec = 1000.0 / frequencyHz;
var running;
var lastts = 0;
@ -269,7 +273,7 @@ var AnimationTimer = function(frequencyHz:number, callback:() => void) {
//
function dumpRAM(ram:number[], ramofs:number, ramlen:number) : string {
export function dumpRAM(ram:number[], ramofs:number, ramlen:number) : string {
var s = "";
// TODO: show scrollable RAM for other platforms
for (var ofs=0; ofs<ramlen; ofs+=0x10) {
@ -285,7 +289,7 @@ function dumpRAM(ram:number[], ramofs:number, ramlen:number) : string {
return s;
}
var Keys = {
export const Keys = {
VK_ESCAPE: {c: 27, n: "Esc"},
VK_F1: {c: 112, n: "F1"},
VK_F2: {c: 113, n: "F2"},
@ -393,7 +397,7 @@ function _metakeyflags(e) {
return (e.shiftKey?2:0) | (e.ctrlKey?4:0) | (e.altKey?8:0) | (e.metaKey?16:0);
}
function setKeyboardFromMap(video, switches, map, func) {
export function setKeyboardFromMap(video, switches, map, func?) {
video.setKeyboardEvents(function(key,code,flags) {
var o = map[key];
if (o && func) {
@ -415,7 +419,7 @@ function setKeyboardFromMap(video, switches, map, func) {
});
}
function makeKeycodeMap(table) {
export function makeKeycodeMap(table) {
var map = {};
for (var i=0; i<table.length; i++) {
var entry = table[i];
@ -424,7 +428,7 @@ function makeKeycodeMap(table) {
return map;
}
function padBytes(data, len) {
export function padBytes(data, len) {
if (data.length > len) {
throw Error("Data too long, " + data.length + " > " + len);
}
@ -433,8 +437,12 @@ function padBytes(data, len) {
return r.mem;
}
type AddressReadWriteFn = ((a:number) => number) | ((a:number,v:number) => void);
type AddressDecoderEntry = [number, number, number, AddressReadWriteFn];
type AddressDecoderOptions = {gmask:number}
// TODO: better performance, check values
function AddressDecoder(table, options) {
export function AddressDecoder(table : AddressDecoderEntry[], options?:AddressDecoderOptions) {
var self = this;
function makeFunction(lo, hi) {
var s = "";
@ -458,3 +466,45 @@ function AddressDecoder(table, options) {
return makeFunction(0x0, 0xffff).bind(self);
}
export function newAddressDecoder(table : AddressDecoderEntry[], options?:AddressDecoderOptions) : (a:number,v?:number) => number {
return new (AddressDecoder as any)(table, options);
}
// STACK DUMP
declare var addr2symbol; // address to symbol name map (TODO: import)
function lookupSymbol(addr) {
var start = addr;
while (addr >= 0) {
var sym = addr2symbol[addr];
// TODO: what about asm?
if (sym && sym.startsWith('_')) {
return addr2symbol[addr] + " + " + (start-addr);
}
addr--;
}
}
export function dumpStackToString(mem:number[], start:number, end:number, sp:number) : string {
var s = "";
var nraw = 0;
//s = dumpRAM(mem.slice(start,start+end+1), start, end-start+1);
while (sp < end) {
sp++;
var addr = mem[sp] + mem[sp+1]*256;
var opcode = mem[addr-2];
if (opcode == 0x20) { // JSR
s += "\n$" + hex(sp) + ": ";
s += hex(addr,4) + " " + lookupSymbol(addr);
sp++;
nraw = 0;
} else {
if (nraw == 0)
s += "\n$" + hex(sp) + ": ";
s += hex(mem[sp+1]) + " ";
if (++nraw == 8) nraw = 0;
}
}
return s+"\n";
}

View File

@ -1,6 +1,8 @@
"use strict";
function PixelEditor(parentDiv:HTMLElement, fmt, palette, initialData, thumbnails?) {
import { hex } from "../util";
export function PixelEditor(parentDiv:HTMLElement, fmt, palette, initialData, thumbnails?) {
var self = this;
var width = fmt.w;
var height = fmt.h;
@ -232,7 +234,7 @@ function convertToHexStatements(s) {
});
}
function parseHexBytes(s) {
export function parseHexBytes(s) {
var arr = [];
var m;
while (m = pixel_re.exec(s)) {
@ -248,7 +250,7 @@ function parseHexBytes(s) {
return arr;
}
function replaceHexBytes(s, bytes) {
export function replaceHexBytes(s, bytes) {
var result = "";
var m;
var li = 0;
@ -384,20 +386,20 @@ function convertPaletteBytes(arr,r0,r1,g0,g1,b0,b1) {
return result;
}
var palette;
var paletteSets;
var paletteSetIndex=0;
var currentPixelEditor;
var parentSource;
var parentOrigin;
var allimages;
var currentFormat;
var currentByteStr;
var currentPaletteStr;
var currentPaletteFmt;
var allthumbs;
export var palette;
export var paletteSets;
export var paletteSetIndex=0;
export var currentPixelEditor;
export var parentSource;
export var parentOrigin;
export var allimages;
export var currentFormat;
export var currentByteStr;
export var currentPaletteStr;
export var currentPaletteFmt;
export var allthumbs;
function pixelEditorDecodeMessage(e) {
export function pixelEditorDecodeMessage(e) {
parentSource = e.source;
parentOrigin = e.origin;
currentFormat = e.data.fmt;

View File

@ -1,5 +1,11 @@
"use strict";
import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502 } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM } from "../emu";
import { hex, lzgmini } from "../util";
declare var jt; // 6502
var APPLE2_PRESETS = [
{id:'sieve.c', name:'Sieve'},
{id:'mandel.c', name:'Mandelbrot'},
@ -19,6 +25,8 @@ var GR_HIRES = 8;
var Apple2Platform = function(mainElement) {
var self = this;
this.__proto__ = new (Base6502Platform as any)();
var cpuFrequency = 1023000;
var cpuCyclesPerLine = 65;
var cpu, ram, bus;
@ -39,9 +47,7 @@ var Apple2Platform = function(mainElement) {
// value to add when reading & writing each of these banks
// bank 1 is E000-FFFF, bank 2 is D000-DFFF
var bank2rdoffset=0, bank2wroffset=0;
this.__proto__ = new Base6502Platform();
this.getPresets = function() {
return APPLE2_PRESETS;
}

View File

@ -1,5 +1,8 @@
"use strict";
import { Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, getToolForFilename_6502 } from "../baseplatform";
import { PLATFORMS } from "../emu";
var Atari8_PRESETS = [
{id:'hello.a', name:'Hello World (ASM)'},
{id:'hellopm.a', name:'Hello Sprites (ASM)'},

View File

@ -1,5 +1,8 @@
"use strict";
import { Platform, BaseZ80Platform, BaseMAMEPlatform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes } from "../emu";
var BASEZ80_PRESETS = [
{id:'simple1.c', name:'Multiply by 2'},
{id:'simple2.c', name:'Divide by 4'},
@ -11,7 +14,7 @@ var BASEZ80_PRESETS = [
var Base_Z80Platform = function(mainElement) {
var self = this;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom, timer;
@ -22,13 +25,13 @@ var Base_Z80Platform = function(mainElement) {
this.start = function() {
ram = new RAM(0x8000);
membus = {
read: new AddressDecoder([
[0x0000, 0x7fff, 0x7fff, function(a) { return rom ? rom[a] : null; }],
[0x8000, 0xffff, 0x7fff, function(a) { return ram.mem[a]; }],
]),
write: new AddressDecoder([
[0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }],
]),
read: newAddressDecoder([
[0x0000, 0x7fff, 0x7fff, function(a) { return rom ? rom[a] : null; }],
[0x8000, 0xffff, 0x7fff, function(a) { return ram.mem[a]; }],
]),
write: newAddressDecoder([
[0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
};
this.readAddress = membus.read;

View File

@ -1,42 +0,0 @@
"use strict";
var C64_PRESETS = [
{id:'hello.a', name:'Hello World (ASM)'},
{id:'hellopm.a', name:'Hello Sprites (ASM)'},
];
/// MAME support
var C64MAMEPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseMAMEPlatform();
this.loadROM = function(title, data) {
this.loadROMFile(data);
this.loadRegion(":basic", data);
}
this.getPresets = function() { return C64_PRESETS; }
this.getToolForFilename = getToolForFilename_6502;
this.getDefaultExtension = function() { return ".c"; };
this.start = function() {
self.startModule(mainElement, {
jsfile:'mamec64.js',
biosfile:'c64.zip', // TODO: load multiple files
//cfgfile:'atari5200.cfg',
driver:'c64',
width:336*2,
height:225*2,
romfn:'/emulator/cart.rom',
romsize:0x2000,
preInit:function(_self) {
},
});
}
}
///
PLATFORMS['c64'] = C64MAMEPlatform;

View File

@ -1,230 +0,0 @@
"use strict";
// http://www.colecovision.eu/ColecoVision/development/tutorial1.shtml
// http://www.colecovision.eu/ColecoVision/development/libcv.shtml
// http://www.kernelcrash.com/blog/recreating-the-colecovision/2016/01/27/
// http://www.atarihq.com/danb/files/CV-Tech.txt
// http://www.atarihq.com/danb/files/CV-Sound.txt
// http://www.colecoboxart.com/faq/FAQ05.htm
// http://www.theadamresource.com/manuals/technical/Jeffcoleco.html
// http://bifi.msxnet.org/msxnet//tech/tms9918a.txt
// http://www.colecovision.dk/tools.htm?refreshed
// http://www.theadamresource.com/manuals/technical/ColecoVision%20Coding%20Guide.pdf
// http://www.unige.ch/medecine/nouspikel/ti99/tms9918a.htm
var ColecoVision_PRESETS = [
{id:'text.c', name:'Text Mode'},
{id:'hello.c', name:'Scrolling Text'},
{id:'text32.c', name:'32-Column Text'},
{id:'stars.c', name:'Scrolling Starfield'},
{id:'cursorsmooth.c', name:'Moving Cursor'},
{id:'simplemusic.c', name:'Simple Music'},
{id:'musicplayer.c', name:'Multivoice Music'},
{id:'mode2bitmap.c', name:'Mode 2 Bitmap'},
{id:'lines.c', name:'Mode 2 Lines'},
{id:'multicolor.c', name:'Multicolor Mode'},
{id:'siegegame.c', name:'Siege Game'},
{id:'shoot.c', name:'Solarian Game'},
{id:'platform.c', name:'Platform Game'},
];
// doesn't work, use MAME
var ColecoVisionPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseZ80Platform();
var cpu, ram, membus, iobus, rom, bios;
var video, audio, psg, timer, pixels;
var inputs = [0xff, 0xff, 0xff, 0xff^0x8]; // most things active low
var palbank = 0;
var XTAL = 3579545*2;
var totalScanlinesPerFrame = 262.5;
var visibleScanlinesPerFrame = 192;
var visiblePixelsPerScanline = 256;
var cpuFrequency = XTAL/2;
var hsyncFrequency = XTAL*3/(2*322);
var vsyncFrequency = hsyncFrequency/totalScanlinesPerFrame;
var cpuCyclesPerLine = cpuFrequency/hsyncFrequency;
var framestats;
function RGB(r,g,b) {
return (r << 0) + (g << 8) + (b << 16) | 0xff000000;
}
var palette = [
RGB(0x00,0x00,0x00),RGB(0x00,0x00,0x00),RGB(0x47,0xB7,0x3B),RGB(0x7C,0xCF,0x6F),
RGB(0x5D,0x4E,0xFF),RGB(0x80,0x72,0xFF),RGB(0xB6,0x62,0x47),RGB(0x5D,0xC8,0xED),
RGB(0xD7,0x6B,0x48),RGB(0xFB,0x8F,0x6C),RGB(0xC3,0xCD,0x41),RGB(0xD3,0xDA,0x76),
RGB(0x3E,0x9F,0x2F),RGB(0xB6,0x64,0xC7),RGB(0xCC,0xCC,0xCC),RGB(0xFF,0xFF,0xFF)
];
// videoram 0xc000-0xc3ff
// RAM 0xc400-0xc7ff
// charram 0xc800-0xcfff
function drawScanline(pixels, sl) {
if (sl >= visibleScanlinesPerFrame) return;
var pixofs = sl * 256;
var outi = pixofs; // starting output pixel in frame buffer
var vramofs = (sl>>3)<<5; // offset in VRAM
var yy = sl & 7; // y offset within tile
for (var xx=0; xx<32; xx++) {
var code = ram.mem[vramofs+xx];
var data = ram.mem[0x800 + (code<<3) + yy];
var col = (code>>5) + (palbank<<3);
var color1 = palette[col&15];
var color2 = 0;
for (var i=0; i<8; i++) {
var bm = 128>>i;
pixels[outi] = (data&bm) ? color2 : color1;
outi++;
}
}
}
var CARNIVAL_KEYCODE_MAP = makeKeycodeMap([
[Keys.VK_SPACE, 2, -0x20],
[Keys.VK_SHIFT, 2, -0x40],
[Keys.VK_LEFT, 1, -0x10],
[Keys.VK_RIGHT, 1, -0x20],
[Keys.VK_UP, 1, -0x40],
[Keys.VK_DOWN, 1, -0x80],
[Keys.VK_1, 2, -0x10],
[Keys.VK_2, 3, -0x20],
[Keys.VK_5, 3, 0x8],
]);
this.getPresets = function() {
return ColecoVision_PRESETS;
}
this.start = function() {
ram = new RAM(0x400);
//bios = COLECO_BIOS;
membus = {
read: new AddressDecoder([
[0x0000, 0x1fff, 0x1fff, function(a) { return bios ? bios[a] : null; }],
[0x6000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }],
]),
write: new AddressDecoder([
[0x6000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
};
this.readAddress = membus.read;
iobus = {
read: function(addr) {
return inputs[addr&3];
},
write: function(addr, val) {
console.log(addr,val);
}
};
cpu = this.newCPU(membus, iobus);
video = new RasterVideo(mainElement,visiblePixelsPerScanline,visibleScanlinesPerFrame);
audio = new MasterAudio();
psg = new AY38910_Audio(audio);
//var speech = new VotraxSpeech();
//audio.master.addChannel(speech);
video.create();
var idata = video.getFrameData();
setKeyboardFromMap(video, inputs, CARNIVAL_KEYCODE_MAP);
pixels = video.getFrameData();
timer = new AnimationTimer(60, function() {
if (!self.isRunning())
return;
var debugCond = self.getDebugCallback();
var targetTstates = cpu.getTstates();
for (var sl=0; sl<visibleScanlinesPerFrame; sl++) {
drawScanline(pixels, sl);
targetTstates += cpuCyclesPerLine;
self.runCPU(cpu, targetTstates - cpu.getTstates());
}
video.updateFrame();
self.restartDebugState();
});
}
this.loadROM = function(title, data) {
rom = padBytes(data, 0x8000);
self.reset();
}
this.loadState = function(state) {
cpu.loadState(state.c);
ram.mem.set(state.b);
inputs[0] = state.in0;
inputs[1] = state.in1;
inputs[2] = state.in2;
inputs[3] = state.in3;
palbank = state.pb;
}
this.saveState = function() {
return {
c:self.getCPUState(),
b:ram.mem.slice(0),
in0:inputs[0],
in1:inputs[1],
in2:inputs[2],
in3:inputs[3],
pb:palbank,
};
}
this.getCPUState = function() {
return cpu.saveState();
}
this.isRunning = function() {
return timer && timer.isRunning();
}
this.pause = function() {
timer.stop();
audio.stop();
}
this.resume = function() {
timer.start();
audio.start();
}
this.reset = function() {
cpu.reset();
psg.reset();
if (!this.getDebugCallback()) cpu.setTstates(0); // TODO?
}
}
/// MAME support
var ColecoVisionMAMEPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseMAMEPlatform();
//
this.start = function() {
self.startModule(mainElement, {
jsfile:'mamecoleco.js',
cfgfile:'coleco.cfg',
biosfile:'coleco/313 10031-4005 73108a.u2',
driver:'coleco',
width:280*2,
height:216*2,
romfn:'/emulator/cart.rom',
romsize:0x8000,
preInit:function(_self) {
},
});
}
this.loadROM = function(title, data) {
this.loadROMFile(data);
this.loadRegion(":coleco_cart:rom", data);
}
this.getPresets = function() { return ColecoVision_PRESETS; }
this.getToolForFilename = getToolForFilename_z80;
this.getDefaultExtension = function() { return ".c"; };
}
///
PLATFORMS['coleco'] = ColecoVisionMAMEPlatform;

69
src/platform/coleco.ts Normal file
View File

@ -0,0 +1,69 @@
"use strict";
import { Platform, BaseMAMEPlatform, getToolForFilename_z80 } from "../baseplatform";
import { PLATFORMS } from "../emu";
// http://www.colecovision.eu/ColecoVision/development/tutorial1.shtml
// http://www.colecovision.eu/ColecoVision/development/libcv.shtml
// http://www.kernelcrash.com/blog/recreating-the-colecovision/2016/01/27/
// http://www.atarihq.com/danb/files/CV-Tech.txt
// http://www.atarihq.com/danb/files/CV-Sound.txt
// http://www.colecoboxart.com/faq/FAQ05.htm
// http://www.theadamresource.com/manuals/technical/Jeffcoleco.html
// http://bifi.msxnet.org/msxnet//tech/tms9918a.txt
// http://www.colecovision.dk/tools.htm?refreshed
// http://www.theadamresource.com/manuals/technical/ColecoVision%20Coding%20Guide.pdf
// http://www.unige.ch/medecine/nouspikel/ti99/tms9918a.htm
var ColecoVision_PRESETS = [
{id:'text.c', name:'Text Mode'},
{id:'hello.c', name:'Scrolling Text'},
{id:'text32.c', name:'32-Column Text'},
{id:'stars.c', name:'Scrolling Starfield'},
{id:'cursorsmooth.c', name:'Moving Cursor'},
{id:'simplemusic.c', name:'Simple Music'},
{id:'musicplayer.c', name:'Multivoice Music'},
{id:'mode2bitmap.c', name:'Mode 2 Bitmap'},
{id:'lines.c', name:'Mode 2 Lines'},
{id:'multicolor.c', name:'Multicolor Mode'},
{id:'siegegame.c', name:'Siege Game'},
{id:'shoot.c', name:'Solarian Game'},
{id:'platform.c', name:'Platform Game'},
];
/// MAME support
var ColecoVisionMAMEPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseMAMEPlatform();
//
this.start = function() {
self.startModule(mainElement, {
jsfile:'mamecoleco.js',
cfgfile:'coleco.cfg',
biosfile:'coleco/313 10031-4005 73108a.u2',
driver:'coleco',
width:280*2,
height:216*2,
romfn:'/emulator/cart.rom',
romsize:0x8000,
preInit:function(_self) {
},
});
}
this.loadROM = function(title, data) {
this.loadROMFile(data);
this.loadRegion(":coleco_cart:rom", data);
}
this.getPresets = function() { return ColecoVision_PRESETS; }
this.getToolForFilename = getToolForFilename_z80;
this.getDefaultExtension = function() { return ".c"; };
}
///
PLATFORMS['coleco'] = ColecoVisionMAMEPlatform;

View File

@ -1,5 +1,9 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
var GALAXIAN_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'},
{id:'shoot2.c', name:'Solarian Game'},
@ -35,7 +39,7 @@ var SCRAMBLE_KEYCODE_MAP = makeKeycodeMap([
var GalaxianPlatform = function(mainElement, options) {
var self = this;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
options = options || {};
var romSize = options.romSize || 0x4000;
@ -45,7 +49,9 @@ var GalaxianPlatform = function(mainElement, options) {
var missileWidth = options.missileWidth || 4;
var missileOffset = options.missileOffset || 0;
var cpu, ram, vram, oram, membus, iobus, rom, palette, outlatches;
var cpu;
var ram, vram, oram : RAM;
var membus, iobus, rom, palette, outlatches;
var video, audio, timer, pixels;
var psg1, psg2;
var inputs;
@ -96,7 +102,7 @@ var GalaxianPlatform = function(mainElement, options) {
for (var sprnum=7; sprnum>=0; sprnum--) {
var base = (sprnum<<2) + 0x40;
var base0 = oram.mem[base];
var sy = 240 - (base0 - (sprnum<3)); // the first three sprites match against y-1
var sy = 240 - (base0 - ((sprnum<3)?1:0)); // the first three sprites match against y-1
var yy = (sl - sy);
if (yy >= 0 && yy < 16) {
var sx = oram.mem[base+3] + 1; // +1 pixel offset from tiles
@ -133,7 +139,7 @@ var GalaxianPlatform = function(mainElement, options) {
var missile = 0xff;
for (var which=0; which<8; which++) {
var sy = oram.mem[0x60 + (which<<2)+1];
if (((sy + sl - (which<3))&0xff) == 0xff) {
if (((sy + sl - ((which<3)?1:0))&0xff) == 0xff) {
if (which != 7)
shell = which;
else
@ -202,7 +208,7 @@ var GalaxianPlatform = function(mainElement, options) {
if (options.scramble) {
inputs = [0xff,0xfc,0xf1];
membus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x47ff, 0x7ff, function(a) { return ram.mem[a]; }],
// [0x4800, 0x4fff, 0x3ff, function(a) { return vram.mem[a]; }],
@ -220,7 +226,7 @@ var GalaxianPlatform = function(mainElement, options) {
[0x9212, 0x9212, 0, function(a) { return m_protection_result; }], // scramble (protection)
//[0, 0xffff, 0, function(a) { console.log(hex(a)); return 0; }]
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x4000, 0x47ff, 0x7ff, function(a,v) { ram.mem[a] = v; }],
[0x4800, 0x4fff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
[0x5000, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],
@ -240,7 +246,7 @@ var GalaxianPlatform = function(mainElement, options) {
} else {
inputs = [0xe,0x8,0x0];
membus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x47ff, 0x3ff, function(a) { return ram.mem[a]; }],
[0x5000, 0x57ff, 0x3ff, function(a) { return vram.mem[a]; }],
@ -250,7 +256,7 @@ var GalaxianPlatform = function(mainElement, options) {
[0x7000, 0x7000, 0, function(a) { return inputs[2]; }],
[0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x4000, 0x47ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
[0x5000, 0x57ff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
[0x5800, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],

View File

@ -1,5 +1,9 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
// http://www.computerarcheology.com/Arcade/
var MW8080BW_PRESETS = [
@ -10,7 +14,7 @@ var MW8080BW_PRESETS = [
var Midway8080BWPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom;
var probe;
@ -45,11 +49,11 @@ var Midway8080BWPlatform = function(mainElement) {
ram = new RAM(0x2000);
//displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2));
membus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0000, 0x1fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
[0x2000, 0x3fff, 0x1fff, function(a) { return ram.mem[a]; }],
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x2000, 0x23ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
[0x2400, 0x3fff, 0x1fff, function(a,v) {
ram.mem[a] = v;

View File

@ -1,5 +1,11 @@
"use strict";
import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, cpuStateToLongString_6502, getToolForFilename_6502 } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM, dumpStackToString } from "../emu";
import { hex, lpad, lzgmini } from "../util";
declare var jsnes : any;
var JSNES_PRESETS = [
{id:'ex0.asm', name:'Initialization (ASM)'},
{id:'ex1.asm', name:'Scrolling Demo (ASM)'},
@ -56,7 +62,7 @@ var JSNES_KEYCODE_MAP = makeKeycodeMap([
var JSNESPlatform = function(mainElement) {
var self = this;
this.__proto__ = new Base6502Platform();
this.__proto__ = new (Base6502Platform as any)();
this.debugPCDelta = 1;
var nes;
@ -147,7 +153,7 @@ var JSNESPlatform = function(mainElement) {
this.runToVsync = function() {
var frame0 = frameindex;
platform.runEval(function(c) { return frameindex>frame0; });
this.runEval(function(c) { return frameindex>frame0; });
}
this.getCPUState = function() {
@ -160,7 +166,7 @@ var JSNESPlatform = function(mainElement) {
var s = nes.toJSON();
s.c = s.cpu;
this.copy6502REGvars(s.c);
s.cpu.mem = s.cpu.mem.slice(0);
s.b = s.cpu.mem = s.cpu.mem.slice(0);
s.ppu.vramMem = s.ppu.vramMem.slice(0);
s.ppu.spriteMem = s.ppu.spriteMem.slice(0);
return s;
@ -197,13 +203,14 @@ var JSNESPlatform = function(mainElement) {
}
this.getDebugCategories = function() {
return ['CPU','ZPRAM','PPU'];
return ['CPU','ZPRAM','Stack','PPU'];
}
this.getDebugInfo = function(category, state) {
switch (category) {
case 'CPU': return cpuStateToLongString_6502(state.c);
case 'ZPRAM': return dumpRAM(state.cpu.mem, 0, 0x100);
case 'PPU': return this.ppuStateToLongString(state.ppu, state.cpu.mem);
case 'CPU': return cpuStateToLongString_6502(state.c);
case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100);
case 'Stack': return dumpStackToString(state.b, 0x100, 0x1ff, 0x100+state.c.SP);
case 'PPU': return this.ppuStateToLongString(state.ppu, state.b);
}
}
this.ppuStateToLongString = function(ppu, mem) {

View File

@ -1,10 +1,15 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
var KONAMISOUND_PRESETS = [
];
var KonamiSoundPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, rom, membus, iobus;
var audio, master;
@ -25,11 +30,11 @@ var KonamiSoundPlatform = function(mainElement) {
this.start = function() {
ram = new RAM(0x400);
membus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x5fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x4000, 0x5fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },

View File

@ -1,5 +1,9 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
var WILLIAMS_SOUND_PRESETS = [
{id:'swave.c', name:'Wavetable Synth'},
];
@ -30,7 +34,7 @@ var WILLIAMS_SOUND_PRESETS = [
var WilliamsSoundPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, rom, membus, iobus;
var audio, master;
@ -60,11 +64,11 @@ var WilliamsSoundPlatform = function(mainElement) {
this.start = function() {
ram = new RAM(0x400);
membus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },

View File

@ -1,5 +1,13 @@
"use strict";
import { Platform, cpuStateToLongString_6502, BaseMAMEPlatform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, dumpRAM } from "../emu";
import { hex, lpad, tobin, byte2signed } from "../util";
declare var platform : Platform; // global platform object
declare var Javatari : any;
declare var jt : any; // 6502
var VCS_PRESETS = [
{id:'examples/hello', chapter:4, name:'Hello 6502 and TIA'},
{id:'examples/vsync', chapter:5, name:'Painting on the CRT', title:'Color Bars'},
@ -100,7 +108,7 @@ var VCSPlatform = function() {
}
*/
this.readAddress = function(addr) {
return current_output[addr & 0xfff]; // TODO: use bus to read
return this.current_output[addr & 0xfff]; // TODO: use bus to read
}
this.runUntilReturn = function() {
var depth = 1;
@ -215,7 +223,7 @@ function getClockCountsAtPC(pc) {
return meta; // minCycles, maxCycles
}
function _traceInstructions(pc, minclocks, maxclocks, subaddr, constraints) {
function _traceInstructions(pc:number, minclocks:number, maxclocks:number, subaddr:number, constraints) {
//console.log("trace", hex(pc), minclocks, maxclocks);
if (!minclocks) minclocks = 0;
if (!maxclocks) maxclocks = 0;
@ -274,7 +282,7 @@ function _traceInstructions(pc, minclocks, maxclocks, subaddr, constraints) {
pc = addr; // TODO: make sure in ROM space
break;
case 0x60: // RTS
if (subaddr) {
if (subaddr) { // TODO: 0 doesn't work
// TODO: combine with previous result
var result = jsrresult[subaddr];
if (!result) {
@ -325,7 +333,7 @@ function showLoopTimingForPC(pc, sourcefile, ed) {
pc2maxclocks = {};
jsrresult = {};
// recurse through all traces
_traceInstructions(pc | platform.getOriginPC(), MAX_CLOCKS, MAX_CLOCKS);
_traceInstructions(pc | platform.getOriginPC(), MAX_CLOCKS, MAX_CLOCKS, 0, {});
ed.editor.clearGutter("gutter-bytes");
// show the lines
for (var line in sourcefile.line2offset) {

View File

@ -1,5 +1,9 @@
"use strict";
import { Platform, BaseZ80Platform, Base6502Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, VectorVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
// http://www.computerarcheology.com/Arcade/Asteroids/DVG.html
// http://arcarc.xmission.com/Tech/neilw_xy.txt
@ -58,7 +62,7 @@ var AtariVectorPlatform = function(mainElement) {
var switches = new RAM(16).mem;
var nmicount = cpuCyclesPerNMI;
this.__proto__ = new Base6502Platform();
this.__proto__ = new (Base6502Platform as any)();
this.getPresets = function() {
return VECTOR_PRESETS;
@ -72,7 +76,7 @@ var AtariVectorPlatform = function(mainElement) {
// bus
bus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0, 0x3ff, 0x3ff, function(a) { return cpuram.mem[a]; }],
[0x2001, 0x2001, 0, function(a) { return ((clock/500) & 1) ? 0xff : 0x00; }],
[0x2000, 0x2007, 0x7, function(a) { return switches[a]; }],
@ -82,7 +86,7 @@ var AtariVectorPlatform = function(mainElement) {
[0x6800, 0x7fff, 0, function(a) { return rom[a - 0x6800]; }],
], {gmask:0x7fff}),
write: new AddressDecoder([
write: newAddressDecoder([
[0x0, 0x3ff, 0x3ff, function(a,v) { cpuram.mem[a] = v; }],
[0x3000, 0x3000, 0, function(a,v) { dvg.runUntilHalt(0); }],
// TODO: draw asynchronous or allow poll of HALT ($2002)
@ -183,7 +187,7 @@ var AtariColorVectorPlatform = function(mainElement) {
var nmicount = cpuCyclesPerNMI;
var earom_offset, earom_data;
this.__proto__ = new Base6502Platform();
this.__proto__ = new (Base6502Platform as any)();
this.getPresets = function() {
return VECTOR_PRESETS;
@ -201,7 +205,7 @@ var AtariColorVectorPlatform = function(mainElement) {
// bus
bus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0, 0x7ff, 0x7ff, function(a) { return cpuram.mem[a]; }],
[0x2000, 0x27ff, 0x7ff, function(a) { return dvgram.mem[a]; }],
[0x2800, 0x5fff, 0x7fff, function(a) { return vecrom[a - 0x2800]; }],
@ -217,7 +221,7 @@ var AtariColorVectorPlatform = function(mainElement) {
[0x9000, 0xffff, 0xffff, function(a) { return rom[a - 0x9000]; }],
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x0, 0x7ff, 0x7ff, function(a,v) { cpuram.mem[a] = v; }],
[0x2000, 0x27ff, 0x7ff, function(a,v) { dvgram.mem[a] = v; }],
[0x6000, 0x67ff, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }],
@ -324,7 +328,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
var switches = new RAM(16).mem;
var mathram = new RAM(16).mem;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
this.getPresets = function() {
return VECTOR_PRESETS;
@ -351,7 +355,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
// bus
bus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0, 0x7fff, 0, function(a) { return rom[a]; }],
[0x8000, 0x800f, 0xf, function(a) { return switches[a]; }],
[0x8100, 0x810f, 0xf, function(a) { return mathram[a]; } ],
@ -359,7 +363,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
[0xe000, 0xffff, 0x1fff, function(a) { return cpuram.mem[a]; }],
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x8000, 0x800f, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }],
[0x8010, 0x801f, 0xf, function(a,v) { audio.pokey2.setRegister(a, v); }],
[0x8100, 0x810e, 0xf, function(a,v) { mathram[a] = v; } ],

View File

@ -1,5 +1,8 @@
"use strict";
import { Platform } from "../baseplatform";
import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
var VERILOG_PRESETS = [
{id:'clock_divider.v', name:'Clock Divider'},
{id:'hvsync_generator.v', name:'Video Sync Generator'},
@ -53,12 +56,14 @@ var VERILOG_KEYCODE_MAP = makeKeycodeMap([
var vl_finished = false;
var vl_stopped = false;
var VL_UL = function(x) { return x|0; }
var VL_ULL = function(x) { return x|0; }
var VL_TIME_Q = function() { return (new Date().getTime())|0; }
// TODO: these have to be global
var VL_UL = this.VL_UL = function(x) { return x|0; }
var VL_ULL = this.VL_ULL = function(x) { return x|0; }
var VL_TIME_Q = this.VL_TIME_Q = function() { return (new Date().getTime())|0; }
/// Return true if data[bit] set
var VL_BITISSET_I = this.VL_BITISSET_I = function(data,bit) { return (data & (VL_UL(1)<<VL_BITBIT_I(bit))); }
var VL_BITISSET_I = this.VL_BITISSET_I = function(data,bit) { return (data & (VL_UL(1)<<VL_UL(bit))); }
var VL_EXTENDSIGN_I = this.VL_EXTENDSIGN_I = function(lbits, lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
@ -73,16 +78,16 @@ var vl_stopped = false;
var VL_NEGATE_I = this.VL_NEGATE_I = function(x) { return -x; }
var VL_LTS_III = this.VL_LTS_III = function(x,lbits,y,lhs,rhs) {
return 0 | (VL_EXTENDS_II(x,lbits,lhs) < VL_EXTENDS_II(x,lbits,rhs)); }
return (VL_EXTENDS_II(x,lbits,lhs) < VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_GTS_III = this.VL_GTS_III = function(x,lbits,y,lhs,rhs) {
return 0 | (VL_EXTENDS_II(x,lbits,lhs) > VL_EXTENDS_II(x,lbits,rhs)); }
return (VL_EXTENDS_II(x,lbits,lhs) > VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_LTES_III = this.VL_LTES_III = function(x,lbits,y,lhs,rhs) {
return 0 | (VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs)); }
return (VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_GTES_III = this.VL_GTES_III = function(x,lbits,y,lhs,rhs) {
return 0 | (VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs)); }
return (VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
var VL_MODDIV_III = this.VL_MODDIV_III = function(lbits,lhs,rhs) {
return (((rhs)==0)?0:(lhs)%(rhs)); }
@ -561,13 +566,13 @@ var VerilogPlatform = function(mainElement, options) {
vcanvas.mousedown(function(e) {
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
mouse_pressed = true;
if (e.target.setCapture) e.target.setCapture(); // TODO: pointer capture
//if (e.target.setCapture) e.target.setCapture(); // TODO: pointer capture
dirty = true;
refreshFrame();
});
vcanvas.mouseup(function(e) {
mouse_pressed = false;
if (e.target.setCapture) e.target.releaseCapture(); // TODO: pointer capture
//if (e.target.setCapture) e.target.releaseCapture(); // TODO: pointer capture
dirty = true;
refreshFrame();
});
@ -842,17 +847,6 @@ var VerilogPlatform = function(mainElement, options) {
};
function traceTiming() {
// TODO: merge with main setCode(text)
var text = editor.getValue();
worker.postMessage({
code:text,
dependencies:loadFileDependencies(text),
platform:platform_id,
tool:'yosys'
});
}
////////////////
PLATFORMS['verilog'] = VerilogPlatform;

View File

@ -1,5 +1,9 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
var VICDUAL_PRESETS = [
{id:'minimal.c', name:'Minimal Example'},
{id:'hello.c', name:'Hello World'},
@ -12,7 +16,7 @@ var VICDUAL_PRESETS = [
var VicDualPlatform = function(mainElement) {
var self = this;
this.__proto__ = new BaseZ80Platform();
this.__proto__ = new (BaseZ80Platform as any)();
var cpu, ram, membus, iobus, rom;
var video, audio, psg, timer, pixels;
@ -99,11 +103,11 @@ var VicDualPlatform = function(mainElement) {
this.start = function() {
ram = new RAM(0x1000);
membus = {
read: new AddressDecoder([
read: newAddressDecoder([
[0x0000, 0x7fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x8000, 0xffff, 0x0fff, function(a) { return ram.mem[a]; }],
]),
write: new AddressDecoder([
write: newAddressDecoder([
[0x8000, 0xffff, 0x0fff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },

View File

@ -1,5 +1,9 @@
"use strict";
import { Platform, BaseZ80Platform, Base6809Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
var WILLIAMS_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'},
{id:'sprites.c', name:'Sprite Test'},
@ -81,14 +85,14 @@ var WilliamsPlatform = function(mainElement, proto) {
// Defender
var ioread_defender = new AddressDecoder([
var ioread_defender = newAddressDecoder([
[0x400, 0x5ff, 0x1ff, function(a) { return nvram.mem[a]; }],
[0x800, 0x800, 0, function(a) { return video_counter; }],
[0xc00, 0xc07, 0x7, function(a) { return pia6821[a]; }],
[0x0, 0xfff, 0, function(a) { /*console.log('ioread',hex(a));*/ }],
]);
var iowrite_defender = new AddressDecoder([
var iowrite_defender = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
[0x3fc, 0x3ff, 0, function(a,v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
[0x400, 0x5ff, 0x1ff, function(a,v) { nvram.mem[a] = v; }],
@ -96,7 +100,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
]);
var memread_defender = new AddressDecoder([
var memread_defender = newAddressDecoder([
[0x0000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, function(a) {
switch (banksel) {
@ -111,7 +115,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0xd000] : 0; }],
]);
var memwrite_defender = new AddressDecoder([
var memwrite_defender = newAddressDecoder([
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_defender],
@ -121,7 +125,7 @@ var WilliamsPlatform = function(mainElement, proto) {
// Robotron, Joust, Bubbles, Stargate
var ioread_williams = new AddressDecoder([
var ioread_williams = newAddressDecoder([
[0x804, 0x807, 0x3, function(a) { return pia6821[a]; }],
[0x80c, 0x80f, 0x3, function(a) { return pia6821[a+4]; }],
[0xb00, 0xbff, 0, function(a) { return video_counter; }],
@ -129,7 +133,7 @@ var WilliamsPlatform = function(mainElement, proto) {
[0x0, 0xfff, 0, function(a) { /* console.log('ioread',hex(a)); */ }],
]);
var iowrite_williams = new AddressDecoder([
var iowrite_williams = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
[0x80c, 0x80c, 0xf, function(a,v) { if (worker) worker.postMessage({command:v}); }],
//[0x804, 0x807, 0x3, function(a,v) { console.log('iowrite',a); }], // TODO: sound
@ -141,14 +145,14 @@ var WilliamsPlatform = function(mainElement, proto) {
//[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
]);
var memread_williams = new AddressDecoder([
var memread_williams = newAddressDecoder([
[0x0000, 0x8fff, 0xffff, function(a) { return banksel ? rom[a] : ram.mem[a]; }],
[0x9000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, ioread_williams],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0x4000] : 0; }],
]);
var memwrite_williams = new AddressDecoder([
var memwrite_williams = newAddressDecoder([
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_williams],
@ -166,7 +170,7 @@ var WilliamsPlatform = function(mainElement, proto) {
}
}
function write_display_byte(a,v) {
function write_display_byte(a:number,v:number) {
ram.mem[a] = v;
drawDisplayByte(a, v);
if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter
@ -228,7 +232,7 @@ var WilliamsPlatform = function(mainElement, proto) {
else
sstart += syinc;
}
return w * h * (2 + ((flags&0x4)!=0)); // # of memory accesses
return w * h * (2 + ((flags&0x4)>>2)); // # of memory accesses
}
function blit_pixel(dstaddr, srcdata, flags) {

View File

@ -1,6 +1,7 @@
"use strict";
import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, WorkerResult } from "./workertypes";
import { getFilenameForPath, getFilenamePrefix } from "./util";
type BuildResultCallback = (result:WorkerResult) => void;
type BuildStatusCallback = (busy:boolean) => void;

View File

@ -110,7 +110,7 @@ function copyFromOldStorageFormat(platformid:string, newstore, callback:()=>void
migrateNext(); // start the conversion
}
function createNewPersistentStore(platformid:string, callback:()=>void) {
export function createNewPersistentStore(platformid:string, callback:()=>void) {
var store = localforage.createInstance({
name: "__" + platformid,
version: 2.0

View File

@ -1,5 +1,7 @@
"use strict";
import { getFilenameForPath, getFilenamePrefix, highlightDifferences, invertMap } from "./util";
// 8bitworkshop IDE user interface
import $ = require("jquery");
@ -8,14 +10,13 @@ import { CodeProject } from "./project";
import { WorkerResult, SourceFile } from "./workertypes";
import { ProjectWindows } from "./windows";
import { Platform, Preset } from "./baseplatform";
import { PLATFORMS } from "./emu";
import * as Views from "./views";
// external libs (TODO)
declare var Octokat, ga, Tour, GIF, saveAs;
declare function createNewPersistentStore(platform_id : string);
declare function showLoopTimingForPC(pc:number, sourcefile:SourceFile, wnd:Views.ProjectView);
// loaded by platform js file
declare var PLATFORMS;
// make sure VCS doesn't start
if (window['Javatari']) window['Javatari'].AUTO_START = false;
@ -926,7 +927,7 @@ function startUI(loadplatform : boolean) {
} else {
// load and start platform object
if (loadplatform) {
var scriptfn = 'src/platform/' + platform_id.split(/[.-]/)[0] + '.js';
var scriptfn = 'gen/platform/' + platform_id.split(/[.-]/)[0] + '.js';
var script = document.createElement('script');
script.onload = function() {
console.log("loaded platform", platform_id);

View File

@ -1,37 +1,37 @@
"use strict";
function lpad(s:string, n:number):string {
export function lpad(s:string, n:number):string {
s += ''; // convert to string
while (s.length<n) s=" "+s;
return s;
}
function byte2signed(b:number):number {
export function byte2signed(b:number):number {
b &= 0xff;
return (b < 0x80) ? b : -(256-b);
}
function getFilenameForPath(s:string):string {
export function getFilenameForPath(s:string):string {
var toks = s.split('/');
return toks[toks.length-1];
}
function getFilenamePrefix(s:string):string {
export function getFilenamePrefix(s:string):string {
var pos = s.lastIndexOf('.');
return (pos > 0) ? s.substr(0, pos) : s;
}
function hex(v:number, nd?:number) {
export function hex(v:number, nd?:number) {
if (!nd) nd = 2;
return toradix(v,nd,16);
}
function tobin(v:number, nd?:number) {
export function tobin(v:number, nd?:number) {
if (!nd) nd = 8;
return toradix(v,nd,2);
}
function toradix(v:number, nd:number, radix:number) {
export function toradix(v:number, nd:number, radix:number) {
try {
var s = v.toString(radix).toUpperCase();
while (s.length < nd)
@ -42,7 +42,7 @@ function toradix(v:number, nd:number, radix:number) {
}
}
function arrayCompare(a:any[], b:any[]):boolean {
export function arrayCompare(a:any[], b:any[]):boolean {
if (a == null && b == null) return true;
if (a == null) return false;
if (b == null) return false;
@ -53,7 +53,7 @@ function arrayCompare(a:any[], b:any[]):boolean {
return true;
}
function invertMap(m:{}):{} {
export function invertMap(m:{}):{} {
var r = {};
if (m) {
for (var k in m) r[m[k]] = k;
@ -61,7 +61,7 @@ function invertMap(m:{}):{} {
return r;
}
function highlightDifferences(s1:string, s2:string):string {
export function highlightDifferences(s1:string, s2:string):string {
var split1 = s1.split(/(\S+\s+)/).filter(function(n) {return n});
var split2 = s2.split(/(\S+\s+)/).filter(function(n) {return n});
var i = 0;
@ -87,7 +87,7 @@ function highlightDifferences(s1:string, s2:string):string {
return result;
}
function lzgmini() {
export function lzgmini() {
// Constants
var LZG_HEADER_SIZE = 16;
@ -294,14 +294,14 @@ function lzgmini() {
}
}
function stringToByteArray(s:string) : Uint8Array {
export function stringToByteArray(s:string) : Uint8Array {
var a = new Uint8Array(s.length);
for (var i=0; i<s.length; i++)
a[i] = s.charCodeAt(i);
return a;
}
function removeBOM(s:string) {
export function removeBOM(s:string) {
if (s.charCodeAt(0) === 0xFEFF) {
s = s.substr(1);
}

View File

@ -4,6 +4,7 @@ import $ = require("jquery");
import { CodeProject } from "./project";
import { SourceFile, WorkerError } from "./workertypes";
import { Platform } from "./baseplatform";
import { hex } from "./util";
export interface ProjectView {
createDiv(parent:HTMLElement, text:string) : HTMLElement;

View File

@ -745,6 +745,7 @@ function linkLD65(step) {
var aout = FS.readFile("main", {encoding:'binary'});
var mapout = FS.readFile("main.map", {encoding:'utf8'});
var viceout = FS.readFile("main.vice", {encoding:'utf8'});
//var dbgout = FS.readFile("main.dbg", {encoding:'utf8'});
putWorkFile("main", aout);
putWorkFile("main.map", mapout);
putWorkFile("main.vice", viceout);
@ -814,7 +815,7 @@ function compileCC65(step) {
var FS = CC65['FS'];
setupFS(FS, '65-'+step.platform.split('-')[0]);
populateFiles(step, FS);
execMain(step, CC65, ['-T', '-g', /*'-Cl',*/
execMain(step, CC65, ['-T', '-g',
'-Oirs',
'-Cl', // static locals
'-I', '/share/include',

View File

@ -1,12 +1,7 @@
var vm = require('vm');
var fs = require('fs');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
includeInThisContext("gen/emu.js");
var emu = require('gen/emu.js');
function assert(b, msg) {
if (!b) { throw new Error(msg); }
@ -17,12 +12,12 @@ function assertEquals(a,b) {
describe('Address decoder', function() {
it('Should work empty', function() {
var decoder = new AddressDecoder([]);
var decoder = new emu.AddressDecoder([]);
assertEquals(0, decoder(0x1234));
assertEquals(0, decoder(0x123456));
});
it('Should work with 1 range', function() {
var decoder = new AddressDecoder([
var decoder = new emu.AddressDecoder([
[0x1000, 0x7fff, 0xff, function(a) { return a+2; }]
]);
assertEquals(0, decoder(0xfff));

View File

@ -2,21 +2,17 @@
var vm = require('vm');
var fs = require('fs');
var assert = require('assert');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
includeInThisContext("gen/util.js");
includeInThisContext("gen/pixed/pixeleditor.js");
var util = require("gen/util.js");
var pixed = require("gen/pixed/pixeleditor.js");
describe('Pixel editor', function() {
it('Should decode', function() {
var paldatastr = " 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x38, 0x70, 0x7f, 0xf8, ";
var fmt = {w:14,h:16,bpp:4,brev:1};
var datastr = "0x00,0x00,0xef,0xef,0xe0,0x00,0x00, 0x00,0xee,0xee,0xfe,0xee,0xe0,0x00, 0x0e,0xed,0xef,0xef,0xed,0xee,0x00, 0x0e,0xee,0xdd,0xdd,0xde,0xee,0x00, 0x0e,0xee,0xed,0xde,0xee,0xee,0x00, 0x00,0xee,0xee,0xde,0xee,0xe0,0x00, 0x00,0xee,0xee,0xde,0xee,0xe0,0x00, 0x00,0x00,0xed,0xdd,0xe0,0x00,0x0d, 0xdd,0xdd,0xee,0xee,0xed,0xdd,0xd0, 0x0d,0xee,0xee,0xee,0xee,0xee,0x00, 0x0e,0xe0,0xee,0xee,0xe0,0xee,0x00, 0x0e,0xe0,0xee,0xee,0xe0,0xee,0x00, 0x0e,0xe0,0xdd,0xdd,0xd0,0xde,0x00, 0x0d,0x00,0xee,0x0e,0xe0,0x0d,0x00, 0x00,0x00,0xed,0x0e,0xe0,0x00,0x00, 0x00,0x0d,0xdd,0x0d,0xdd,0x00,0x18,";
pixelEditorDecodeMessage({data:{fmt:fmt,bytestr:datastr,palfmt:{pal:332,n:16},palstr:paldatastr}});
assert.deepEqual(palette, [0xff000000,
pixed.pixelEditorDecodeMessage({data:{fmt:fmt,bytestr:datastr,palfmt:{pal:332,n:16},palstr:paldatastr}});
assert.deepEqual(pixed.palette, [0xff000000,
0xff000060,
0xff006020,
0xff404000,
@ -33,8 +29,8 @@ describe('Pixel editor', function() {
0xff40e0e0,
0xffc0e000,
]);
assert.deepEqual(allimages, [[0,0,0,0,14,15,14,15,14,0,0,0,0,0,0,0,14,14,14,14,15,14,14,14,14,0,0,0,0,14,14,13,14,15,14,15,14,13,14,14,0,0,0,14,14,14,13,13,13,13,13,14,14,14,0,0,0,14,14,14,14,13,13,14,14,14,14,14,0,0,0,0,14,14,14,14,13,14,14,14,14,0,0,0,0,0,14,14,14,14,13,14,14,14,14,0,0,0,0,0,0,0,14,13,13,13,14,0,0,0,0,13,13,13,13,13,14,14,14,14,14,13,13,13,13,0,0,13,14,14,14,14,14,14,14,14,14,14,0,0,0,14,14,0,14,14,14,14,14,0,14,14,0,0,0,14,14,0,14,14,14,14,14,0,14,14,0,0,0,14,14,0,13,13,13,13,13,0,13,14,0,0,0,13,0,0,14,14,0,14,14,0,0,13,0,0,0,0,0,0,14,13,0,14,14,0,0,0,0,0,0,0,0,13,13,13,0,13,13,13,0,0,1,8]]);
assert.deepEqual(pixed.allimages, [[0,0,0,0,14,15,14,15,14,0,0,0,0,0,0,0,14,14,14,14,15,14,14,14,14,0,0,0,0,14,14,13,14,15,14,15,14,13,14,14,0,0,0,14,14,14,13,13,13,13,13,14,14,14,0,0,0,14,14,14,14,13,13,14,14,14,14,14,0,0,0,0,14,14,14,14,13,14,14,14,14,0,0,0,0,0,14,14,14,14,13,14,14,14,14,0,0,0,0,0,0,0,14,13,13,13,14,0,0,0,0,13,13,13,13,13,14,14,14,14,14,13,13,13,13,0,0,13,14,14,14,14,14,14,14,14,14,14,0,0,0,14,14,0,14,14,14,14,14,0,14,14,0,0,0,14,14,0,14,14,14,14,14,0,14,14,0,0,0,14,14,0,13,13,13,13,13,0,13,14,0,0,0,13,0,0,14,14,0,14,14,0,0,13,0,0,0,0,0,0,14,13,0,14,14,0,0,0,0,0,0,0,0,13,13,13,0,13,13,13,0,0,1,8]]);
assert.equal(" 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1F, 0x37, 0xE0, 0xA4, 0xFD, 0xFF, 0x38, 0x70, 0x7F, 0xF8, ",
replaceHexBytes(paldatastr, parseHexBytes(paldatastr)));
pixed.replaceHexBytes(paldatastr, pixed.parseHexBytes(paldatastr)));
});
});

View File

@ -3,10 +3,6 @@
var vm = require('vm');
var fs = require('fs');
var assert = require('assert');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
var localItems = {};
var localMods = 0;
@ -44,12 +40,10 @@ global.localStorage = {
}
};
includeInThisContext("localForage/dist/localforage.js");
includeInThisContext("gen/util.js");
includeInThisContext("gen/store.js");
//var sto = require("../../gen/store.js");
//var wtypes = require("../../gen/workertypes.js");
var prj = require("../../gen/project.js");
global.localforage = require("localForage/dist/localforage.js");
var util = require("gen/util.js");
var mstore = require("gen/store.js");
var prj = require("gen/project.js");
var test_platform_id = "_TEST";
@ -59,7 +53,7 @@ describe('Store', function() {
localStorage.setItem('_TEST/test', 'a');
localStorage.setItem('_TEST/local/test', 'b');
assert.equal(2, localMods);
var store = createNewPersistentStore(test_platform_id, function() {
var store = mstore.createNewPersistentStore(test_platform_id, function() {
assert.equal('true', localItems['__migrated__TEST']);
store.getItem('test', function(err, result) {
if (err) done(err);
@ -77,7 +71,7 @@ describe('Store', function() {
it('Should load local project', function(done) {
localStorage.clear();
localStorage.setItem('_TEST/test', 'a');
var store = createNewPersistentStore(test_platform_id, function() {
var store = mstore.createNewPersistentStore(test_platform_id, function() {
var worker = {};
var platform = {};
var project = new prj.CodeProject(worker, test_platform_id, platform, store);
@ -105,7 +99,7 @@ describe('Store', function() {
]
}
];
var store = createNewPersistentStore(test_platform_id);
var store = mstore.createNewPersistentStore(test_platform_id);
var worker = {
postMessage: function(m) { msgs.push(m); },
};
@ -131,7 +125,7 @@ describe('Store', function() {
localStorage.clear();
localItems['__migrated__TEST'] = 'true';
var msgs = [];
var store = createNewPersistentStore(test_platform_id);
var store = mstore.createNewPersistentStore(test_platform_id);
var worker = {
};
var platform = {

View File

@ -2,18 +2,111 @@
var vm = require('vm');
var fs = require('fs');
var assert = require('assert');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
};
includeInThisContext("gen/emu.js");
includeInThisContext("gen/util.js");
includeInThisContext("src/platform/nes.js");
var emu = require("gen/emu.js");
var util = require("gen/util.js");
var nes = require("gen/platform/nes.js");
var NES_CONIO_ROM_LZG = [
76,90,71,0,0,160,16,0,0,11,158,107,131,223,83,1,9,17,21,22,78,69,83,26,2,1,3,0,22,6,120,216,
162,0,134,112,134,114,134,113,134,115,154,169,32,157,0,2,157,0,3,157,0,4,232,208,244,32,134,130,32,85,129,169,
0,162,8,133,2,134,3,32,93,128,32,50,129,32,73,129,76,0,128,72,152,72,138,72,169,1,133,112,230,107,208,2,
230,108,32,232,129,169,32,141,6,32,169,0,22,129,141,5,22,66,104,170,104,168,104,64,160,0,240,7,169,105,162,128,
76,4,96,96,162,0,21,23,0,32,22,195,1,22,194,63,21,37,21,134,22,197,41,21,27,173,41,96,201,4,32,169,
129,240,3,76,158,128,76,188,128,169,184,162,130,24,109,41,96,144,1,232,160,0,32,130,129,141,7,21,36,238,41,96,
21,32,76,140,128,21,47,33,21,246,201,17,14,61,15,21,253,227,128,76,1,129,169,169,17,24,61,209,21,125,17,2,
180,17,10,130,5,22,201,128,17,4,172,30,141,1,32,76,46,129,22,65,96,173,0,96,174,1,96,32,112,130,173,2,
96,174,3,21,65,160,4,76,105,128,17,3,228,188,162,130,17,2,228,169,188,133,10,169,130,133,11,169,0,133,12,169,
96,133,13,162,214,169,255,133,18,160,0,232,240,13,177,10,145,12,200,208,246,230,11,230,13,208,240,230,18,208,239,96,
133,10,134,11,162,0,177,10,96,208,42,162,0,138,96,240,36,22,163,30,48,28,22,227,2,16,20,22,227,14,144,12,
21,200,176,4,22,226,162,0,169,1,96,165,115,208,252,96,169,255,197,115,240,252,96,133,118,132,116,134,117,32,193,129,
164,113,165,116,153,0,2,165,117,153,0,3,165,118,153,0,4,200,132,113,230,115,96,164,115,208,1,96,166,114,169,14,
141,42,96,189,0,2,141,6,32,189,0,3,22,163,4,141,7,32,232,136,240,93,17,19,14,71,17,19,14,49,17,19,
14,27,17,19,14,5,206,42,96,208,141,134,114,132,115,96,169,0,162,0,72,165,2,56,233,2,133,2,176,2,198,3,
160,1,138,145,2,104,136,145,2,96,169,41,133,10,169,96,17,34,41,168,162,0,240,10,145,10,200,208,251,230,11,202,
208,246,192,2,240,5,21,70,247,96,78,111,32,99,97,114,116,32,108,111,97,100,101,100,0,1,0,16,32,17,66,184,
141,18,96,142,19,96,141,25,96,142,26,96,136,185,255,255,141,35,22,196,34,96,140,37,96,32,255,255,160,255,208,232,
96,17,71,230,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,10,53,128,0,128,92,128,
17,14,14,204,204,51,51,22,106,0,24,60,126,24,22,1,22,231,16,48,127,127,48,16,0,22,230,12,18,48,124,48,
98,252,22,231,0,0,3,62,118,54,54,22,231,127,127,17,4,80,22,230,224,224,96,22,3,22,230,24,24,24,248,248,
21,16,22,230,204,153,51,102,22,106,51,153,204,22,107,21,27,255,255,17,4,67,22,227,3,22,13,17,6,188,22,230,
17,2,172,22,13,31,31,22,236,255,255,22,236,31,31,17,4,136,22,227,22,1,248,248,21,5,22,233,17,14,123,17,
3,64,22,230,17,3,64,21,248,17,8,29,21,216,17,6,88,17,3,64,22,230,240,22,13,21,233,21,243,22,230,17,
6,16,22,226,192,192,48,48,22,106,15,22,1,21,84,22,230,17,10,4,22,226,17,10,52,22,230,17,6,16,17,10,
44,22,6,17,35,220,0,24,22,231,102,102,17,34,107,0,22,233,255,22,33,102,22,231,24,62,96,60,6,124,21,40,
22,229,0,102,12,24,48,102,70,22,231,60,102,60,56,103,102,63,22,231,6,12,17,36,59,22,230,21,30,48,48,24,
12,22,231,22,97,12,21,4,22,231,0,102,60,255,60,17,2,115,22,230,24,24,126,17,35,70,22,230,17,4,173,21,
33,22,231,126,21,205,22,231,21,80,22,232,3,6,12,24,48,96,22,231,60,102,110,118,102,102,60,22,231,24,24,56,
24,24,24,126,22,231,60,102,6,12,48,96,22,235,28,6,21,168,22,228,6,14,30,102,127,6,6,22,231,126,96,124,
6,21,80,22,230,60,102,96,124,17,4,88,22,228,126,102,12,17,35,83,22,230,60,21,13,21,216,22,231,62,21,240,
22,228,17,34,124,22,66,22,236,17,2,224,22,228,14,24,48,96,48,24,14,0,22,230,17,2,239,17,4,241,22,228,
112,24,12,6,12,24,112,22,231,17,2,192,24,21,52,22,232,110,110,96,98,17,3,248,22,227,24,60,102,126,17,34,
228,22,230,124,102,102,22,66,22,231,60,102,96,96,96,17,4,200,22,227,120,108,21,30,108,120,22,231,126,96,96,120,
96,96,126,22,237,96,22,231,21,48,110,17,37,8,22,227,21,46,17,3,96,22,230,60,17,99,19,21,24,22,229,30,
12,22,1,108,56,22,231,102,108,120,112,120,108,21,40,22,229,17,132,62,126,22,231,99,119,127,107,99,99,99,22,231,
102,118,126,126,110,17,2,88,22,229,60,102,22,2,17,35,88,22,227,17,2,205,21,49,22,231,21,144,60,14,22,231,
21,80,17,2,96,22,230,60,102,96,60,17,37,208,22,227,17,163,13,17,34,200,22,229,21,111,17,5,208,22,232,60,
17,5,16,22,225,99,99,99,107,127,119,99,22,231,21,77,60,17,3,248,22,230,21,1,17,4,64,22,227,126,17,67,
159,126,22,231,60,48,22,2,60,22,231,96,48,24,12,6,3,0,22,231,60,17,34,32,12,21,24,22,229,17,34,193,
17,68,244,22,229,22,3,17,165,133,22,225,17,134,203,22,230,21,58,6,62,102,62,22,232,96,17,66,176,124,22,232,
0,60,96,96,96,17,66,144,22,229,6,21,31,21,96,22,230,0,60,102,126,21,216,22,228,14,24,62,17,3,84,22,
230,0,21,95,6,124,22,231,17,3,80,102,17,5,88,22,225,24,0,56,17,34,240,22,231,6,0,6,22,1,60,22,
231,96,96,108,17,34,128,22,231,21,30,21,160,22,230,0,102,127,127,107,99,22,233,17,2,79,21,32,22,231,17,34,
210,17,4,152,22,228,17,36,242,22,232,17,3,144,6,22,232,124,17,66,226,21,160,22,228,17,131,225,22,232,17,130,
127,17,98,112,22,230,17,35,226,17,34,0,22,233,60,17,2,240,22,230,99,107,127,62,17,226,24,22,230,17,35,241,
22,234,21,47,12,120,22,232,126,12,24,48,17,98,194,22,228,28,48,24,112,24,48,28,22,231,17,164,159,22,3,22,
227,56,12,24,14,24,12,56,0,22,230,51,255,204,17,35,206,22,230,22,14,17,194,92,22,10,17,236,246,204,204,255,
231,195,129,231,22,1,22,231,239,207,128,128,207,239,255,22,230,243,237,207,131,207,157,3,22,231,255,255,252,193,137,201,
201,22,231,128,128,17,4,80,22,230,31,31,159,22,3,22,230,231,231,231,7,7,21,16,22,230,17,236,246,204,17,237,
246,51,153,17,227,11,17,4,67,22,227,252,22,13,17,6,188,22,230,17,2,172,22,13,224,224,22,236,0,0,22,236,
224,224,17,4,136,22,227,22,1,7,7,21,5,22,233,17,14,123,17,3,64,22,230,17,3,64,21,248,17,8,29,21,
216,17,6,88,17,3,64,22,230,17,226,124,22,10,17,238,244,22,226,17,6,16,22,226,63,63,207,207,22,106,17,226,
192,21,84,22,230,17,10,4,17,230,220,17,14,60,17,234,252,17,6,44,22,6,17,35,220,255,231,22,231,153,153,17,
34,107,255,22,233,0,22,33,153,22,231,231,193,159,195,249,131,21,40,22,229,255,153,243,231,207,153,185,22,231,195,153,
195,199,152,153,192,22,231,249,243,17,36,59,22,230,21,30,207,207,231,243,22,231,22,97,243,21,4,22,231,255,153,195,
0,195,17,2,115,22,230,231,231,129,17,35,70,22,230,17,4,173,21,33,22,231,129,21,205,22,231,21,80,22,232,252,
249,243,231,207,159,22,231,195,153,145,137,153,153,195,22,231,231,231,199,231,231,231,129,22,231,195,153,249,243,207,159,22,
235,227,249,21,168,22,228,249,241,225,153,128,249,249,22,231,129,159,131,249,21,80,22,230,195,153,159,131,17,4,88,22,
228,129,153,243,17,35,83,22,230,195,21,13,21,216,22,231,193,21,240,22,228,17,34,124,22,66,22,236,17,2,224,22,
228,241,231,207,159,207,231,241,255,22,230,17,2,239,17,4,241,22,228,143,231,243,249,243,231,143,22,231,17,2,192,231,
21,52,22,232,145,145,159,157,17,3,248,22,227,231,195,153,129,17,34,228,22,230,131,153,153,22,66,22,231,195,153,159,
159,159,17,4,200,22,227,135,147,21,30,147,135,22,231,129,159,159,135,159,159,129,22,237,159,22,231,21,48,145,17,37,
8,22,227,21,46,17,3,96,22,230,195,17,99,19,21,24,22,229,225,243,22,1,147,199,22,231,153,147,135,143,135,147,
21,40,22,229,17,132,62,129,22,231,156,136,128,148,156,156,156,22,231,153,137,129,129,145,17,2,88,22,229,195,153,22,
2,17,35,88,22,227,17,2,205,21,49,22,231,21,144,195,241,22,231,21,80,17,2,96,22,230,195,153,159,195,17,37,
208,22,227,17,163,13,17,34,200,22,229,21,111,17,5,208,22,232,195,17,5,16,22,225,156,156,156,148,128,136,156,22,
231,21,77,195,17,3,248,22,230,21,1,17,4,64,22,227,129,17,67,159,129,22,231,195,207,22,2,195,22,231,159,207,
231,243,249,252,255,22,231,195,17,34,32,243,21,24,22,229,17,34,193,17,68,244,22,229,22,3,17,165,133,22,225,17,
134,203,22,230,21,58,249,193,153,193,22,232,159,17,66,176,131,22,232,255,195,159,159,159,17,66,144,22,229,249,21,31,
21,96,22,230,255,195,153,129,21,216,22,228,241,231,193,17,3,84,22,230,255,21,95,249,131,22,231,17,3,80,153,17,
5,88,22,225,231,255,199,17,34,240,22,231,249,255,249,22,1,195,22,231,159,159,147,17,34,128,22,231,21,30,21,160,
22,230,255,153,128,128,148,156,22,233,17,2,79,21,32,22,231,17,34,210,17,4,152,22,228,17,36,242,22,232,17,3,
144,249,22,232,131,17,66,226,21,160,22,228,17,131,225,22,232,17,130,127,17,98,112,22,230,17,35,226,17,34,0,22,
233,195,17,2,240,22,230,156,148,128,193,17,226,24,22,230,17,35,241,22,234,21,47,243,135,22,232,129,243,231,207,17,
98,194,22,228,227,207,231,143,231,207,227,22,231,17,164,159,22,3,22,227,199,243,231,241,231,243,199,255,22,230,204,0,
51,17,35,206,22,230,22,14,9,19,0,13,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,22,31,
22,31,22,31,22,31,22,31,22,31,22,30,22,28
];
describe('LZG', function() {
it('Should decode LZG', function() {
var rom = new Uint8Array(new lzgmini().decode(NES_CONIO_ROM_LZG));
var rom = new Uint8Array(new util.lzgmini().decode(NES_CONIO_ROM_LZG));
assert.equal(40977, rom.length);
});
});

View File

@ -3,8 +3,11 @@ var assert = require('assert');
var fs = require('fs');
var wtu = require('./workertestutils.js');
includeInThisContext('gen/emu.js');
includeInThisContext('src/platform/verilog.js');
var emu = require('gen/emu.js');
var verilog = require('gen/platform/verilog.js');
var VerilogPlatform = emu.PLATFORMS['verilog'];
Object.assign(global, verilog); // copy global VL_* properties
function loadPlatform(msg) {
var platform = new VerilogPlatform();